NoGo - A Scriptable Game Framework - v1.5

Forum for technical discussions regarding development. If you have a general suggestion, problem or comment, please use one of the other forums.

Moderator: OpenTTD Developers

User avatar
Zuu
OpenTTD Developer
OpenTTD Developer
Posts: 4553
Joined: 09 Jun 2003 18:21
Location: /home/sweden

Re: NoGo - A Scriptable Game Framework - v1.5

Post by Zuu »

Is there a bit left in the server list protocol to let servers indicate if they have a GameScript running or not? It would be nice if there is also a way to see the name of the script in the server info dialog but that would require more than just a single bit. :-)
My OpenTTD contributions (AIs, Game Scripts, patches, OpenTTD Auto Updater, and some sprites)
Junctioneer (a traffic intersection simulator)
Simn
Engineer
Engineer
Posts: 15
Joined: 05 Jan 2012 19:43

Re: NoGo - A Scriptable Game Framework - v1.5

Post by Simn »

TrueBrain wrote:If you can come up with other useful texts, we can have up to 32 buttons. So we have a few to go. Let me know what you think about this, and enjoy ;)
Make sure to include the generic
BUTTON_1
BUTTON_2
BUTTON_3
so choices can be made that are described in the text. This would, for instance, enable random events like in Civilization IV, where a company gets to react to an event in one way or another, each way having particular advantages, disadvantages and/or risks.

The gouvernment of SomeTown asked you to provide transportation for their next annual work outing, free of charge.
1) Who do they think they are? (Offer might be extended to your competition)
2) Always glad to help! (Pay money, gain rating with SomeTown)
3) Agree, but forget to actually send the buses. (Lose rating with SomeTown)
lugo
Engineer
Engineer
Posts: 100
Joined: 12 Oct 2010 13:55

Re: NoGo - A Scriptable Game Framework - v1.5

Post by lugo »

I remember in civilization 1 you had to answer random questions to get a free 'step' in your scientific advancement.
A trivia quiz like implementation seems possible with this buttons feature (and others) if i'm not mistaken (?)
But i'm struggling with ideas what this reward could be in ottd, respecting the scope of this framework,
just throwing out money seems dull...
Last edited by lugo on 07 Jan 2012 03:03, edited 1 time in total.
Supercheese
Tycoon
Tycoon
Posts: 1660
Joined: 16 Dec 2007 22:24
Location: Idaho, USA

Re: NoGo - A Scriptable Game Framework - v1.5

Post by Supercheese »

lugo wrote:I remember in civilization 1 you had to answer random questions to get a free 'step' in your scientific advancement.
A trivia quiz like impentation seems possible with this buttons feature (and others) if i'm not mistaken (?)
But i'm struggling with ideas what this reward could be in ottd, respecting the scope of this framework,
just throwing out money seems dull...
Increase in town/station ratings perhaps?
Eyecandy Road Vehicles | Fake Subways | Supercheese's NewObjects

"Fashions and cultures change, but steam trains shall always be majestic."
-Professor Hershel Layton
Kogut
Tycoon
Tycoon
Posts: 2493
Joined: 26 Aug 2009 06:33
Location: Poland

Re: NoGo - A Scriptable Game Framework - v1.5

Post by Kogut »

Unlocking vehicles? Changing industry production? New industry/town?
Correct me If I am wrong - PM me if my English is bad
AIAI - AI for OpenTTD
Simn
Engineer
Engineer
Posts: 15
Joined: 05 Jan 2012 19:43

Re: NoGo - A Scriptable Game Framework - v1.5

Post by Simn »

I wonder... would it be possible to implement an invest/research functionality with this which gradually unlocks new vehicles and buildings? As an extreme example, you could start the game with knowledge of basic road vehicles only. A predefined tech tree lets you choose what to research so your company can specialize in different transportation methods. This means you can focus for instance on trains by researching railways and different kinds of engines, or you focus on planes. If the Api allows un/locking of basic features, this mechanic could provide a very interesting gameplay aspect, especially in multiplayer games.
User avatar
Lordmwa
President
President
Posts: 899
Joined: 20 May 2006 19:30
Location: West Sussex, England

Re: NoGo - A Scriptable Game Framework - v1.5

