Open Nostrademous opened 5 years ago
Yeah this prompted me to do some design thinking.. how do we deal with multiple bot versions playing bot vs bot? For sure though everything should be governed by the Actions proto message. Whatever fits in there should just be blindly executed by the respective bot.
On Wed, Dec 19, 2018, 14:30 Nostrademous <notifications@github.com wrote:
Since we are moving to multi-agent design I wanted to raise the question of how many agents do we actually want.
At start there are two possibilities:
- One Agent Per Hero (5 agents per Team)
- One Master Agent that controls 5 heroes
*3) One Agent Per Hero and Per Controllable Unit (meaning summons (Nerconomicon, Warlock Ultimate, Beastmaster Hawk & Boar, etc.), illusions (Manta, Illusion Rune, Wall of Replica, Disruption, etc.), clones (Meepo), doubles (Arc Warden Ultimate) or dominated (i.e., Helm of Dominator, Enchantress, Chen, etc.) units) - typically these are controlled by the same agent that is controlling the owning Hero that caused the summon/domination to occur, but doesn't have to be.
Each approach has its pros and cons in terms of flexibility (co-play with humans, etc.), agent action synchronization (via shared world state model versus independent world models), training time, and so forth. OpenAI went with #1 https://github.com/TimZaman/dotaservice/issues/1 above, but we do not necessarily have to, although I think I would prefer #1 https://github.com/TimZaman/dotaservice/issues/1 above as well.
Next, there are a few other things that could be their own agents: a) Courier - there is one courier per team - it can be controlled by any Hero Agent and even in real games it often gets abused by numerous players at once. We could make it its own agent. b) Glyph Usage - anyone on the team can use the Glyph (when available) c) Minimap Scan - anyone on the team can use the Minimap Scan function
*d) One Team Agent to control a), b) and c) as a single entity
Just wanted to throw this out there to think about and post your thoughts.
— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/TimZaman/dotaservice/issues/25, or mute the thread https://github.com/notifications/unsubscribe-auth/AHXSRPBRxT2Nq2TzivU41yhfL-ybpo0Zks5u6j-QgaJpZM4ZaP5G .
By the way, I see that you are using "auto-generated files" as a means to communicate between the bots and the agent. This assumes they always exist on the same hardware, basically disallowing the possibility of dotaservice running on one physical host while the agent code runs on a different one (well, short of doing network file transfers between the two).
I previously implemented the comms method of using CreateHTTPRequest() API (and I believe there is also a CreateRemoteHTTPRequest() API - could be wrong - Valve kept flip-flopping between allowing this and not): https://github.com/Nostrademous/Dota2-WebAI/blob/master/webserver_out.lua#L443-L467
While not necessarily "reliable", it is WAY faster than using files as a comms method. Currently I'm seeing the Think() function take 18-20ms for Nevermore, whereas I believe the method I had above was about 10x less time. I believe this has to do with "loadfile" being rather slow, but I could be wrong.
The http thing is unreliable. The lua wrapper sucks too, the callback only comes in after 2 frames, and the callback isn't purely async: you can't wait for it. So: you cannot do anything synchronously. The lua files are the way things keep synchronous. Notice I am running at 8x host_timescale on average, and I play smoothly with the bots to far. 10~15 ms is fine. The way you want to roll something like this out to the public is into a lua file that has the weights, or some cpp library, not through dotaserivce. You need to be synchronous to keep sanity or you will go bananas. The http callback is also slow, because you're guaranteed you have to wait for 2 ticks to get your callback executed, so that's guaranteed to be at least 2/30 seconds latency.
On Wed, Dec 19, 2018 at 3:08 PM Nostrademous notifications@github.com wrote:
By the way, I see that you are using "auto-generated files" as a means to communicate between the bots and the agent. This assumes they always exist on the same hardware, basically disallowing the possibility of dotaservice running on one physical host while the agent code runs on a different one (well, short of doing network file transfers between the two).
I previously implemented the comms method of using CreateHTTPRequest() API (and I believe there is also a CreateRemoteHTTPRequest() API - could be wrong - Valve kept flip-flopping between allowing this and not):
https://github.com/Nostrademous/Dota2-WebAI/blob/master/webserver_out.lua#L443-L467
While not necessarily "reliable", it is WAY faster than using files as a comms method. Currently I'm seeing the Think() function take 18-20ms for Nevermore, whereas I believe the method I had above was about 10x less time. I believe this has to do with "loadfile" being rather slow, but I could be wrong.
— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/TimZaman/dotaservice/issues/25#issuecomment-448608433, or mute the thread https://github.com/notifications/unsubscribe-auth/AHXSRJWyK6WFkBQk1iDw6RQ1q0B1ilHHks5u6khzgaJpZM4ZaP5G .
I'm fine with file passing providing it's "fast enough" which I believe it is.
Back to the initial question though - as we slowly transition to 5 agents and self-play (10 agents) - what about courier/glyph/scan functions - are they part of each agent or their own entities?
The Actions protobuf allows each actor to do this, so that's what makes sense. When when we know the C++ API, we can use that immediatelly and scrap half of the dotaservice's code. https://github.com/TimZaman/dotaservice/tree/master/botcpp
On Wed, Dec 19, 2018 at 5:28 PM Nostrademous notifications@github.com wrote:
I'm fine with file passing providing it's "fast enough" which I believe it is.
Back to the initial question though - as we slowly transition to 5 agents and self-play (10 agents) - what about courier/glyph/scan functions - are they part of each agent or their own entities?
— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/TimZaman/dotaservice/issues/25#issuecomment-448657464, or mute the thread https://github.com/notifications/unsubscribe-auth/AHXSREMYfNFZmkOqjkLFVbN1un1c80Yoks5u6mkhgaJpZM4ZaP5G .
which library/executable did the "Init" reside in?
I guess I'm asking if you know if the functions I am to find the signatures for exist in the main dota2 binary or a specific library that gets loaded for handling bots
libserver.dylib calls them. There are exactly 4 symbols expected, but we have zero knowledge of the full signature.
On Wed, Dec 19, 2018 at 8:44 PM Nostrademous notifications@github.com wrote:
which library/executable did the "Init" reside in?
I guess I'm asking if you know if the functions I am to find the signatures for exist in the main dota2 binary or a specific library that gets loaded for handling bots
— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/TimZaman/dotaservice/issues/25#issuecomment-448720352, or mute the thread https://github.com/notifications/unsubscribe-auth/AHXSRPuiP8af3GE4ReWPrynikd7uWctFks5u6pcGgaJpZM4ZaP5G .
Observe(size_t teamID, void , void )
First arg is team ID. 2 for Radiant, 3 for Dire.
Busy with kids right now but I believe 2nd will be pointer to protobuf.
Yep
void Observe(int team_id, const CMsgBotWorldState& ws)
On Thu, Dec 20, 2018, 01:07 Nostrademous <notifications@github.com wrote:
Observe(size_t teamID, void , void )
First arg is team ID. 2 for Radiant, 3 for Dire.
Busy with kids right now but I believe 2nd will be pointer to protobuf.
— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/TimZaman/dotaservice/issues/25#issuecomment-448798966, or mute the thread https://github.com/notifications/unsubscribe-auth/AHXSRLIKfukALe-3DaBKQDRfcJiIyVKMks5u6tS0gaJpZM4ZaP5G .
* thread #1, name = 'MainThrd', queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
* frame #0: 0x0000000090f2f9e0 botcpp_radiant.so`Observe
frame #1: 0x00000000892c53e1 libserver.dylib`___lldb_unnamed_symbol90409$$libserver.dylib + 769
frame #2: 0x00000000892bc2cd libserver.dylib`___lldb_unnamed_symbol90399$$libserver.dylib + 925
frame #3: 0x000000008923ab65 libserver.dylib`___lldb_unnamed_symbol89338$$libserver.dylib + 629
frame #4: 0x0000000088829641 libserver.dylib`___lldb_unnamed_symbol30869$$libserver.dylib + 129
frame #5: 0x0000000088b5c8bb libserver.dylib`___lldb_unnamed_symbol46417$$libserver.dylib + 155
frame #6: 0x0000000088b385c6 libserver.dylib`___lldb_unnamed_symbol45980$$libserver.dylib + 1510
frame #7: 0x00000000064b97d7 libengine2.dylib`___lldb_unnamed_symbol7478$$libengine2.dylib + 503
frame #8: 0x000000000639c3fe libengine2.dylib`___lldb_unnamed_symbol2598$$libengine2.dylib + 174
frame #9: 0x0000000006398b5e libengine2.dylib`___lldb_unnamed_symbol2557$$libengine2.dylib + 126
frame #10: 0x00000000063950a7 libengine2.dylib`___lldb_unnamed_symbol2521$$libengine2.dylib + 2855
frame #11: 0x0000000006387c8b libengine2.dylib`___lldb_unnamed_symbol2351$$libengine2.dylib + 1339
frame #12: 0x0000000006387712 libengine2.dylib`___lldb_unnamed_symbol2350$$libengine2.dylib + 18
frame #13: 0x000000000637b150 libengine2.dylib`___lldb_unnamed_symbol2189$$libengine2.dylib + 384
frame #14: 0x000000000637b880 libengine2.dylib`___lldb_unnamed_symbol2190$$libengine2.dylib + 1040
frame #15: 0x000000000637bbaa libengine2.dylib`Source2Main + 298
frame #16: 0x000000000630cd65 dota2`___lldb_unnamed_symbol6$$dota2 + 197
frame #17: 0x00007fff69c6908d libdyld.dylib`start + 1
That's the callstack to get to our Observe call
The only open q is: what should Act return?
I agree, makes the most sense, but wouldn't it have to be wrapped in a CMsgBotWorldState anyways?
How? What do you mean?
Well, isn't the Msg Actions protobuf embedded inside the CMsgBotWorldState?
It's just a submessage of it, not a field though.
On Thu, Dec 20, 2018 at 5:30 AM Nostrademous notifications@github.com wrote:
Well, isn't the Msg Actions protobuf embedded inside the CMsgBotWorldState?
— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/TimZaman/dotaservice/issues/25#issuecomment-448863802, or mute the thread https://github.com/notifications/unsubscribe-auth/AHXSRKiYRpZwhmQN7cdKwlzgSIk2ywkAks5u6xJUgaJpZM4ZaP5G .
Okay, at least reading the Observe() is done.
Example Code:
extern "C" void Observe(int teamID, const CMsgBotWorldState &ws) {
// The intention of this script is most probably to setup a connection with the
// worldstate sockets. Kinda weird though, because the dota game would be the server
// and then this script would be the client of that..
// Observe is called every tick that corresponds to the worldstate server's ticks,
// Exactly before the Act() is called.
cout << "Observe::cout" << endl;
cout << "TeamID: " << ws.team_id() << endl;
cout << "DotaTime: " << ws.dota_time() << endl;
cout << "GameState: " << ws.game_state() << endl;
for (CMsgBotWorldState_Player player : ws.players() ) {
cout << "\tPlayerID: " << player.player_id() << endl;
cout << "\tHeroID: " << player.hero_id() << endl;
}
}
Example Output:
Observe::cout
TeamID: 2
DotaTime: -77.2335
GameState: 4
PlayerID: 0
HeroID: 11
PlayerID: 1
HeroID: 35
PlayerID: 2
HeroID: 35
PlayerID: 3
HeroID: 35
PlayerID: 4
HeroID: 35
PlayerID: 5
HeroID: 35
PlayerID: 6
HeroID: 35
PlayerID: 7
HeroID: 35
PlayerID: 8
HeroID: 35
PlayerID: 9
HeroID: 35
yep. again, the only remaining question is: what does act return?
On Thu, Dec 20, 2018 at 5:33 AM Nostrademous notifications@github.com wrote:
Okay, at least reading the Observe() is done.
Example Code:
extern "C" void Observe(int teamID, const CMsgBotWorldState &ws) { // The intention of this script is most probably to setup a connection with the // worldstate sockets. Kinda weird though, because the dota game would be the server // and then this script would be the client of that.. // Observe is called every tick that corresponds to the worldstate server's ticks, // Exactly before the Act() is called. cout << "Observe::cout" << endl; cout << "TeamID: " << ws.team_id() << endl; cout << "DotaTime: " << ws.dota_time() << endl; cout << "GameState: " << ws.game_state() << endl;
for (CMsgBotWorldState_Player player : ws.players() ) { cout << "\tPlayerID: " << player.player_id() << endl; cout << "\tHeroID: " << player.hero_id() << endl; }
}
Example Output:
Observe::cout TeamID: 2 DotaTime: -77.2335 GameState: 4 PlayerID: 0 HeroID: 11 PlayerID: 1 HeroID: 35 PlayerID: 2 HeroID: 35 PlayerID: 3 HeroID: 35 PlayerID: 4 HeroID: 35 PlayerID: 5 HeroID: 35 PlayerID: 6 HeroID: 35 PlayerID: 7 HeroID: 35 PlayerID: 8 HeroID: 35 PlayerID: 9 HeroID: 35
— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/TimZaman/dotaservice/issues/25#issuecomment-448864624, or mute the thread https://github.com/notifications/unsubscribe-auth/AHXSRFPvhsdK3NpFSoZ2AkeH_LMBfwi0ks5u6xMZgaJpZM4ZaP5G .
Well, we could do a guessing game, but how will we know when we are right?
When we see some movement! It's 99.9% the Actions protobuf object.
On Thu, Dec 20, 2018 at 5:36 AM Nostrademous notifications@github.com wrote:
Well, we could do a guessing game, but how will we know when we are right?
— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/TimZaman/dotaservice/issues/25#issuecomment-448865671, or mute the thread https://github.com/notifications/unsubscribe-auth/AHXSRChqrYkmXA0kcHdUnsX_7Wdpgxiqks5u6xPpgaJpZM4ZaP5G .
Well I agree... so easy to test.
So it's (probably)
const CMsgBotWorldState::Actions& Act(int team_id)
But the action is: what are the strictly required values? Or possibly, we might need to return something in Init (or Observe) that toggles some functionality. And still: why is it that we need to keep the worldstate sockets open?
So I assume we need to open the socket in Init() just to trigger pumping the world state through the ports.
could it not be:
extern "C" void Act(int team_id, CMsgBotWorldState_Actions &msg)
I'm thinking that way we don't have to allocate the protobuf and keep track of the memory. Perhaps an INOUT variable.
Tried a bunch of stuff, can't say i was successful on Act() yet.
I think maybe init should register which bots it is going to control or something.
On Thu, Dec 20, 2018 at 6:47 AM Nostrademous notifications@github.com wrote:
Tried a bunch of stuff, can't say i was successful on Act() yet.
— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/TimZaman/dotaservice/issues/25#issuecomment-448881313, or mute the thread https://github.com/notifications/unsubscribe-auth/AHXSRP3_aHJS6z9ux1Agvr3x1g1723m0ks5u6yRngaJpZM4ZaP5G .
Will check back tomorrow and work some more on it. 1am here and I have to get up at 6am. Calling it a night for now.
I'm thinking there is a 2nd arg to Act() (only valid after game starts, it's NULL during hero selection. I believe it might be the ArenaAllocator().
Currently this compiles and doesn't crash but still doesn't move.
CMsgBotWorldState_Actions * actions_pb;
CMsgBotWorldState_Action_MoveToLocation * mtl_pb;
CMsgBotWorldState_Vector * loc_pb;
// Returning std::shared_ptr<CMsgBotWorldState::Actions> crashes upon return.
// Returning CMsgBotWorldState::Actions craches.
// void, void *, char* is fine, even if its contents are totally bogus.
extern "C" const CMsgBotWorldState::Actions * Act(int team_id) {
// Act seems to be called practically _exactly_ after Observe is called.
// Since it is called once per team, all team-decisions need to be made here. That means
// that we need to communicate all actions. Probably that means we need to return the actions
// protobuf somehow. I think returning the protobuffer itself, from this function makes
// the most sense.
// This call is fully blocking the entire game, so possible they are indeed waiting for a
// synchronous return.
auto timenow = chrono::system_clock::to_time_t(chrono::system_clock::now());
cout << "Act::cout @" << ctime(&timenow) << endl;
cout << "TeamID: " << team_id << endl;
mtl_pb = new CMsgBotWorldState_Action_MoveToLocation;
loc_pb = new CMsgBotWorldState_Vector;
loc_pb->set_x(0.0);
loc_pb->set_y(0.0);
loc_pb->set_z(0.0);
cout << "loc set - addr: " << loc_pb << endl;
mtl_pb->add_units(test_id);
mtl_pb->set_allocated_location(loc_pb);
actions_pb = new CMsgBotWorldState_Actions;
cout << "new actions_pb created" << endl;
CMsgBotWorldState_Action * action_pb = actions_pb->add_actions();
cout << "action_pb referenced" << endl;
action_pb->set_actiontype(CMsgBotWorldState_Action_Type_DOTA_UNIT_ORDER_MOVE_TO_POSITION);
action_pb->set_player(4);
action_pb->set_allocated_movetolocation(mtl_pb);
std::string s;
if (google::protobuf::TextFormat::PrintToString(*actions_pb, &s)) {
std::cout << "Your message:\n" << s;
} else {
std::cerr << "Message not valid (partial content: " << actions_pb->ShortDebugString() << ")\n";
}
cout << "Gonna return from act..\n";
return actions_pb;
}
BTW, as expected, the first arg of Init() is int teamID
Notes for self:
* thread #1, name = 'MainThrd', queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
* frame #0: 0x0000000090a539e0 botcpp_radiant.so`Act
frame #1: 0x00000000893523f5 libserver.dylib`___lldb_unnamed_symbol90409$$libserver.dylib + 789
frame #2: 0x00000000893492cd libserver.dylib`___lldb_unnamed_symbol90399$$libserver.dylib + 925
frame #3: 0x00000000892c7b65 libserver.dylib`___lldb_unnamed_symbol89338$$libserver.dylib + 629
frame #4: 0x00000000888b6651 libserver.dylib`___lldb_unnamed_symbol30869$$libserver.dylib + 129
frame #5: 0x0000000088be98cb libserver.dylib`___lldb_unnamed_symbol46417$$libserver.dylib + 155
frame #6: 0x0000000088bc55d6 libserver.dylib`___lldb_unnamed_symbol45980$$libserver.dylib + 1510
frame #7: 0x000000000de567d7 libengine2.dylib`___lldb_unnamed_symbol7478$$libengine2.dylib + 503
frame #8: 0x000000000dd393fe libengine2.dylib`___lldb_unnamed_symbol2598$$libengine2.dylib + 174
frame #9: 0x000000000dd35b5e libengine2.dylib`___lldb_unnamed_symbol2557$$libengine2.dylib + 126
frame #10: 0x000000000dd320a7 libengine2.dylib`___lldb_unnamed_symbol2521$$libengine2.dylib + 2855
frame #11: 0x000000000dd24c8b libengine2.dylib`___lldb_unnamed_symbol2351$$libengine2.dylib + 1339
frame #12: 0x000000000dd24712 libengine2.dylib`___lldb_unnamed_symbol2350$$libengine2.dylib + 18
frame #13: 0x000000000dd18150 libengine2.dylib`___lldb_unnamed_symbol2189$$libengine2.dylib + 384
frame #14: 0x000000000dd18880 libengine2.dylib`___lldb_unnamed_symbol2190$$libengine2.dylib + 1040
frame #15: 0x000000000dd18baa libengine2.dylib`Source2Main + 298
frame #16: 0x000000000dca9d65 dota2`___lldb_unnamed_symbol6$$dota2 + 197
frame #17: 0x00007fff69c6908d libdyld.dylib`start + 1
It's also very much possible the 2nd argument is actually a pointer to an already created [empty] Actions protobuf...
Function that calls our botcpp_*.so
0x8931f3f3 is where Act() is called
(lldb) disassemble --frame -mixed
libserver.dylib`___lldb_unnamed_symbol90409$$libserver.dylib:
0x8931f0e0 <+0>: pushq %rbp
0x8931f0e1 <+1>: movq %rsp, %rbp
0x8931f0e4 <+4>: pushq %r15
0x8931f0e6 <+6>: pushq %r14
0x8931f0e8 <+8>: pushq %r13
0x8931f0ea <+10>: pushq %r12
0x8931f0ec <+12>: pushq %rbx
0x8931f0ed <+13>: subq $0x18, %rsp
0x8931f0f1 <+17>: movq %rdi, %r15
0x8931f0f4 <+20>: movq 0xdca14d(%rip), %r13 ; (void *)0x0000000006bb6418: g_VProfCurrentProfile
0x8931f0fb <+27>: movl 0x1020(%r13), %r12d
0x8931f102 <+34>: testl %r12d, %r12d
0x8931f105 <+37>: je 0x8931f1d7 ; <+247>
0x8931f10b <+43>: rdtsc
0x8931f10d <+45>: movq %rdx, %rbx
0x8931f110 <+48>: shlq $0x20, %rbx
0x8931f114 <+52>: orq %rax, %rbx
0x8931f117 <+55>: movq 0x1020(%r13), %rax
0x8931f11e <+62>: testl %eax, %eax
0x8931f120 <+64>: jne 0x8931f131 ; <+81>
0x8931f122 <+66>: movabsq $0xff00000000, %rcx ; imm = 0xFF00000000
0x8931f12c <+76>: andq %rcx, %rax
0x8931f12f <+79>: jne 0x8931f1a2 ; <+194>
0x8931f131 <+81>: movq 0x1e18(%r13), %r14
0x8931f138 <+88>: callq 0x89c883b4 ; symbol stub for: ThreadGetCurrentId
0x8931f13d <+93>: cmpq %rax, %r14
0x8931f140 <+96>: jne 0x8931f1a2 ; <+194>
0x8931f142 <+98>: movq 0x1028(%r13), %rax
0x8931f149 <+105>: leaq 0xb8b5c9(%rip), %rcx ; "CDOTA_TeamCommander::SendBotWorldStateToSocket"
0x8931f150 <+112>: cmpq %rcx, (%rax)
0x8931f153 <+115>: je 0x8931f17a ; <+154>
0x8931f155 <+117>: leaq 0xb8b5bd(%rip), %rsi ; "CDOTA_TeamCommander::SendBotWorldStateToSocket"
0x8931f15c <+124>: leaq 0xb7d0b0(%rip), %rcx ; "Bots"
0x8931f163 <+131>: xorl %edx, %edx
0x8931f165 <+133>: movl $0x4, %r8d
0x8931f16b <+139>: movq %rax, %rdi
0x8931f16e <+142>: callq 0x89c88636 ; symbol stub for: CVProfNode::GetSubNode(char const*, int, char const*, int)
0x8931f173 <+147>: movq %rax, 0x1028(%r13)
0x8931f17a <+154>: movslq 0x70(%rax), %rax
0x8931f17e <+158>: movq 0x10e0(%r13), %rcx
0x8931f185 <+165>: shlq $0x4, %rax
0x8931f189 <+169>: orl $0x4, 0x8(%rcx,%rax)
0x8931f18e <+174>: movq 0x1028(%r13), %rdi
0x8931f195 <+181>: callq 0x89c88630 ; symbol stub for: CVProfNode::EnterScope()
0x8931f19a <+186>: movb $0x0, 0x1024(%r13)
0x8931f1a2 <+194>: rdtsc
0x8931f1a4 <+196>: shlq $0x20, %rdx
0x8931f1a8 <+200>: orq %rax, %rdx
0x8931f1ab <+203>: subq %rbx, %rdx
0x8931f1ae <+206>: movdqu 0x1010(%r13), %xmm0
0x8931f1b7 <+215>: movq %rdx, %xmm1
0x8931f1bc <+220>: movl $0x1, %eax
0x8931f1c1 <+225>: movq %rax, %xmm2
0x8931f1c6 <+230>: punpcklqdq %xmm2, %xmm1 ; xmm1 = xmm1[0],xmm2[0]
0x8931f1ca <+234>: paddq %xmm0, %xmm1
0x8931f1ce <+238>: movdqu %xmm1, 0x1010(%r13)
0x8931f1d7 <+247>: movq 0x11f0(%r15), %rdi
0x8931f1de <+254>: callq 0x892edb60 ; ___lldb_unnamed_symbol90248$$libserver.dylib
0x8931f1e3 <+259>: movq 0x11f0(%r15), %rbx
0x8931f1ea <+266>: cmpl $-0x1, 0x8(%rbx)
0x8931f1ee <+270>: jne 0x8931f23c ; <+348>
0x8931f1f0 <+272>: cmpl $0x0, (%rbx)
0x8931f1f3 <+275>: je 0x8931f23c ; <+348>
0x8931f1f5 <+277>: leaq 0x8(%rbx), %rsi
0x8931f1f9 <+281>: leaq 0x10(%rbx), %rdi
0x8931f1fd <+285>: leaq -0x30(%rbp), %rdx
0x8931f201 <+289>: callq 0x89b34c50 ; ___lldb_unnamed_symbol148171$$libserver.dylib
0x8931f206 <+294>: testl %eax, %eax
0x8931f208 <+296>: jne 0x8931f23c ; <+348>
0x8931f20a <+298>: cmpq $0x0, 0x70(%rbx)
0x8931f20f <+303>: jne 0x8931f23c ; <+348>
0x8931f211 <+305>: cmpb $0x0, 0xc(%rbx)
0x8931f215 <+309>: je 0x8931f23c ; <+348>
0x8931f217 <+311>: movq $0x0, (%rsp)
0x8931f21f <+319>: leaq -0x31606(%rip), %rdi ; ___lldb_unnamed_symbol90249$$libserver.dylib
0x8931f226 <+326>: xorl %edx, %edx
0x8931f228 <+328>: xorl %ecx, %ecx
0x8931f22a <+330>: xorl %r8d, %r8d
0x8931f22d <+333>: xorl %r9d, %r9d
0x8931f230 <+336>: movq %rbx, %rsi
0x8931f233 <+339>: callq 0x89c88294 ; symbol stub for: CreateSimpleThread
0x8931f238 <+344>: movq %rax, 0x70(%rbx)
0x8931f23c <+348>: movq 0x11f0(%r15), %rbx
0x8931f243 <+355>: movl 0x8(%rbx), %esi
0x8931f246 <+358>: cmpl $-0x1, %esi
0x8931f249 <+361>: je 0x8931f463 ; <+899>
0x8931f24f <+367>: leaq 0x10(%rbx), %r14
0x8931f253 <+371>: movq %r14, %rdi
0x8931f256 <+374>: callq 0x89b345f0 ; ___lldb_unnamed_symbol148161$$libserver.dylib
0x8931f25b <+379>: cmpl $0x3, %eax
0x8931f25e <+382>: jne 0x8931f463 ; <+899>
0x8931f264 <+388>: movb $0x0, -0x2a(%rbp)
0x8931f268 <+392>: movl 0x8(%rbx), %esi
0x8931f26b <+395>: leaq 0x19c5ad6(%rip), %rcx ; pcre_stack_free + 1080
0x8931f272 <+402>: leaq -0x2a(%rbp), %rdx
0x8931f276 <+406>: movl $0x1, %r8d
0x8931f27c <+412>: movq %r14, %rdi
0x8931f27f <+415>: callq 0x89b34470 ; ___lldb_unnamed_symbol148159$$libserver.dylib
0x8931f284 <+420>: testl %eax, %eax
0x8931f286 <+422>: jne 0x8931f463 ; <+899>
0x8931f28c <+428>: cmpb $0x0, -0x2a(%rbp)
0x8931f290 <+432>: je 0x8931f463 ; <+899>
0x8931f296 <+438>: movq 0x11f0(%r15), %r14
0x8931f29d <+445>: leaq 0x19f973c(%rip), %rax
0x8931f2a4 <+452>: movq (%rax), %rax
0x8931f2a7 <+455>: movl 0x18(%rax), %eax
0x8931f2aa <+458>: cltd
0x8931f2ab <+459>: idivl 0x4(%r14)
0x8931f2af <+463>: testl %edx, %edx
0x8931f2b1 <+465>: jne 0x8931f463 ; <+899>
0x8931f2b7 <+471>: cmpb $0x0, 0xc(%r14)
0x8931f2bc <+476>: jne 0x8931f2c7 ; <+487>
0x8931f2be <+478>: jmp 0x8931f322 ; <+578>
0x8931f2c0 <+480>: movq 0x11f0(%r15), %r14
0x8931f2c7 <+487>: cmpl $0x0, 0x10078(%r14)
0x8931f2cf <+495>: je 0x8931f322 ; <+578>
0x8931f2d1 <+497>: movl 0x8(%r14), %esi
0x8931f2d5 <+501>: cmpl $-0x1, %esi
0x8931f2d8 <+504>: je 0x8931f322 ; <+578>
0x8931f2da <+506>: leaq 0x10(%r14), %rbx
0x8931f2de <+510>: movq %rbx, %rdi
0x8931f2e1 <+513>: callq 0x89b345f0 ; ___lldb_unnamed_symbol148161$$libserver.dylib
0x8931f2e6 <+518>: cmpl $0x3, %eax
0x8931f2e9 <+521>: jne 0x8931f322 ; <+578>
0x8931f2eb <+523>: movb $0x0, -0x29(%rbp)
0x8931f2ef <+527>: movl 0x8(%r14), %esi
0x8931f2f3 <+531>: movl $0x1, %r8d
0x8931f2f9 <+537>: movq %rbx, %rdi
0x8931f2fc <+540>: leaq -0x29(%rbp), %rdx
0x8931f300 <+544>: leaq 0x19c5a41(%rip), %rcx ; pcre_stack_free + 1080
0x8931f307 <+551>: callq 0x89b34470 ; ___lldb_unnamed_symbol148159$$libserver.dylib
0x8931f30c <+556>: testl %eax, %eax
0x8931f30e <+558>: jne 0x8931f322 ; <+578>
0x8931f310 <+560>: cmpb $0x0, -0x29(%rbp)
0x8931f314 <+564>: je 0x8931f322 ; <+578>
0x8931f316 <+566>: callq 0x89c883cc ; symbol stub for: ThreadYield
0x8931f31b <+571>: jmp 0x8931f2c0 ; <+480>
0x8931f31d <+573>: jmp 0x8931f51e ; <+1086>
0x8931f322 <+578>: leaq 0xf10(%r15), %r14
0x8931f329 <+585>: movq %r15, %rdi
0x8931f32c <+588>: movq %r14, %rsi
0x8931f32f <+591>: callq 0x8932fa30 ; ___lldb_unnamed_symbol90466$$libserver.dylib
0x8931f334 <+596>: leaq 0x1080(%r15), %rbx
0x8931f33b <+603>: movq %r14, %rdi
0x8931f33e <+606>: movq %rbx, %rsi
0x8931f341 <+609>: callq 0x8855d3b0 ; ___lldb_unnamed_symbol9268$$libserver.dylib
0x8931f346 <+614>: movq %rbx, %rdi
0x8931f349 <+617>: callq 0x8855a570 ; ___lldb_unnamed_symbol9262$$libserver.dylib
0x8931f34e <+622>: movq 0x11f0(%r15), %rbx
0x8931f355 <+629>: leaq 0x78(%rbx), %rsi
0x8931f359 <+633>: movl $0x10000, %edx ; imm = 0x10000
0x8931f35e <+638>: movq %r14, %rdi
0x8931f361 <+641>: callq 0x89a7fabc ; ___lldb_unnamed_symbol144614$$libserver.dylib
0x8931f366 <+646>: testb %al, %al
0x8931f368 <+648>: jne 0x8931f378 ; <+664>
0x8931f36a <+650>: leaq 0xb85f81(%rip), %rdi ; "Overflow in GetSerializedWorldState!\n"
0x8931f371 <+657>: xorl %eax, %eax
0x8931f373 <+659>: callq 0x89c885f4 ; symbol stub for: DevWarning(char const*, ...)
0x8931f378 <+664>: movq (%r14), %rax
0x8931f37b <+667>: movq 0x60(%rax), %rax
0x8931f37f <+671>: movq %r14, %rdi
0x8931f382 <+674>: callq *%rax
0x8931f384 <+676>: movl %eax, 0x10078(%rbx)
0x8931f38a <+682>: cmpb $0x0, 0xc(%rbx)
0x8931f38e <+686>: je 0x8931f390 ; <+688>
0x8931f390 <+688>: movq 0x11f0(%r15), %rdi
0x8931f397 <+695>: cmpb $0x0, 0xc(%rdi)
0x8931f39b <+699>: jne 0x8931f3a2 ; <+706>
0x8931f39d <+701>: callq 0x892eda10 ; ___lldb_unnamed_symbol90247$$libserver.dylib
0x8931f3a2 <+706>: leaq 0x1b60157(%rip), %rdi
0x8931f3a9 <+713>: movl $0x1, %esi
0x8931f3ae <+718>: callq 0x89c88b3a ; symbol stub for: sigsetjmp
0x8931f3b3 <+723>: testl %eax, %eax
0x8931f3b5 <+725>: je 0x8931f3ca ; <+746>
0x8931f3b7 <+727>: cmpl $0x2, 0x350(%r15)
0x8931f3bf <+735>: jne 0x8931f3f7 ; <+791>
0x8931f3c1 <+737>: leaq 0xb3144c(%rip), %rsi ; "radiant"
0x8931f3c8 <+744>: jmp 0x8931f3fe ; <+798>
0x8931f3ca <+746>: movq 0x1428(%r15), %rax
0x8931f3d1 <+753>: movq 0x18(%rax), %rcx
0x8931f3d5 <+757>: testq %rcx, %rcx
0x8931f3d8 <+760>: je 0x8931f3e8 ; <+776>
0x8931f3da <+762>: movl (%rax), %edi
0x8931f3dc <+764>: movq %r14, %rsi
0x8931f3df <+767>: callq *%rcx
0x8931f3e1 <+769>: movq 0x1428(%r15), %rax
0x8931f3e8 <+776>: movq 0x20(%rax), %rcx
0x8931f3ec <+780>: testq %rcx, %rcx
0x8931f3ef <+783>: je 0x8931f463 ; <+899>
0x8931f3f1 <+785>: movl (%rax), %edi
0x8931f3f3 <+787>: callq *%rcx
0x8931f3f5 <+789>: jmp 0x8931f463 ; <+899>
0x8931f3f7 <+791>: leaq 0xb3141e(%rip), %rsi ; "dire"
0x8931f3fe <+798>: leaq 0xb8b343(%rip), %rdi ; "Segfault in %s bot API\n"
0x8931f405 <+805>: xorl %eax, %eax
0x8931f407 <+807>: callq 0x89c88588 ; symbol stub for: Warning
0x8931f40c <+812>: movq 0x1428(%r15), %rbx
0x8931f413 <+819>: movq 0x28(%rbx), %rax
0x8931f417 <+823>: testq %rax, %rax
0x8931f41a <+826>: je 0x8931f420 ; <+832>
0x8931f41c <+828>: movl (%rbx), %edi
0x8931f41e <+830>: callq *%rax
0x8931f420 <+832>: movq 0x8(%rbx), %rdi
0x8931f424 <+836>: testq %rdi, %rdi
0x8931f427 <+839>: je 0x8931f453 ; <+883>
0x8931f429 <+841>: callq 0x89c889f0 ; symbol stub for: dlclose
0x8931f42e <+846>: testl %eax, %eax
0x8931f430 <+848>: je 0x8931f44b ; <+875>
0x8931f432 <+850>: callq 0x89c889f6 ; symbol stub for: dlerror
0x8931f437 <+855>: movq %rax, %rcx
0x8931f43a <+858>: leaq 0xb85e91(%rip), %rdi ; "Could not close old botcpp: %s\n"
0x8931f441 <+865>: xorl %eax, %eax
0x8931f443 <+867>: movq %rcx, %rsi
0x8931f446 <+870>: callq 0x89c88588 ; symbol stub for: Warning
0x8931f44b <+875>: movq $0x0, 0x8(%rbx)
0x8931f453 <+883>: movq $0x0, 0x20(%rbx)
0x8931f45b <+891>: movq $0x0, 0x18(%rbx)
0x8931f463 <+899>: testl %r12d, %r12d
0x8931f466 <+902>: je 0x8931f50f ; <+1071>
0x8931f46c <+908>: rdtsc
0x8931f46e <+910>: movq %rdx, %rbx
0x8931f471 <+913>: shlq $0x20, %rbx
0x8931f475 <+917>: orq %rax, %rbx
0x8931f478 <+920>: cmpb $0x0, 0x1024(%r13)
0x8931f480 <+928>: je 0x8931f48d ; <+941>
0x8931f482 <+930>: movl 0x1020(%r13), %eax
0x8931f489 <+937>: testl %eax, %eax
0x8931f48b <+939>: je 0x8931f4da ; <+1018>
0x8931f48d <+941>: movq 0x1e18(%r13), %r14
0x8931f494 <+948>: callq 0x89c883b4 ; symbol stub for: ThreadGetCurrentId
0x8931f499 <+953>: cmpq %rax, %r14
0x8931f49c <+956>: jne 0x8931f4da ; <+1018>
0x8931f49e <+958>: movq 0x1028(%r13), %rdi
0x8931f4a5 <+965>: callq 0x89c88642 ; symbol stub for: CVProfNode::ExitScope()
0x8931f4aa <+970>: movq 0x1028(%r13), %rcx
0x8931f4b1 <+977>: testb %al, %al
0x8931f4b3 <+979>: je 0x8931f4c8 ; <+1000>
0x8931f4b5 <+981>: movq 0x58(%rcx), %rax
0x8931f4b9 <+985>: testq %rax, %rax
0x8931f4bc <+988>: je 0x8931f4c8 ; <+1000>
0x8931f4be <+990>: movq %rax, 0x1028(%r13)
0x8931f4c5 <+997>: movq %rax, %rcx
0x8931f4c8 <+1000>: leaq 0x1030(%r13), %rax
0x8931f4cf <+1007>: cmpq %rax, %rcx
0x8931f4d2 <+1010>: sete 0x1024(%r13)
0x8931f4da <+1018>: rdtsc
0x8931f4dc <+1020>: shlq $0x20, %rdx
0x8931f4e0 <+1024>: orq %rax, %rdx
0x8931f4e3 <+1027>: subq %rbx, %rdx
0x8931f4e6 <+1030>: movdqu 0x1010(%r13), %xmm0
0x8931f4ef <+1039>: movq %rdx, %xmm1
0x8931f4f4 <+1044>: movl $0x1, %eax
0x8931f4f9 <+1049>: movq %rax, %xmm2
0x8931f4fe <+1054>: punpcklqdq %xmm2, %xmm1 ; xmm1 = xmm1[0],xmm2[0]
0x8931f502 <+1058>: paddq %xmm0, %xmm1
0x8931f506 <+1062>: movdqu %xmm1, 0x1010(%r13)
0x8931f50f <+1071>: addq $0x18, %rsp
0x8931f513 <+1075>: popq %rbx
0x8931f514 <+1076>: popq %r12
0x8931f516 <+1078>: popq %r13
0x8931f518 <+1080>: popq %r14
0x8931f51a <+1082>: popq %r15
0x8931f51c <+1084>: popq %rbp
0x8931f51d <+1085>: retq
0x8931f51e <+1086>: movq %rax, %r14
0x8931f521 <+1089>: testl %r12d, %r12d
0x8931f524 <+1092>: je 0x8931f5d4 ; <+1268>
0x8931f52a <+1098>: rdtsc
0x8931f52c <+1100>: movq %rdx, %rbx
0x8931f52f <+1103>: shlq $0x20, %rbx
0x8931f533 <+1107>: orq %rax, %rbx
0x8931f536 <+1110>: cmpb $0x0, 0x1024(%r13)
0x8931f53e <+1118>: je 0x8931f54b ; <+1131>
0x8931f540 <+1120>: movl 0x1020(%r13), %eax
0x8931f547 <+1127>: testl %eax, %eax
0x8931f549 <+1129>: je 0x8931f598 ; <+1208>
0x8931f54b <+1131>: movq 0x1e18(%r13), %r15
0x8931f552 <+1138>: callq 0x89c883b4 ; symbol stub for: ThreadGetCurrentId
0x8931f557 <+1143>: cmpq %rax, %r15
0x8931f55a <+1146>: jne 0x8931f598 ; <+1208>
0x8931f55c <+1148>: movq 0x1028(%r13), %rdi
0x8931f563 <+1155>: callq 0x89c88642 ; symbol stub for: CVProfNode::ExitScope()
0x8931f568 <+1160>: movq 0x1028(%r13), %rcx
0x8931f56f <+1167>: testb %al, %al
0x8931f571 <+1169>: je 0x8931f586 ; <+1190>
0x8931f573 <+1171>: movq 0x58(%rcx), %rax
0x8931f577 <+1175>: testq %rax, %rax
0x8931f57a <+1178>: je 0x8931f586 ; <+1190>
0x8931f57c <+1180>: movq %rax, 0x1028(%r13)
0x8931f583 <+1187>: movq %rax, %rcx
0x8931f586 <+1190>: leaq 0x1030(%r13), %rax
0x8931f58d <+1197>: cmpq %rax, %rcx
0x8931f590 <+1200>: sete 0x1024(%r13)
0x8931f598 <+1208>: rdtsc
0x8931f59a <+1210>: jmp 0x8931f5a1 ; <+1217>
0x8931f59c <+1212>: movq %rax, %r14
0x8931f59f <+1215>: rdtsc
0x8931f5a1 <+1217>: shlq $0x20, %rdx
0x8931f5a5 <+1221>: orq %rax, %rdx
0x8931f5a8 <+1224>: subq %rbx, %rdx
0x8931f5ab <+1227>: movdqu 0x1010(%r13), %xmm0
0x8931f5b4 <+1236>: movq %rdx, %xmm1
0x8931f5b9 <+1241>: movl $0x1, %eax
0x8931f5be <+1246>: movq %rax, %xmm2
0x8931f5c3 <+1251>: punpcklqdq %xmm2, %xmm1 ; xmm1 = xmm1[0],xmm2[0]
0x8931f5c7 <+1255>: paddq %xmm0, %xmm1
0x8931f5cb <+1259>: movdqu %xmm1, 0x1010(%r13)
0x8931f5d4 <+1268>: movq %r14, %rdi
0x8931f5d7 <+1271>: callq 0x89c88942 ; symbol stub for: _Unwind_Resume
0x8931f5dc <+1276>: movq %rax, %rcx
0x8931f5df <+1279>: rdtsc
0x8931f5e1 <+1281>: jmp 0x8931f5e8 ; <+1288>
0x8931f5e3 <+1283>: movq %rax, %rcx
0x8931f5e6 <+1286>: rdtsc
0x8931f5e8 <+1288>: shlq $0x20, %rdx
0x8931f5ec <+1292>: orq %rax, %rdx
0x8931f5ef <+1295>: subq %rbx, %rdx
0x8931f5f2 <+1298>: movdqu 0x1010(%r13), %xmm0
0x8931f5fb <+1307>: movq %rdx, %xmm1
0x8931f600 <+1312>: movl $0x1, %eax
0x8931f605 <+1317>: movq %rax, %xmm2
0x8931f60a <+1322>: punpcklqdq %xmm2, %xmm1 ; xmm1 = xmm1[0],xmm2[0]
0x8931f60e <+1326>: paddq %xmm0, %xmm1
0x8931f612 <+1330>: movdqu %xmm1, 0x1010(%r13)
0x8931f61b <+1339>: movq %rcx, %rdi
0x8931f61e <+1342>: callq 0x883c0460 ; ___lldb_unnamed_symbol3$$libserver.dylib
0x8931f623 <+1347>: nopw %cs:(%rax,%rax)
It's also very much possible the 2nd argument is actually a pointer to an already created [empty] Actions protobuf...
I thought that too, but when I tried dumping it to string I would get a crash.
Still working on making sense of the code.
I believe Line #153 is call to Observe() I believe Line #158 is call to Act()
Regarding the first IDA image I posted (2 images above)
I believe Line #153 is call to Observe() I believe Line #158 is call to Act()
By the way... it looks like the intention is for us to be able to just call functions to take actions directly inside the Act(), and not use any protobuf. It just happens that in the Observe call the 2nd arg points the internal CMsgBot CLASS to the right offset so we sit at the WorldState implementation, but the class itself is full of virtual functions and other information.
When they pass the same data to Act() its probably for purposes of orientation but the intent might be to directly invoke using function pointers the appropriate actions using the provided class.
The code is something like this:
iteratePlayers(a1, *(double *)v17.m128_u64, *(double *)time_delta.m128i_i64);
sub_F5ABE0(a1);
sub_F5B1D0(a1);
considerGlyph(a1);
controlCourier(a1);
calculateLaneFronts(a1);
updatePotentialLocationGrid(a1);
updateAvoidanceGrid(a1);
if ( a1->gap354[725] > 0 )
{
v18 = 0;
do
{
v19 = *(_QWORD *)&a1->gap354[727];
v20 = 48LL * v18;
v17.m128_f32[0] = sub_6908D0(v19 + v20 + 24);
if ( v17.m128_f32[0] >= *(float *)(v19 + v20 + 36) )
{
v22 = a1->gap354[725];
if ( a1->gap354[725] - v18 - 1 > 0 )
{
memmove(
(void *)(*(_QWORD *)&a1->gap354[727] + v20),
(const void *)(*(_QWORD *)&a1->gap354[727] + 48LL * (v18 + 1)),
48LL * (a1->gap354[725] - v18 - 1));
v22 = a1->gap354[725];
}
v21 = v22 - 1;
a1->gap354[725] = v21;
--v18;
}
else
{
v21 = a1->gap354[725];
}
++v18;
}
while ( v18 < v21 );
}
if ( a1->gap354[731] > 0 )
{
v23 = 0;
do
{
v24 = *(_QWORD *)&a1->gap354[733];
v17 = (__m128)*(unsigned int *)(v24 + 8LL * v23 + 4);
v25 = *(float *)(v24 + 8LL * v23 + 4);
v17.m128_f32[0] = sub_A94280();
if ( v17.m128_f32[0] <= v25 )
{
v27 = a1->gap354[731];
}
else
{
v26 = a1->gap354[731];
if ( a1->gap354[731] - v23 - 1 > 0 )
{
memmove(
(void *)(*(_QWORD *)&a1->gap354[733] + 8LL * v23),
(const void *)(*(_QWORD *)&a1->gap354[733] + 8LL * (v23 + 1)),
8LL * (a1->gap354[731] - v23 - 1));
v26 = a1->gap354[731];
}
v27 = v26 - 1;
a1->gap354[731] = v27;
--v23;
}
++v23;
}
while ( v23 < v27 );
}
setRuneInfo(a1, (__m128i)v17);
callDynamicallyLoadedLibrary(a1, v28, (__m128)time_delta);
execLuaBotThink(a1, "TeamThink", *(_QWORD *)&a1->gap354[975], 0LL, 0LL);
updateLanePushDesires(a1);
updateLaneDefendDesires(a1);
updateFarmLaneDesires(a1);
updateRoamDesires(a1, *(double *)v17.m128_u64, (__m128)time_delta, a5);
updateRoshanDesire(a1, v17, (__m128)time_delta, a5);
updateItemsDesire(a1);
v29 = a1;
sub_F690D0((struct_a1 *)((char *)a1 + 20), a1, *(double *)v17.m128_u64, *(double *)time_delta.m128i_i64);
dota_time = a1->gap354[959];
if ( *(float *)&dota_time >= 0.0 )
{
v31 = qword_299B380;
if ( *(_DWORD *)(qword_299B380 + 920) == 4 )
{
if ( *(float *)&dota_time == 0.0 )
{
v32 = *(float *)(qword_299B380 + 2876);
*(float *)&dota_time = v32 + RandomFloat(COERCE_DOUBLE(1084227584LL), COERCE_DOUBLE(1097859072LL));
a1->gap354[959] = dota_time;
v31 = qword_299B380;
}
if ( *(float *)(v31 + 2876) >= *(float *)&dota_time )
{
v29 = (struct_a1 *)"dota_chatwheel_message_GLHF";
sub_F6B1E0(a1, "dota_chatwheel_message_GLHF", "", 0LL, 0LL);
a1->gap354[959] = 3212836864;
}
}
}
Our DLL sits inside the callDynamicallyLoadedLibrary Function
That would mean you need headers? And that wouldnt make much sense since its a dlopen..
On Fri, Dec 21, 2018, 16:55 Nostrademous <notifications@github.com wrote:
By the way... it looks like the intention is for us to be able to just call functions to take actions directly inside the Act(), and not use any protobuf. It just happens that in the Observe call the 2nd arg points the internal CMsgBot CLASS to the right offset so we sit at the WorldState implementation, but the class itself is full of virtual functions and other information.
When they pass the same data to Act() its probably for purposes of orientation but the intent might be to directly invoke using function pointers the appropriate actions using the provided class.
— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/TimZaman/dotaservice/issues/25#issuecomment-449425050, or mute the thread https://github.com/notifications/unsubscribe-auth/AHXSRAo1dWJ3tknEpJhOZFEpE2TLI4hNks5u7QRmgaJpZM4ZaP5G .
Inside the callDynamicallyLoadedLibrary functions is a stub that eventually does:
{
baseFuncPtr = *(_QWORD *)&a1->CMsgBot[1077];
Observe = *(void (__fastcall **)(__int64 *, int *))(baseFuncPtr + 0x18);
if ( Observe )
{
libraryTeamID = (__int64 *)*(unsigned int *)baseFuncPtr;
v21 = &a1->CMsgBot[751];
Observe(libraryTeamID, &a1->CMsgBot[751]);
baseFuncPtr = *(_QWORD *)&a1->CMsgBot[1077];
}
Act = *(__int64 (__fastcall **)(__int64 *, int *))(baseFuncPtr + 0x20);
if ( Act )
{
libraryTeamID = (__int64 *)*(unsigned int *)baseFuncPtr;
LODWORD(baseFuncPtr) = Act(libraryTeamID, v21);
}
}
That would mean you need headers? And that wouldnt make much sense since its a dlopen..
You don't need headers, you just extern anything you want to call that exists somewhere else; and honestly, in reality most of those functions would be access via function pointers available inside the main CMsgBot class that's passed to us (we just don't know what offsets points to what yet).
Btw, OpenAI are doing all of this with LD_PRELOAD
. But i am entirely
unsure which calls they are overloading.
On Fri, Dec 21, 2018 at 8:38 AM Nostrademous notifications@github.com wrote:
That would mean you need headers? And that wouldnt make much sense since its a dlopen.. … <#m1243224858975479198> On Fri, Dec 21, 2018, 16:55 Nostrademous @.*** wrote: By the way... it looks like the intention is for us to be able to just call functions to take actions directly inside the Act(), and not use any protobuf. It just happens that in the Observe call the 2nd arg points the internal CMsgBot CLASS to the right offset so we sit at the WorldState implementation, but the class itself is full of virtual functions and other information. When they pass the same data to Act() its probably for purposes of orientation but the intent might be to directly invoke using function pointers the appropriate actions using the provided class. — You are receiving this because you commented. Reply to this email directly, view it on GitHub <#25 (comment) https://github.com/TimZaman/dotaservice/issues/25#issuecomment-449425050>, or mute the thread https://github.com/notifications/unsubscribe-auth/AHXSRAo1dWJ3tknEpJhOZFEpE2TLI4hNks5u7QRmgaJpZM4ZaP5G .
You don't need headers, you just extern anything you want to call that exists somewhere else; and honestly, in reality most of those functions would be access via function pointers available inside the main CMsgBot class that's passed to us (we just don't know what offsets points to what yet).
— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/TimZaman/dotaservice/issues/25#issuecomment-449436436, or mute the thread https://github.com/notifications/unsubscribe-auth/AHXSRJ5n4EKrPMGhRVboiXsIpzUhV1oaks5u7Q6EgaJpZM4ZaP5G .
Since we are moving to multi-agent design I wanted to raise the question of how many agents do we actually want.
At start there are two possibilities: 1) One Agent Per Hero (5 agents per Team) 2) One Master Agent that controls 5 heroes
*3) One Agent Per Hero and Per Controllable Unit (meaning summons (Nerconomicon, Warlock Ultimate, Beastmaster Hawk & Boar, etc.), illusions (Manta, Illusion Rune, Wall of Replica, Disruption, etc.), clones (Meepo), doubles (Arc Warden Ultimate) or dominated (i.e., Helm of Dominator, Enchantress, Chen, etc.) units) - typically these are controlled by the same agent that is controlling the owning Hero that caused the summon/domination to occur, but doesn't have to be.
Each approach has its pros and cons in terms of flexibility (co-play with humans, etc.), agent action synchronization (via shared world state model versus independent world models), training time, and so forth. OpenAI went with #1 above, but we do not necessarily have to, although I think I would prefer #1 above as well.
Next, there are a few other things that could be their own agents: a) Courier - there is one courier per team - it can be controlled by any Hero Agent and even in real games it often gets abused by numerous players at once. We could make it its own agent. b) Glyph Usage - anyone on the team can use the Glyph (when available) c) Minimap Scan - anyone on the team can use the Minimap Scan function
*d) One Team Agent to control a), b) and c) as a single entity
Just wanted to throw this out there to think about and post your thoughts.