[SOLVED] Can't figure out error in conversion of pies?

Post Reply
Icalasari
Member
Posts: 166
Joined: Tue Sep 23, 2014 05:29
IRC: Icalasari
In-game: Icalasari

[SOLVED] Can't figure out error in conversion of pies?

by Icalasari » Post

The error isn't actually pointing to what's wrong (or else I am somehow misunderstanding it greatly), since it seems to be more about some bit of implementation I did

On a suggestion, I put everything on GitHub (but you'll see how messy it is soon enough)

Error

Code: Select all

ModError: Failed to load and run script from D:\Users\Vee\Documents\!!!Games\Open World\minetest-5.5.1-win64\bin\..\mods\mindeca\Mindeca Main\init.lua:
...-5.5.1-win64\bin\..\mods\mindeca\Mindeca Main/baking.lua:78: 'end' expected (to close 'for' at line 26) near '<eof>'
stack traceback:
	[C]: in function 'dofile'
	...st-5.5.1-win64\bin\..\mods\mindeca\Mindeca Main\init.lua:16: in main chunk
Check debug.txt for details.
Code (I still haven't cleaned it up fully)

Code: Select all

local hbmod = minetest.global_exists("hbhunger")

-----
--Pies
-----

mindeca.mpies = {
	--{"Fruit",	"Hunger Boost",	"Effect (To Be Implemented once I figure out how"},
	--Spring
	--Summer
	{"peach",	4,		nil}
	--Autumn
	--Winter
}

mindeca.pieparts = {
	--Spring
	--Summer
	peach = {
		mpiedesc = "Peach\n\nA juicy peach for a quick snack.\n\nMindeca",
	},
	--Autumn
	--Winter
}

for i in ipairs(mindeca.mpies) do
	local mpie = mindeca.mpies[i][1]
	local mhun = mindeca.mpies[i][2]
	local mpieseat = 1
minetest.register_node("mindeca:item_cook_pie_"..mpie..mpieseat, {
	description = mindeca.baking[pieparts].mpiedesc,
	drawtype = "mesh",
	collision_box = {
		type = "fixed",
		fixed =	{-8/16, -8/16, -8/16, 8/16, -2/16, 8/16},
	},
	selection_box = {
		type = "fixed",
		fixed =	{-8/16, -8/16, -8/16, 8/16, -2/16, 8/16},
	},
	mesh = "mindeca_pie"..mpieseat..".obj",
	tiles = {"mindeca_cook_pie_"..mpie..".png"},
	inventory_image = "mindeca_item_cook_pie_tin.png",
	groups = {oddly_breakable_by_hand = 1},
	drop = "mindeca:item_cook_pie_"..mpie,
	sounds = default.node_sound_stone_defaults(),

--Right Click function thanks to Blockhead and TenPlus
	on_rightclick = function(pos, node, clicker)
		if hbmod then	
			local sat = tonumber(hbhunger.SAT_MAX)
			local h = tonumber(hbhunger.hunger[clicker:get_player_name()])
			h = math.min(h + mhun)
			if h > sat then
				h = sat
			end
			hbhunger.hunger[clicker:get_player_name()] = h
			hbhunger.set_hunger_raw(clicker)
			minetest.sound_play("mindeca_eat", {
				pos = pos, gain = 0.7, max_hear_distance = 4})
			mpieseat = math.min(mpieseat + 1)
				if mpieseat > 4 then
					minetest.set_node(pos, {name = "mindeca:item_cook_pie_tin"})
				else minetest.set_node(pos, {name = "mindeca:item_cook_pie_"..mpie..mpieseat})
			end
		else local h = clicker:get_hp()
			h = math.min(h + mhun, 20)
			clicker:set_hp(h)
			minetest.sound_play("mindeca_eat", {
				pos = pos, gain = 0.7, max_hear_distance = 4})
			mpieseat = math.min(mpieseat + 1)
				if mpieseat > 4 then
					minetest.set_node(pos, {name = "mindeca:item_cook_pie_tin"})
				else minetest.set_node(pos, {name = "mindeca:item_cook_pie_"..mpie..mpieseat})
			end
		end
	end
})
-----

Repository: https://github.com/Icalasari/Mindeca-Ma ... eca%20Main

(Yes it's a huge mess, it'll be cleaned up closer to release)

EDIT: Right, forgot to explain why I think it's not what it says. When I do add more ends, it then switches to wanting me to put }) at a portion that would cut out a chunk of the code. So something else seems to be up
Last edited by Icalasari on Fri Aug 12, 2022 19:33, edited 1 time in total.

loosewheel
Member
Posts: 155
Joined: Mon Dec 28, 2020 01:19
GitHub: loosewheel
In-game: loosewheel

Re: Can't figure out error in conversion of pies?

by loosewheel » Post

I don't know where you put the extra end, but it needs to go after the }). The registration code is inside the for loop.

User avatar
sirrobzeroone
Member
Posts: 593
Joined: Mon Jul 16, 2018 07:56
GitHub: sirrobzeroone
Contact:

Re: Can't figure out error in conversion of pies?

by sirrobzeroone » Post

loosewheel wrote:
Wed Aug 10, 2022 02:33
I don't know where you put the extra end, but it needs to go after the }). The registration code is inside the for loop.

edit -Okay there's a lot going on there any reason your split across two tables for pie info? I'd do a single table for pies and make the key the name and then put the defs in the sub table. I can't fully follow whats going on in the on_rightclick down in the else, some of the variables I'm not understanding what you wanted to achieve, is it just remove a pie if the person is hungry and they right click on the pie when it's placed?. The below may load and run I'm not sure?

Also not sure what is this? "mpieseat = 1"

Code: Select all

mindeca = {} 
mindeca.is_hbmod = minetest.global_exists("hbhunger")

-----
--Pies
-----
mindeca.pies = {
	--Spring
	--Summer
	peach = {
			hunger = 4,
			pie_desc = "Peach\n\nA juicy peach for a quick snack.\n\nMindeca",
			unknown = nil
	},
	--Autumn
	--Winter
}

for name,def in pairs(mindeca.pies) do
	
	local mpieseat = 1  -- not sure what is this?
	
	minetest.register_node("mindeca:item_cook_pie_"..name, {
		description = def.pie_desc,
		drawtype = "mesh",
		collision_box = {
			type = "fixed",
			fixed =	{-8/16, -8/16, -8/16, 8/16, -2/16, 8/16},
		},
		selection_box = {
			type = "fixed",
			fixed =	{-8/16, -8/16, -8/16, 8/16, -2/16, 8/16},
		},
		mesh = "mindeca_pie_"..name..".obj",  -- does each pie have a unique mesh? if not "mindeca_pie_mesh.obj" might be what your after
		tiles = {"mindeca_cook_pie_"..name..".png"},
		inventory_image = "mindeca_item_cooked_"..name.."_inv.png",
		groups = {oddly_breakable_by_hand = 1},
		drop = "mindeca:item_cook_pie_"..name, -- drop self no need to define drop at all but it's okay to do so.
		sounds = default.node_sound_stone_defaults(),

	--Right Click function thanks to Blockhead and TenPlus
		on_rightclick = function(pos, node, clicker)
			if mindeca.is_hbmod then	
				local sat = tonumber(hbhunger.SAT_MAX)
				local h = tonumber(hbhunger.hunger[clicker:get_player_name()])
				h = math.min(h + def.hunger) 
				if h > sat then
					h = sat
				end
				hbhunger.hunger[clicker:get_player_name()] = h
				hbhunger.set_hunger_raw(clicker)
				minetest.sound_play("mindeca_eat", {
					pos = pos, gain = 0.7, max_hear_distance = 4})
				mpieseat = math.min(mpieseat + 1)
					if mpieseat > 4 then
						minetest.set_node(pos, {name = "mindeca:item_cook_pie_tin"})
					else minetest.set_node(pos, {name = "mindeca:item_cook_pie_"..name})
				end
			else local h = clicker:get_hp()
				h = math.min(h + def.hunger, 20)
				clicker:set_hp(h)
				minetest.sound_play("mindeca_eat", {
					pos = pos, gain = 0.7, max_hear_distance = 4})
				mpieseat = math.min(mpieseat + 1)
					if mpieseat > 4 then
						minetest.set_node(pos, {name = "mindeca:item_cook_pie_tin"})
					else minetest.set_node(pos, {name = "mindeca:item_cook_pie_"..name})
				end
			end
		end
	})
end
Justa thought for testing if you like you could do just the below the pies will then register you can then work on your right_click code:

Code: Select all

mindeca.is_hbmod = minetest.global_exists("hbhunger")

-----
--Pies
-----
mindeca.pies = {
	--Spring
	--Summer
	peach = {
			hunger = 4,
			pie_desc = "Peach\n\nA juicy peach for a quick snack.\n\nMindeca",
			unknown = nil
	},
	--Autumn
	--Winter
}

for name,def in pairs(mindeca.pies) do
	
	local mpieseat = 1  -- not sure what is this?
	
	minetest.register_node("mindeca:item_cook_pie_"..name, {
		description = def.pie_desc,
		drawtype = "mesh",
		collision_box = {
			type = "fixed",
			fixed =	{-8/16, -8/16, -8/16, 8/16, -2/16, 8/16},
		},
		selection_box = {
			type = "fixed",
			fixed =	{-8/16, -8/16, -8/16, 8/16, -2/16, 8/16},
		},
		mesh = "mindeca_pie"..name..".obj",   -- does each pie have a unique mesh? if not "mindeca_pie_mesh.obj" might be what your after
		tiles = {"mindeca_cook_pie_"..name..".png"},
		inventory_image = "mindeca_item_cooked_"..name.."_inv.png",
		groups = {oddly_breakable_by_hand = 1},
		drop = "mindeca:item_cook_pie_"..name,
		sounds = default.node_sound_stone_defaults(),

	--Right Click function thanks to Blockhead and TenPlus
		on_rightclick = function(pos, node, clicker)
			
		end
	})

end

User avatar
Blockhead
Member
Posts: 1602
Joined: Wed Jul 17, 2019 10:14
GitHub: Montandalar
IRC: Blockhead256
In-game: Blockhead Blockhead256
Location: Land Down Under
Contact:

Re: Can't figure out error in conversion of pies?

by Blockhead » Post

Your indentation is totally borked. If you consistently write your indentation correctly as you code, the source of syntax errors like these should become much more obvious. In fact, if you're having trouble, then I'd suggest that for instance after you write any if line, go and write any elseif and/or else you will have on their own lines, and then write the end statement. Then you should have your proper outline:

Code: Select all

if
elseif
elseif
else
end
Then go ahead and insert the bodies into that outline properly indented. You shouldn't have problems with syntax errors like you're having now if you do this.

Put the end of a function in line with the column that the function starts in. Similarly, put the end of for statements and if statements in line with the column where those started. Similarly put table and function call-ending brackets }) in line with the column where the function call started, at least for function calls split over more than 2 lines and for tables that aren't one-liners.

