Posts for Gunty


1 2 3 4 5 6 7
Experienced Forum User, Published Author, Player (198)
Joined: 12/3/2006
Posts: 151
Wow, I hadn't noticed the OP's date either. :) I agree with Xkeeper that a TAS rescuing no passengers could be quite boring after all, so that's off the table. A TAS featuring the "best ending" would have to collect about 5-6 passengers I think, however this leads to the following problems: The general lacking AI of the passengers: In realtime the passengers often aren't able to make jumps the player can make. I can only imagine this being worse in a TAS since it would have a lot of "impossible" jumps. The speed of the passengers: Everytime you want the passengers to follow you to a certain point you have to call them. Calling them automatically stops your movement. To make the matter even worse, if the passengers ever exit the screen they are often not going to respond to your calls. This means you have to stop and call the passengers every time you have moved a bit. In my opinion, those are the two major things that makes a TAS both annoying to make and less entertaining to watch, unless there are some obvious solutions to the above problems..
Experienced Forum User, Published Author, Player (198)
Joined: 12/3/2006
Posts: 151
http://dehacked.2y.net/microstorage.php/info/4139/SOStest.smv A little bit of recording of what I think to be the optimal route using Capris and rescuing no passengers. To avoid desynchs, you should disable Interpolated Sound. I'm pretty sure you cannot manipulate the time when the ship tilts, but you can manipulate it's direction. This could eliminate two of the three waiting parts in the movie now. Though, when I'm looking back at the movie I'm not really sure if this would the best game to TAS. Adding some optimised jumping and running could change that however.
Experienced Forum User, Published Author, Player (198)
Joined: 12/3/2006
Posts: 151
I had never heard of this game before, but I now played it for a while and I must say it's extremely fun to play. For making a TAS however, I'm not sure if rescuing every passenger is the best option. Not only does it take more time talking to them, but you also have to wait for them every room (unless there's some fast way for them to keep up with you). Instead, I'm thinking the best option would be completing the game and totally ignoring all the people asking you for help, which seems quite hilarious if you ask me :). As for making the TAS itself, the biggest challenge would be finding the fastest path to the boiler room, and manipulating luck to have the best possible 'ship tilts'. And, of course, there's the question which character to play...
Post subject: Re: #1446: Aqfaq's Genesis Gods in 07:32.93
Experienced Forum User, Published Author, Player (198)
Joined: 12/3/2006
Posts: 151
  $i = (int)($length + 0.5);
