The other day I was bored and decided to make a program that could be programmed by a user to play any game on any emulator. Basically it's like a tas-bot but you make a chain of nodes that each have their own goal etc.
I'm far along enough to start worrying about how to interface this thing with the actual emulators. Rather than post this message every time in each of the emulator forums, I figured I'd just put it here once. If this post needs to get moved I'm sorry.
My question is if there is a way to interact with the emulators without having to edit their individual source code. That way I can keep the universal idea. My hope is that someone here has done something similar in the past.
Thanks to anyone who can offer advice.
Generally, no. Some emulators have shared memory support which is being boo'd down by some people (including me). Bisqwit took the source modification route. I think that's the way it's going to need to be.
Unless you want to ptrace the emulator.
Joined: 5/1/2004
Posts: 4096
Location: Rio, Brazil
I think it's easier to give the TASer better tools to see the "behind the scenes" on how the game is working than programming this impossible thing.
Memory watch is good, but what if you could click on an enemy sprite and get some info connected to it? Or get an alert or pause the emulator as soon as a certain memory value has been reached?
The way i see it, preparing a bot to do a ramdom search will take much longer than if you know what you have to do and just do it. We have the making tools: slowdown, frame advance, savestates. Now we're advancing into the tools to see what the normal player can't. We have memory watch, what else can we have? I'd say this is the way to go. Bots just don't seem to be too practical.
Keep in mind I know jack squat about the practical side of applications programming, but couldn't you just make a device driver that fakes keyboard / joystick input? All the emulators already recognize input from the keyboard, so ... problem solved?
TASbots could probally do a game like Mario 1, but I'm not so sure about something like Sonic, which has infinitely more possiblilties of movemenTs. It would probally be more conplex than a chess program and it would not look for glitches. I don't think it would be any better since the developers would snap this up, which effectivley means fewer no testers for games. TASbots would probally have to be programmed for each individiual game since it would have to know what the exact goal and route was, but yeah if it has to look for glitches then it would take till the year 3000. The way I've always thought of it is
Human = dum
Computer = dummer
Human + Computer = deadly combination
So basically I think humans using tools will always be better than a computer testing 100,000's of possibilties through a 5 minute game.
I suppose along similar lines (since I can abstractly see how the above could be tricky) maybe it'd be possible to hook into the emulators' keyboard code? I guess the way to find out would be to see how the movie playback talks to the emulated console's buttons, but I'd guess that you also need to be able to take over the tool controls so I'm not sure if those could be helpful.
However, I guess that doesn't really help, does it? You need access to all of the emulator's memory pretty much, right? In other words, you're interested in how Bisqbot was hooked in, right?
I guess I don't really have an useful or practical thoughts other than to build it into the emulators themselves. :-\
Joined: 2/28/2006
Posts: 2275
Location: Milky Way -> Earth -> Brazil
hmm... maybe it could emulate a controller, so we could add it to the gamepads list, and assign it to any emulator.
"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
On this subject, I remember within the past few years there was a programming competition where one of the challenges was to find the fastest path through a number of tracks. Basically, you were given a bitmap of the tracks and some physics rules, and you had to optimize the path. One of the top teams utilized a very BisqBot-like approach where they built an engine to allow them to drive around on the tracks, record their best times, and then used random perturbations to optimize segments along the best path predetermined by humans.
At this point my main concern is being able to read the memory of the emulator, not really send it input. I'm trying to implement the memory watching aspect, once that's done, it would be easy to implement many additional features.
Just curious why you are not in support of shared memory.
My goal in making this was to be able to have a computer more intelligently play a part of a game. This idea basically came to me when I was absolutely sick of trying to get a battletoad+double dragon to jump over a hole as fast as possible without getting hit by birds or something. I figured that a bot that followed a set of instructions would be more effective at solving the problem than a random input generator because basically, every small action in a game could be characterized by a set of simple instructions. I could say JumpOverHole:=input run sequence -> hold forward and jump -> let go of buttons; I then could assign a goal condition and repeat condition for each step, and have a program generate input that follows these instructions. Worst case it could be done by brute force.
So I do agree that doing a random search would be horribly inefficient, I am hoping that this way would be better.
Then again, programming a bot to do all of this is taking a lot longer than just jumping over the stupid hole...
It appears that I have found a way to read the memory of the emulator without editing the source for it using the windows functions ReadProcessMemory() and WriteProcessMemory(). Currently the ram for fceu has appeared at the same offset each time I tested the program; hopefully it will stay that way. I guess my main question would now be as to the best way to send input to the emulators.
Wouldn't it be easier to decide on some functions you'll need and put them in a few emulators, instead of interfacing with the emulator by poking around in its memory without its knowledge?
If you had bothered to read the thread, you would've found that he doesn't want to do that, to keep the whole "Universal" feel.
Simply updating some memory addresses is infinitely easier than downloading the source of every emulator, adding functions and correctly placing them in the proper format fo rtht emulator, and then recompiling them for each OS.
The Super Mario Kart thread in the SNES forum is VERY similar to this, Huffers designed a bot that read values in memory in the SNES, then had the bot input stuff, loading save states as needed. He ran into a few hitches with the way save states are handled, but it did complete a track overnight... and then he lost all his data when his HD died, but you should talk to him since he seems to have something that works reasonably well.
How do you have a HDD that just crashes overnight? I've never, ever had that happen. Weird.
Also, this is just anothe rexample of why you should take backups. Often. This is probably the third horror story of someone losing tons of work due to inadequiate* backups.
(*this word intentionally spelled wrong)
Emulator Coder, Site Developer, Site Owner, Expert player
(3574)
Joined: 11/3/2004
Posts: 4754
Location: Tennessee
I applaud your efforts here Ash Williams!
One other useful feature would be the ability to program macros like a + frame advance, a + fa, up+a+fa or some other combo. This would allow a TASer to program certain common button patterns into a single command. Like programming the button presses for the flying knee combo in double dragon 2 for instance.
Even more useful is a macro function with a random x frames option in it. Something like: "20 random frames, then hold right and press A". This would especially be useful in luck manipulation for rpg's.
The linux users will boo you for your efforts but the rest of us will grateful. Keep up the good work.
Don't assume I haven't read the thread. I'm claiming that "updating some memory addresses" is actually much more difficult than adding those functions to each emulator. Mainly because he does not really know where those addresses are (except where they happen to be at the time on his computer), and because providing input at the correct speed by editing the emulator's memory while it's running would be nearly impossible and would need to be re-written per emulator. It would be easier to make a universal interface for the emulators to "plug in" to.
I highly doubt that. At least not a *generic* tasbot.
It may be possible to build a program which is highly optimized specifically for Mario 1 and uses algorithms and heuristics created for achieving the goals in that game. However, it's just not possible to create a *generic* bot which could complete a game (any game) in any feasible way. Heck, it would be really, really difficult to even make it search for the optimal play for 10 seconds of playing time. In fact, even if optimality is not the goal but just trying to search the goal by any path, it would still be very unlikely.
That's because the number of possible combinations of button presses increase exponentially in consecutive frames. To get an idea, let's just assume that it's enough for the program to test the 4 directional buttons to reach the desired goal:
In 1 frame the amount of combinations to test is 4.
In 2 frames the amount of combinations is 16.
In 3 frames it's 64.
In 10 frames it's already 1048576.
In 100 frames it's 1606938044258990275541962092341162602522202993782792835301376.
In 1000 frames it's 11481306952742545242328332011776819840223177020886952004776427368257\
66261392370313856659486316506269918445964638987462773447118960863055\
33142593135616665318539129989145312280000688779148240044871428926990\
06348624478161546364638836394731702604046635397090499655816239880894\
46296056233116495361642219703326813441689089844585056023794848079140\
58900934776500429002716706625830522008132236281291761267883317206598\
99539641812702177985840404215985318325154088943390209192055495778358\
96720391600819572166305827553804255837260155283487864194320545089152\
75783882625175435528800822842770817965453762184851149029376
I think it goes without saying that the goal (here) in making a "generic" tasbot would be to make something that can be tuned to any particular game in order to achieve performance as if it had been written specifically for that game, without actually needing a full reprogramming for each game. (Or, at least, simplifying that reprogramming as much as possible.) It's either that or making something with amazingly good AI... Anything that needs to try 4^(movie length) combinations is unworkable and isn't being seriously considered.
I highly doubt that. At least not a *generic* tasbot.
It may be possible to build a program which is highly optimized specifically for Mario 1 and uses algorithms and heuristics created for achieving the goals in that game. However, it's just not possible to create a *generic* bot which could complete a game (any game) in any feasible way. Heck, it would be really, really difficult to even make it search for the optimal play for 10 seconds of playing time. In fact, even if optimality is not the goal but just trying to search the goal by any path, it would still be very unlikely.
That's because the number of possible combinations of button presses increase exponentially in consecutive frames. To get an idea, let's just assume that it's enough for the program to test the 4 directional buttons to reach the desired goal:
*brackets mean example of how it appplies to a game
A Tasbot would know all the specific rules a certain game and like I said earlier it would be designed like a chess program, when a chess program is playing it would not think of every piece on the board and decide where it could be put and then say to itself "Oh darn I can't do that since its not legal". It would know all the legal moves it can do(game controller actions) and know where the oponents pieces are and how they move and where they can go in the next turn (walls and enemies and moving obstacles). So if a high value piece e.g. queen is being threatened is not going to go through every possible option of what it and the oponent could do since it obvious that the oponnent will take the queen next turn if it can do so. So the options will come tumbling down to either
1. Move queen to safety
2. Take piece thats threatening the queen
3. Threating the other queen
4. Put the oponent in check
5. Block path to queen with other piece
6. Take oponents queen
That would limit the situation down to about 15-20 moves and of those moves its likely that only 2 or 3 would be reasonable instead of searching through the
75068352983405739055035602592843 moves that you were sugesting. Of course the huge difference between a TASbot and chess program is a chess program tries to limit the number of reasonable moves that a oponent can do so to make the next 20-30 moves a little easier to compute. For example if would be completely unreasonable for a compute to test out possibilties such as left, right or move left at the start of a level unless there was some form of interaction that would dramatically speed up the level e.g. bouncer at the start of Spring Yard 2, but yeah a doubt a generic TASbot would be coming around anytime soon.
I don't think there's a way for the computer to know what the outcome of game would be in the future so it would have to 'go' through it countless number of times. Changing 1 frame at a time because it doesn't know how nonsensical the route it could be taking is.. and how would it stop and try again?
No PC could do this