Post by Lordmwa »

Simn wrote:I wonder... would it be possible to implement an invest/research functionality with this which gradually unlocks new vehicles and buildings? As an extreme example, you could start the game with knowledge of basic road vehicles only. A predefined tech tree lets you choose what to research so your company can specialize in different transportation methods. This means you can focus for instance on trains by researching railways and different kinds of engines, or you focus on planes. If the Api allows un/locking of basic features, this mechanic could provide a very interesting gameplay aspect, especially in multiplayer games.
You spend money on reasearch that reduces the random element of how long it takes to become avaliable? Sort of realistic i guess
The TT forums trivia tournament! Come along and join in the fun
http://www.funtrivia.com/private/main.cfm?tid=90722
Simn
Engineer
Engineer
Posts: 15
Joined: 05 Jan 2012 19:43

Re: NoGo - A Scriptable Game Framework - v1.5

Post by Simn »

It seems like there are some odd things going on when using GSCompanyMode and GSNews.Create:

Code: Select all

function MyGS::Start()
{
	this.Sleep(200);

	for (local company_id_t = GSCompany.COMPANY_FIRST; company_id_t <= GSCompany.COMPANY_LAST; company_id_t++)
	{
		local company_id = GSCompany.ResolveCompanyID(company_id_t);
		if (company_id == GSCompany.COMPANY_INVALID) continue;
		
		// Normal mode
		GSNews.Create(GSNews.NT_GENERAL, "Test 1", GSCompany.COMPANY_INVALID);
		GSLog.Info(GSError.GetLastErrorString()); // ERR_NONE
		
		// Unbound company
		GSCompanyMode(company_id);
		GSNews.Create(GSNews.NT_GENERAL, "Test 2", GSCompany.COMPANY_INVALID);
		GSLog.Info(GSError.GetLastErrorString()); // ERR_NONE
		
		// Bound company
		local company = GSCompanyMode(company_id);
		GSNews.Create(GSNews.NT_GENERAL, "Test 3", GSCompany.COMPANY_INVALID);
		GSLog.Info(GSError.GetLastErrorString()); // ERR_UNKNOWN
		
		// Company bound to invalid
		company = GSCompanyMode(GSCompany.COMPANY_INVALID);
		GSNews.Create(GSNews.NT_GENERAL, "Test 4", GSCompany.COMPANY_INVALID);
		GSLog.Info(GSError.GetLastErrorString()); // ERR_NONE
	}
	
	// Normal mode?
	GSNews.Create(GSNews.NT_GENERAL, "Test 5", GSCompany.COMPANY_INVALID);
	GSLog.Info(GSError.GetLastErrorString()); // ERR_UNKNOWN
}
I thought Test 3 failed due to the script trying to create news as a company and figured this might be a "feature", but I really don't understand why Test 5 is failing, given that company should be out of scope again. Am I misunderstanding now GSCompanyMode works?
User avatar
Zuu
OpenTTD Developer
OpenTTD Developer
Posts: 4553
Joined: 09 Jun 2003 18:21
Location: /home/sweden

Re: NoGo - A Scriptable Game Framework - v1.5

Post by Zuu »

Why do you use the company mode with News?

I think it is intended to be used along with functions that would normally be used by an AI when playing as a specific company. The GSCompanyMode enables a GS to execute API calls as if they were executing them as an AI for that company. The Create function of GSNews have a parameter for company and is probably intended to be used at the global GS "company". Thus you are probably violating a pre condition that GSNews. Create has to be executed as the GS "company" and not as a specific company. After all the News API is not available for AIs to use.

That said, as my hypothesis of a pre-condition of which company you need to execute the command as is not documented, it is a bug that should be reported.

For reference you can find the AI APIs here: http://noai.openttd.org/api/ So if a class is listed as GSXYZ but not AIXYZ or a method in that class only exist in the GS context, then the function is something new intended for Game Script usage only and not for AIs. Your best bet is probably that these functions are not intended to be used in the company mode. Instead I think the company mode is intended to execute so called DoCommands (actions that modify the game state in some way) as a specific company.
My OpenTTD contributions (AIs, Game Scripts, patches, OpenTTD Auto Updater, and some sprites)
Junctioneer (a traffic intersection simulator)
Simn
Engineer
Engineer
Posts: 15
Joined: 05 Jan 2012 19:43

