Dixie's Lua Thread

Discussion of Lua and LuaWML support, development, and ideas.

Moderator: Forum Moderators

User avatar
Dixie
Posts: 1757
Joined: February 10th, 2010, 1:06 am
Location: $x1,$y1

Re: Dixie's Lua Thread

Post by Dixie »

Thanks! I will have to look up those special fields in the manual eventually, seems like there's a lot of potential in there.

About your untested function: it seems mostyl reasonnable, but I can't figure what n is. The length of cfg? Wouldn't it update itself with the function table.remove? Or is it merely to indicate how many children named name the function has to find and delete (in the case of an array)? Also, I'm guessing return is there so the for doesn't skip an entry in its loop, since the index has changed?
Jazz is not dead, it just smells funny - Frank Zappa
Current projects: Internet meme Era, The Settlers of Wesnoth
silene
Posts: 1109
Joined: August 28th, 2004, 10:02 pm

Re: Dixie's Lua Thread

Post by silene »

Dixie wrote:About your untested function: it seems mostyl reasonnable, but I can't figure what n is.
Hmm... I had misunderstood, the function isn't exactly what you need. It is a function for deleting the "n"-th child with given name, while you wanted to delete all the children with given name. So the code would rather look like:

Code: Select all

function remove_children(cfg, name)
  for i = #cfg,1,-1 do
    if cfg[i][1] == name then table.remove(cfg, i) end
  end
end
User avatar
Dixie
Posts: 1757
Joined: February 10th, 2010, 1:06 am
Location: $x1,$y1

Re: Dixie's Lua Thread

Post by Dixie »

Oooh the thread was almost off to the second page, there may yet be hope for me :)

So I am trying to have some functions defined for specific scenarios that can place labels and scenery and stuff. I figured I could create a file my_scenario_name.lua, and access it with wesnoth.require, changing the path depending on the args with string.format. So I have this:
Spoiler:
So the problem is that for some reason, action isn't indexed. It always returns nil, for some reason. The path -must be- correct, I've checked it like a dozen times, plus it's mostly the same I've copied from my dofiles, which work. Also, string.format works with wesnoth.require, I tried to grab the helper with it and it worked. I just really can't see what I did wrong. You could suggest just doing it some other way, without wesnoth.require, but, well, there are some other functionnalities I wanted it this fitted well. And even so, I'd still like to understand why it won't work and learn from it.

Thank :)
Jazz is not dead, it just smells funny - Frank Zappa
Current projects: Internet meme Era, The Settlers of Wesnoth
Anonymissimus
Inactive Developer
Posts: 2461
Joined: August 15th, 2008, 8:46 pm
Location: Germany

Re: Dixie's Lua Thread

Post by Anonymissimus »

Try placing a
return scenario
at the end of the require'd file. I made that mistake too, should be made clearer.
projects (BfW 1.12):
A Simple Campaign: campaign draft for wml startersPlan Your Advancements: mp mod
The Earth's Gut: sp campaignSettlers of Wesnoth: mp scenarioWesnoth Lua Pack: lua tags and utils
updated to 1.8 and handed over: A Gryphon's Tale: sp campaign
User avatar
Dixie
Posts: 1757
Joined: February 10th, 2010, 1:06 am
Location: $x1,$y1

Re: Dixie's Lua Thread

Post by Dixie »

Ok, totally unrelated with anything else in this thread, except that this is about Lua. I have been playing around a bit with wesnoth.find_reach to try and help someone in WML Workshop, and testing seems to indicate that there's an error in the wiki.

LuaWML:Pathfinder#wesnoth.find_reach
LuaWML:Pathfinder#wesnoth.find_reach wrote: Returns all the locations reachable by a unit. The unit is given either by its two coordinates or by a proxy object. Only the maximum movement points of the unit are considered, not its current ones.
But testing and printing stuff on the console, wesnoth.find_reach obivously doesn't use the maximum movement, but rather it's current movement points. Let's say I wesnoth.find_reach a 7 moves unit, and I get over 80 hexes. If I move around with him until he has only 1 movepoint left, wesnoth.find_reach only returns 7 hexes (the one the unit is standing on and the 6 adjacent hexes). Movecost is 1 everywhere, for the sake of testing, btw.

Also, and I,m not 100% sure about what I'm gonna say, but the stored hexes are represented by a table with three entries, where v[1]=x, v[2]=y, and v[3]=remaining mps after movement (I think). It took me some testing to figure out what the third value was for, might be worth mentionning on the wiki?

And while I'm at it, what would you suggest I do if I wanted to find reach using the maximum movement points of the unit?
Jazz is not dead, it just smells funny - Frank Zappa
Current projects: Internet meme Era, The Settlers of Wesnoth
Anonymissimus
Inactive Developer
Posts: 2461
Joined: August 15th, 2008, 8:46 pm
Location: Germany

Re: Dixie's Lua Thread

Post by Anonymissimus »

