Icon representing a recipe

Recipe: ScriptV2 Recipe Basics

created by GaryForbis

Profile


Name
ScriptV2 Recipe Basics
ID
100039
Shared with
Public
Parent
None
Children
None
Created on
October 26, 2014 at 04:46 AM UTC
Updated on
October 26, 2014 at 04:46 AM UTC
Description

Version 0.5. Learn the ScriptV2 Recipe language basics. This Recipe has a series of lessons to help you learn the language so you can read and modify existing recipes and write your own. Learn by doing.

Best for


Code


--ScriptV2 Basics v0.5 --lesson1 = 'done' --[[ ========================================================================== Lesson 1: Copy a recipe and modify it. You cannot save a modified version of someone else's recipe without fooling the system. You will find it helpful to keep the original recipe unmodified and save a copy of the recipe under a different name. This recipe is designed as a series of lessons with one or more tasks in each lesson. By the time you complete all the lessons you should be able to read and modify other people's recipes and create your own recipes. After you complete this lesson you will know how to save a copy of a recipe. To complete lesson 1: 1. Click on the "Edit Recipe" icon. (you've done that.) 2. Remove the two dashes from line two. (now it should look like: lesson1 = 'done' 3. Click on the "Save As" icon. 4. Append your name to the end of the Recipe Title. 5. Click on the "OK" icon. 6. Click on the "Close" icon. 7. Run your new recipe. ]] --[[ ========================================================================== Lesson 2: Identify Comments and Code. After you complete this lesson you will be able to recognize comments and distinguish comments from code most of the time. You will also recognize: 1. String literals. 2. A simple assignment statement. 3. One of the forms of the print statement. Comments are ignored by the computer. Code causes the computer to do something. Computers do things by executing the code. Programmers add comments in their programs to: 1. Document what the code does. 2. Disable code they don't want executed. The text you are now reading is inside a level 0 long comment. This comment started with the closest prior two dashes(-) followed by two open brackets([). This comment is ended by the first two close brackets(]) appearing later in the program. Short comments begin with two dashes not appearing inside a long comment or a string literal and end at the end of the line. A short comment is a very common way to disable a line of code. lesson 2 uses print statements to print in the Recipe Output window. Print statements and their parameters are part of the code. When a print statement is followed by a string literal the string is the print statement's parameter and the string will appear in the Recipe Output window. String literals will be defined shortly. There are several ways to open the Recipe Output window. Here is one: On the left side of the cookbook window the third icon from the bottom will display "Show recipe output" if you let the mouse pointer hover over it. Click on the "Show recipe output" icon. Here is another: While the recipe is running a window will appear. Click on the "Show Output" Icon. If you click on the "Save" icon in the recipe editor your changes to the recipe will still be here later even if you close the session or look at a different recipe. If you do not click on the "Save" icon your changes will be lost when you close foldit or open another recipe. If the computer doesn't know what it is being told to do it will print an error message in the Recipe Output window. Using the error message to help you fix your code is called "debugging". ]] -- Lesson 2, Task 1: Disable a print statement. -- run your recipe before and after you make your change to it. -- don't do multiple tasks at the same time because it makes debugging harder. -- Disable the following print statement by turning it into a short comment. print 'print a string literal.' --[=[ Lesson 2, Task 2: Temporarily enable a block of code inside a long comment. Several lines of code can be disabled by placing them inside a long comment. To temporarily enable a disabled block of code you can turn the start of a long comment into a short comment by placing one or more dashes in front of it or separating the brackets from the dashes. For instance by changing: --[[ the start of a level 0 long comment to one of these: ---[[ the start of a level 0 long comment -- --[[ the start of a level 0 long comment -- [[ the start of a level 0 long comment the start of the long comment becomes a short comment that can easily be restored to the original to once again disable the block of code. by putting -- before the ]], the -- starts a short comment when not embedded in a long comment. The end of a disabled block of code will commonly look like this: --]] Now temporarily enable the following disabled block of code. When you are done learning about short string literals again disable the block of code so it doesn't clutter the Recipe Output window. ]=] --[[ This is the start of a long comment as originally written. print 'Dashes like this -- are part of the string literal when inside quotes.' print "A short string literal begins and ends with either a single or double quote." print "A short string ends with the next occurrence of the character that started it." print "This means it's possible to include instances of the other character in a string." - this is either a short comment or the end of a long comment ]] --[[ Lesson 2, Task 3: fix a bug. Lua scans the program from left to right, top to bottom. It finishes what it's doing before moving on. This means comments and string literals can become entangled. That has happened here. First enable to part of the program inside the level 2 long comment and run the program. Then fix a bug by turning a level 0 long comment into a level 1 long comment. Then enable the part of the program inside the new level 1 long comment to print the string literal with the brackets inside it. note: you may need to close the editor window to see the recipe output window ]] --[==[ the start of a level 2 long comment --[[ the start of an embedded level 0 long comment print "a short string literal with ]] in it." --]] --]==] -- Lesson 2, Task 4: work with long string literals -- long strings follow the rules of long comments except without the leading dashes -- Play around with the long string literal to prove to yourself you understand it. --[==[ print [[ By tradition if the open string token is followed by a carriage return then that blank line doesn't print. Can you make two adjacent close brackets appear in the output of this print statement while still using a long string? ]] --]==] -- Lesson 2 Task 5: enable this assignment to the variable lesson2 to -- tell the program you've completed lesson2. -- lesson2 = 'done' --[[ ========================================================================== Lesson 3: The Building Blocks of a Lua Program. After you complete this lesson you will be able to understand most of what a Lua program is doing. Some things may still seem strange. Why the programmer wrote the program the way it is written may never be clear. The important part is making the program do what you want it to do. The smallest piece of Lua code is called a lexical unit or token. Lua is a free form, case sensitive language. This means that except to help identify one token from another spaces, tabs, and new lines don't make a difference to the code. Other than some special character tokens, tokens can be broadly categorized as names, keywords, and literals. Here are the special character tokens other than the ones used to denote the start and end of long strings and comments: + - * / % ^ # == ~= <= >= < > = ( ) { } [ ] :: ; : , . .. ... Here are the keywords: and break do else elseif end false for function goto if in local nil not or repeat return then true until while Names start with an underscore(_) or letter. Subsequent letters, digits, and underscores are part of the name. Names identify variables, table fields, and labels. Variables have values assigned to them. The default value is nil. Variables starting with underscore and continuing upper case letters are generally reserved for system variables. String literals have, for the most part been defined earlier as short strings and long strings. Numeric literals start with either a digit (0 through 9) or with the negation sign(-). Numeric literals have special form for scientific notation and hexadecimal notation. I'll not go into the gory details. If you care you can find them at: http://www.lua.org/manual/5.1/manual.html#2.1 A Lua program is composed of one or more statements. Statements include declarations, assignments, control structures, and function calls. A list of statements is called a block of code. The list of statements execute sequentially. While this even applies to control structures and function calls their execution causes other statements to be executed out of order or to be ignored. You will be given less direction as you progress. You are expected to remember to enable and disable code to try the examples. You will learn more by taking the opportunity to create your own variations of the examples. ]] --[[ Lesson 3, Task 1: Identify arithmetic expressions and types of numeric literals. An arithmetic expression is either a number or the result of an evaluation of an arithmetic operator. Numeric literals are either integers or real numbers. Integers do not have decimal points where real numbers do. Unless you encounter hexadecimal or scientific notation you don't need to worry about them right now. The normal arithmetic operators exist in Lua and have their normal meanings. The lexical tokens for these operators are: + - * / % ^ Most people recognize the first 4 but % and ^ may be new. % is the modulo operator and ^ is the exponentiation operator. The order in which operators are evaluated can be controlled by parentheses. Programmers often shorten that to parens. ]] -- enable and modify this code to help you understand and verify your -- understanding of arithmetic operators --[[ integers and real numbers and operations involving them. print ("3 + 2 is",3 + 2) -- this is the second form of a function call. print ("3 / 2 is", 3 / 2) print ("3.0 / -2 is", 3.0 / -2) print ("1 + (1 * 2) is", 1 + (1*2)) print ("(1+1) * 2 is",(1+1)*2) -- The order in which operations are evaluated is call precedence. -- If in doubt use parentheses. -- For more information see http://www.lua.org/manual/5.1/manual.html#2.5.6 --]] --[[ the modulo operator x = 0 repeat -- The start of a control structure -- that ends with the expression after the keyword 'until' x = x + 1 print (x," % 3 is",x % 3) until x == 10 -- == is a relational operator. --]] --[[ the exponent operator print("2 ^ 1 is",2^1) -- 2 raised to the 1st power print("2 ^ 2 is",2^2) -- 2 raised to the 2nd power (2 squared) print("2 ^ 3 is",2^3) print("2 * 2 is",2*2) print("2 * 2 * 2 is",2*2*2) print("") print("4 ^ 0.5 is",4 ^ 0.5) -- the square root of 4 --]] --[[ Lesson 3, Task 2: Identify string expressions There is only one operator for strings, the concatenation operator. To concatenate strings means to combine them and form one string. A string expression is either a string or the result of the concatenation operator. Enable this code and modify it to learn and verify your understanding of the concatenation operator ]] --[[ x, y = 'combine two ', 'strings together' -- assign values to two strings in one statement. print(x..y) print("2+2 is "..tostring(2+2)) -- print with one argument, a string expression print("2+2 is ",2+2) -- print with two arguments, a string literal and a numeric expression. --]] --[[ Lesson 3, Task 3: Identify boolean expressions The keywords true and false are the two boolean literals. The boolean negation operator is the keyword not. The result of a relational operator is a boolean. While the keywords and and or can be boolean operators, technically they are not. Enable this code and modify it to learn and verify your understanding of boolean expressions. ]] --[[ true and false are opposite boolean values. print ('not true is',not true) print ('not false is',not false) print ('not (not false) is',not (not false)) -- nil is a type upon itself but not nil returns true print('not nil is',not nil) --]] --[[ The relational operators == and ~=. -- == means equals. To be equal the expressions on both sides of the equals -- sign must be of the same type and value. print ('6 is of type',type(6)) print ('"6" is of type',type("6")) print ("6 == '6' is",6 == '6') -- type matters print ("6 == 6 is",6 == 6) print ("'this' == 'this' is",'this' == 'this') print ("'this' == 'This' is",'this' == 'This') -- capitalization matters print ("nil == false is",nil == false) -- ~= means does not equal. ~= returns the opposite of == -- Modify the prior print statements to verify. --]] --[=[ The relational operators >, >=, <, and <=. --[[ The expressions on both sides of these operators must be of the same type and be of types string or number. > means greater than. >= means greater than or equal to. < means less than. <= means less than or equal to. ]] x,y,z = 1,2,2 print(x,'<',y,'is',x < y) a,z,A,Z,zero,one,colon = 'a','z','A','Z','0','1',':' print(a,'<',A,'is',a < A) -- The way characters in a string compare is called the collating sequence -- Different systems have different collating sequences. print(a,'>',A,'is',a>A) print(a,'>',Z,'is',a>Z) print(z,'>',A,'is',z>A) --]=] --[[ Lesson 3, Task 4: Identify function definitions, function declarations, and function calls. A function declaration is a statement. A function definition is an expression. A function call can be either a statement or an expression. A function declaration has the form: function functionname (paramlist) body end A function definition has the form: function (paramlist) body end body is a chunk of code. This chunk of code doesn't execute until the function is called. paramlist is a set of names to which values will be assigned before executing the body of the function. Most function calls have one of these forms: functionname ( explist ) functionname string When a function is done executing so is the function call explist is a comma separated list of expressions. Before the body of a function is executed the list of expressions are evaluated and their values assigned to the names in the paramlist. Even if you use the very same names for what you think is the very same thing in the paramlist and outside the function the names in the paramlist reference different variables than ones with the same name that might exist outside the function. enable and modify this code to learn and verify your understanding of functions and calls to functions ]] --[[ A function's parameters have a limited life. This is called the scope of a variable. function func1 (x) print (x) x=10 end x = 4 func1 (x) print (x) --]] --[[ A function can return a list of values by executing a return statement function func2 (x) if type(x) == 'number' then return x + 1,type(x) else return nil,type(x) end print "After executing the return no more statements in the function are executed" end a,b = func2(5) print (a,b) a,b = func2('test') print(a,b) --]] --[[ The purpose of a function definition may not be clear right now. -- Programmers have strange habits. func3 = function () return "strange" end print (func3()) print (type(func3)) print (type(func3())) --]] --[[ Lesson 3, Task 5: Identify the logical operators and control structures Lua has 8 basic types of values. You've seen five of them: nil, boolean, number, string, and function. Of the three remaining you will only see the value type table in foldit. Tables will be explained in the next lesson. I mention them here because the logical operators aren't all that logical and a value of type table will be used in the for loop. For now you just need to recognize a table definition, constructor, begins with a open brace({) and ends with a close brace (}). The three logical operators are: and -- so called conjunction operator -- returns the first value if nil or false -- otherwise returns the second. or -- so called disjunction operator -- returns the first value if not nil or false -- otherwise returns the second. not -- so called logical negation operator -- returns true if the value following it is nil or false -- otherwise returns false. There is one more operator not discussed in this lesson, the length operator #. I will discuss it in the next lesson. I'll not discuss the order in which operators are evaluated. If you care read http://www.lua.org/manual/5.1/manual.html#2.5.6 I prefer you use parentheses to indicate order where there is any question. The control structures are: if statement -- Conditionally execute a block of code. for loop -- Execute a block of code a fixed number of times -- or over a set of indexes into a table. repeat loop -- Execute the same block of code until some condition is met. while loop -- Execute the same block of code while some condition exists. Enable the following code and modify it to learn and verify your understanding ]] --[[ The and operator print ('1 and 2 is',1 and 2) print ("0 and 'a' is",0 and 'a') -- Zero is a number. it is neither false nor nil. print ('0 and false is',0 and false) print ('false and 5 is',false and 5) ]] --[[ The or operator print (type(x)) -- type is a predefined function print ("x or 'x is not assigned a value' is",x or 'x is not assigned a value') x = x or 'x is assigned a value' print ("x or 'x is not assigned a value' is",x or 'x is not assigned a value') x = x or "x is assigned a value if one wasn't already assigned" print ("x or 'x is not assigned a value' is",x or 'x is not assigned a value') print ("x or nil is",x or nil) print (type(x)) --]] --[[ the not operator has previously been defined. this is a review print ("not aNamedVariable is",not aNamedVariable) aNamedVariable = 'now it has a value assigned' print ("not aNamedVariable is",not aNamedVariable) --]] --[[ the if statement x = 5 if x then -- type and tostring are predefined function print('The value of x is the '..type(x)..': '..tostring(x)) end if y then print('The value of y is the '..type(y)..': '..tostring(y)) else print("y has the default value "..type(y)) print("so assign y = '5'") y = '5' end if x == y then print('x and y are of the same type and have the same value') elseif type(x) == type(y) then print('x and y are both of type '..type(x)..'\nbut have different values') else print ('A '..type(x).." just isn't equal(==) to a "..type(y)) if (type(x)=='number') and (type(y)=='string') then -- an embedded if statement if (tostring(x) == y) then print("When x is converted to a string\nit has the same value, ('"..y.."') , as y") end -- you can include as many elseif clauses as you want elseif (type(x)=='string') and (type(y)=='number') then if (x == tostring(y)) then print("When y is converted to a string\nit has the same value, ('"..x.."') , as x") end end end --]] --[[ The for loop There are two forms of for loops for name = startvalue, endvalue, step do block end -- step is optional it defaults to 1 for namelist in iterator do block end -- iterator is a special type of function whose explanation is beyond the -- scope of this lesson. The iterator ipairs will be used in example code. ]] --[[ the variable named in the for statement is local to the for statement y = 5 for x = y-1, y+1 do print ('inside the for loop x is',x) end print ('outside the for loop x is',x) --]] --[[ when step is negative the loop stops when name is less than or equal to the endvalue for a = 1, -10, -10 do print (a) b = a -- even though a has a local scope other variables needn't be local end print ('outside the loop b is ',b) --]] --[[ the second variety of for loop aTable={'red','white','blue'} for place,color in ipairs(aTable) do print(color,'is in position',place) end --]] --[[ the repeat loop repeat print "Press a button" a = (a or 0) + 1 -- When a variable is declared local it's scope is the block of code in which it is declared. -- A variable may be assigned a value when it is declared local x = dialog.CreateDialog('Repeat loop?') -- in this case x is a special type of table. x.l = dialog.AddLabel('You have been through the loop '..tostring(a)..' time(s).') x.b1 = dialog.AddButton('Repeat',1) -- x.b1 is a named field within the table. x.b2 = dialog.AddButton('Quit',0) -- dialog is also a special table called a library y = dialog.Show(x) -- if you "x" out of the box it returns 0 print ("dialog.Show(x) returned",y) until y == 0 -- quit when y is 0 print("outside the loop a is",a) print("outside the loop y is",y) print("outside the loop x is",x) --]] --[[ the while loop, the do statement, and the break statement The while loop has this form: while expression do block end The block of code executes as long as the expression is not nil or false. There is a statement called a do statement. It has the form: do block end The keyword do in the while statement is part of the while statement and not the start of a do statement. You can exit a for, repeat, or while loop early by using the break statement. You cannot use the break to exit a do statement. The do statement is used to limit the scope of a variable. ]] --[[ this for and while loop produce the same results except for the scope of the variables print 'The for loop example' for x = 1, 3 do print(x) end print ('The value of x is',x) -- the scope of x is the for loop print 'The while loop example' x = 1 while x <= 3 do print(x) x=x+1 end print ('The value of x is',x) print 'The while loop equivalent to the for loop' print 'using a do statement and a local variable' x = nil do local x = 1 while x <= 3 do print(x) x=x+1 end end print ('The value of x is',x) --]] --[[ the use of a break statement do local a, x while true do x = (x or 11) - 1 print (x) if x == 1 then print "abort!" a = 'That was close.' break -- this breaks out of the while loop end a = 'still counting' end print (a) print ('We stopped counting at',x) end if a then -- a was defined as local to the do statement print ("a has value",a) end --]] -- Lesson 3, Task 6: Indicate Lesson 3 is done, Yipee! --lesson3 = 'done' --[[ There are a few more language constructs. You won't see them very often. If you run into something you don't know and want to know find out what it means you can look it up at http://www.lua.org/manual/5.1/manual.html ]] --[[ ========================================================================== Lesson 4: Working with Tables. Tables are the primary way of grouping objects into a collection. A table constructor is an expression so can appear on the right side of a variable assignment. The Lua manual formally defines a table constructor this way: tableconstructor ::= { [fieldlist] } fieldlist ::= field {fieldsep field} [fieldsep] field ::= [ exp ] = exp | Name = exp | exp fieldsep ::= , | ; Programmers learn this notation or variants of it called Backus Normal Form or BackusNaur Form. In this case items inside a pair of brackets are optional. Items inside parentheses are optional and can be repeated. Items inside quotes are required. Items separated by pipes are alternatives one of which must be selected. This will become clear as the lesson progresses. ]] --[[ Lesson 4, Task 1: Identify a sequence and the length operator A sequence is the portion of the table with sequential counting number indexes without a gap. The normal way to describe a sequence is by not assigning index values. ]] --[[ a normal sequence table x = {'Red','White','Blue'} -- assign the name x to a sequence table. print 'Using the length operator' for i=1,#x do -- use the length operator to find the length of the sequence. print(x[i]..' is a color') end print 'Using the ipairs iterator' for i,v in ipairs(x) do print ('x['..tostring(i)..'] is',x[i]) end --]] --[[ a sequence table with nil values x = {'Ball',3,'Blue',nil,4.2} -- assign the name x to a sequence table. print 'Using the length operator on a sequence' for i=1,#x do -- use the length operator to find the length of the sequence. print('x['..tostring(i)..'] is',x[i]) end -- ipairs stops at the first nil value in counting number indexes print 'Using the ipairs iterator' for i,v in ipairs(x) do print ('x['..tostring(i)..'] is',x[i]) end -- pairs ignores nil values print 'Using the pairs iterator' for i,v in pairs(x) do print ('x['..tostring(i)..'] is',x[i]) end --]] --[[ an advanced topic related to the length operator and sequences x = {'Ball',3.1,'Blue',nil,4.2} print 'normal behavior' for i=1,#x do -- use the length operator to find the length of the sequence. print('x['..tostring(i)..'] is',x[i]) end -- assigning nil to an index in the a sequence whose indexes haven't been modified x[3]=nil print 'normal assignment inside the sequence' for i=1,#x do -- use the length operator to find the length of the sequence. print('x['..tostring(i)..'] is',x[i]) end -- attempting to modify the size of the sequence after declared cause strange behaviors print 'extending a sequence containing a nil value' table.insert(x,'insert at end') -- inserts at the end of the sequence for i=1,#x do -- use the length operator to find the length of the sequence. print('x['..tostring(i)..'] is',x[i]) end for i=1,5 do -- the end of the sequence is #x+1 but what is #x table.insert(x,'test'..tostring(i)) end print 'after 5 inserts' for i=1,#x do -- use the length operator to find the length of the sequence. print('x['..tostring(i)..'] is',x[i]) end -- attempting to assign nil to an index in the sequence after modifying its declared indexes -- I cannot explain this behavior. If you can figure it out let me know. print 'assigning nil after extending a sequence' x[3]=nil -- inside the originally declared indexes x[7]=nil -- outside the originally declared indexes --x[8]=nil -- try running with this line disabled and with it enabled for i=1,#x do -- use the length operator to find the length of the sequence. print('x['..tostring(i)..'] is',x[i]) end --]] --[[ Lesson 4, Task 2: Work with tables other than sequences. Tables are more generic than a sequence table. You can assign a value to a name or other index. The contiguous set of counting number indexes still work as though a sequence. During a table declaration values not assigned to a specific index are assigned sequentially to the counting numbers starting with 1. This happens even when you have previously assigned a value to the counting number index Try various tests to make sure you understand tables, the length operator when applied to tables, and how to index a multi-dimension table. ]] --[[ x = { [2]='Red', [3]='White', [1]='Yellow', grey='Grey', -- this might help explain what the length operator is really doing. [5]='Orange', ['members']=function() for i,v in pairs(x) do print('index',i,'has value',v) end end, 'Blue', -- this is the first value not assigned assigned to a specific index list={4,3,nil,1} } print 'working with the "sequence"' for i=1,#x do -- use the length operator to find the length of the sequence. print(x[i]..' is a color') end -- When a string index conforms to the form of a name one can use "dot" notation -- even though it was defined or assigned using an index notation. x.members() -- notice the way the print statement handles functions and tables as values? -- The sequence is still identified by the contiguous set of counting numbers -- even though some where specifically identified print ('The sequence has length '..tostring(#x)) x[4]='Yellow' print ('Now the length is '..tostring(#x)) -- list is a table within a table. You can pass through it just like any other table. for i = 1,#x.list do print('x.list['..tostring(i)..'] is '..tostring(x.list[i])) print('x.["list"]['..tostring(i)..'] is '..tostring(x["list"][i])) end --]] --[[ an advanced topic, a formatted print of a two dimensional table -- there shouldn't be much call for this in foldit. x={ -- declare the table as a sequence of sequences {'a', 'b', 'c', 2}, {'d', 'e', 'f', -3}, {'g', 'h', 'i', 14.5} } for i=1,#x do local s = ' ' for j=1,#x[i] do s=s..string.format('%-5s',x[i][j]) -- format a string as a left justified 5 character string end print (s) end print ' ' for i=1,#x do -- unpack returns a list of the table values print(string.format(' %-2s%-4s%5s%% : % 8.2f',unpack(x[i]))) end -- formatting patterns, default is right justify. -- %[flags][width][.precision]specifier -- flags: - means left justify, + means always show sign, space means allow space for minus sign -- specifiers: s means string, d means decimal, f means float. (There are more but seldom used.) -- You must have as many additional parameters as you have formatting patterns in the first parameter. -- %% inserts a % where it appears. other characters are copied to the output. ]] --[[ Lesson 4, Task 3: Track down the standard libraries Lua has several standard libraries defined at http://www.lua.org/manual/5.1/manual.html#5 The Foldit implementers have restricted access to some of them and to some of the basic library. The basic library functions aren't inside a table. If you see a function call and you don't find a definition for the function then it is likely part of the basic library. In addition to the basic library the following libraries are collected into tables called packages: table name -- Library coroutine -- coroutine library package -- package library string -- string manipulation table -- table manipulation math -- mathematical functions bit32 -- bitwise operations io -- input and output os -- operating system facilities debug -- debug facilities ]] --[=[ basic={ -- the basic library functions are not declared inside a table _G=_G, -- the left side is the named index in the basic table _VERSION=_VERSION, -- the right side is the value of the named object if it exists assert=assert, collectgarbage=collectgarbage, dofile=dofile, error=error, getfenv=getfenv, getmetatable=getmetatable, ipairs=ipairs, load=load, loadfile=loadfile, loadstring=loadstring, next=next, pairs=pairs, pcall=pcall, print=print, rawequal=rawequal, rawget=rawget, rawset=rawset, select=select, setfenv=setenv, setmetatable=setmetatable, tonumber=tonumber, tostring=tostring, type=type, unpack=unpack, xpcall=xpcall } libraries={ coroutine=coroutine, -- to the left of the = sign is the named index package=package, -- to the right is the name of a table uses as a library string=string, table=table, math=math, bit32=bit32, io=io, os=os, debug=debug } print('Foldit implements lua version '.._VERSION..'.\n') -- \n means new line for i, v in pairs(libraries) do if v then print ('the library '..i..' is at least partially implemented.') end end print [[ The implemented functions or named values are: ]] for i, v in pairs(libraries) do if v then for i2, v2 in pairs(v) do print (' '..i..'.'..i2) end end end for i, v in pairs(basic) do if v then print (' '..i) end end --]=] --lesson4='done' --[[ ========================================================================== Lesson 5: The Foldit Libraries. You can get more information by pressing the help button. also http://foldit.wikia.com/wiki/Foldit_Lua_Functions Some of the older recipes use the old foldit functions. You will need to rely upon the wiki to figure them out. Look at the code inside recipes you like. Copy the portions you especially like into your own recipes. You will find the easiest way to start writing a recipe is to first outline it in comments then add the code to cause the computer to do what you've outlined. I've found many of my bright ideas for recipes didn't pan out. Don't be discouraged. You learn from these failures by analysing why they didn't work. I will cover the foldit functions in more detail in another recipe. ]] -- help() --lesson5='done' --[[ ========================================================================== Lesson 6: Parting Thoughts. Let me know what you think and how I can make this more useful for you. Let me know if you don't think it of value at all. my username is GaryForbis. Send me a message. This recipe is about 1,000 lines long. Most of the time I used notepad++ to edit it. It was much easier to find the errors that way as well. You can get a copy at http://notepad-plus-plus.org/resources.html You can copy the recipe by pressing alt-c. You can cut the recipe by pressing alt-x. You can paste into the recipe editor by pressing alt-v. I set my notepad++ Language to lua. I set my notepad++ Settings,preferences tab setting for lua to 2, replacing by space. I set my notepad++ Edit, EOF Conversion to UNIX/OSX Format. I save my recipe on disk with the lua extension. I make major changes to my recipe I cut the recipe from the recipe editor. I then copy my recipe from notepad++ and paste it into the recipe editor. If I make minor changes, such as fixing syntax errors, I will make them in the recipe editor then copy my recipe back into notepad++. The line numbers in the recipe output window are easy to find in notepad++. ]] lesson6='done' --[[ ========================================================================== The following is the part of the program that causes the dialogue boxes to be displayed. You should be able to read and understand this code once you complete all of the lessons. If you cannot you might want to review the lessons. ]] intro=intro or {} -- this says define intro as a table if it isn't already. intro.Title = 'ScriptV2 Basics' intro.Version = '0.5' -- 2014-10-25 intro.Author = 'Gary Forbis' intro.lesson=intro.lesson or {} intro.lesson[1]={ "Copy a recipe and modify it.", -- lesson title lesson1, -- status { "Be brave "..user.GetPlayerName()..".", "You can do the exercises.", '', 'ScriptV2 recipes use the Lua programming language.', "To the right of the recipe's name are the icons:", ' "Cut Recipe", "Edit Recipe", and "Run Recipe".', '', 'To complete lesson 1:', '1. Click on the "Edit Recipe" icon.', '2. Remove the two dashes from line two.', '3. Click on the "Save As" icon.', '4. Append your name to the end of the Recipe Title.', '5. Click the "OK" icon.', '6. Click on the "Close" icon.', '6. Run your new recipe.' } } intro.lesson[2]={ 'Identify Comments and Code.', lesson2, { 'The computer ignores comments and executes code.', 'Programmers add comments in their programs to:', '1. Document what the code does.', "2. Disable code they don't want executed.", '', 'Lua has multle levels of comments.', 'Excluding some special rules covered later:', '1. Everything to the right of -- is a comment', ' called a short comment.', '2. Everything between --[[ and ]], including --', ' is a comment called a level 1 long comment', '3. Everything between --[=[ and ]=], including', ' --, --[[, and ]] is a comment called a level 2', ' long comment.', 'Add additional = between opening and closing', 'brackets for deeper levels of long comments.', '', 'Everything else is code.' } } intro.lesson[3]={ 'The Building Blocks of a Lua Program.', lesson3, { 'Lua scans the program text, ignoring comments,', 'and breaks it into tokens, lexical elements,', 'acording to s formal grammer.', '', 'Except to separate one token from another spaces,', 'tabs, and new lines are ignored.', '', 'Tokens are broadly categorized as names, keywords,', 'literals, and special character tokens.', '', 'Tokens are combined to form statements.', 'Statements are broadly categorized as assignments,', 'declarations, function calls, and control structures.', '', 'Statements are combined into lists called blocks', 'of code where the totality of all statements is', 'the program.', '', 'These things will be explained in more detail', 'as you complete the Lesson 3 tasks.' } } intro.lesson[4]={ 'Working with Tables.', lesson4, { 'Tables are a set of indexed values.', 'They are useful for defining lists and other', 'collections such as library packages.', '', 'A table constructor starts with { and ends with }', 'and may contain zero or more expressions along', 'with an optional index to which the expression is', 'assigned. Table fields appearing in the constructor', 'are separated by either a comma or a semicolon.', "When the index isn't given sequential numeric indexes,", 'starting with 1, are assigned to field expressions.', '', 'A table field is referenced by the value of an', 'expression appearing between [ and ]. If the', 'index is a string conforming to definition of a', 'name the field can referenced using the "dot"', 'notation. x.y and x["y"] reference the same field.', 'On the other hand, x[2] and x["2"] reference', 'different fields.' } } intro.lesson[5]={ 'The Foldit Libraries.', lesson5, { 'Prior to ScriptV2 the Foldit functions were jumbled', "in with the basic Lua functions. That's not a good", 'idea. While those functions still exist there are', 'replacements grouped into library packages.', '', 'You can see a cursory definition of the functions', 'by pressing the help button on the recipe editor.', '', 'The tables for the various foldit packages are:', 'absolutebest, band, behavior, contactmap,', 'creditbest, current, dialog, freeze, puzzle,', 'recentbest, recipe, rotamer, save, scoreboard,', 'selection, structure, ui, undo, and user.' } } intro.lesson[6]={ 'Parting Thoughts.', lesson6, { 'Lessons 5 and 6 are stubs right now.', "I'm hoping for some feedback to help me improve", 'this recipe or find out no one wants it.', '', 'Send me your thoughts. My Foldit username is', 'GaryForbis' } } -- showLesson displays the lesson outline for lessonNo -- It returns a number telling doLessons what to do next. function intro.showLesson(lessonNo) -- convert lessonNo to a string once and use many times. local lessonNoS = tostring(lessonNo) -- The structure of entries in intro.lesson is local Title = intro.lesson[lessonNo][1] -- a string local Status = intro.lesson[lessonNo][2] -- a string local Text = intro.lesson[lessonNo][3] -- a table of strings -- now start building the dialogue box local dlg=dialog.CreateDialog('Intro to Lua: Lesson '..lessonNoS) dlg.lb1 = dialog.AddLabel("Lesson "..lessonNoS..": "..Title) dlg.lb2 = dialog.AddLabel('') --[[ I don't know why you have to assign labels to named indices in the dialogue box's table. This does that for an arbitrary number of lines in the table at intro.lesson[lessonNo][3] ]] for i = 1, #Text, 1 do dlg["l"..tostring(i)] = dialog.AddLabel(Text[i]) end dlg.le1 = dialog.AddLabel('') if Status ~= 'done' then -- the following line isn't appropriate if you reviewing a prior lesson. dlg.le2 = dialog.AddLabel('Quit the recipe and edit it to complete lesson '..lessonNoS..'.') elseif lessonNo < #(intro.lesson) then -- but if you are reviewing prior lessons then add the 'Next' button dlg.next = dialog.AddButton('Next',lessonNo+1) end dlg.review = dialog.AddButton('Review',-1) dlg.quit = dialog.AddButton('Quit',0) return dialog.Show(dlg) end -- preface displays an outline of the process. -- it returns a number telling doLessons what to do next function intro.preface() local Text = { intro.Title, 'Version '..intro.Version..' By '..intro.Author, '', 'This recipe is designed to teach you how to', 'read LUA code sufficiently well to copy and', "modify someone else's Lua recipe and to start", 'building your own recipes.', '', 'You learn by modifying a copy of this recipe.', 'The steps are divided into lessons. Each lesson', 'has one or more tasks for you to do.', '', 'You will need to open the Recipe Output window', 'so you can see the effects of your lessons.', 'To open the Recipe Output window click on the', '"Show Output" Icon.', '', 'To get started press Lesson 1.', 'To see a list of the lessons press Review.' } local dlg=dialog.CreateDialog(intro.Title) for i = 1, #Text, 1 do dlg["l"..tostring(i)] = dialog.AddLabel(Text[i]) end dlg.le1 = dialog.AddLabel('') dlg.next = dialog.AddButton('Lesson 1',1) dlg.review = dialog.AddButton('Review',-1) dlg.quit = dialog.AddButton('Quit',0) return dialog.Show(dlg) end -- display the review dialogue box. function intro.review(priorLesson, maxReview) local nextLesson = priorLesson + 1 if nextLesson > maxReview then nextLesson = 1 end local dlg = dialog.CreateDialog('Intro to Lua: Review') for i, lesson in ipairs(intro.lesson) do dlg['l'..tostring(i)] = dialog.AddLabel('Lesson '..tostring(i)..': '..lesson[1]) end dlg.r0 = dialog.AddLabel('') if maxReview > 1 then dlg.r1 = dialog.AddLabel('Select the number of the lesson to review.') dlg.r2 = dialog.AddSlider("Lesson:",nextLesson,1,maxReview,0) dlg.bs = dialog.AddButton('Select',1) dlg.bq = dialog.AddButton('Quit',0) if dialog.Show(dlg) == 0 then return 0 else return dlg.r2.value end else dlg.bs = dialog.AddButton('Lesson 1',1) dlg.bq = dialog.AddButton('Quit',0) return dialog.Show(dlg) end end -- The outer loop that controls which dialogue box to display. function intro.doLessons() -- find the first lesson not marked done. local currentLesson = 1 while (intro.lesson[currentLesson][2] == 'done') and (currentLesson < #intro.lesson) do currentLesson = currentLesson+1 end -- you can't review lessons beyond the one you are currently doing. local maxReview = currentLesson local priorLesson = currentLesson if currentLesson == 1 then currentLesson = intro.preface() end while currentLesson ~= 0 do if currentLesson == -1 then currentLesson = intro.review(priorLesson, maxReview) else priorLesson = currentLesson currentLesson = intro.showLesson(currentLesson) end end end intro.doLessons() -- this is the code the dialogue boxes to be displayed.