Re: NoGo - A Scriptable Game Framework - v1.5

Post by Simn »

Well I sort of figured it out. Have a look at this:

Code: Select all

function MyTownGS::Start()
{
	this.Sleep(200);

	for (local company_id_t = GSCompany.COMPANY_FIRST; company_id_t <= GSCompany.COMPANY_LAST; company_id_t++)
	{
		local company_id = GSCompany.ResolveCompanyID(company_id_t);
		if (company_id == GSCompany.COMPANY_INVALID) continue;

		local company = GSCompanyMode(company_id);
		// Disaster
		//company = GSCompanyMode(company_id);
	}
	
	GSGoal.Question(0, GSCompany.COMPANY_INVALID, "Test", GSGoal.BUTTON_OK);
	GSLog.Info(GSError.GetLastErrorString());
}
This works, but uncommenting the line after the Disaster comment makes the precondition fail. It seems Squirrel has a pretty funky way of resolving assignment scope. I don't know in which scope the company variable actually ends up, but it surely ain't the block scope of the for loop. What a pitfall...
Yexo
Tycoon
Tycoon
Posts: 3663
Joined: 20 Dec 2007 12:49

Re: NoGo - A Scriptable Game Framework - v1.5

Post by Yexo »

When a GSCompanyMode object is created it saves the old value of current company so it can restore that when the object is removed. Your disaster line first creates a new GSCompanyMode object and assigns it to the variable "company". That means that after creating your new GSCompanyMode the old value from the original GSCompanyMode is restored.

You can probably avoid this by doing "company = null;" right before your disaster line. A better way would be to never re-assign something to a variable holding a GSCompanyMode object and never use GSCompanyMode twice in the same scope (in sub-scopes it would be ok, but only in a different variable).
Simn
Engineer
Engineer
Posts: 15
Joined: 05 Jan 2012 19:43

Re: NoGo - A Scriptable Game Framework - v1.5

Post by Simn »

Yexo wrote:When a GSCompanyMode object is created it saves the old value of current company so it can restore that when the object is removed. Your disaster line first creates a new GSCompanyMode object and assigns it to the variable "company". That means that after creating your new GSCompanyMode the old value from the original GSCompanyMode is restored.
Thank you for the explanation. It's still not entirely clear why this happens though. I finally understand that the whole GSCompanyMode thing is related to instance lifetime, not instance scope (as I thought it was all the time).

This doesn't explain why a double assignment causes issues though, because the first assigned instance loses all references the moment the second assignment occurs, and should thus be destroyed and restore the previous state (push pop push pop). This is either a Squirrel memory leak where the first instance is never destroyed, or a bug in your state handling code that causes it to miss the instance destruction.
Yexo
Tycoon
Tycoon
Posts: 3663
Joined: 20 Dec 2007 12:49

Re: NoGo - A Scriptable Game Framework - v1.5

Post by Yexo »

Simn wrote:
Yexo wrote:When a GSCompanyMode object is created it saves the old value of current company so it can restore that when the object is removed. Your disaster line first creates a new GSCompanyMode object and assigns it to the variable "company". That means that after creating your new GSCompanyMode the old value from the original GSCompanyMode is restored.
Thank you for the explanation. It's still not entirely clear why this happens though. I finally understand that the whole GSCompanyMode thing is related to instance lifetime, not instance scope (as I thought it was all the time).

This doesn't explain why a double assignment causes issues though, because the first assigned instance loses all references the moment the second assignment occurs, and should thus be destroyed and restore the previous state (push pop push pop). This is either a Squirrel memory leak where the first instance is never destroyed, or a bug in your state handling code that causes it to miss the instance destruction.
First the second instance is constructed (= assignment to some global of new company value). After that the new instance is assigned to the existing variable. When this happens the old instance is removed, which assigned the value it backed up when it was created to that global. That is why assigning null to the variable before assigning it a new instance might help.
Simn
Engineer
Engineer
Posts: 15
Joined: 05 Jan 2012 19:43

Re: NoGo - A Scriptable Game Framework - v1.5

Post by Simn »