wiki wrote:The locations are stored as triples in an array. The first two elements of a triple are the coordinates of a reachable tile, the third one is the number of movement points left when reaching the tile.
...

The "current moves are used for calculation instead of max_moves" issue is right. Probably that's the way it's supposed to be and not a bug. Comment in the commented lines to use max_moves:

Code: Select all

		local Hamel = wesnoth.get_units({ id = "Hamel" })[1]
--~ 		local moves = Hamel.moves
--~ 		Hamel.moves = Hamel.max_moves
		local locs = wesnoth.find_reach(Hamel)
--~ 		Hamel.moves = moves

		for index, table in ipairs(locs) do
			wml_actions.label({ x = table[1], y = table[2], text = string.format("%u: %u", index, table[3])})
		end
(It's Hamel since I'm testing it in the testscenario of my addon...)
projects (BfW 1.12):
A Simple Campaign: campaign draft for wml startersPlan Your Advancements: mp mod
The Earth's Gut: sp campaignSettlers of Wesnoth: mp scenarioWesnoth Lua Pack: lua tags and utils
updated to 1.8 and handed over: A Gryphon's Tale: sp campaign
User avatar
Dixie
Posts: 1757
Joined: February 10th, 2010, 1:06 am
Location: $x1,$y1

Re: Dixie's Lua Thread

Post by Dixie »

I guess the moves thing was kinda obvious, maybe I jsut didn't take the time to think it through, or I'm getting rusty, I dunno... Well thanks! :)

And the bit about the third value... I guess it was just me being dumb and overlooking it: it is pretty obivous. Darn :doh:
Jazz is not dead, it just smells funny - Frank Zappa
Current projects: Internet meme Era, The Settlers of Wesnoth
silene
Posts: 1109
Joined: August 28th, 2004, 10:02 pm

Re: Dixie's Lua Thread

Post by silene »

Anonymissimus wrote:The "current moves are used for calculation instead of max_moves" issue is right. Probably that's the way it's supposed to be and not a bug.
Indeed, it's not a bug, that's how the engine works. No idea why I wrote that in the wiki, I will fix it.
User avatar
Dixie
Posts: 1757
Joined: February 10th, 2010, 1:06 am
Location: $x1,$y1

Re: Dixie's Lua Thread

Post by Dixie »

I was not sure wether to post this in my WML thread or in my Lua thread, but since I kinda intend on coding this in lua (unless it surprisingly is easier in WML), I'll post it here.

So, this is the single most ambitious piece of code I've attempted in my relatively short (a few months) life as a coder. Basically, in the add-on I am working on, players can place "road" units, and I need a function that would find the longest line of such units for a side and return how long it is. Because an image is worth a thousand words:
Ok, it's not the nicest thing I've ever drawn :P
Ok, it's not the nicest thing I've ever drawn :P
path.png (12 KiB) Viewed 3098 times
In the above, imagine each hex corner and each hex side is a Wesnoth hex, and each actually drawn hex's inside is void. For the purpose of the function I need, "corner" hexes don,t matter, as the units we are interested in can only placed on the sides. On the picture, each big red dot represents one such unit, and the smaller dots represent the possible paths. In this case, the green-dot path would be the longest, with 6 units.

This case is not protrayed in the above picture, but we also have to be wary of units going all around an hex (forming a loop), so as not to count any road twice for a single path/freeze the engine in a loop.

So far, I have this code, but I am stuck in two places (see comments), so I can't really test if I did something wrong. It can also probably be optimized quite a bit:
Spoiler:
Thanks a lot for your insight in advance! :)
Jazz is not dead, it just smells funny - Frank Zappa
Current projects: Internet meme Era, The Settlers of Wesnoth
silene
Posts: 1109
Joined: August 28th, 2004, 10:02 pm

Re: Dixie's Lua Thread

Post by silene »

Dixie wrote:So far, I have this code, but I am stuck in two places (see comments), so I can't really test if I did something wrong. It can also probably be optimized quite a bit:
There are a few things I don't understand. First, I don't understand the location filter you are using. How does it relate to what you draw on your picture? Second, I don't understand the value returned by sow_getting_path_length; it is some kind of tree. Shouldn't it be just an integer (the length of the longest path)?

Anyway, you can make the function much shorter. (It returns an integer here, but it still uses the same filter as yours.)

Code: Select all

function sow_getting_path_length(player, start, seen_ids, length)
	local actual_id = start.id
	seen_ids = string.format("%s,%s", actual_id, seen_ids)
	local actual_length = 1 + length
	local best_length = actual_length
	local next_road = wesnoth.get_units({type="sow_roadn,sow_roadne,sow_roadnw", side=player, {"filter_location",{ {"and"{radius=2, {"filter",{id=actual_id}}, {"not",{ {"filter",{id=seen_ids}} }} }} }} })
	for i,v in ipairs(next_road) do
		best_length = math.max(best_length, sow_getting_path_length(player, v, seen_ids, actual_length))
	end
	return best_length
end
User avatar
Dixie
Posts: 1757
Joined: February 10th, 2010, 1:06 am
Location: $x1,$y1

