Array Question (Simple)

The place to post your WML questions and answers.

Moderator: Forum Moderators

Forum rules
  • Please use [code] BBCode tags in your posts for embedding WML snippets.
  • To keep your code readable so that others can easily help you, make sure to indent it following our conventions.
Post Reply
Syath
Posts: 13
Joined: November 29th, 2009, 6:07 pm

Array Question (Simple)

Post by Syath »

I've looked through the Wiki and can not find the answer to a bit of an issue I'm having.

I'm developing a scenario that will require an array to have roughly 21 values, and need to be able to shuffle the values of that array to completely randomize them, so no one will know what they are.

Is it possible with a simple function, or is there a complex function someone else has written that I can use?

Any help is appreciated as always :)
User avatar
Sapient
Inactive Developer
Posts: 4453
Joined: November 26th, 2005, 7:41 am
Contact:

Re: Array Question (Simple)

Post by Sapient »

I imagine something like the Fisher-Yates shuffle would be easy enough to implement in WML:

Code: Select all

#define SHUFFLE_ARRAY ARR
{VARIABLE n ${ARR}.length}
[while]
 [variable]
  name=n
  greater_than=1
 [/variable]
 [do]
  {VARIABLE_OP n add "-1"}
  {VARIABLE_OP k rand "0..$n"}
  [set_variables]
   name=temp
   to_variable={ARR}[$k]
  [/set_variables]
  [set_variables]
   name={ARR}[$k]
   to_variable={ARR}[$n]
  [/set_variables]
  [set_variables]
   name={ARR}[$n]
   to_variable=temp
  [/set_variables]
 [/do]
[/while]
#enddef
disclaimer: untested
http://www.wesnoth.org/wiki/User:Sapient... "Looks like your skills saved us again. Uh, well at least, they saved Soarin's apple pie."
Syath
Posts: 13
Joined: November 29th, 2009, 6:07 pm

Re: Array Question (Simple)

Post by Syath »

Thank you, I'll give it a try.

Another array question.


Why does FOREACH not work inside [message] to generate [options]?

Basically, I would like this to work, but it will not =/

Code: Select all

[event]
 name=turn 2


  [message]
   message=_ "The list of suspects"
   
 {FOREACH suspects s}
   [option]
    message=_"The $suspects[$s].name| is a suspect."
  [command]
   {SHOW $suspects[$s] $side_number} (example command)
  [/command]
  [/option]
 {NEXT s}
[/message]

[/event]

Edit: This code does work, but the values will not stay constant, some will be shuffled, removed, added to a different array, etc. This was to make sure that the array was accessible (it is):

Code: Select all

[event]
name=turn 2

  [message]
    message=_ "The list of suspects"

    [option]
      message=_"The $suspects[0].name| is a suspect."
    [/option]
    [option]
      message=_"The $suspects[1].name| is a suspect."
    [/option]
    [option]
      message=_"The $suspects[2].name| is a suspect."
    [/option]
    [option]
      message=_"The $suspects[3].name| is a suspect."
    [/option]
    [option]
      message=_"The $suspects[4].name| is a suspect."
    [/option]
    [option]
      message=_"The $suspects[5].name| is a suspect."
    [/option]

[/message]


[/event]


Variables are defined as such:

Code: Select all

{VARIABLE suspects[0].name "Fencer"}
{VARIABLE suspects[1].name "Bowman"}
{VARIABLE suspects[2].name "Spearman"}
{VARIABLE suspects[3].name "Mage"}
{VARIABLE suspects[4].name "Knight"}
{VARIABLE suspects[5].name "Thief"}
Syath
Posts: 13
Joined: November 29th, 2009, 6:07 pm

Re: Array Question (Simple)

Post by Syath »

Also attempted this, to no avail.

Code: Select all

[set_menu_item]
  id=smi_view_hand
  description=_"View your hand"

  [command]
	[message]
	  message=_ "Suspects!"
	    {VARIABLE i 0}
	    [while]
	      [variable]
		name=i
		less_than=5
	      [/variable]
	      [do]
		[option]
		  message=_"The $suspects[$i].name| is a suspect."
		[/option]
		{VARIABLE i (i+1)}
	      [/do]
	    [/while]
	[/message]
  [/command]