This line is always executed, meaning the seconds will always be rounded up if the subsecond amount was greater or equal to 50. Even when subseconds are displayed... I think?
Experienced Forum User, Published Author, Player (198)
Joined: 12/3/2006
Posts: 151
Sorry, I was in a bit of a hurry when I made that post, so that uncompilable line is indeed a copy/paste error, I'll fix it. As for the code, this was more of a test thing, so I purposely ignored the critical and defend mechanism since they would probably not be used in battle anyways. Same goes for the Flash thingy, since in an optimal battle the Catfish would not cast Flash at all. Thanks for the correction on Dive though. I really thought I had double checked that :p. I'm probably going to (try to) make a more generic simulator in the future without all those assumptions. That way I can use it on different bosses with a little tweaking on the AI part. Oh, and the rounding parts you speak of, Java does it automatically after each division, since I'm working with integers.
Experienced Forum User, Published Author, Player (198)
Joined: 12/3/2006
Posts: 151
AI:
public void AI(int def){

    while(rng.callRN()>42){}
    if(rng.callRN()>192){           		// megaquake (65 ATP) check  (25%)
        int damage = (rng.callRN()/8*65/256+65-maxim[4]/def)/2;
        rng.wasteRN(20);
        maxim[0] = maxim[0] - damage;
    }else if(rng.callRN()>224){     		// flash (81 ATP) check      ( 9%)
        int damage = (rng.callRN()/8*81/256+81-maxim[6]/2)/2;
        rng.wasteRN(20);
        rng.wasteRN(7);             		// Flash' animation
        maxim[0] = maxim[0] - damage;
    }else{                          		// attack (45 ATP)          (66%)
        int damage = (rng.callRN()/4*45/256+45-maxim[4]/def)/2;
        rng.wasteRN(20);
        maxim[0] = maxim[0] - damage;
    }
}
Experienced Forum User, Published Author, Player (198)
Joined: 12/3/2006
Posts: 151
For some weird reason the AI's method doesn't get displayed when I paste it, so I'll try making another post after this one. Anyways this is the part that simulates Maxim's action (defends, attack, dive (IP attack), boomerang, potion). Now this version does not have any IP checks for performing Dive, and I'm pretty sure the way I calculated 'defend' is wrong, but it doesn't really matter since an optimal fight would only involve boomerangs and potions anyways.
public void action(int n){

    rng.wasteRN(6);                 		// agility check (but Maxim always wins)
    int def = 2;                    		// defence modifier
    int rngwaste = 0;               		// delayed RNG calls
    
    if(n==0){                       		// defend
        def = 1;
    }else if(n==1){                 		// attack   
        int damage = (rng.callRN()/4*maxim[3]/256+maxim[3]-10/2)/2;
        rng.wasteRN(20);
        cfhealth = cfhealth - damage;        
    }else if(n==2){                 		// dive (2x damage)
        int damage = (rng.callRN()/4*maxim[3]/256+maxim[3]-10/2);
        rng.wasteRN(20);
        cfhealth = cfhealth - damage;
    }else if(n==3){                 		// boomerang ("ATP" = 100)
        while(rng.callRN()>42){}
        int damage = (rng.callRN()/8*100/256+100-10/2)/2;
        rng.wasteRN(20);
     	rngwaste = 30;
    	cfhealth = cfhealth - damage;
    }else if(n==4){                 // potion   ("ATP" = 30)
        int heal = rng.callRN()*11/256*30/256+30;
        rng.wasteRN(20);
        maxim[0] = maxim[0] + heal;
        if(maxim[0]>maxim[1]){maxim[0] = maxim[1];}     // check if HP does not exceed max HP
    }

    if(cfhealth<1){                     	// if the catfish died:
        if(rng.callRN()<64>63 && a<128){          // secundary item drop check
                result = 3;             	// item drop checks succeeded
            }else{
                result = 2;             	// item drop checks failed
            }
        }
    }else{                              	// if the catfish lives:
        if(rngwaste!=0){                	// call the RNG during spell animation (after item drop checks)
            rng.wasteRN(rngwaste); 
            rngwaste=0;
        }
        AI(def);                       		// Catfish' turn
        if(maxim[0]<1){
            result = 1;
        }
    }
}
Edit: fixed copy/paste error
Experienced Forum User, Published Author, Player (198)
Joined: 12/3/2006
Posts: 151
Inspired by Dromiceius' wacky idea I have decided to make another Lufia II TAS. The idea would be for this TAS to live up to the "Tool-assisted" part of it's definition, using tools to actually calculate the fastest way to kill a boss, solving a puzzle, having an item drop and so on instead of 'trying randomly' like in my currently published TAS. This TAS will probably be a (very) long term project, since it will involve a lot of programming and ASM deciphering, but I really want it to be perfect :). Edit: Here's a demo showing the possibilities of successfully using this technique
Experienced Forum User, Published Author, Player (198)
Joined: 12/3/2006
Posts: 151
Hmm, you're right. According to this page I'm apparantly making a 'shallow copy' of the object, meaning both objects use the same fields (not sure if this is the right terminology). I'm sure I can figure this out now. Also, you're right about the boomerang targetting behaviour and I did not know the Catfish couldn't cast two consecutive flashes. Thanks a bunch (again!). Edit: Well this is neat. I was able to search through the first 5000'th sets of Random Numbers in less than a minute and it's actually possible to beat the Catfish within 4 rounds and getting the item drop. Unfortunately the first time this can happen is at the 1045'th Random Number set, while you will typically encounter the Catfish near the 200'th Random Number set. A 5 round victory on the other hand is possible at the 184'th and 242'th set of Random Number, so these might actually be possible (I have a 6 round victory in my current speedrun).
Experienced Forum User, Published Author, Player (198)
Joined: 12/3/2006
Posts: 151
In this case, yes. Attacking normally calls the RNG 21 times. Using a boomerang keeps calling the RNG until it's lesser than 46, after that 21 times and finally 30 times during the animation. I have tested the actual simulation program, and Im pretty sure it's bug free. The thing I'm having trouble with is the 'test all possible combinations' part.
Experienced Forum User, Published Author, Player (198)
Joined: 12/3/2006
Posts: 151
Excuse my double post but; I have been working on something like this for the past few days. The game I chose to (partially) brute force is Lufia II (the Catfish fight) since I'm very familiar with it's AI and such. The first thing I did was building a simulator, which turned out to be able to simulate ~500000 battle rounds per second. However, now I was trying to make a program to actually test all possible actions using nested for loops, but somehow the different variables got mixed up :(. I suppose I could post the code here if I add some more comments to it, but I was wondering if someone could give me some generic advice on actually building such a program. PS: I worked in Java since that's the only language I'm (somewhat) familiar with. Edit: Here is the bruteforce method I constructed. state[] is an array containing the entire statespace for all rounds (maxim's health, catfish' health, RNG state etc). This statespace also contains the variable 'result' which contains the outcome of that particular round (0= no one died, 1= Maxim died, 2= Catfish died; no item drop, 3= Catfish died; Jewel dropped). The method state[round].action(i) perform action #i (0= defend, 1= attack, 2= dive, 3= boomerang, 4= potion) and stores the result in that same array. Anyways, when executing this method all goes well untill the third round. When Maxim defends 3 times in a row he dies, so the next action for that partical round should be tried. However, when trying the other action in round 3, Maxim's health is still at 0 meaning the statespace was not reloaded. Here's the method, but please keep in mind I'm a programming novice.
private void testallactions(int round){                 // round=1 to start at round 1

    for(int i=0;i<5;i++){                               // loop through all possible actions

        state[round]=state[round-1];                    // load last round's state
        state[round].action(i);                         // execute action #i

        command[round]=i;                               // log the executed action
        if(state[round].result==0 && round<maxround){   // no one died and max roundnumber is not reached
            testallactions(round+1);                    // test all possible actions in the next round

        }else{ 
            for(int j=1;j<=round;j++){
                System.out.print(command[j] + " ");     // print all executed actions
            }
            if(state[round].result==1){                 // maxim died
                System.out.println("Maxim died.");

            }else if(state[round].result==2){           // catfish died, no jewel
                System.out.println("Catfish died - no jewel.");

            }else if(state[round].result==3){           // catfish died, jewel dropped
                System.out.println("Catfish died - jewel dropped.");
            }
        }                                               // try next action
    }
}
Experienced Forum User, Published Author, Player (198)
Joined: 12/3/2006
Posts: 151
The reason why this topic is usually kept at discussion is because it simply requires alot of time, both writing a bruteforce program and actually performing it. Most of the time it's faster to just manually find the fastest solution. Frustrating how fast the human brain can do this compared to a computer :P. If you're interested in brute force results you can find some in my Lufia II tas that recently got published. I used brute force on a few puzzles to find the fastest solution, though quite some bruteforcing results turned out to be just as fast as the ones I had found manually.
Experienced Forum User, Published Author, Player (198)
Joined: 12/3/2006
Posts: 151
Entering the town adds it to my warp list, so I can just warp to that town instead of walking when I need to go through the tower again. Also, entering the town resets the memory address that counts the amount of steps I made on the world map, which makes it possible to skip all random battles.
Experienced Forum User, Published Author, Player (198)
Joined: 12/3/2006
Posts: 151
I don't think the ingame framerate counter can display higher than 60 or 50. I used fraps, using the OpenGL bilinear mode in the emulator. The reason because you get a lower framrate in turbo mode is because the emulator skips rendering a few frames, in your case around 10 I guess.
Experienced Forum User, Published Author, Player (198)
Joined: 12/3/2006
Posts: 151
Maximus: you should try turning off the 'Automatic Frame Skip' option, that removes the cap from frame rate.
Experienced Forum User, Published Author, Player (198)
Joined: 12/3/2006
Posts: 151
I'm not sure if you understood what I meant, but the idea would be to recreate the enemy AI in your own program, so you wouldn't need to use the emulator at all. This custom AI would be faster for bruteforcing purposes since it doesn't calculate useless things like graphics, sound etc. As for the framerate in Snes9x, I usually get somewhere between 400 and 700 fps when using turbo mode without skipping frames. Edit: Using a Pentium M 1.70 GHz, 768 MB RAM, Ati Mobility Radeon 9600 with 64 MB video memory.
Experienced Forum User, Published Author, Player (198)
Joined: 12/3/2006
Posts: 151
I think your best bet would be to actually dissamble the rom and try to simulate the game. This would make programming much more easy and of course faster. If the RNG is actually manipulable on frame precision, I don't think it's possible to brute force, but you could always try different strategies until a sufficient fast one is found. Games with RNGs manipulable on a turn based precision on the other hand could actually be viable to brute force. Interesting idea I must say :).
Experienced Forum User, Published Author, Player (198)
Joined: 12/3/2006
Posts: 151
I'll second the WTF-factor this tas had. Also, I agree with the password decision you made; 5 minutes of a camera trying to keep up with the player is perfect, any more could get repetitive. Yes vote.
Experienced Forum User, Published Author, Player (198)
Joined: 12/3/2006
Posts: 151
jaysmad wrote:
Wow, already published? That was fast!
Indeed it was! One minor thing for the description though. This game does contain random battles. These can only occur on the world map, but are all avoided by entering the menu briefly.
Experienced Forum User, Published Author, Player (198)
Joined: 12/3/2006
Posts: 151
After that, if the first number succeeded, it generates a number 0-3, and a 1 (i.e., 0x40-0x7F) makes the item drop. In a multi-target attack, this occurs before the effects on the next enemy are determined.
This seems to be the missing link I've been looking for all this time (also the reason my calculated item drop chances were way too high). I'll definitely have some fun with this. Thanks!
Experienced Forum User, Published Author, Player (198)
Joined: 12/3/2006
Posts: 151
Wow, impressive, I'd have never been able to get all that information from that code. Do you by any chance have some notes on how item drops are determined as well?
Experienced Forum User, Published Author, Player (198)
Joined: 12/3/2006
Posts: 151
There is a way to darken all tiles with two bombs, but that will not solve the puzzle. I'm pretty sure the current solution is optimal, unless you can prove me wrong of course :).
Experienced Forum User, Published Author, Player (198)
Joined: 12/3/2006
Posts: 151
What Nitrodon said is indeed true. When generating the next floor the first 5 bits of the counter at 7E0040 determine the amount of 'wasted' random number pulled from the RNG before continuing with the routine. That means there should be 32 different time dependant floor layouts. I tried looking further into the code but I'm afraid my knowledge of assembly code (based solely on a few online guides) isn't sufficient to actually predict how the next floor will be generated. At least you now know what determines the randomness.
Experienced Forum User, Published Author, Player (198)
Joined: 12/3/2006
Posts: 151
Actually, taking more damage usually is faster since it allows for more IP attacks. The only way I think they could be useful is through instant-death attacks, which aren't available to the lower level capsule monsters.
Experienced Forum User, Published Author, Player (198)
Joined: 12/3/2006
Posts: 151
Haha, I agree. During the last part of my TAS I think I finished the game about 10 times just for fun, and the ending never got old :). AceOfShades: That part is explained in the dialogue with Iris in the Northern Lighthouse (accessable from savestate 4 from the file I posted). It actually makes sense.. somewhat.
1 2 3 4 5 6 7