~ubuntu-branches/ubuntu/trusty/enigma/trusty-proposed

« back to all changes in this revision

Viewing changes to doc/reference/ConceptLuaAPI2.txt

  • Committer: Package Import Robot
  • Author(s): Erich Schubert
  • Date: 2013-04-06 14:54:02 UTC
  • mfrom: (1.1.10)
  • Revision ID: package-import@ubuntu.com-20130406145402-jgjrtk7hac8gtvza
Tags: 1.20-dfsg.1-1
* New upstream release (Closes: #704595)
  (Repacked: dropped zipios++ source and main menu music)
* Update watch file, sf.net again.
* Fix documentation links (Closes: #653508)
* Conflict with enigma-level-previews to encourage deinstallation
  (Pregenerated level previews were only used with version 1.01)
* Use dh7 for building instead of CDBS
* Update to policy 3.9.4.0 (no changes)
* Register documentation with doc-base

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
Concept Lua API 2         (Draft 0.6)
2
 
=================
3
 
 
4
 
 
5
 
C1 - Object Based Syntax   (coded - besides lines starting with a ".")
6
 
------------------------
7
 
 
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).
13
 
 
14
 
The following example based description explains the idea of the
15
 
new object based syntax additions:
16
 
 
17
 
Namespace "en"
18
 
 
19
 
  Any system object or function is addressable as "sysname" and "en.sysname" 
20
 
 
21
 
Special value types:
22
 
 
23
 
  position      - a position within the world that can be described by an
24
 
                  x and y coordinate
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,
30
 
                  item, stone, actor)
31
 
  tiles         - a singleton type for the repository of all tile instances
32
 
 
33
 
Special objects given at init:
34
 
 
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>
38
 
 
39
 
Let "obj" be an example object reference of a stone/item/floor (type <object>).
40
 
 
41
 
Grid Positions are table/objects:
42
 
 
43
 
  pos = po(7, 3)            -- a function "po()"
44
 
  pos = po({7, 3})
45
 
  pos = obj                 -- every object is a valid position
46
 
  pos = po(12.3, 3.7)       -- position within a grid (for an actor) 
47
 
 
48
 
Position constants
49
 
  {7,3}     -- a valid position for all arguments and operations (see caveats)
50
 
 
51
 
Access to x, y coordinates:
52
 
 
53
 
  x, y = pos.x, pos.y
54
 
  x, y = pos["x"], pos["y"]
55
 
  x, y = pos:xy()
56
 
  x, y = obj.x, obj.y
57
 
  x, y = obj:xy()
58
 
 
59
 
Position calculation
60
 
 
61
 
  pos = obj + {2,7}
62
 
  dpos = obj1 - obj2
63
 
  dpos2 = 2 * dpos
64
 
 
65
 
Center positions for set actors
66
 
 
67
 
  pos_centered1 = pos + {0.5, 0.5}
68
 
  pos_centered2 = #pos
69
 
  pos_centered3 = #obj
70
 
 
71
 
Round a position to a grid
72
 
 
73
 
  grid_pos = pos:grid()
74
 
 
75
 
Position comparison
76
 
 
77
 
  pos_centered1 == pos_centered2
78
 
 
79
 
Setting a single attribute of objects including global attributes of world:
80
 
 
81
 
  obj["attr_name"] = value
82
 
  wo["Brittleness"] = 7
83
 
 
84
 
 
85
 
Setting multiple attributes at once:
86
 
 
87
 
  obj:set({attr_name1=value1, attr_name2=value2})
88
 
 
89
 
Requesting attributes of objects including global attributes of world:
90
 
 
91
 
  value = obj["attr_name"]
92
 
  value = wo["Brittleness"]
93
 
 
94
 
  if wo["IsDifficult"] then ... end
95
 
 
96
 
Reset an attribute to its default - "delete":
97
 
 
98
 
  obj["attr_name"] = nil
99
 
 
100
 
Creating a new object:
101
 
 
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
107
 
 
108
 
Naming an object:
109
 
 
110
 
  no["Atrax"] = obj
111
 
 
112
 
Consecutive naming of objects (building object groups)
113
 
 
114
 
  wo[pos] = {"st_chess", color = 0, name="Atrax#"}
115
 
 
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", ...
118
 
 
119
 
Requesting an object:
120
 
 
121
 
  obj = it(pos)
122
 
  obj = it(x, y)
123
 
  obj = st(pos)
124
 
  obj = wo:it(pos)
125
 
  my_item = it(my_floor)    -- get the item that is on top of the given floor
126
 
  
127
 
  obj = no["Atrax"]
128
 
 
129
 
Killing an object:
130
 
 
131
 
  obj:kill()
132
 
  wo[pos] = {"it_nil"}
133
 
 
134
 
Comparing objects
135
 
 
136
 
  obj1 == obj2
137
 
 
138
 
Existance of an object
139
 
 
140
 
  obj:exists()
141
 
  -obj                -- unary minus operator on object
142
 
  if -obj then ...
143
 
 
144
 
Messages:
145
 
 
146
 
  my_boulder:message("direction", WEST)
147
 
  my_boulder:direction(EAST)