Yexo wrote:First the second instance is constructed (= assignment to some global of new company value). After that the new instance is assigned to the existing variable. When this happens the old instance is removed, which assigned the value it backed up when it was created to that global. That is why assigning null to the variable before assigning it a new instance might help.
I see, thank you again for the explanation. It's really obvious that the second construction happens before the first destruction, so I don't know why it took me so long to figure this out. Still, this whole concept is very prone to introducing subtle bugs, so it should at the very least be well documented.
Yexo
Tycoon
Tycoon
Posts: 3663
Joined: 20 Dec 2007 12:49

Re: NoGo - A Scriptable Game Framework - v1.5

Post by Yexo »

Technically it is documented (apart from the fact that when you assign a new instance to an existing variable the new instance is created before the old one is destroyed), but I completely agree it would be good to mention this pitfall better. Could you write an example of text we could include in the documentation for GSCompanyMode (so http://nogo.openttd.org/docs/trunk/clas ... yMode.html under the detailed description)?
Simn
Engineer
Engineer
Posts: 15
Joined: 05 Jan 2012 19:43

Re: NoGo - A Scriptable Game Framework - v1.5

Post by Simn »

Be very careful when assigning several instances of GSCompanyMode to the same variable within the same scope:

Code: Select all

local company = GSCompanyMode(company_1);
company = GSCompanyMode(company_2);
Due to execution order, the second instance is created before the first one gets destroyed. This is almost never what you want to do as company_1 will be the active company once the second instance got destructed, because it was the active company when the second instance got constructed and is consequentially recovered. If you want to use the same variable again, you can null it before making a new assignment, which will cause its destructor to be executed.
It just occured to me while writing this that there should be another problem: The backup company of the first instance should be the active company after the second line, right? The first destructor gets executed after the second constructor, so it will recover the company which was active when the first instance is constructed.
User avatar
Zuu
OpenTTD Developer
OpenTTD Developer
Posts: 4553
Joined: 09 Jun 2003 18:21
Location: /home/sweden

Re: NoGo - A Scriptable Game Framework - v1.5

Post by Zuu »

In programming languages that support variable sub scopes within named functions, I tend to put in extra scopes when I have temporary instances that I want to make sure get destroyed at some point. Eg. when you have a temporary variable that holds user input that has not yet been safe guarded. This also works good for the ***Mode classes in the AI/NoGo API in OpenTTD as squirrel is good at deleting variables when they run out of scope.

But you can also just null the mode variable and the reference counting should kick in and destroy the instance.
My OpenTTD contributions (AIs, Game Scripts, patches, OpenTTD Auto Updater, and some sprites)
Junctioneer (a traffic intersection simulator)
Yexo
Tycoon
Tycoon
Posts: 3663
Joined: 20 Dec 2007 12:49

Re: NoGo - A Scriptable Game Framework - v1.5

Post by Yexo »

Zuu wrote:as squirrel is good at deleting variables when they run out of scope.
Little correction: OpenTTD's version of squirrel is good at that.
Simn
Engineer
Engineer
Posts: 15
Joined: 05 Jan 2012 19:43

Re: NoGo - A Scriptable Game Framework - v1.5

Post by Simn »

Yexo wrote:
Zuu wrote:as squirrel is good at deleting variables when they run out of scope.
Little correction: OpenTTD's version of squirrel is good at that.
Could you elaborate? I'm quite interested in these internals as it always helps to write scripts with a good performance.
Yexo
Tycoon
Tycoon
Posts: 3663
Joined: 20 Dec 2007 12:49

Re: NoGo - A Scriptable Game Framework - v1.5

Post by Yexo »

Simn wrote:Could you elaborate? I'm quite interested in these internals as it always helps to write scripts with a good performance.
Not sure how much I can say about it. The official squirrel docs are here: http://squirrel-lang.org/doc/squirrel2.html
OpenTTD's code contains a few changes to the original squirrel code. IIRC one of these changes it to make sure the stack is cleaned when a scope ends (so objects are destroyed at the end of scope). In original squirrel this didn't always happen, objects might live a bit longer which (in combination with some of the api objects) could lead to unwanted behavior.
Post Reply

Return to “OpenTTD Development”

Who is online

Users browsing this forum: Amazon [Bot] and 13 guests