[/set_menu_item]
But, of course, this works:

Code: Select all

[set_menu_item]
  id=smi_view_hand
  description=_"View your hand"

  [command]
	[message]
	  message=_ "Suspects!"
	  side_for=$side_number
	    [option]
	      message=_"The $suspects[0].name| is a suspect."
	    [/option]
	    [option]
	      message=_"The $suspects[1].name| is a suspect."
	    [/option]
	    [option]
	      message=_"The $suspects[2].name| is a suspect."
	    [/option]
	    [option]
	      message=_"The $suspects[3].name| is a suspect."
	    [/option]
	    [option]
	      message=_"The $suspects[4].name| is a suspect."
	    [/option]
	    [option]
	      message=_"The $suspects[5].name| is a suspect."
	    [/option]
	[/message]
  [/command]
[/set_menu_item]

CONFUSING @.@ !!
User avatar
Sapient
Inactive Developer
Posts: 4453
Joined: November 26th, 2005, 7:41 am
Contact:

Re: Array Question (Simple)

Post by Sapient »

Not any WML can go anywhere! :eng:
{FOREACH} macro is just a shortcut for using [while] loops.
[while] loops belongs to the class of WML known as "ActionWML"
ActionWML goes inside events and commands.

What kind of WML can go inside [message]?
Read the description of [message] on the ReferenceWML.
ActionWML cannot be placed directly inside the [message].
It only takes [option] tags.

However, there is a special way to insert other tags from a variable!
That is [insert_tag].
It is not ActionWML; it can go anywhere that variables are understood (variables are understood anywhere that you care about for now).

So you can build your array of options with [set_variable] (or [set_variables]) and then insert it with [insert_tag].

Make sense?
http://www.wesnoth.org/wiki/User:Sapient... "Looks like your skills saved us again. Uh, well at least, they saved Soarin's apple pie."
User avatar
Ken_Oh
Moderator Emeritus
Posts: 2178
Joined: February 6th, 2006, 4:03 am
Location: Baltimore, Maryland, USA

Re: Array Question (Simple)

Post by Ken_Oh »

EDIT: Sapient beat me to it. Hope the example helps.
Syath wrote:Another array question.


Why does FOREACH not work inside [message] to generate [options]?
Because [while] doesn't go inside of [message].

What you need to do is use [insert_tag]. I do it a bunch in Wesband, but I'll try to boil it down for you really quick.

Code: Select all

#use foreach to make a list of the options you want

{FOREACH unit.inventory.potions i}
	[set_variables]
		name=sell_item_insert
		mode=append
		[value]
			message="the item variables for display go here, like $unit.inventory.potions[$i].name"		
			[command]
				{VARIABLE_OP unit.gold add $unit.inventory.potions[$i].value}
				[set_variables]
					name=potion_shop
					mode=append
					[insert_tag]
						name=literal
						variable=unit.inventory.potions[$i]
					[/insert_tag]
				[/set_variables]
				[clear_variable]
					name=unit.inventory.potions[$i]
				[/clear_variable]
			[/command]
		[/value]
	[/set_variables]
{NEXT i}

Code: Select all

#later, use the sell_item_insert variable in [insert_tag]

[message]
	speaker=narrator
	message="Sell which item?"
	[option]
		message="End selling."
		[command]
			{VARIABLE exit_shop 1}
		[/command]
	[/option]
	[insert_tag]
		name=option
		variable=sell_item_insert
	[/insert_tag]
[/message]
The end result is an option list that is varied in content and length, like in Wesband: http://files.dropbox.com/u/776904/wesband9.jpg
Last edited by Ken_Oh on December 17th, 2009, 11:11 am, edited 1 time in total.
User avatar
Sapient
Inactive Developer
Posts: 4453
Joined: November 26th, 2005, 7:41 am
Contact:

Re: Array Question (Simple)

Post by Sapient »

