Professional Documents
Culture Documents
Download pdf Ai Ia 2019 Advances In Artificial Intelligence Xviiith International Conference Of The Italian Association For Artificial Intelligence Rende Italy November 19 22 2019 Proceedings Mario Alviano ebook full chapter
Download pdf Ai Ia 2019 Advances In Artificial Intelligence Xviiith International Conference Of The Italian Association For Artificial Intelligence Rende Italy November 19 22 2019 Proceedings Mario Alviano ebook full chapter
https://textbookfull.com/product/artificial-intelligence-
xxxvi-39th-sgai-international-conference-on-artificial-
intelligence-ai-2019-cambridge-uk-
AI 2019 Advances in Artificial Intelligence 32nd
Australasian Joint Conference Adelaide SA Australia
December 2 5 2019 Proceedings Jixue Liu
https://textbookfull.com/product/ai-2019-advances-in-artificial-
intelligence-32nd-australasian-joint-conference-adelaide-sa-
australia-december-2-5-2019-proceedings-jixue-liu/
AI*IA 2019 –
LNAI 11946
Advances in
Artificial Intelligence
XVIIIth International Conference
of the Italian Association for Artificial Intelligence
Rende, Italy, November 19–22, 2019
Proceedings
123
Lecture Notes in Artificial Intelligence 11946
Series Editors
Randy Goebel
University of Alberta, Edmonton, Canada
Yuzuru Tanaka
Hokkaido University, Sapporo, Japan
Wolfgang Wahlster
DFKI and Saarland University, Saarbrücken, Germany
Founding Editor
Jörg Siekmann
DFKI and Saarland University, Saarbrücken, Germany
More information about this series at http://www.springer.com/series/1244
Mario Alviano Gianluigi Greco
• •
AI*IA 2019 –
Advances in
Artificial Intelligence
XVIIIth International Conference
of the Italian Association for Artificial Intelligence
Rende, Italy, November 19–22, 2019
Proceedings
123
Editors
Mario Alviano Gianluigi Greco
University of Calabria University of Calabria
Rende, Italy Rende, Italy
Francesco Scarcello
University of Calabria
Rende, Italy
This Springer imprint is published by the registered company Springer Nature Switzerland AG
The registered company address is: Gewerbestrasse 11, 6330 Cham, Switzerland
Preface
This volume contains the papers presented at the main track of AI*IA 2019, the 18th
International Conference of the Italian Association for Artificial Intelligence held
during November 19–22, 2019, in Rende, Italy. The conference is organized by the
Italian Association for Artificial Intelligence (AI*IA – Associazione Italiana per
l’Intelligenza Artificiale), which is a non-profit scientific society founded in 1988
devoted to the promotion of Artificial Intelligence. The association aims to increase the
public awareness of AI, encourage the teaching of it, and promote research in the field.
The main track of the conference received 86 submissions, and 67 of them were
selected for the technical review process. Each selected submission was reviewed by at
least three Program Committee members. The committee decided to accept 41 papers
for presentation at the conference and publication in this volume. The program also
included four invited talks by Giuseppe De Giacomo, Sridhar Mahadevan, Michela
Milano, and Philipp Slusallek. Moreover, as in previous editions of the conference, the
program was enriched by several workshops on specific fields of AI. Finally, a novelty
for this edition of the conference was the presentation of discussion papers about
recently published research.
We acknowledge EasyChair (https://easychair.org/) for providing their conference
management system that significantly simplified the whole process from receiving the
submissions to producing the proceedings. Finally, we thank all the authors who
contributed to the workshops, the Program Committee members and the additional
reviewers for their effort to produce timely and wise reviews.
Conference Chair
Nicola Leone University of Calabria, Italy
Program Chairs
Mario Alviano University of Calabria, Italy
Gianluigi Greco University of Calabria, Italy
Francesco Scarcello University of Calabria, Italy
Organization Chairs
Francesco Ricca University of Calabria, Italy
Chiara Ghidini FBK Trento, Italy
Publicity Chair
Luca Pulina University of Sassari, Italy
Program Committee
Fabrizio Angiulli University of Calabria, Italy
Davide Bacciu University of Pisa, Italy
Farshad Badie Aalborg University, Denmark
Matteo Baldoni University of Turin, Italy
Stefania Bandini CSAI - Complex Systems and Artificial Intelligence
Research Center, Italy
Roberto Basili University of Roma Tor Vergata, Italy
Nicola Basilico University of Milan, Italy
Federico Bergenti University of Parma, Italy
Tarek Richard Besold Alpha Health AI Lab, Telefonica Innovation Alpha,
Germany
Stefano Bistarelli University of Perugia, Italy
Andrea Burattin Technical University of Denmark, Denmark
Elena Cabrio Université Côte d’Azur, CNRS, Inria, I3S, France
Stefano Cagnoni University of Parma, Italy
Marco Calautti University of Calabria, Italy
Diego Calvanese Free University of Bozen-Bolzano, Italy
Luigia Carlucci Aiello Sapienza University of Rome, Italy
Amedeo Cesta CNR - National Research Council of Italy, Italy
Federico Chesani University of Bologna, Italy
viii Organization
Additional Reviewers
AI and Computation
AI and Humans
1 Introduction
When comparing declarative, rule-based, formalisms with imperative languages,
one can notice how it can be much easier to solve a problem using the first
approach rather than the second one in a variety of settings. On the one hand,
rule-based knowledge representation techniques feature solid theoretical bases,
they do not need algorithm encoding and they are based on easily modifiable and
maintainable knowledge bases; on the other hand, imperative languages enjoy
a better efficiency, a much wider user base, easier interoperability and better
handling of arbitrary data structures.
Combining these two radically different paradigms, so to achieve the bene-
fits of both worlds, is therefore desirable. Consider for instance the context of
c Springer Nature Switzerland AG 2019
M. Alviano et al. (Eds.): AI*IA 2019, LNAI 11946, pp. 3–17, 2019.
https://doi.org/10.1007/978-3-030-35166-3_1
4 D. Angilica et al.
In the remainder of this paper, we first illustrate the Unity engine and the
requirements that must be met when integrating rule-based reasoning tech-
niques in the context of such a game development engine. We then describe
the ThinkEngine module, which has been developed in the form of a Unity re-
usable asset, and we showcase a Unity-based game where the player is controlled
by rule-based reasoning modules programmed in ASP.
INITIALIZATION
EDITOR
PHYSICS
FIXEDUPDATE
INPUT EVENTS
GAME LOGIC
UPDATE
YIELD STARTCOROUTINE
SCENE RENDERING
GIZMO RENDERING
GUI RENDERING
END OF FRAME
PAUSING
DECOMMISSIONING
Unity; however, within these latter most of the Unity API and game object data
structures are purposely made not accessible in that they are not thread-safe.
On the other hand, reasoning tasks are time-consuming and cannot be easily
accommodated in a single-thread execution flow, without slowing down the game
workflow. We thus delegated reasoning tasks to auxiliary threads and introduced
an information passing layer allowing the reasoning side to access and act on a
representation of the game world. This representation is independent from the
Tight Integration of Rule-Based Tools in Game Development 7
UNITY
EXECUTION
CORE GAME
WORLD
UNITY THREAD
THINKENGINE
SENSORS ACTUATORS
MANAGER MANAGER
REFLECTION LAYER
SENSORS ACTUATORS
UNITY THREAD
PASSING LAYER
AUXILIARY THREAD(S)
SOLVER
EXECUTOR
ASP SOLVER
REASONING LAYER
Unity API and can be accessed separately. The whole run-time ThinkEngine
architecture is shown in Fig. 2.
In particular the ThinkEngine consists of:
1. A reasoning layer, in which the game world is accessible and encoded in terms
of logical assertions. An answer set solver [5] can elaborate the current state
of the game and produces decisions which are encoded in form of answer sets.
2. An information passing layer which allows to mediate between the reasoning
layer and the actual game logic. In this layer, sensors store data originated
from the upper layers. Sensors correspond to parts of the game world data
structures which are visible from the reasoning layer. On the other hand,
actuators collect decisions taken by the reasoning layer and are used to modify
the game state.
3. A reflection layer, in which a Sensors Manager and an Actuators Manager
keep the mapping between the game world data structures and the lower
layers. On the one hand the Sensors Manager reads selected game world
data which, this way, is made accessible from the reasoning layer. On the
other hand the Actuators Manager updates selected parts of the game world,
based on input coming from the reasoning layer.
8 D. Angilica et al.
4. One or more brains that can control the three layers. Each brain can access
his own view of the world (i.e. a selected collection of sensors and actuators),
and can be used for programming a separate reasoning activity, like a separate
artificial player logic, etc.
A brain controls both the Sensors Manager and the Solver Executor . The
former is activated periodically or after a configurable trigger condition is met.
The Sensors Manager is responsible of updating all the sensors data mapped to
the current brain.
The brain at hand can concurrently wake the Solver Executor up. This can
happen either when a sensors update is completed or on a configurable trigger
condition. When a Solver Executor is started, it will generate a representation
W of the world expressed in terms of logical assertions (set of input facts) and
it will invoke the ASP solver. The ASP solver is fed in input with W and with a
logical knowledge base KB encoding the AI of the current brain. As soon as the
solver provides decisions encoded in form of an answer set, the Solver Executor
populates the actuators associated with the corresponding brain. The Actuators
Manager monitors actuators values and updates accordingly the properties of
the GO associated with each actuator.
where
2
For space reasons we will not describe how matrices are translated.
Tight Integration of Rule-Based Tools in Game Development 9
– nested propertyij .name is the name of the j-th property of the object
referred by the i-th property;
– basic type propertyi .name is the textual name of p, i.e. the i-th basic type
property selected in the properties hierarchy of o;
– the VALUE is the current value of the filter associated to p.
Developers can access to a list of the GOs used in the game scene via a custom
Unity window editor4 as in Fig. 3. It is possible to browse objects and select
which properties are mapped on the reasoning side. We will use next some of
the typical terminology used to describe our infrastructure and the Tetris game,
as recalled here:
Arena: as shown in Fig. 3, the arena is a GO that contains all the properties
relative to the playable game scene (i.e. a matrix of tiles, the properties max-
TileX, maxTileY etc.);
tiles: a matrix of GOs of type ArenaTile. This matrix can be expanded by the
user in order to configure some extra properties;
Tetromino: a geometric shape composed of four squares;
currentTetromino: in the Tetris game it represents the tetromino that is cur-
rently dropping in the Arena;
Spawner: a GO that manages the generation of a new Tetromino when the
previously created one can not drop further down in the Arena.
We bound to the reasoning side, as sensors, the Arena, the currentTetromino and
the Spawner, and, in a similar way, we configured the actuators. By means of the
3
https://github.com/MaciejKitowski/Tetris.
4
I.e. a window similar to the Unity inspector. The inspector displays detailed infor-
mation about the currently selected game object, including all attached components.
10 D. Angilica et al.
Actuator Configuration Window one can select the AI script that is needed to
be mapped within the ASP module. The single selected actuator, called player,
contains the properties: nMove, nLatMove, nRot, typeLatMove. The meaning
of these properties will be explained in Subsect. 4.2 when we will discuss the
AIPlayer script.
After configuring the sensors (arenaGrid, tetromino and spawner) and the actu-
ator (player), we added to the GO hierarchy a new GO with an attached com-
ponent of type brain. The brain consists in a standard script belonging to the
ThinkEngine asset that will coordinate the sensors, the actuator and the solver
executor.
The brain component can be configured via the inspector tab (Fig. 4). Sen-
sors, actuators and some other additional features can be attached to a brain via
the visual interface. In our example, we setup the conditions5 to meet in order to
(a) update the sensors and run the ASP Solver; (b) let the Actuators Manager
apply the actuators actions.
When the game starts, thus at run-time, the brain will start updating sensors
and will also run an external thread that will execute the ASP solver if sensors
5
Conditions are selected from a set of boolean functions customized by the developer.
Tight Integration of Rule-Based Tools in Game Development 11
have data to share and the solver is not already running. Every time that it is
necessary to invoke the solver, the Sensor Mapper produces a representation, in
the form of logical assertions, of the filtered sensors values attached to the brain.
Then, the ASP solver is invoked by passing it this sensor representation and
a knowledge base KBT expressing the desired brain AI. After the ASP solver
ends its execution, its answer sets (i.e. a set of output logical assertions), will be
mapped to actuators by means of the actuators manager, thus influencing the
game world.
In the setting of the Tetris game, the solver’s output encodes the position
and orientation in which the current tetromino should be dropped. This is then
translated to the corresponding number of rotations and lateral moves of the
tetromino. In turn, a corresponding number of simulated swipes is commanded
via Unity procedural code and the tetromino is eventually dropped.
assures that each model produced by the solver will contain exactly one bestSol.
The lowest row that the tetromino can reach when positioned with a given
rotation in a chosen column is described as follows.
1. free (R ,C , C1 ) : - tile (R ,C , true ) , C1 = C +1.
2. free (R ,C , C2 ) : - free (R ,C , C1 ) , tile (R , C1 , true ) , C2 = C1 +1.
3. firstEmpty ( R ) : - nCol ( C ) , # max { R1 : free ( R1 ,0 , C ) }= R .
4. canPut ( R ) : - bestSol (X ,Y , C ) , free (R ,C , C1 ) , firstEmpty ( R ) , confMaxW (X ,Y , W ) ,
C1 = C + W .
5. canPut ( R ) : - bestSol (X ,Y , C ) , canPut ( R1 ) , free (R ,C , C1 ) , confMaxW (X ,Y , W ) ,
C1 = C +W , R = R1 +1.
6. freeUpTo ( R ) : - canPut ( R ) , not canPut ( R1 ) , R1 = R +1.
7. oneMore ( R1 ) : - bestSol (X ,Y , C ) , botSpace (X ,Y ,I , J ) , freeUpTo ( R ) , R1 = R +1 ,
free ( R1 , C1 , C2 ) , C1 = C +I , C2 = C + J .
8. twoMore ( R1 ) : - bestSol (X ,Y , C ) , oneMore ( R ) , extraRow (X , Y ) , botSpace (X ,Y ,I , J ) ,
free ( R1 , C1 , C2 ) , R1 = R +1 , C1 = C +I , C2 = C + J .
9. bestRow ( R ) : - freeUpTo ( R ) , not oneMore ( R2 ) , botSpace (X ,Y ,0 ,0) , R2 = R +1 ,
bestSol (X ,Y , _ ) .
10. bestRow ( R1 ) : - freeUpTo ( R ) , not oneMore ( R2 ) , not extraRow (X , Y ) ,
bestSol (X ,Y , _ ) , not botSpace (X ,Y ,0 ,0) , R1 =R -1 , R2 = R +1.
11. bestRow ( R1 ) : - bestSol (X ,Y , _ ) , not oneMore ( R2 ) , freeUpTo ( R ) , extraRow (X , Y ) ,
not botSpace (X ,Y ,0 ,0) , R1 =R -2 , R2 = R +1.
12. bestRow ( R ) : - oneMore ( R ) , not twoMore ( R1 ) , bestSol (X ,Y , _ ) , R1 = R +1 ,
not extraRow (X , Y ) .
13. bestRow ( R ) : - twoMore ( R ) .
14. : -# count { R : bestRow ( R ) }=0.
The tile6 predicate is used to derive in which rows the tetromino can be
placed. The space occupied by a tetromino is encoded by a number of assertions,
like e.g. confMaxW(x,y,w) which expresses that the maximum horizontal amount
of cells occupied by the tetromino x on which it has been applied the rota-
tion y is w; other similar assertions are botSpace(x,y,c,c1), topSpace(x,y,h),
leftSpaceWrtSpawn(x,y,l), extraRow(x,y).
Rules 1. and 2. describe, for each row of the arena, all the sequences of free
slots of the matrix (0−2, 0−3...0−10, 1−2, ..., 1−10..., note that the second index
is exclusive). Rule 3. derives the highest row in the arena completely empty, thus
the first row in which the tetromino can be placed in whatever column. Starting
from this row, rules from 4. to 8. describe in which row the tetromino, in the
chosen rotation configuration, is allowed to be placed, according also with the
current tetromino shape. Finally, rules from 9. to 13., describe the lowest line
that the tetromino will drop to.
The next set of rules describe which row the tetromino will reach (in height)
once it is placed (rule 15.) and how many holes will remain in the row immedi-
ately below (rules from 16. to 20.).
6
This assertion maps facts derived from the ArenaGrid sensor mapped by the predi-
cate arenaGrid(arena(arena(tiles(X,Y,arenaTile(empty(T)))))).
Tight Integration of Rule-Based Tools in Game Development 13
Weak constraints 21. and 22. have been assigned to the same priority (4) since
we want, at the same time, to minimize the number of holes and to maximize
the lowest line that the tetromino will drop to. However, since we want to give
a bit more importance to the holes, we decided to assign a triple weight with
respect to the lowest row optimization criterion. At a lower priority level, we find
the minimization of the row reached in height by the tetromino (23.). The last
two constraints, 24. and 25., are used to assure that no more than one answer
set is produced. Indeed, when having two answer sets with the same costs for
respectively the number of holes criterion, for the lowest line criterion and for
the top most row criterion, we will choose the solution occupying the leftmost
column and requiring the lowest number of rotations.
Note that this artificial player, although not optimal, can be easily modified
by changing the heuristic associated to the weight of constraint in 21.; intro-
ducing new weak constraints expressing other desiderata; changing the priority
level of the constraints and so on. The above artificial player, including both
the declarative code and all the procedural code, can be downloaded at https://
github.com/DeMaCS-UNICAL/Tetris-AI4Unity.
5 Benchmark
One of the most common measuring indicators used for assessing the perfor-
mance of a videogame is the framerate. i.e. the number of frames that can be
displayed in a second.
The framerate appears to be a good measure even for the evaluation of the
ThinkEngine impact on the game performance. Using the Tetris showcase, we
compared the framerate of the game when played by a human agent and the
framerate obtained using the ThinkEngine asset. The performance is expected
14 D. Angilica et al.
to be higher when a human agent controls the game, since the thinking phase
is absent and substituted by a quick keyboard reading; on the other hand if the
game is controlled by ThinkEngine, some impact on performance is expected.
Videogames are generally designed in order to keep a constant acceptable fram-
erate, which, in the case of Unity games, is set by default to a target of 60 frames
per second. Figure 5 shows how, for our setting, the framerate is not constant,
but it can vary on each frame. The two curves represent, respectively, the fram-
erate obtained when a human is playing (the blue one) and when the game is
controlled by the ThinkEngine (the red one). The two curves generally keep the
target framerate, although they present some occasional negative spikes. How-
ever, the ThinkEngine framerate has specific negative spikes that are caused by
the overhead introduced by the sensors update phase (red crosses in the figure).
These spikes do not have a visible impact on the graphical update as they are
sufficiently isolated and the moving average (light green curve in Fig. 5) over 25
frames is almost constant. This analysis can be used as an indication for how
often one should update the sensors: the game would stall if this is done too
often. The actuators update step, instead, has no appreciable impact on the
performance of the game (green diamonds in the figure). Obviously, the sensors
update needs more time with respect to actuators since they have to track down
an entire matrix of values on the game board.
70
Normal Mode ThinkEngine Moving Average
65
60
55
50
Frame Rate
45
40
35
30
25
20
15
10
5
0
0
50
0
10
15
20
25
30
35
40
45
50
55
60
65
70
75
80
85
Frames
Another aspect that is interesting to look at, is the time that the ThinkEngine
needs to auto-generate the input facts for the ASP solver and how fast is this
latter in producing a solution. These two measures cannot be tracked in the
framerate analysis since the two operations are performed in a separate thread
and the main one which is in charge of updating the graphics. However, an
Tight Integration of Rule-Based Tools in Game Development 15
intuition of the amount of time elapsed between a sensors update and a solution
generation can be spotted in the Fig. 5. Indeed, the number of frames between
a sensors update and an actuators update is really low. The Table 1 shows the
time needed on average on a single Tetris match for both facts and answer set
generation: the last row is the overall average.
6 Related Work
also for dynamic environments and for problems that can take advantage of
the incremental reasoning. The EmbASP architecture [2], also used in this work
for calling external ASP solvers, is an abstract architecture allowing to inte-
grate ASP in external tools for which authors presented a Java and a Python
implementation. The EmbASP architecture can be easily implemented in any
programming language, deployed for multiple platforms and can take advantage
of different, non necessarily ASP, solvers.
Similar to EmbASP, with dual aspects, is PY-ASPIO presented in [10]. Even
if this solution is annotations-based, these can be put in the ASP program instead
that in the external application.
In [9], it has been proposed the Videas infrastructure as a different way of
making ASP useful for object-oriented programmers. The authors proposed a
visual tool based on the model-driven engineering in fact encouraging program-
mers to use ER diagram to describe a data model. In this way designers can
automatically generate constraints in the ASP program obtained from a ER dia-
gram. Finally, the ActHex system [7] allows to attach and execute action scripts
to specific truth values appearing in answer sets, and to generate execution plans
accordingly.
References
1. Buccafurri, F., Leone, N., Rullo, P.: Strong and weak constraints in disjunctive
datalog. In: Dix, J., Furbach, U., Nerode, A. (eds.) LPNMR 1997. LNCS, vol. 1265,
pp. 2–17. Springer, Heidelberg (1997). https://doi.org/10.1007/3-540-63255-7 2
2. Calimeri, F., Fuscà, D., Germano, S., Perri, S., Zangari, J.: Fostering the use of
declarative formalisms for real-world applications: the EmbASP framework. New
Gener. Comput. 37(1), 29–65 (2019)
3. Calimeri, F., Germano, S., Ianni, G., Pacenza, F., Perri, S., Zangari, J.: Integrating
rule-based AI tools into mainstream game development. In: Benzmüller, C., Ricca,
F., Parent, X., Roman, D. (eds.) RuleML+RR 2018. LNCS, vol. 11092, pp. 310–
317. Springer, Cham (2018). https://doi.org/10.1007/978-3-319-99906-7 23
4. Creighton, R.H.: Unity 3D game development by example: a seat-of-your-pants
manual for building fun, groovy little games quickly. Packt Publishing Ltd (2010)
Tight Integration of Rule-Based Tools in Game Development 17
5. Eiter, T., Ianni, G., Krennwallner, T.: Answer set programming: a primer. In:
Tessaris, S., et al. (eds.) Reasoning Web 2009. LNCS, vol. 5689, pp. 40–110.
Springer, Heidelberg (2009). https://doi.org/10.1007/978-3-642-03754-2 2
6. Febbraro, O., Leone, N., Grasso, G., Ricca, F.: JASP: a framework for integrating
answer set programming with Java. In: KR (2012)
7. Fink, M., Germano, S., Ianni, G., Redl, C., Schüller, P.: ActHEX: implementing
HEX programs with action atoms. In: Cabalar, P., Son, T.C. (eds.) LPNMR 2013.
LNCS (LNAI), vol. 8148, pp. 317–322. Springer, Heidelberg (2013). https://doi.
org/10.1007/978-3-642-40564-8 31
8. Gebser, M., Kaminski, R., Kaufmann, B., Ostrowski, M., Schaub, T., Wanko, P.:
Theory solving made easy with clingo 5. In: ICLP. Technical Communications
(2016)
9. Oetsch, J., Pührer, J., Seidl, M., Tompits, H., Zwickl, P.: VIDEAS: a development
tool for answer-set programs based on model-driven engineering technology. In:
Delgrande, J.P., Faber, W. (eds.) LPNMR 2011. LNCS (LNAI), vol. 6645, pp.
382–387. Springer, Heidelberg (2011). https://doi.org/10.1007/978-3-642-20895-
9 45
10. Rath, J., Redl, C.: Integrating answer set programming with object-oriented lan-
guages. In: Lierler, Y., Taha, W. (eds.) PADL 2017. LNCS, vol. 10137, pp. 50–67.
Springer, Cham (2017). https://doi.org/10.1007/978-3-319-51676-9 4
11. Ricca, F.: The DLV Java wrapper. In: de Vos, M., Provetti, A. (eds.) ASP 2003,
pp. 305–316 (2003)
Another random document with
no related content on Scribd:
1.E.6. You may convert to and distribute this work in any binary,
compressed, marked up, nonproprietary or proprietary form,
including any word processing or hypertext form. However, if you
provide access to or distribute copies of a Project Gutenberg™ work
in a format other than “Plain Vanilla ASCII” or other format used in
the official version posted on the official Project Gutenberg™ website
(www.gutenberg.org), you must, at no additional cost, fee or expense
to the user, provide a copy, a means of exporting a copy, or a means
of obtaining a copy upon request, of the work in its original “Plain
Vanilla ASCII” or other form. Any alternate format must include the
full Project Gutenberg™ License as specified in paragraph 1.E.1.
• You pay a royalty fee of 20% of the gross profits you derive from
the use of Project Gutenberg™ works calculated using the
method you already use to calculate your applicable taxes. The
fee is owed to the owner of the Project Gutenberg™ trademark,
but he has agreed to donate royalties under this paragraph to
the Project Gutenberg Literary Archive Foundation. Royalty
payments must be paid within 60 days following each date on
which you prepare (or are legally required to prepare) your
periodic tax returns. Royalty payments should be clearly marked
as such and sent to the Project Gutenberg Literary Archive
Foundation at the address specified in Section 4, “Information
about donations to the Project Gutenberg Literary Archive
Foundation.”
• You comply with all other terms of this agreement for free
distribution of Project Gutenberg™ works.
1.F.
1.F.4. Except for the limited right of replacement or refund set forth in
paragraph 1.F.3, this work is provided to you ‘AS-IS’, WITH NO
OTHER WARRANTIES OF ANY KIND, EXPRESS OR IMPLIED,
INCLUDING BUT NOT LIMITED TO WARRANTIES OF
MERCHANTABILITY OR FITNESS FOR ANY PURPOSE.
Please check the Project Gutenberg web pages for current donation
methods and addresses. Donations are accepted in a number of
other ways including checks, online payments and credit card
donations. To donate, please visit: www.gutenberg.org/donate.
Most people start at our website which has the main PG search
facility: www.gutenberg.org.