Re: Dixie's Lua Thread

Post by Dixie »

Yeah, I figured there were some wrong stuff about my code overnight. Like the tree thing, for instance.
I've tried my hand at a better image, by the way:
path.png
path.png (28.27 KiB) Viewed 3083 times
Here is the code I have at present, largely based on your try:
Spoiler:
I have played around with it a bit, and will have to take a better look at it, but at the time being, sow_longest_check always returns 1. I have some papers to write for university, so I can't put much more time on this right now, but maybe tonight. I was also not sure whether your code would consider the pale blue line on the picture, but I didn't get 'round to testing it just yet. The weird filter_location was incomplete and was aimed at seeing if a road was a start (only "adjacent" to none or only one other road), but I figured it might as well start counting from any road in the middle: it shouldn't be the longest in that case, and shouldn't matter.

Thanks again in advance!
Jazz is not dead, it just smells funny - Frank Zappa
Current projects: Internet meme Era, The Settlers of Wesnoth
silene
Posts: 1109
Joined: August 28th, 2004, 10:02 pm

Re: Dixie's Lua Thread

Post by silene »

Dixie wrote:I was also not sure whether your code would consider the pale blue line on the picture, but I didn't get 'round to testing it just yet.
It does consider it. But I now understand from your picture that it is not what you wanted. So, if I get it correctly, you want all the units that are from a road type at distance 2 of the current tile (but not the current tile) but not at a distance 2 of any previously visited tile. So the filter should be (with the usual "T = helper.set_wml_tag_metatable {}"):

Code: Select all

type = "sow_roadn,sow_roadne,sow_roadnw",
side = player,
T.not { id = start.id },
T.filter_location {
  T.and { radius = 2, T.filter { id = start.id } },
  seen_ids and (T.not { radius = 2, T.filter { id = seen_ids } })
}
Notice the "seen_ids and ()" part; it prevents the [not] part from being output when then [filter] part would be empty, which would cause it to match any unit and hence the overall filter to return no unit. Presumably, that's what causing your current function to always return 1.
User avatar
Dixie
Posts: 1757
Joined: February 10th, 2010, 1:06 am
Location: $x1,$y1

Re: Dixie's Lua Thread

Post by Dixie »

The tag metatable thing scared me a bit at first, but I went ahead and read the wiki, and it doesn't look so bad. It's strictly a syntactic shortcut, where T.filter {} replaces {"filter",{}}, right? No other side effects?

By the way, your code gave me this error:

Code: Select all

20101205 19:24:29 error scripting/lua: ...ort/Wesnoth_1.9/data/add-ons/Settlers_of_Wesnoth/utils/sow_lua-utils.lua:1166: '<name>' expected near 'not'
stack traceback:
	[C]: in function 'dofile'
	[string "..."]:4: in function 'bytecode'
	... 192.app/Contents/Resources/.//data/lua/wml-tags.lua:206: in function 'cmd'
	... 192.app/Contents/Resources/.//data/lua/wml-tags.lua:220: in function <... 192.app/Contents/Resources/.//data/lua/wml-tags.lua:213>
The faulty line being : T.not { id = start.id }

By the way, I thought some more about the filter I'd need. Here's another image:
paths.png
paths.png (31.07 KiB) Viewed 3064 times
Your first alternative would have allowed both the green and the yellow paths. The last code you suggested would have allowed neither. Ideally, I'd like to allow the green but not the yellow. So I figured seen_ids needn't be in the radius 2 thing, but only in a simple "not" in the basic filter. And I also figured I'd create a temporary "ignore these ids" variable for other options at intersections, but that wouldn't disqualify the ignored roads for later use, if they somehow reconnect at some point.

Anyway, I currently have the following code, which looks OK to me but is subject to the same error as yours (shown above) because I used the metatable thing. I'd only need to correct this, and maybe your aproval on the final code (although if I could fix the error, I'd test and approve myself):
Spoiler:
Thanks again!
Jazz is not dead, it just smells funny - Frank Zappa
Current projects: Internet meme Era, The Settlers of Wesnoth
Luther
Posts: 128
Joined: July 28th, 2007, 5:19 pm
Location: USA

Re: Dixie's Lua Thread

Post by Luther »

Dixie wrote: The faulty line being : T.not { id = start.id }
That particular line won't work because 'not' is a reserved word. As in "if not some_boolean then...". Change the "T.not" to "T['not']" and you should be fine.
User avatar
Dixie
Posts: 1757
Joined: February 10th, 2010, 1:06 am
Location: $x1,$y1

Re: Dixie's Lua Thread

Post by Dixie »

By the way, it just occured to me: helper.set_wml_tag_metatable {} really is some kinda shortcut for wesnoth.fire, right or wrong? Or maybe it's only useful when used within filters or something and won't actually "fire" an action tag?
Jazz is not dead, it just smells funny - Frank Zappa
Current projects: Internet meme Era, The Settlers of Wesnoth
Post Reply