Code: Select all

-- wrong
function a(x,y)
	return x+y
	end
	
-- right
function a(x, y)
	return x + y
end

-- wrong
for i=1,10 do
print(i)
end

-- wrong
for i=1,10 do
		print(i)
	end
	
-- right
for i=1,10 do
	print(i)
end

-- wrong
t = { wew = "lad",
foo = "bar"}

-- wrong
t = {
wew = "lad"
foo = "bar"}

-- right, but tight
t = {wew = "lad", foo = "bar"}

-- right, and loose
t = {
	wew = "lad",
	foo = "bar", -- always leave the trailing comma so you don't forget it if you add more table entries.
}

Certainly don't regress indentation:

Code: Select all

-- current, wrong
	local mpieseat = 1
minetest.register_node("mindeca:item_cook_pie_"..mpie..mpieseat, {
	description = mindeca.baking[pieparts].mpiedesc,

-- right
	local mpieseat = 1
	minetest.register_node("mindeca:item_cook_pie_"..mpie..mpieseat", {
		description = mindeca.baking[pieparts].mpiedesc,
		...
	})




-- current, wrong
sounds = default.node_sound_stone_defaults(),

--Right Click function thanks to Blockhead and TenPlus
	on_rightclick = function(pos, node, clicker)
	
-- right
sounds = default.node_sound_stone_defaults(),

	--Right Click function thanks to Blockhead and TenPlus
	on_rightclick = function(pos, node, clicker)

Don't abitrarily add indentation either:

Code: Select all

-- wrong
			mpieseat = math.min(mpieseat + 1)
				if mpieseat > 4 then
					minetest.set_node(pos, {name = "mindeca:item_cook_pie_tin"})
				else minetest.set_node(pos, {name = "mindeca:item_cook_pie_"..mpie..mpieseat})
			end

-- right, also nicer spacing to avoid too-long lines
			mpieseat = math.min(mpieseat + 1)
			if mpieseat > 4 then
				minetest.set_node(pos,
					{name = "mindeca:item_cook_pie_tin"})
			else
				minetest.set_node(pos,
					{name = "mindeca:item_cook_pie_"..mpie..mpieseat})
			end
Please note the above is purely a code style review. sirrobzeroone tried to help you address the logic problems you also have. In particular it looks like mpieseat = 1 is wrong.. it looks like it should be a loop variable, declared outside the loop body. In fact it looks like you need two nested loops: one to register each partial-eaten state of the pie, and inside it one to register each type of pie (assuming every pie has a constant 8 partial-eaten states):

Code: Select all

for eatstate=1,8 do
	for i in ipairs(mindeca.mpies) do
		local mpie = mindeca.mpies[i][1]
		local mhun = mindeca.mpies[i][2]
		minetest.register_node("mindeca:item_cook_pie_"..mpie..eatstate, {
But this is all my guessing at what you're trying to do.

Hope that helps.
Last edited by Blockhead on Wed Aug 10, 2022 10:09, edited 1 time in total.
/˳˳_˳˳]_[˳˳_˳˳]_[˳˳_˳˳\ Advtrains enthusiast | My map: Noah's Railyard | My Content on ContentDB ✝️♂

Icalasari
Member
Posts: 166
Joined: Tue Sep 23, 2014 05:29
IRC: Icalasari
In-game: Icalasari

Re: Can't figure out error in conversion of pies?

by Icalasari » Post

mpieseat was basically for the state of the pie, and the indentation issues are admitredly because I could not figure out how to indent it

End goal with the nested functions was to get it to turn to an empty pie tin when all four pieces got ate

So guess the issue was mostly me using coding I thought I understood and resulting in a mess. Woo slow, incremental improvement?

Edit: The two tables was basically to make it a bit nicer looking and easier to find. Guess I forgot I can just do linebreaks

Icalasari
Member
Posts: 166
Joined: Tue Sep 23, 2014 05:29
IRC: Icalasari
In-game: Icalasari

Re: Can't figure out error in conversion of pies?

by Icalasari » Post

Alright, got changes put in, now it's a new error. Which... Pretty sure there shouldn't be a comma needed there?

Error

Code: Select all

ModError: Failed to load and run script from D:\Users\Vee\Documents\!!!Games\Open World\minetest-5.5.1-win64\bin\..\mods\mindeca\Mindeca Main\init.lua:
...-5.5.1-win64\bin\..\mods\mindeca\Mindeca Main/baking.lua:19: ',' expected near 'do'
stack traceback:
	[C]: in function 'dofile'
	...st-5.5.1-win64\bin\..\mods\mindeca\Mindeca Main\init.lua:16: in main chunk
Check debug.txt for details.


Code (There is probably a better way to make it drop a pie tin if on eat state 2, 3, or 4 but it's late here so I'm not thinking quite now and just want to get it working first before I shorten the code)

Code: Select all

local hbmod = minetest.global_exists("hbhunger")

-----
--Pies
-----

mindeca.mpies = {
	--{"Fruit",	"Hunger Boost",	"Effect (To Be Implemented once I figure out how"},
	--Spring
	--Summer
	peach = {
		hunger = 4,
		pie_desc = "Peach\n\nA juicy peach for a quick snack.\n\nMindeca",
		effect = nil}
	--Autumn
	--Winter
}

for eatstate=1 do
	for name,def in pairs(mindeca.pies) do
		minetest.register_node("mindeca:item_cook_pie_"..name..eatstate, {
			description = def.pie_desc,
			drawtype = "mesh",
			collision_box = {
				type = "fixed",
				fixed =	{-8/16, -8/16, -8/16, 8/16, -2/16, 8/16},
			},
			selection_box = {
				type = "fixed",
				fixed =	{-8/16, -8/16, -8/16, 8/16, -2/16, 8/16},
			},
			mesh = "mindeca_pie"..eatstate..".obj",
			tiles = {"mindeca_cook_pie_"..name..".png"},
			inventory_image = "mindeca_item_cook_pie_tin.png",
			groups = {oddly_breakable_by_hand = 1},
			drop = "mindeca:item_cook_pie_"..name..eatstate,
			sounds = default.node_sound_stone_defaults(),

		--Right Click function thanks to Blockhead and TenPlus
			on_rightclick = function(pos, node, clicker)
				if hbmod then	
					local sat = tonumber(hbhunger.SAT_MAX)
					local h = tonumber(hbhunger.hunger[clicker:get_player_name()])
					h = math.min(h + def.hunger)
					if h > sat then
						h = sat
					end
					hbhunger.hunger[clicker:get_player_name()] = h
					hbhunger.set_hunger_raw(clicker)
					minetest.sound_play("mindeca_eat", {
						pos = pos, gain = 0.7, max_hear_distance = 4})
					eatstate = math.min(eatstate + 1)
						minetest.set_node(pos, {name = "mindeca:item_cook_pie_"..name..eatstate})
					end
				end
				else local h = clicker:get_hp()
				h = math.min(h + def.hunger, 20)
					clicker:set_hp(h)
					minetest.sound_play("mindeca_eat", {
						pos = pos, gain = 0.7, max_hear_distance = 4})
					eatstate = math.min(eatstate + 1)
						if eatstate > 4 then
							minetest.set_node(pos, {name = "mindeca:item_cook_pie_tin"})
						else minetest.set_node(pos, {name = "mindeca:item_cook_pie_"..name..eatstate})
					end
				end
			end
		end
	end
})
end

for eatstate=2,4 do
	for name,def in pairs(mindeca.pies) do
		minetest.register_node("mindeca:item_cook_pie_"..name..eatstate, {
			description = def.pie_desc,
			drawtype = "mesh",
			collision_box = {
				type = "fixed",
				fixed =	{-8/16, -8/16, -8/16, 8/16, -2/16, 8/16},
			},
			selection_box = {
				type = "fixed",
				fixed =	{-8/16, -8/16, -8/16, 8/16, -2/16, 8/16},
			},
			mesh = "mindeca_pie"..eatstate..".obj",
			tiles = {"mindeca_cook_pie_"..name..".png"},
			inventory_image = "mindeca_item_cook_pie_tin.png",
			groups = {oddly_breakable_by_hand = 1},
			drop = "mindeca:item_cook_pie_tin",
			sounds = default.node_sound_stone_defaults(),

		--Right Click function thanks to Blockhead and TenPlus
			on_rightclick = function(pos, node, clicker)
				if hbmod then	
					local sat = tonumber(hbhunger.SAT_MAX)
					local h = tonumber(hbhunger.hunger[clicker:get_player_name()])
					h = math.min(h + def.hunger)
					if h > sat then
						h = sat
					end
					hbhunger.hunger[clicker:get_player_name()] = h
					hbhunger.set_hunger_raw(clicker)
					minetest.sound_play("mindeca_eat", {
						pos = pos, gain = 0.7, max_hear_distance = 4})
					eatstate = math.min(eatstate + 1)
						if eatstate > 4 then
							minetest.set_node(pos, {name = "mindeca:item_cook_pie_tin"})
						else minetest.set_node(pos, {name = "mindeca:item_cook_pie_"..name..eatstate})
					end
				end
				else local h = clicker:get_hp()
				h = math.min(h + def.hunger, 20)
					clicker:set_hp(h)
					minetest.sound_play("mindeca_eat", {
						pos = pos, gain = 0.7, max_hear_distance = 4})
					eatstate = math.min(eatstate + 1)
						if eatstate > 4 then
							minetest.set_node(pos, {name = "mindeca:item_cook_pie_tin"})
						else minetest.set_node(pos, {name = "mindeca:item_cook_pie_"..name..eatstate})
					end
				end
			end
		end
	end
})
end
EDIT: I feel I need to apologize for needing so much help with this. I'm still learning Lua as I go (seems I remember way less about programming from high school than I thought I did...), so it's slow going

User avatar
sirrobzeroone
Member
Posts: 593
Joined: Mon Jul 16, 2018 07:56
GitHub: sirrobzeroone
Contact:

Re: Can't figure out error in conversion of pies?

by sirrobzeroone » Post

Icalasari wrote:
Wed Aug 10, 2022 06:23
EDIT: I feel I need to apologize for needing so much help with this. I'm still learning Lua as I go (seems I remember way less about programming from high school than I thought I did...), so it's slow going
All good without the help of a number of people on forum boards I would have been truly stumped, so trying to pay it fwd if I can, my lua is pretty rugged at times. Blockhead has given some really good pointers above.

first do indenting was a little out and some extra ends in few spots think I got them all - are you using notepad++ with language set to Lua (Language tab at the top) - apologises if your using something more advance I just find notepad++ with syntax highlighting very helpful - also for just syntax/base function testing I use the lua demo site a fair bit just to make sure I'm not borking up something basic much quicker than load MT get error then check code (https://www.lua.org/demo.html)

If Im guessing right your trying to register a pie object with 4 states - full-3/4-1/2-1/4 with empty being pie-dish. If a player right clicks the pie then a slice or more vanishes depending how hungry they are. Basically pie gorging if your supper hungry you eat the whole thing in 1 bite.

Saying that your loops out I think you more want this - you can paste this into Lua demo above just pretend the print statements are your minetest.register_node() info:

Code: Select all

for i=1,4 ,1 do
	if i == 1 then
		print("special "..i.." case")
	else
		print("case"..i)
	end
end
I'm also not sure the above is what you want from what I can see the difference between pie1 and pie2-4 is that pie1 will drop pie1 but pie 2-4 will drop empty pie dish? wouldn't you want these to drop the pie partially eaten?

if so you may just need this:

Code: Select all

for i=1,4 ,1 do
	print("minetest.register_node({def_pie"..i.."})")
end
Hope the below helps some:

Code: Select all

for i=1,4 ,1 do
	local eatstate = i
	for name,def in pairs(mindeca.pies) do
		minetest.register_node("mindeca:item_cook_pie_"..name..eatstate, {
			description = def.pie_desc,
			drawtype = "mesh",
			collision_box = {
				type = "fixed",
				fixed =	{-8/16, -8/16, -8/16, 8/16, -2/16, 8/16},
			},
			selection_box = {
				type = "fixed",
				fixed =	{-8/16, -8/16, -8/16, 8/16, -2/16, 8/16},
			},
			mesh = "mindeca_pie"..eatstate..".obj",
			tiles = {"mindeca_cook_pie_"..name..".png"},
			inventory_image = "mindeca_item_cook_pie_tin.png",
			groups = {oddly_breakable_by_hand = 1},
			drop = "mindeca:item_cook_pie_"..name..eatstate,
			sounds = default.node_sound_stone_defaults(),

		--Right Click function thanks to Blockhead and TenPlus
			on_rightclick = function(pos, node, clicker)
				if hbmod then	
					local sat = tonumber(hbhunger.SAT_MAX)
					local h = tonumber(hbhunger.hunger[clicker:get_player_name()])
					h = math.min(h + def.hunger)
					if h > sat then
						h = sat
					end
					hbhunger.hunger[clicker:get_player_name()] = h
					hbhunger.set_hunger_raw(clicker)
					minetest.sound_play("mindeca_eat", {
						pos = pos, gain = 0.7, max_hear_distance = 4})
					eatstate = math.min(eatstate + 1)
						minetest.set_node(pos, {name = "mindeca:item_cook_pie_"..name..eatstate})

				else 
					local h = clicker:get_hp()
					h = math.min(h + def.hunger, 20)
					clicker:set_hp(h)
					minetest.sound_play("mindeca_eat", {
						pos = pos, gain = 0.7, max_hear_distance = 4})
					eatstate = math.min(eatstate + 1)
					
					if eatstate > 4 then
						minetest.set_node(pos, {name = "mindeca:item_cook_pie_tin"})
					else 
						minetest.set_node(pos, {name = "mindeca:item_cook_pie_"..name..eatstate})
					end
				end
			end
		})
	end
end
Edit: knew I'd seen that syntax somewhere in default:

This would be the shorthand ie lua demo version of the do statments your looking for in your post

Code: Select all

-- just register pie1
print("minetest.register_node({def_pie1})")

-- loop register pie 2-4
for i = 2, 4 do
	print("minetest.register_node({def_pie"..i.."})")
end

loosewheel
Member
Posts: 155
Joined: Mon Dec 28, 2020 01:19
GitHub: loosewheel
In-game: loosewheel

Re: Can't figure out error in conversion of pies?

by loosewheel » Post

I don't know about the rest of your code, but the error is because of the line
for eatstate=1 do
There is no final value for the for loop. The parser expects a comma and a final value following the 1 (before do).

Icalasari
Member
Posts: 166
Joined: Tue Sep 23, 2014 05:29
IRC: Icalasari
In-game: Icalasari

Re: Can't figure out error in conversion of pies?

by Icalasari » Post

sirrobzeroone wrote:
Wed Aug 10, 2022 09:16
If Im guessing right your trying to register a pie object with 4 states - full-3/4-1/2-1/4 with empty being pie-dish. If a player right clicks the pie then a slice or more vanishes depending how hungry they are. Basically pie gorging if your supper hungry you eat the whole thing in 1 bite.
One slice disappears at a time, but otherwise yeah
I'm also not sure the above is what you want from what I can see the difference between pie1 and pie2-4 is that pie1 will drop pie1 but pie 2-4 will drop empty pie dish? wouldn't you want these to drop the pie partially eaten?
I eventually, once I figure out how, want to include effects per pie type (e.g. Peach is extra filling, Apple gives extra health on top of filling hunger, cherry slightly increases speed for a bit), so I'm implementing it this way for checking on balancing later. It's also why the first one is mostly a clone - If it ends up being unneeded, I can just delete the later section then change 1,1 to 1,4
Hope the below helps some:
<code>
Mostly helped, now getting a weird error. In that the game loads fine, but when I eat the pie, it's taking one slice, then one slice, then two slices, then the next pie it takes three slices, then gives back two slices, then it takes three slices, then every pie after it eats in one bite. And that was after an attempted fix to make it just set the eat state back to one after (before this, the error was that after finishing one pie, all the pies after are eaten in one bite)

Code: Select all

local hbmod = minetest.global_exists("hbhunger")

-----
--Pies
-----

mindeca.mpies = {
	--{"Fruit",	"Hunger Boost",	"Effect (To Be Implemented once I figure out how"},
	--Spring
	--Summer
	peach = {
		hunger = 4,
		pie_desc = "Peach\n\nA juicy peach for a quick snack.\n\nMindeca",
		effect = nil}
	--Autumn
	--Winter
}

for eatstate=1,1 do
	for name,def in pairs(mindeca.mpies) do
		minetest.register_node("mindeca:item_cook_pie_"..name..eatstate, {
			description = def.pie_desc,
			drawtype = "mesh",
			collision_box = {
				type = "fixed",
				fixed =	{-8/16, -8/16, -8/16, 8/16, -2/16, 8/16},
			},
			selection_box = {
				type = "fixed",
				fixed =	{-8/16, -8/16, -8/16, 8/16, -2/16, 8/16},
			},
			mesh = "mindeca_pie"..eatstate..".obj",
			tiles = {"mindeca_cook_pie_"..name..".png"},
			inventory_image = "mindeca_item_cook_pie_tin.png",
			groups = {oddly_breakable_by_hand = 1},
			drop = "mindeca:item_cook_pie_"..name..eatstate,
			sounds = default.node_sound_stone_defaults(),

		--Right Click function thanks to Blockhead and TenPlus
			on_rightclick = function(pos, node, clicker)
				if hbmod then	
					local sat = tonumber(hbhunger.SAT_MAX)
					local h = tonumber(hbhunger.hunger[clicker:get_player_name()])
					h = math.min(h + def.hunger)
					if h > sat then
						h = sat
					end
					hbhunger.hunger[clicker:get_player_name()] = h
					hbhunger.set_hunger_raw(clicker)
					minetest.sound_play("mindeca_eat", {
						pos = pos, gain = 0.7, max_hear_distance = 4})
					eatstate = math.min(eatstate + 1)
						if eatstate > 4 then
							minetest.set_node(pos, {name = "mindeca:item_cook_pie_tin"})
						else minetest.set_node(pos, {name = "mindeca:item_cook_pie_"..name..eatstate})
					end
				else
					local h = clicker:get_hp()
					h = math.min(h + def.hunger, 20)
					clicker:set_hp(h)
					minetest.sound_play("mindeca_eat", {
						pos = pos, gain = 0.7, max_hear_distance = 4})
					eatstate = math.min(eatstate + 1)

					if eatstate >= 4 then
						eatstate = 1
						minetest.set_node(pos, {name = "mindeca:item_cook_pie_tin"})
					else
						minetest.set_node(pos, {name = "mindeca:item_cook_pie_"..name..eatstate})
					end
				end
			end
		})
	end
end

for eatstate=2,4 do
	for name,def in pairs(mindeca.mpies) do
		minetest.register_node("mindeca:item_cook_pie_"..name..eatstate, {
			description = def.pie_desc,
			drawtype = "mesh",
			collision_box = {
				type = "fixed",
				fixed =	{-8/16, -8/16, -8/16, 8/16, -2/16, 8/16},
			},
			selection_box = {
				type = "fixed",
				fixed =	{-8/16, -8/16, -8/16, 8/16, -2/16, 8/16},
			},
			mesh = "mindeca_pie"..eatstate..".obj",
			tiles = {"mindeca_cook_pie_"..name..".png"},
			inventory_image = "mindeca_item_cook_pie_tin.png",
			groups = {oddly_breakable_by_hand = 1},
			drop = "mindeca:item_cook_pie_tin",
			sounds = default.node_sound_stone_defaults(),

		--Right Click function thanks to Blockhead and TenPlus
			on_rightclick = function(pos, node, clicker)
				if hbmod then	
					local sat = tonumber(hbhunger.SAT_MAX)
					local h = tonumber(hbhunger.hunger[clicker:get_player_name()])
					h = math.min(h + def.hunger)
					if h > sat then
						h = sat
					end
					hbhunger.hunger[clicker:get_player_name()] = h
					hbhunger.set_hunger_raw(clicker)
					minetest.sound_play("mindeca_eat", {
						pos = pos, gain = 0.7, max_hear_distance = 4})
					eatstate = math.min(eatstate + 1)
						if eatstate > 4 then
							minetest.set_node(pos, {name = "mindeca:item_cook_pie_tin"})
						else minetest.set_node(pos, {name = "mindeca:item_cook_pie_"..name..eatstate})
					end
				else
					local h = clicker:get_hp()
					h = math.min(h + def.hunger, 20)
					clicker:set_hp(h)
					minetest.sound_play("mindeca_eat", {
						pos = pos, gain = 0.7, max_hear_distance = 4})
					eatstate = math.min(eatstate + 1)

					if eatstate >= 4 then
						eatstate = math.min(1)
						minetest.set_node(pos, {name = "mindeca:item_cook_pie_tin"})
					else
						minetest.set_node(pos, {name = "mindeca:item_cook_pie_"..name..eatstate})
					end
				end
			end
		})
	end
end

User avatar
sirrobzeroone
Member
Posts: 593
Joined: Mon Jul 16, 2018 07:56
GitHub: sirrobzeroone
Contact:

Re: Can't figure out error in conversion of pies?

by sirrobzeroone » Post

Loading is always good much easier to crush bugs once it loads.

Noticed before you are setting eatstate on node reg, I've never tried to do that. I'd think it might actually register a global variable called eatstate on load but then the behaviour your seeing seems a little odd for that - although your not getting undefined variable error

Code: Select all

eatstate = math.min(eatstate + 1)
Blockhead wrote:
May be better to comment as I'm not familiar with hbmod code

just walking through the else line by line - more for me:

Code: Select all

-- get player current hp - yep
local h = clicker:get_hp()
local old_hp = h* -- see note lower down

-- just catching we don;t set health above 20
h = math.min(h + def.hunger, 20)

-- Set the players Hp and play cool eat sound
clicker:set_hp(h)
minetest.sound_play("mindeca_eat", {
pos = pos, gain = 0.7, max_hear_distance = 4})

-- depending on the pie registered eat state will end up between
-- 2 and 5 here as we set eatstate during pie reg
-- I don't think this is what you want reading the code lower down
-- I'm going t assume 1 slice = 1 hp restored try
-- I think you need to compare old hp total against new hp total 

local restored_hp = math.min(h - old_hp + 1)

-- I think your pie dishes run as 1 = full 2= 3/4, 3= 1/2 4 = 1/4
-- if the above correct the below should work
if restored_hp >= 4 then
	minetest.set_node(pos, {name = "mindeca:item_cook_pie_tin"})
else
	minetest.set_node(pos, {name = "mindeca:item_cook_pie_"..name..restored_hp})
end
The above code will probably work however it doesn't take into account pie_state ie did we start with a full pie or a half pie?

to do that you need pie_state which i think is what your eatstate was trying to do - the below should combine the two - note I can't test this so maybe a syntax error or bug somewhere - sorry :(

just thinking more I'm surprised the code worked at all, looking over the code again I think eatstate is being set as a global variable on register....edited the above to reflect that thinking not sure - sorry doing this as I go so apologies if it's a bit rambly

The below is just how I would write the else not saying it's the best way to go I'm pretty new to Lua as well, my programming knowledge can be summed up as enthusiastic amature :). The below does go step further and allows return of unused pie, I've been a bit verbose with comments to help explain my thinking.

Code: Select all

else
	-- get data metrics
	local hp = clicker:get_hp()

	-- convert eaten pie state to avaliable hp points as 
	-- pie1 = 4 and pie4 = 1
	-- you can do this in 1 line I left in two for easy
	-- readability.
	-- were I have 5 you can replace with a global table ref
	-- or you can add a value against the node meta on_place
	-- or you can add a value against the node reg
	local eat_state = tonumber(string.sub(node.name, -1))
	local pie_hp_max = 5 - eat_state
	
	-- eg
    -- local pie_hp_max = (mindeca.mpies[name].hunger + 1) - eat_state	
	-- local pie_hp_max = (minetest.registered_nodes[node.name].pie_hp +1) - eat_state
	
	-- the max allowed hp is stored in player properties I may
	-- have the name wrong really need to dump clicker/player 
	-- properties which I cant do at the minute so I set a fallback of 20
	-- increases mod portability across games
	local hp_max = clicker:get_properties().hp_max or 20 
	
	-- how hungry is our player
	local p_hunger = hp_max - hp
	
	-- how much pie are we going to use
	local pie_used = pie_hp_max - p_hunger
	
	-- first we used all of pie or potentially more then all the pie
	if pie_used <= 0 then
		
		minetest.set_node(pos, {name = "mindeca:item_cook_pie_tin"})
		
		clicker:set_hp(hp + pie_hp_max)
		minetest.sound_play("mindeca_eat", {
		pos = pos, gain = 0.7, max_hear_distance = 4})
		
	-- or we didn't eat all the pie
	else 
		-- gets the all of the pie_name except state number at the end
		local pie_name = string.sub(node.name,1,-2)
		local new_pie_state = 5 - (pie_hp_max - pie_used)
		minetest.set_node(pos, {name = pie_name..new_pie_state})
		
		-- only add hp == pie_used
		clicker:set_hp(hp + pie_used)
		minetest.sound_play("mindeca_eat", {
		pos = pos, gain = 0.7, max_hear_distance = 4})
	end	
	
	-- note in the above you could wrap the set_hp in math_min for safety
	-- clicker:set_hp(math.min(hp + pie_hp_max,hp_max))
	-- clicker:set_hp(math.min(hp + pie_used,hp_max))
end

Edit: didn't end up using old_hp removed it - missed when i proofed the code

Edit2: There is one hole in my code at least - thats if you try and eat pie and hp are full it'll actually loop through the else and replace the pie with the same pie - probably need a catch for that event especially if later you plan on allowing eat piece of pie get super run for 60 seconds etc.

User avatar
Blockhead
Member
Posts: 1602
Joined: Wed Jul 17, 2019 10:14
GitHub: Montandalar
IRC: Blockhead256
In-game: Blockhead Blockhead256
Location: Land Down Under
Contact:

Re: Can't figure out error in conversion of pies?

by Blockhead » Post

sirrobzeroone wrote:
Thu Aug 11, 2022 01:40
Loading is always good much easier to crush bugs once it loads.

Noticed before you are setting eatstate on node reg, I've never tried to do that. I'd think it might actually register a global variable called eatstate on load but then the behaviour your seeing seems a little odd for that - although your not getting undefined variable error
Ho ho ho, this is quite a pickle we've got ourselves in with Lua's more advanced functionality. Let's get down to some explanations.

eatstate is the loop variable, so it's not global, it's local as all loop variables are by default if not previously declared. But as you have noticed, it's referenced inside a function that will be called much later than eatstate would expect to exist. If you don't understand local and global scope already, the following is going to be hard to follow..

How can it be that this variable persists? Well, this variable is what is called in Lua an upvalue, which the relevant Programming in Lua chapter explains as an "external local variable". In lay terms we might say eatstate sticks around and is accessible in future calls to functions that use it. In technical terms, we say eatstate forms part of the closure of the anonymous function on_rightclick. A closure is a function and all the local variables encapsulated with it that are persistent across function runs. I don't perfectly understand the magic of where eatstate will live in memory, but it's kind of irrelevant for a Lua programmer. All you need to know is that Lua keeps track of variables in a smart way that will allow your closures to access them later. C actually has this kind of functionality through static variables that live inside functions.

You may have seen and used closures before without knowing what they are. They are common when writing a function that returns a function. For what it's worth, I didn't realise at first that a loop variable could be an upvalue for a closure either, because typically I use a function that uses its own local variables in a closure, and not a loop variable that appears at the top level, unindented. The other weirdness is that it's used as if it's constant in the first argument of minetest.register_node - well, the result of string concatenation means the string won't suddenly change, it's copied the value out.

One more important thing to understand, and this is key to the mindeca problems, there is one copy of the loop variable as an upvalue for each iteration of the loop. Here is your closures "homework" question which demonstrates this. Try to evaluate it on paper, run it with a Lua command line interpreter, check your answer, evaluate it again if you were wrong the first time. And yes, there is a little bit of typical exam question trolling with variable names.

Code: Select all

tfuncs = {}
for i=1,10 do
	local f = function(x)
		i = i + 1
		return string.format("%d x %d = %d", x, i, x*i)
	end
	table.insert(tfuncs, f)
end


for i=1,10 do
	for _, f in ipairs(tfuncs) do
		print(f(i))
	end
	print("---")
end

print("===")

print(tfuncs[1](5))
print(tfuncs[1](5))
print(tfuncs[1](5))
print(tfuncs[1](5))
print(tfuncs[1](5))
Okay, you can go and complete that exercise now. I'm sure that you will read the next section after doing your homework :)

...

So, what must we do to fix the problem? Because eatstate as used in the loop body will persist into our on_rightclick function, and is mutable, we must be careful ensure that it does not mutate (change value). That mutation is what is causing strange behaviours. What we have created cannot be considered mathematically to be a function - it produces different outputs for the same inputs, because eatstate is a hidden state inside the function (it also produces side effects, but that is beside the point).

Here is the problem area for when we have hbhunger installed - the solution is similar for when we do not. Also I have fixed the indentation again.

Code: Select all

					eatstate = math.min(eatstate + 1)
					if eatstate > 4 then
						minetest.set_node(pos, {name = "mindeca:item_cook_pie_tin"})
					else
						minetest.set_node(pos, {name = "mindeca:item_cook_pie_"..name..eatstate})
					end
Now instead use a local variable that copies eatstate but does not mutate it. Also I am removing math.min because there's no condition under which eatstate will not be an integer, and using tostring() on new_eatstate because I do not like the implicit conversion from number to string that Lua does.

Code: Select all

					local new_eatstate = eatstate + 1
					if new_eatstate > 4 then
						minetest.set_node(pos, {name = "mindeca:item_cook_pie_tin"})
					else
						minetest.set_node(pos,
							{name = "mindeca:item_cook_pie_"..name..tostring(new_eatstate)})
					end
There are a lot of other code cleanup issues left in the file as well, but this post is already long enough and this is the critical information.
/˳˳_˳˳]_[˳˳_˳˳]_[˳˳_˳˳\ Advtrains enthusiast | My map: Noah's Railyard | My Content on ContentDB ✝️♂

Icalasari
Member
Posts: 166
Joined: Tue Sep 23, 2014 05:29
IRC: Icalasari
In-game: Icalasari

Re: Can't figure out error in conversion of pies?

by Icalasari » Post

Whew boy, always wondered when my style of learning would turn and bite me

Will try following all this when it's not half an hour to midnight, but I do have a bit of confusion

Won't new_eatstate cause the pie to not follow the loop correctly? What's allowing the start to read new_eatstate as eatstate? Is it to do with tostring(...)?

User avatar
sirrobzeroone
Member
Posts: 593
Joined: Mon Jul 16, 2018 07:56
GitHub: sirrobzeroone
Contact:

Re: Can't figure out error in conversion of pies?

by sirrobzeroone » Post

Blockhead wrote:
Thu Aug 11, 2022 04:51
...
Thanks Blockhead, I found the above really interesting and informative as well :)

Icalasari
Member
Posts: 166
Joined: Tue Sep 23, 2014 05:29
IRC: Icalasari
In-game: Icalasari

Re: Can't figure out error in conversion of pies?

by Icalasari » Post

Alright, it's all working properly now, but I still can't quite understand why it's working now. Would rather not mark as solved until I can understand the why, since I am sure I will continue to have similar but not quite the same problems if I just accept it works

Code: Select all

tfuncs = {}
for i=1,10 do
	local f = function(x)
		i = i + 1
		return string.format("%d x %d = %d", x, i, x*i)
	end
	table.insert(tfuncs, f)
end


for i=1,10 do
	for _, f in ipairs(tfuncs) do
		print(f(i))
	end
	print("---")
end

print("===")

print(tfuncs[1](5))
print(tfuncs[1](5))
print(tfuncs[1](5))
print(tfuncs[1](5))
print(tfuncs[1](5))
The x and d I'm not getting here enough to even try on paper, for example, and I understand this helps explain some of this (also need to find a Lua line interpreter. Honestly, this thread has taught me that Lua isn't a weird, random language that is basically different with every game it's used on [Which I am sure probably explains a lot of why I have struggled with some things to begin with - I thought it was basically just a standardized file name for games that want to make their own psuedo language])

Guh not sure if I'm just so rusty from when I programmed on a TI or if it was just so drastically different from Lua that it's why I'm getting hung up so easily

User avatar
Skamiz Kazzarch
Member
Posts: 613
Joined: Fri Mar 09, 2018 20:34
GitHub: Skamiz
In-game: Skamiz
Location: la lojbaugag.

Re: Can't figure out error in conversion of pies?

by Skamiz Kazzarch » Post

A helpful resource I regularly make use of: https://plugins.geany.org/geanylua/luarefv51.html
Screenshot from 2022-08-12 14-59-44.png
Screenshot from 2022-08-12 14-59-44.png (35.95 KiB) Viewed 531 times


return string.format("%d x %d = %d", x, i, x*i)

%d here basically means: replace this with the next function argument, formatted as a decimal integer.

Icalasari
Member
Posts: 166
Joined: Tue Sep 23, 2014 05:29
IRC: Icalasari
In-game: Icalasari

Re: Can't figure out error in conversion of pies?

by Icalasari » Post

Ah, thank you Block!

Guess the next thing to do is to study the hell out of that resource. Hopefully it reduces a lot of confusion for me

Post Reply

Who is online

Users browsing this forum: No registered users and 1 guest