Ken, there appears to be a typo here?
variable=unit.inventory.potions[$i].
Your example may be more confusing than the original question, though. ;)
http://www.wesnoth.org/wiki/User:Sapient... "Looks like your skills saved us again. Uh, well at least, they saved Soarin's apple pie."
Syath
Posts: 13
Joined: November 29th, 2009, 6:07 pm

Re: Array Question (Simple)

Post by Syath »

:oops:

Code: Select all

[set_menu_item]
  id=smi_view_hand
  description=_"View suspect list"
  image=none


{FOREACH suspects s}
   [set_variables]
      name=current_suspects_list
      value=$suspects[$s].name
      mode=append
   [/set_variables]
{NEXT s}


  [command]
	[message]
	  message=_ "Suspects!"
	  side_for=$side_number
	        [insert_tag]
		    name=option
		    variable=current_suspects_list
		[/insert_tag]
	[/message]
  [/command]
[/set_menu_item]
or

Code: Select all

{FOREACH suspects i}
   [set_variables]
      name=suspects_insert
      mode=append
      [value]
         message="the item variables for display go here, like suspects[$i].name"      
         [command]
            [set_variables]
               name=suspects
               mode=append
               [insert_tag]
                  name=literal
                  variable=suspects[$i].name
               [/insert_tag]
            [/set_variables]
            [clear_variable]
               name=suspects[$i].name
            [/clear_variable]
         [/command]
      [/value]
   [/set_variables]
{NEXT i}

Code: Select all

	[message]
	  message=_ "Suspects!"
	  side_for=$side_number
	        [insert_tag]
		    name=option
		    variable=suspects_insert
		[/insert_tag]
	[/message]
:evil: :evil: :evil: :evil: :evil: :evil: :evil: :evil: :evil: :evil: :evil: :evil: :evil: :evil: :evil: :evil:

:oops:

Is there a way to code a scenario in nothing but Python? I'm trying hard, I've been working with WML about a week now and I really can see no logic in it @.@
User avatar
Sapient
Inactive Developer
Posts: 4453
Joined: November 26th, 2005, 7:41 am
Contact:

Re: Array Question (Simple)

Post by Sapient »

You can code it in Lua, but it's basically just a wrapper for coding in WML, so you would need to understand how the underlying WML works.

Your last attempt there was actually pretty close, so I'll revise it slightly:

Code: Select all

[event]
  name=side turn
  first_time_only=no
  [fire_event]
    name=update suspicions
  [/fire_event]
[/event]

[event]
  name=update suspicions
  first_time_only=no

{CLEAR_VARIABLE suspects_insert}

{FOREACH suspects i}
   [set_variables]
      name=suspects_insert
      mode=append
      [value]
         message="the item variables for display go here, like suspects[$i].name"      
         [command]
            [set_variables]
               name=accused
               mode=append
               [value]
                  name=$suspects[$i].name
               [/value]
            [/set_variables]
            [clear_variable]
               name=suspects[$i]
            [/clear_variable]
            [fire_event]
               name=update suspicions
            [/fire_event]
         [/command]
      [/value]
   [/set_variables]
{NEXT i}

[/event]

If that doesn't work, then tell me what version you're using and what went wrong.
http://www.wesnoth.org/wiki/User:Sapient... "Looks like your skills saved us again. Uh, well at least, they saved Soarin's apple pie."
silene
Posts: 1109
Joined: August 28th, 2004, 10:02 pm

Re: Array Question (Simple)

Post by silene »

Syath wrote:Is there a way to code a scenario in nothing but Python?
Python, no. But Lua is available. Here is the Lua version of your original code:

Code: Select all

[set_menu_item]
...
[command]
  [lua]
    code = <<
local options = { message = _ "Suspects!", side_for = side_number }
for k,v in ipairs(get_variable_array "suspects") do
  table.insert(options, { "option", {
    value = string.format(_ "%s is a suspect", v.name),
    { "command", { ... whatever you want to do on selection ... } }
  }})
end
wesnoth.fire("message", options)
>>
[/command]
[/set_menu_item]
The get_variable_array function is left as an exercise to the reader. (Or if your array is not stored at the WML toplevel but somewhere below, you can just use H.child_range(below, "suspects").)
Post Reply