148
 
  my_door:open()
149
 
 
150
 
Classification of objects:
151
 
 
152
 
  obj:is("st_chess")
153
 
  obj:is("st")
154
 
  obj:is("st_chess_black")
155
 
 
156
 
Group of objects:
157
 
 
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
162
 
 
163
 
Many operations can be applied to groups
164
 
 
165
 
  floor_group[friction] = 3.2      -- set attribute on all floors in the group
166
 
  door_group:message("open")
167
 
  door_group:open()
168
 
  stone_group:kill()
169
 
  wo[floor_group] = {"it-coin2"}   -- add some money on all floor positions
170
 
  
171
 
  wo[pos] = {"st_switch", target=door_group, action="open"}
172
 
  wo[pos] = {"st_switch", target="door#*", action="close"}
173
 
 
174
 
Group operations
175
 
 
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
179
 
 
180
 
For loops over a group
181
 
 
182
 
  for i = 1, #mygroup do obj = mygroup[i] ... end
183
 
  for obj in mygroup do ... end
184
 
 
185
 
Setting and connecting two vortices:
186
 
 
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"}}
190
 
 
191
 
 
192
 
Tiles:
193
 
 
194
 
  ti["  "] = {"fl_sand"}
195
 
  ti[" w"] = ti["  "] .. {"it_wand"}
196
 
  ti["  "] = {"fl_abyss"}   -- redefinition causes error to avoid common
197
 
                            --   mistakes
198
 
 
199
 
  wo[{3,4}] = ti[" w"]
200
 
  wo[{5,6}] = ti["  "] .. {"st_chess"}
201
 
 
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 
205
 
  "########"
206
 
  })
207
 
 
208
 
Note: Tiles kann be used after the initialization as well:
209
 
 
210
 
function my_callback(value, sender)
211
 
    wo[sender] = ti[" w"]
212
 
end
213
 
 
214
 
 
215
 
 
216
 
 
217
 
C2 - Object reference validity and usability   (done)
218
 
--------------------------------------------
219
 
 
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.
224
 
 
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.
228
 
 
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.
234
 
 
235
 
 
236
 
C3 - Booleans and Nil   (mainly done)
237
 
---------------------
238
 
 
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.
243
 
 
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.
246
 
 
247
 
Setting an attribute value to "nil" causes the value to be deleted.
248
 
Any further access returns the default value for the attribute.
249
 
 
250
 
C4 - Multitarget and Multiaction (coded)
251
 
--------------------------------
252
 
 
253
 
The target-action paradigm is extended to a multitarget and multiaction
254
 
messaging system that is even configurable on the senders state. 
255
 
 
256
 
Every object can take objects, groups of objects or namestrings (including
257
 
wildcards) as target:
258
 
 
259
 
  {"st_switch", target=my_laser, action="on_off"}
260
 
 
261
 
  {"st_switch", target=no["my_doors#*"], action="open_close"}
262
 
  {"st_switch", target="my_doors#*", action="open_close"}
263
 
 
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.
270
 
 
271
 
Multiple targets can be declared and each target can take a different action:
272
 
 
273
 
  {"st_switch", target={my_laser, "my_door#*", "my_function"},
274
 
                action={"on_off", "open_close", "callback"}}
275
 
 
276
 
The default action for all functions is "callback", which can thus be
277
 
omitted:
278
 
 
279
 
  {"st_switch", target="my_function"}
280
 
 
281
 
The default action for all objects is "toggle", which can thus be
282
 
omitted:
283
 
 
284
 
  {"st_switch", target="my_laser"}
285
 
 
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,...
291
 
 
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:
296
 
 
297
 
  {"st_switch", target_0="my_door", action_0="close",
298
 
                target_1="my_laser", action_1="off"}
299
 
 
300
 
 
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.
305
 
 
306
 
 
307
 
C5 - Renaming (partially done)
308
 
-------------
309
 
 
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.
313
 
 
314
 
Note that valid Lua names start with letter or underscore and consist
315
 
just of these plus numbers.
316
 
 
317
 
Just the following rules and conditions need to be observed:
318
 
 
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
325
 
  all objects
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, ...)
331
 
 
332
 
  Decision of Draft 0.60: all object names will uses exclusivly underscore! 
333
 
 
334
 
 
335
 
C6 - Global Variables   (coded)
336
 
---------------------
337
 
 
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
341
 
silently ignored.
342
 
 
343
 
 
344
 
C7 - Critical functions
345
 
-----------------------
346
 
 
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.
351
 
 
352
 
 
353
 
C8 - Oxyd   (coded)
354
 
---------
355
 
 
356
 
The color attribute is an integer value (0, 1, ..., 7).
357
 
 
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.
360
 
 
361
 
To guarantee fair distributions and levels that are solvable the
362
 
author can declare minimum and maximum conditions and groups of
363
 
oxyds like:
364
 
 
365
 
wo:shuffleOxyd({grp1, max=0}, {grp1, grp2, min=2}, 
366
 
    {grp1, grp3, min=1, max=1})
367
 
 
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.
371
 
 
372
 
wo:shuffleOxyd({grp(ox1, ox2, ox3, ox4, ox5, ox6), circular=true},
373
 
    {grp2, linear=true})
