Page 2 of 4

RE: UncleBob's annoying API questions

Posted: Sun Oct 30, 2011 4:25 am
by UncleBob

Quote:
A subclass is an object that builds on a more generic parent object.
Yes, and usually when I declare an inherited class I only have access to the members of its parent class(es), not its child class. Unless I did something wrong in C++ all the time, which wouldn't be surprising either. Anyways, I've got it to work, allthough I don't quite get the logic behind it yet. Know let's see about that CallEvery...Uhhh, Bummer! It looks that I don't have access to a planet's attributes (like radius), which I guess I would need to set a sensible distance limit... hmmm. Maybe completing the mission a certain time after entering the frame? Not quite satisfying, but the only sensible way to go unless I know how large the planet in question is. :(

RE: UncleBob's annoying API questions

Posted: Sun Oct 30, 2011 5:23 am
by robn

UncleBob wrote:


Quote:
A subclass is an object that builds on a more generic parent object.
Yes, and usually when I declare an inherited class I only have access to the members of its parent class(es), not its child class. Unless I did something wrong in C++ all the time, which wouldn't be surprising either.
Sorry, I misunderstood. The way the Lua object stuff works is that each object can be accessed for what it is, not what its type is claimed to be. So if an event or method receives or returns a Body, and a Player is passed instead, then you can call Player methods on it. That's why the "isa" method is important.
Quote:
Uhhh, Bummer! It looks that I don't have access to a planet's attributes (like radius), which I guess I would need to set a sensible distance limit... hmmm. Maybe completing the mission a certain time after entering the frame? Not quite satisfying, but the only sensible way to go unless I know how large the planet in question is. :(
Those attributes are trivial to expose. We just haven't done it yet because much of the Lua API is being extended on demand. Please open a feature request and we'll get right one it :)

RE: UncleBob's annoying API questions

Posted: Sun Oct 30, 2011 5:55 am
by UncleBob
Ah, silly me. in onFrameChange(body), body is only the name of the variable, not the expected class. So basically, that function could pass me ANYTHING back.
Quote:
Those attributes are trivial to expose. We just haven't done it yet because much of the Lua API is being extended on demand. Please open a feature request and we'll get right one it
Great! Do I have to do this via GitHub, or right here on the forum?

RE: UncleBob's annoying API questions

Posted: Sun Oct 30, 2011 6:28 am
by robn
Github. I have a terrible memory - I may not remember this thread in the morning. If its in the issue tracker then it can't be ignored :)

RE: UncleBob's annoying API questions

Posted: Sun Oct 30, 2011 2:27 pm
by UncleBob
added to Github, but I seem incapable of assigning a type (feature request, bug, etc).

RE: UncleBob's annoying API questions

Posted: Sun Oct 30, 2011 4:36 pm
by robn

robn wrote:
Github. I have a terrible memory - I may not remember this thread in the morning. If its in the issue tracker then it can't be ignored :)
Yep, that's an admin power. We'll take care of that. Cheers :)

RE: UncleBob's annoying API questions

