1
Concept Lua API 2 (Draft 0.6)
5
C1 - Object Based Syntax (coded - besides lines starting with a ".")
6
------------------------
8
The new API provides successor functions for all basic functions of the
9
old API with simplified names and arguments. (As the naming of the
10
successor functions is not yet fixed just a few examples are listed. This
11
set of functions will be completed to ensure that all previous styles of
12
level programming are supported in the API as well).
14
The following example based description explains the idea of the
15
new object based syntax additions:
19
Any system object or function is addressable as "sysname" and "en.sysname"
23
position - a position within the world that can be described by an
25
object - an Enimga object like a stone, item, floor, rubberband,...
26
world - a singleton type for the world that contains all objects
27
namedobjects - a singleton type for the repository of all named objects
28
group - a list of objects
29
tile - a description of objects at a common grid position (floor,
31
tiles - a singleton type for the repository of all tile instances
33
Special objects given at init:
35
wo world with map and global attributes of type <world>
36
no named object repository of type <namedobjects>
37
ti tile template repository of type <tiles>
39
Let "obj" be an example object reference of a stone/item/floor (type <object>).
41
Grid Positions are table/objects:
43
pos = po(7, 3) -- a function "po()"
45
pos = obj -- every object is a valid position
46
pos = po(12.3, 3.7) -- position within a grid (for an actor)
49
{7,3} -- a valid position for all arguments and operations (see caveats)
51
Access to x, y coordinates:
54
x, y = pos["x"], pos["y"]
65
Center positions for set actors
67
pos_centered1 = pos + {0.5, 0.5}
71
Round a position to a grid
77
pos_centered1 == pos_centered2
79
Setting a single attribute of objects including global attributes of world:
81
obj["attr_name"] = value
85
Setting multiple attributes at once:
87
obj:set({attr_name1=value1, attr_name2=value2})
89
Requesting attributes of objects including global attributes of world:
91
value = obj["attr_name"]
92
value = wo["Brittleness"]
94
if wo["IsDifficult"] then ... end
96
Reset an attribute to its default - "delete":
98
obj["attr_name"] = nil
100
Creating a new object:
102
wo[pos] = {"st_chess", color = 0, name="Atrax"} -- on edge of grid pos
103
wo[#pos] = {"ac_bug"} -- actor centered on grid pos
104
wo[pos] = {"#ac_bug"} -- actor centered on grid pos
105
wo[pos] = {"ac_bug", 0.3, 0.7} -- actor with offsets to pos
106
wo[my_floor] = {"it_wand"} -- set an wand on top of a given foor
112
Consecutive naming of objects (building object groups)
114
wo[pos] = {"st_chess", color = 0, name="Atrax#"}
116
For each call of the line above the new object will be named with a unique
117
number appended after the "#" giving "Atrax#1", "Atrax#2", "Atrax#3", ...
119
Requesting an object:
125
my_item = it(my_floor) -- get the item that is on top of the given floor
138
Existance of an object
141
-obj -- unary minus operator on object
146
my_boulder:message("direction", WEST)
147
my_boulder:direction(EAST)
150
Classification of objects:
154
obj:is("st_chess_black")
158
group = no["Atrax#*"] -- a group of all matching objects
159
-- wildcards "*","?" allowed
160
group = grp(obj1, obj2, obj3)
161
group = grp({obj1, obj2, obj3}) -- a group of objects set up in a table
163
Many operations can be applied to groups
165
floor_group[friction] = 3.2 -- set attribute on all floors in the group
166
door_group:message("open")
169
wo[floor_group] = {"it-coin2"} -- add some money on all floor positions
171
wo[pos] = {"st_switch", target=door_group, action="open"}
172
wo[pos] = {"st_switch", target="door#*", action="close"}
176
doors_lasers = doorgrp + lasergrp -- join of two groups
177
lasergrp = doors_lasers - doorgrp -- difference of two groups
178
common_doors = doorgrp1 * doorgrp2 -- intersection of two groups
180
For loops over a group
182
for i = 1, #mygroup do obj = mygroup[i] ... end
183
for obj in mygroup do ... end
185
Setting and connecting two vortices:
187
wo[{3,4}] = {"it_vortex", name="vortex1", destination="vortex3"}
188
wo[{8,6}] = {"it_vortex", name="vortex2", destination="vortex1"}
189
wo[{8,6}] = {"it_vortex", name="vortex3", destination={"vortex1","vortex2"}}
194
ti[" "] = {"fl_sand"}
195
ti[" w"] = ti[" "] .. {"it_wand"}
196
ti[" "] = {"fl_abyss"} -- redefinition causes error to avoid common
200
wo[{5,6}] = ti[" "] .. {"st_chess"}
202
width, height = wo(ti, " ", { -- second arg: default tile key that
203
"########", -- defines the base, too - this example
204
"## w##", -- is 2 chars per tile/grid
208
Note: Tiles kann be used after the initialization as well:
210
function my_callback(value, sender)
211
wo[sender] = ti[" w"]
217
C2 - Object reference validity and usability (done)
218
--------------------------------------------
220
Objects existance and validity can be checked at via the "obj:exists()"
221
method or the operator "-obj". Not existing objects are still of type
222
object (not nil like in old API!). These "null" objects are not equal
223
concerning the Lua "==" comparison to any object, even themself.
225
Write access, kill of and messages to "null" objects are silently ignored.
226
World set objects to "null" object position is ignored, too. This allows
227
loops and group usage even with "null" targets without problems.
229
All read operations that return object specific values which are not
230
usable for group operations and can just be used with a single object
231
as target will throw an error if this object is a "null" object. The
232
application will no longer crash. Just a backtrace will be shown like
233
on other level exceptions.
236
C3 - Booleans and Nil (mainly done)
237
---------------------
239
All boolean type attributes and values in the new API are Lua 5.0++
240
booleans with values "true" and "false". The engine internal value
241
representation takes boolean as another explicit type. Type mismatches
242
on transfer of boolean values from or to Lua will no longer occur.
244
Some attributes and values of the old API that did take values 0 and 1
245
may change to other types than boolean due to other API concepts.
247
Setting an attribute value to "nil" causes the value to be deleted.
248
Any further access returns the default value for the attribute.
250
C4 - Multitarget and Multiaction (coded)
251
--------------------------------
253
The target-action paradigm is extended to a multitarget and multiaction
254
messaging system that is even configurable on the senders state.
256
Every object can take objects, groups of objects or namestrings (including
257
wildcards) as target:
259
{"st_switch", target=my_laser, action="on_off"}
261
{"st_switch", target=no["my_doors#*"], action="open_close"}
262
{"st_switch", target="my_doors#*", action="open_close"}
264
Note the subtle difference between the last two expressions: The first one
265
evaluates the wildcarded string immediatley and builds a fixed group of the
266
current objects that fit the name pattern. The second string is stored as
267
given and will be evaluated at the moment the action is performed. This is
268
what you need in tile definitions, as the desired target do not exist at the
269
moment of the tile definition.
271
Multiple targets can be declared and each target can take a different action:
273
{"st_switch", target={my_laser, "my_door#*", "my_function"},
274
action={"on_off", "open_close", "callback"}}
276
The default action for all functions is "callback", which can thus be
279
{"st_switch", target="my_function"}
281
The default action for all objects is "toggle", which can thus be
284
{"st_switch", target="my_laser"}
286
Every callback takes the arguments (state_value, sender) where
287
"state_value" is an integer value that represents the internal state
288
of the sender object. For switch like objects the state will be 0 for
289
"off" and 1 for "on". Other objects like fourswitch etc. will count the
290
their states from 0, 1, 2,...
292
For special cases, especially for editor based levels, the author can
293
specify different target/action behaviour based on the value of the
294
sender objects state. For each state the following special targets and
295
actions preceed the default target and actions given above:
297
{"st_switch", target_0="my_door", action_0="close",
298
target_1="my_laser", action_1="off"}
301
The multitarget feature is the successor of the old signal feature. In
302
contrast to signals that were bound to tile positions like "stone on
303
grid {15, 4}" the multitarget addresses objects themselves. The action
304
will find its target even when the user swaps it to another grid postion.
307
C5 - Renaming (partially done)
310
The necessary API changes gives the unique opportunity to simplify
311
many old names and to make them consistence. None of names used above
312
is fixed. It is up to the level authors to agree on a naming scheme.
314
Note that valid Lua names start with letter or underscore and consist
315
just of these plus numbers.
317
Just the following rules and conditions need to be observed:
319
- Short 2 or 3 letter names for the namespace and the special objects
320
- System attribute and message names have to be valid Lua names not
321
starting with underscore
322
- User attributes start with an underscore
323
- System attribute and method names are disjoint
324
- Identical system attributes or methods have identical behaviour for
326
- User names for objects do not start with "$","#" or "%", do not contain a character
327
out of ",;" and do not end with "#"
328
- Object Classnames should use a common scheme of underscore/hyphen
329
usage: Either underscore only, or first hyphen and all other
330
underscore,... (st_chess_black, st-chess_black, ...)
332
Decision of Draft 0.60: all object names will uses exclusivly underscore!
335
C6 - Global Variables (coded)
336
---------------------
338
Global variables are handled as attributes of the special world object
339
"wo". Write access on variables will be checked and can cause actions
340
if necessary. A write to a read only variable like "IsDifficult" will be
344
C7 - Critical functions
345
-----------------------
347
All critical functions will be abolished to ensure that new levels
348
will be suited for upcoming features. For the very few existing levels
349
of the distribution that depend on such features exceptions will be
350
hardcoded that will keep these levels to conflict with the new features.
356
The color attribute is an integer value (0, 1, ..., 7).
358
Oxyds can be set like any other stones. If no color attribute is
359
specified pairs of oxyds with the same color will be set.
361
To guarantee fair distributions and levels that are solvable the
362
author can declare minimum and maximum conditions and groups of
365
wo:shuffleOxyd({grp1, max=0}, {grp1, grp2, min=2},
366
{grp1, grp3, min=1, max=1})
368
As a shortcut groups of oxyds can be declared to be positioned either
369
circular or linear. This declaration expands to all rules necessary to
370
avoid any neighbour oxyd pairs.
372
wo:shuffleOxyd({grp(ox1, ox2, ox3, ox4, ox5, ox6), circular=true},
378
Rubberband is an object that can be referenced and checked for existance.
381
C10 - Name inheritance (partially done)
382
----------------------
384
Items like it_seed, it_rubberband that change into stone or rubberband
385
objects on activation will inherit their name to the successor stone
388
C11 - Checkerboard Floor (coded)
389
------------------------
391
Every floor takes an attribute "checkerboard". If set to an integer value
392
0 the floor will only be placed on grids with x+y being even, if set
393
to 1 the floor will be placed only on grids with x+y being uneven.
395
ti["x"] = ti({"fl_rough_red", checkerboard=0}) +
396
{"fl_rough_blue", checkerboard=1}
398
generates an arbitrary shaped checkboardfloor on areas with tile "x"
404
Puzzles can be autoconfigured and shuffled by the engine. Besides the
405
single puzzle stones a dummy stone named "st_puzzle_auto" can be set.
406
All adjacent "st_puzzle_auto" and "st_puzzle_hollow" of the same color
407
will be configured to a puzzle with maximum number of connections:
409
ti["#"] = {"st_puzzle_auto"}
410
ti["*"] = {"st_puzzle_hollow"}
425
with the upper "+" being a hollow cross.
427
If any of the involved puzzle stones has an attribute "shuffle" set
428
to "true" the complete puzzle will shuffled. If the value of any
429
puzzle stone is an integer it will be taken as the number of permutations
430
to be applied. The maximum number of all values will be taken.
432
Shuffle occurs by permutation of rows and columns that a marble can
433
reverse. By default it is assumed that the user can permute rows and
434
columns on every side which is not blocked by a stone that is not hollow.
436
In case the puzzle is only accessable from one side the author can add
437
attributes "permute_v" and "permute_h" with boolean values to every
438
puzzle stone that does not follow the standard rule.
440
As hollow puzzle stones will never be permuted to the border of a puzzle
441
the author can ensure that every shuffle results in a solvable puzzle.
449
Index/member interpretation and operations of new types:
450
--------------------------------------------------------
452
value = number|string|boolean|object|nil add |group|position ?
455
x, y - grid position access
458
is() - (string) - test kind
459
kind() - () - get most specific kind
460
kill() - () - kill object
461
message() - (string [, value]) - send message with an optional value
462
set() - (table) - set multiple attributes given in a table
466
attribute name - set/get attribute
468
other String not prefixed by "_" - message
471
+ - (object|position|table) + (object|position|table)
472
- - (object|position|table) - (object|position|table)
473
# - #object -- center
474
- (unary) - -object -- existance
475
== - object == object
480
x, y, - grid position access
482
grid() - returns a position aligned to the grid
486
+ - (object|position|table) + (object|position|table)
487
- - (object|position|table) - (object|position|table)
488
* - (number|position) * (number|position)
489
/ - position / number
491
== - position == position
492
. .. - position .. position
496
$String - reserved for future usage
497
String - named object access - returns nil if not existing
498
- name must not include wildcard chars *,?
499
String*? - get named group with wildcards *,?
502
[object|position|table|group] = table|tile - write access to world grid
503
[string] - global world attribute read/write access
505
() - (ti|function, string, table) -- initialization "wo(,,)"
508
fl() - (position|table|obj|(num,num)) - get floor at position
509
it() - (position|table|obj|(num,num)) - get item at position
510
st() - (position|table|obj|(num,num)) - get stone at position
513
init() - (ti|function, string, table) -- method synonym for ()
517
1, 2, 3,... - positve integer as sequence index like table read access
518
String - on write: set attrib on members
519
- on access: call method or send message on object
523
* - intersection of groups
524
- - difference of groups
525
# - length, inherited from table
535
String - table like read access with string as index
536
- write only on not yet existing indices - no overwrite
540
Global Functions (to be defined)
543
po(table|[num,num]|obj)
544
fl(position|table|obj|(num,num))
545
it(position|table|obj|(num,num))
546
st(position|table|obj|(num,num))
552
It is a basic LUA feature that the user has no real control about the used
553
variable types. This causes overall trouble:
558
b - a == c -- is true as 7 - 3 == 4
559
c + a == b -- is false as 4 + 3 == 7 but 7 ~= "7"
561
A similar LUA problem may hit authors in the usage of position constants.
562
Expressions like {7,3} may be used anywhere as position arguments as they are
563
autoconverted into positions. But care must be taken with direct calculations
564
and variable assignments of constant positions:
566
table = {7, 3} -- this variable is a simple table with two numbers at
567
-- the indices 1 and 2 but it is not a position
568
wo[table] = obj -- o.k. as the table gets now converted as an argument
569
pos = #table -- is not a centerd position but a number with value 2
570
-- as it the length operation of a table
571
pos = table + {1,2} -- error as two tables cannot be added like positions
572
pos = obj + table -- o.k. as obj is a position that forces an autoconvert
576
Another similar Lua caveat exists in the position comparison. Even though
577
you can use objects as position standins anywhere else the Lua comparison of
578
variables priorises the type comparison to the value comparison:
581
wo[pos] = {"st-switch"}
583
pos == obj -- false as the types differ
584
pos == po(obj) -- true as types and values are equal
588
Lua index syntax - different treatment of numbers, names and strings:
590
1, 2 -- are valid Lua numbers
591
x, y, otto2, _myX -- are valid Lua names
592
"$secret", "1", "fl-abyss" -- are just Lua strings
596
pos["x"] -- valid table like access to x coordinate
597
pos[x] -- error as pos[7] is accessed
598
pos.x -- valid member access that is equivalent to pos["x"]
599
obj["state"] -- valid access to attribute "state"
600
obj[state] -- error as global variable "state" is first evaluated (nil)
601
obj.state -- valid access to attribute "state"
602
tab[1] -- valid table access to first entry
603
tab["1"] -- table access to entry at key "1" which is not the first
604
-- table entry but likley nil.
605
tab.1 -- error - Lua needs a valid Lua-name as member