374
 
 
375
 
C9 - Rubberband
376
 
---------------
377
 
 
378
 
Rubberband is an object that can be referenced and checked for existance.
379
 
 
380
 
 
381
 
C10 - Name inheritance   (partially done)
382
 
----------------------
383
 
 
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
386
 
object.
387
 
 
388
 
C11 - Checkerboard Floor   (coded)
389
 
------------------------
390
 
 
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.
394
 
 
395
 
ti["x"] = ti({"fl_rough_red", checkerboard=0}) + 
396
 
         {"fl_rough_blue", checkerboard=1}
397
 
 
398
 
generates an arbitrary shaped checkboardfloor on areas with tile "x"
399
 
on the world map.
400
 
 
401
 
C12 - Puzzle
402
 
------------
403
 
 
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:
408
 
 
409
 
ti["#"] = {"st_puzzle_auto"}
410
 
ti["*"] = {"st_puzzle_hollow"}
411
 
 
412
 
wo{ti," ",{
413
 
"  # ",
414
 
"##*#",
415
 
"### ",
416
 
" #  "}
417
 
 
418
 
results in a puzzle:
419
 
 
420
 
   |
421
 
 /T+-
422
 
 \+/
423
 
  |
424
 
 
425
 
with the upper "+" being a hollow cross.
426
 
 
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.
431
 
 
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.
435
 
 
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.
439
 
 
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.
442
 
 
443
 
 
444
 
 
445
 
Appendix
446
 
========
447
 
 
448
 
 
449
 
Index/member interpretation and operations of new types:
450
 
--------------------------------------------------------
451
 
 
452
 
value = number|string|boolean|object|nil    add  |group|position ?
453
 
 
454
 
Enigmaobject:
455
 
  x, y       - grid position access
456
 
 
457
 
  exists()
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
463
 
                                     as key, value pairs
464
 
  xy()
465
 
 
466
 
  attribute name       - set/get attribute
467
 
 
468
 
  other String not prefixed by "_"   - message
469
 
 
470
 
  valid Operations:
471
 
    +            - (object|position|table) + (object|position|table)
472
 
    -            - (object|position|table) - (object|position|table)
473
 
    #            - #object         -- center
474
 
    - (unary)    - -object         -- existance
475
 
    ==           - object == object
476
 
    
477
 
 
478
 
Position:
479
 
 
480
 
  x, y,          - grid position access
481
 
  
482
 
  grid()               - returns a position aligned to the grid
483
 
  xy()                 - returns x, y
484
 
  
485
 
  valid Operations:
486
 
    +            - (object|position|table) + (object|position|table)
487
 
    -            - (object|position|table) - (object|position|table)
488
 
    *            - (number|position) * (number|position)
489
 
    /            - position / number
490
 
    #            - # position
491
 
    ==           - position == position
492
 
.   ..           - position .. position
493
 
 
494
 
Namedobject:
495
 
 
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 *,?
500
 
 
501
 
Worldobject:
502
 
  [object|position|table|group] = table|tile - write access to world grid
503
 
  [string]             - global world attribute read/write access
504
 
  
505
 
  ()             - (ti|function, string, table) -- initialization "wo(,,)"
506
 
  
507
 
 
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
511
 
  
512
 
  
513
 
  init()         - (ti|function, string, table) -- method synonym for () 
514
 
 
515
 
 
516
 
Group:
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
520
 
 
521
 
  valid Operations:
522
 
    +                  - join of groups
523
 
    *                  - intersection of groups
524
 
    -                  - difference of groups
525
 
    #                  - length, inherited from table
526
 
 
527
 
Tile:
528
 
  
529
 
  valid Operations:
530
 
   ..                   - concat tiles
531
 
   ti(table)            - new tile
532
 
 
533
 
 
534
 
Tiles:
535
 
  String               - table like read access with string  as index
536
 
                       - write only on not yet existing indices - no overwrite
537
 
                         assign (table|tile)
538
 
 
539
 
 
540
 
Global Functions  (to be defined)
541
 
----------------
542
 
 
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))
547
 
 
548
 
 
549
 
Lua Caveats:
550
 
============
551
 
 
552
 
It is a basic LUA feature that the user has no real control about the used
553
 
variable types. This causes overall trouble:
554
 
 
555
 
a = "3"
556
 
b = "7"
557
 
c = 4
558
 
b - a == c          -- is true as    7 - 3 == 4
559
 
c + a == b          -- is false as   4 + 3 == 7  but 7 ~= "7"
560
 
 
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:
565
 
 
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
573
 
                    -- of the table
574
 
 
575
 
 
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:
579
 
 
580
 
pos = po(3, 5)
581
 
wo[pos] = {"st-switch"}
582
 
obj = st(pos)
583
 
pos == obj          -- false as the types differ
584
 
pos == po(obj)      -- true as types and values are equal
585
 
 
586
 
 
587
 
 
588
 
Lua index syntax - different treatment of numbers, names and strings:
589
 
 
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
593
 
 
594
 
x = 7
595
 
pos = po(3, 5)
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
606
 
 
607