If statement is true, then assign a boolean and other related questions

Posted by Hidelensman on Mon 31 Oct 2022 12:28 AM — 7 posts, 18,706 views.

#0
Hi Nick and all,

I only have limited experience with Lua and want to know if the following situation is possible:

If a condition is met (or not met), then assign a boolean value to a variable.

My code as following (purpose is to check if players and mobs are in the set list then assign "fighting" is true/false to determine next action):

 
function check_player()
    local match = nil
    -- pplroom = false

    for k, v in pairs (players) do
      if string.match (Char_Name, k:lower ()) then
        match = k  -- remember match
        Note ("Warning, player " .. match .. " here.")
        pplroom = true
      else
        pplroom = false
      end -- if
    end -- for

end -- function


function check_mob()
    local match = nil

    for k, v in pairs (mobs) do
      if string.match (Char_Name, k:lower ()) then
        match = k  -- remember match
        Execute ("say " .. "Mob " .. match .. " here.")
        mobroom = true
      else
        mobroom = false
      end -- if
    end -- for

end -- function



I tried several times but in vain (the code can be executed while pplroom & mobroom are always false) and didn't find any related topic in the forum, thus I'd like to seek for your advice.

Thanks in advance.

P.S. I have some other questions regarding matching values in Lua table which are related to the code I posted here - will ask questions later.
Amended on Mon 31 Oct 2022 12:38 AM by Hidelensman
USA Global Moderator #1
The problem is that you don't stop looking through your tables when you find a match. Stick a return after both of your true assignments.


Programming advice follows:

Setting a non-local pplroom variable instead of returning pplroom looks like a bad practice given what these functions do. If your "pplroom = true" and "mobroom = true" had instead been "return true", you wouldn't have had this problem.

If you're looking for exact matches, then those comparisons are a poor use for string.match. "Char_Name == k:lower()" would make more sense in that case.

Also if you want exact matches then those loops could be reduced to single statements if the players and mobs tables were lowercased, because then you could just check if e.g. players[Char_name] exists.

If you really don't want exact matches, then ignore those last two.
Amended on Mon 31 Oct 2022 03:43 AM by Fiendish
#2
Thanks Fiendish - I'd like to further consult you on the 1st part.

Fiendish said:

The problem is that you don't stop looking through your tables when you find a match. Stick a return after both of your true assignments.


I probably know where you are coming from but could you give me an example on "stick a return after both of true assignments"?

Fiendish said:

Programming advice follows:

Setting a non-local pplroom variable instead of returning pplroom looks like a bad practice given what these functions do. If your "pplroom = true" and "mobroom = true" had instead been "return true", you wouldn't have had this problem.


Does that mean I need to "return pplroom" / "return mobroom" after checking if the Char_Name in my tables? Tried but pplroom and mobroom are shown as nil.

BTW, I like your suggestion on the exact match and single statement - already made adjustment accordingly. Thanks.
Amended on Mon 31 Oct 2022 05:00 AM by Hidelensman
Australia Forum Administrator #3
Quote:

I probably know where you are coming from but could you give me an example on "stick a return after both of true assignments"?



if string.match (Char_Name, k:lower ()) then
        match = k  -- remember match
        Execute ("say " .. "Mob " .. match .. " here.")
        mobroom = true
        return   --<-- HERE
      else
        mobroom = false
        return   --<-- HERE
      end -- if


But that doesn't totally make sense, because you would return on the first iteration. Probably more like:


function check_mob()
    mobroom = false
    for k, v in pairs (mobs) do
      if string.match (Char_Name, k:lower ()) then
        Execute ("say " .. "Mob " .. match .. " here.")
        mobroom = true
        return
      end -- if
    end -- for

end -- function


And to follow Fiendish's suggestion:


function check_mob()
    for k, v in pairs (mobs) do
      if string.match (Char_Name, k:lower ()) then
        Execute ("say " .. "Mob " .. match .. " here.")
        return true  -- match
      end -- if
    end -- for
    return false  -- no match
end -- function



Then you can just call it like this:


  if check_mob () then
    -- mob found
  else
    -- mob not found
  end -- if
USA Global Moderator #4
Nick Gammon said:
But that doesn't totally make sense, because you would return on the first iteration. Probably more like:

Yeah, only after the true assignments, not after the false assignments.


Hidelensman said:

I probably know where you are coming from but could you give me an example on "stick a return after both of true assignments"?
...
Does that mean I need to "return pplroom" / "return mobroom" after checking if the Char_Name in my tables? Tried but pplroom and mobroom are shown as nil.


function check_mob()
   for k, v in pairs(mobs) do
      if Char_Name == k:lower() then
         Execute ("say Mob " .. k .. " here.")
         mobroom = true
         return
      else
         mobroom = false
      end
   end
end


But I favor this version instead:

function check_mob()
   for k, v in pairs(mobs) do
      if Char_Name == k:lower() then
         Execute ("say Mob " .. k .. " here.")
         return true
      end
   end
end


mobroom = check_mob()


Or better yet:

function check_mob(which_mob)
   for k, v in pairs(mobs) do
      if Char_Name:lower() == k:lower() then
         return k
      end
   end
end


mobroom = check_mob()
if mobroom then
   Execute ("say Mob " .. k .. " here.")
end


Or better still because this lets you use only one function instead of two that do the same thing:

function find_in_list(find_what, the_list)
   for k, v in pairs(the_list) do
      if find_what:lower() == k:lower() then
         return k
      end
   end
end


mobroom = find_in_list(Char_Name, mobs)
if mobroom then
   Execute ("say Mob " .. mobroom .. " here.")
else
   pplroom = find_in_list(Char_Name, players)
   if pplroom then
      Note ("Warning, player " .. pplroom .. " here.")
   end
end

I assume there that Char_Name cannot be both a player and a mob.
Amended on Mon 31 Oct 2022 02:24 PM by Fiendish
#5
Wow nice - thanks Nick and Fiendish for these great replies.

Last night I based on Nick's suggestion to re-write the code as below and will try Fiendish's suggestion tonight:


function check_player()

    if players[Char_Name] then
       Note ("Warning, player " .. Char_Name .. " here.")
       return true
    end -- if

    return false

end -- function


function check_mob()

    if mobs[Char_Name] then
       Execute ("say " .. "Mob " .. Char_Name .. " here.")
       return true
    end -- if
    
    return false

end -- function



Another 2 questions want to consult you at this stage -
  1. I use a trigger to activate these functions and check if players/mobs are in the room, then kill the mobs; while if there are many mobs in the same room, the trigger will be fired many times, leading my char easily gets kicked out from the MUD - any good suggestions to only fire trigger once, after a mob killed, then fire the trigger again? I only think of disabling trigger then re-activating it after the mob killed
  2. I understood from other posts that "Simulate" could be used for trigger - Do you have any hints on this? I tried to replace the "say ..." command in my check_mob() function with Simulate but in vain. I know using "Simulate" here might not be ideal but just want to explore more possibilities.


Thanks.
Amended on Tue 01 Nov 2022 05:31 AM by Hidelensman
USA Global Moderator #6
Quote:
I only think of disabling trigger then re-activating it after the mob killed

It sounds like you have answered your own question then.

Quote:
I understood from other posts that "Simulate" could be used for trigger - Do you have any hints on this?

I don't understand what you're trying to accomplish here.