Comments


GaryForbis Lv 1

I figured by the end people would be tired of the foldit editor and were ready to use notepad++

Do you think I should make that lesson 2 instead?

GaryForbis Lv 1

I figured by the end people would be tired of the foldit editor and were ready to use notepad++

Do you think I should make that lesson 2 instead?

GaryForbis Lv 1

print ('6 is of type,type(6))
print ('"6" is of type,type("6"))

should have been:

print ('6 is of type',type(6))
print ('"6" is of type',type("6"))

I was having a hard time making sure I fixed the bugs in the right place. I would do some editing in the foldit editor then repeat the changes in notepad++. I should follow my own advise and save the working copy in a different named recipe then only update the original when I'm completely done. Developing the code while protecting the user experience of it was more trouble than I had expected.

I'll fix the error and release a new version. It wasn't on purpose. I only intended one bug and I said it existed.

I'm hoping people will introduce their own errors as they modify the code and can look at the output knowing their errors are in the code they changed.

GaryForbis Lv 1

Thanks. I have released a new version with these bugs fixed.

Let me know if there are areas I could improve.
Also, please suggest any areas I should cover but didn't.

Bruno Kestemont Lv 1

Whriting in the foldit editor is better for the user (it's quite simple to jump from the editor to the recipe and come back, after some time, we do it quick).

But as I cannot type "[" in the editor, neither select and copy it in order to paste it, I suppose I'm not the only one. But frankly said, I don't find very important to type the multiple level comments back. Possible solutions:

1) May be you can simply delete the suggestion to type them back when the exercise is done?

2) Indeed, making the editor problem lesson 2 is a solution. But it's quite heavy and discouraging to be obliged to download something in order to learn further.

3) or say this possible problem in a note in lesson 2, and preparing it since lesson 1, something like:

In lesson 1, when explaining how to save the personal copy of the recipe, suggest to save as "ScriptV2 Recipe Basics-Your Name -Lesson1" and do the same for each lesson.

and add a note in lesson 2:

"Note: the Foldit editor is limited - If you experience problems typing special characters like "[" from your national keyboard, type this character to an external text editor and copy-paste it here or just don't type it back. You can also always recover the latest recipe you saved, like the version saved in lesson 1. I'll explain much more convenient ways for editing recipes in lesson 6 (using free script editors).

btw, I'll right a feedback to Foldit team on the Foldit editor.

GaryForbis Lv 1

Thanks again for the feedback.

I change long comments into short comments by putting a space between the dashes and the brackets.

–[[ this is a long comment
–]]

– [[ these are two short comments
–]]

the point of putting the two dashes in front of the ]] is so one doesn't have to touch that line when enabling the code. I find it easier to add a space between the – and [[ rather than delete the [[.
That's definitely true when dealing with higher level long comments.

Turning
–[===[ wow I need to fix this code

into

– [===[ wow I need to fix this code

lets one remember what it took to disable the code where deleting the brackets (and equal signs) does not. One could even write this:

– enable this code temporarily –[===[ wow I need to fix this code

I definitely need to explain this better.

Here's some more interesting examples:

—[[ this is a short comment because the third character is a dash.
–[ this is a short comment because the second [ is missing.

You don't need to type the [ back in if you don't remove it.
Do you know why you can't type the bracket in the foldit editor?
Are you using it as a hot key or does your keyboard require a special set of keystrokes to produce it?

I definitely want to discuss ways around this in my script, including the possibility of finding text somewhere else and pasting it into one's program at the cursor. The intent is to keep the changes simple so one doesn't need to use notepad++ or some other editor to learn lua.

Your feedback is definitely quite valuable.