Posted: Thu Nov 17, 2011 3:15 pm
by UncleBob
Ok, another problem just poped up. Probably just some misconception of mine.I'm trying to code the Info-broker for my bounty hunts, and I want them to be consistent. There's one broker per system, and he should always be the same (look the same, same name). I thought this should be easiest by just taking the seed of the first body in a system, as that should be consistent. However, for some reason, my brokers are always different. Here's what I tried to do:
Code:
local makeInfoBroker = function (station)local mBodies = Game.system:GetBodyPaths()BrokerRand = Engine.rand:New(mBodies[1]:GetSystemBody().seed)local Broker = {Gender = BrokerRand:Integer(1) == 1,Name = NameGen.FullName(Gender, BrokerRand),faceseed = BrokerRand:Integer(),flavour = BrokerRand:Integer(1,#broker_flavours),careful = BrokerRand:Integer(1, 10),knowledge = BrokerRand:Number(0.1, 0.9) * Game.system.population,}GlobalBroker = BrokerBrokerAdd = string.interp(broker_flavours[Broker.flavour].adtext, {name = GlobalBroker.Name,})local ref = station:AddAdvert(BrokerAdd, OnBrokerChat)end

RE: UncleBob's annoying API questions

Posted: Thu Nov 17, 2011 4:24 pm
by Brianetta
Why not use a character sheet?Documentation of the APIAn intro into their useThese are available in the nightlies and in master. I wrote the system, so feel free to throw questions my way!

RE: UncleBob's annoying API questions

Posted: Thu Nov 17, 2011 5:11 pm
by UncleBob
i did take a look at that, actually. Problem is, if i'm going to have one broker per system, it doesn't look like an option, there's too many. I could have fewer of course, but then i'd have to define spheres of influence...

RE: UncleBob's annoying API questions

Posted: Thu Nov 17, 2011 5:34 pm
by Brianetta

UncleBob wrote:
i did take a look at that, actually. Problem is, if i'm going to have one broker per system, it doesn't look like an option, there's too many. I could have fewer of course, but then i'd have to define spheres of influence...
Too big? No. They're actually not any bigger than the table you're using. All the extra features and unused defaults are dynamically called from the original Character class object. How about this small modification?
Code:
local makeInfoBroker = function (station)local mBodies = Game.system:GetBodyPaths()BrokerRand = Engine.rand:New(mBodies[1]:GetSystemBody().seed)local Broker = Character.New({female = BrokerRand:Integer(1) == 1,name = NameGen.FullName(Gender, BrokerRand),faceseed = BrokerRand:Integer(),flavour = BrokerRand:Integer(1,#broker_flavours),careful = BrokerRand:Integer(4, 64),knowledge = BrokerRand:Number(0.1, 0.9) * Game.system.population,})GlobalBroker = BrokerBrokerAdd = string.interp(broker_flavours[Broker.flavour].adtext, {name = GlobalBroker.Name,})local ref = station:AddAdvert(BrokerAdd, OnBrokerChat)end
All I did was turn your table into a Character. You can treat it exactly like any other table. The changes I made were Gender=>female and Name=>name (which lets you throw this table at ChatForm.SetFace() directly) and changed the range of careful so that you can do Broker:TestRoll('careful') whenever you need to do a carefulness test.Play with it. Get the Lua console up and try things like this:
Code:
B1=Character.New({careful=25})B2=Character.New({careful=40})print(B1:TestRoll('careful'),' ',B2:TestRoll('careful'))
That last line, you can repeat lots of times using up and return. You should see that B1 ("Broker 1") generally fails his careful test a lot more frequently than B2. You'll see a lot of this:FALSE TRUE...with occasional other results scattered through.

RE: UncleBob's annoying API questions

Posted: Thu Nov 17, 2011 5:42 pm
by Brianetta
Of course, we set the default "careful" there rather naively, but that was just because I can see that you wanted to use your predictable random generator. It'll work, but you're more likely to see extremes of carefulness and uncarefulness. Better would be to rip off the code in the DiceRoll() function in Characters.lua:
Code:
DiceRoll = function ()return ( -- 4xD16, range is 4..64 averaging 34) Engine.rand:Integer(1,16)+ Engine.rand:Integer(1,16)+ Engine.rand:Integer(1,16)+ Engine.rand:Integer(1,16))end
and replace the four calls to Engine.rand with your BrokerRand. This will weight the results toward the centre, making TestRoll() give much saner results.

RE: UncleBob's annoying API questions

Posted: Fri Nov 18, 2011 2:08 am
by UncleBob
thanks,The reason why I thought that the sheets were not usefull for my purposes was not because I thought they were too big, but because I was under the impression that they have to be stored somewhere in the savegame once created. I take it that was a misconception?Anyways, I'm leaving on a two weeks work trip today, so I'll have to get back to this afterwards...

RE: UncleBob's annoying API questions

Posted: Fri Nov 18, 2011 4:47 am
by Brianetta

UncleBob wrote:
The reason why I thought that the sheets were not usefull for my purposes was not because I thought they were too big, but because I was under the impression that they have to be stored somewhere in the savegame once created. I take it that was a misconception?
Like any table, they can be saved, but they do not have to be. Your strategy of predictably re-creating them as needed is sound. One of the big benefits of using a character sheet is that you could, at some point, put a new broker into the bulletin board of a station, and release the old one into the persistent pool to be used by some other script that you wrote. Perhaps he might become an assassination target? The possibilities are endless.

RE: UncleBob's annoying API questions

Posted: Fri Nov 18, 2011 6:10 am
by UncleBob
Ok, I'll switch to using your character sheets, then. After I get back, that is...

RE: UncleBob's annoying API questions

Posted: Sat Dec 10, 2011 10:54 am
by UncleBob
I'm back from my trip, and back with the same old problem it seems. I downloaded Alpha 17 and changed my code to use the new character sheets. Only bare bones currently because first I have to get the thing to work propperly.Code still looks very similar:
Code:
local makeInfoBroker = function (station)local mBodies = Game.system:GetBodyPaths()BrokerRand = Engine.rand:New(mBodies[1]:GetSystemBody().seed)local Broker = Character.New({female = BrokerRand:Integer(1) == 1,name = NameGen.FullName(female, BrokerRand),seed = BrokerRand:Integer(),})GlobalBroker = BrokerBrokerAdd = string.interp(broker_flavours[1].adtext, {name = GlobalBroker.name,})local ref = station:AddAdvert(BrokerAdd, OnBrokerChat)end

Code:
local OnBrokerChat = function (form, ref, option)form:Clear()if option == -1 thenform:Close()returnendif option == 0 thenform:SetFace({ female = GlobalBroker.female, seed = GlobalBroker.seed, name = GlobalBroker.name })local introtext = string.interp(broker_flavours[1].introtext[Engine.rand:Integer(1,#broker_flavours[1].introtext)], {name = GlobalBroker.name})form:SetMessage(introtext)endend
There are two problems: First, the character isn't consistent. It is different every time I start a game, so I'm doing something wrong when getting the seed from the first systembody, because that should be constant. Or I'm doing something wrong when using the seed?The other problem is that the name isn't even consistent within the same add! The introtext shown on the BB shows another name than the individual has when the add opens, even the gender isn't neccesarily the same. This smells like somehow, the character doesn't even get stored in GlobalBroker, although GlobalBroker is defined as a local right in the first few lines of the file, before any functions are declared. I don't get what's going on here...

RE: UncleBob's annoying API questions

Posted: Sun Dec 11, 2011 7:36 pm
by Brianetta
This is your problem:
Code: local mBodies = Game.system:GetBodyPaths() BrokerRand = Engine.rand:New(mBodies[1]:GetSystemBody().seed)
Engine.rand is an instantiated Rand. Use Rand instead, and use a full stop instead of a colon - you were passing Engine.rand's ID (probably junk) to the New() method instead of your seed.Try this instead:
Code: local mBodies = Game.system:GetBodyPaths() BrokerRand = Rand.New(mBodies[1]:GetSystemBody().seed)
Also, does it need to be that seed? Isn't Space.GetBody(1).seed also perfectly predictable?:
Code: BrokerRand = Rand.New(Space.GetBody(1).seed)
Also, you're sort of abusing the Character for SetFace in the second bit of code that you pasted. This:
Code: form:SetFace({ female = GlobalBroker.female, seed = GlobalBroker.seed, name = GlobalBroker.name })
can be written very simply like this:
Code: form:SetFace(GlobalBroker)
The Character sheet already contains all the right fields for SetFace. Your code was really just making extra work for Lua.

RE: UncleBob's annoying API questions

Posted: Mon Dec 12, 2011 5:37 am
by UncleBob

Quote:
Engine.rand is an instantiated Rand. Use Rand instead, and use a full stop instead of a colon - you were passing Engine.rand's ID (probably junk) to the New() method instead of your seed.
ArglBargl!Give me a pedantic language with clear type and method declarations any day! I just don't yet get the mysterious ways in which LUA moves... :?
Quote:
Also, does it need to be that seed? Isn't Space.GetBody(1).seed also perfectly predictable?:
Well, now that I know of it, it looks like it should be, yes! :D
Quote:
The Character sheet already contains all the right fields for SetFace. Your code was really just making extra work for Lua.
Making extra work is the specialty of any n00b... ;) I didn't know that SetFace can receive a character object as a parameter, it's not yet updated in the API docs.Thanks a lot for your help, this should get me a bit further.

RE: UncleBob's annoying API questions

Posted: Mon Dec 12, 2011 6:04 am
by Brianetta

UncleBob wrote:
I didn't know that SetFace can receive a character object as a parameter, it's not yet updated in the API docs.
It's in the Character doc. The Character object is basically just a Lua table (with applied phlebotinum).

RE: UncleBob's annoying API questions

Posted: Mon Dec 12, 2011 4:15 pm
by UncleBob
Say... can it be that the face generator screws up gender every once in a while? Now that the thing works, I have a certain Dan Carpenter as Infobroker of the Sol-system, and he looks more female than Micheal Jackson at his worst... I guess men in his position can allow for a little extravagancia, but it's a bit... disturbing. Then again, it IS the 33rd century...

RE: UncleBob's annoying API questions

Posted: Mon Dec 12, 2011 5:35 pm
by Brianetta

UncleBob wrote:
Say... can it be that the face generator screws up gender every once in a while? Now that the thing works, I have a certain Dan Carpenter as Infobroker of the Sol-system, and he looks more female than Micheal Jackson at his worst... I guess men in his position can allow for a little extravagancia, but it's a bit... disturbing. Then again, it IS the 33rd century...
No, that's you again, I'm afraid...
Code: local Broker = Character.New({ female = BrokerRand:Integer(1) == 1, name = NameGen.FullName(female, BrokerRand), seed = BrokerRand:Integer(), })
In this snippet of yours, you use female as an argument to NameGen.FullName; trouble is, this is all within a table def, so the definition of female that you've used isn't in scope. You need to define female outside of that table definition as a (very local) variable, then use it to define both Broker's "female" and as the argument to Broker's name gen.
Code: local tempbrokerfemale = BrokerRand:Integer(1) == 1, local Broker = Character.New({ female = tempbrokerfemale, name = NameGen.FullName(tempbrokerfemale, BrokerRand), seed = BrokerRand:Integer(), })