Allure-0.5.0.0/ 0000755 0000000 0000000 00000000000 12555263417 011276 5 ustar 00 0000000 0000000 Allure-0.5.0.0/CHANGELOG.md 0000644 0000000 0000000 00000013506 12555263417 013114 0 ustar 00 0000000 0000000 ## [v0.5.0.0, aka 'Halfway through space'](https://github.com/AllureOfTheStars/Allure/compare/v0.4.101.0...v0.5.0.0)
- let AI put excess items in shared stash and use them out of shared stash
- let UI multiple items pickup routine put items that don't fit into equipment into shared stash, if possible, not into inventory pack
- re-enable the ability to hear close, invisible foes
- add a few more AI and autonomous henchmen tactics (CTRL-T)
- keep difficulty setting over session restart
- change some game start keybindings
- replace the Duel game mode with the Raid game mode
- various bugfixes, minor improvements and balancing
## [v0.4.101.1, aka 'Officially fun'](https://github.com/AllureOfTheStars/Allure/compare/v0.4.100.0...v0.4.101.1)
- the game is now officially fun to play, with a seal of the Galactic Council
- introduce unique boss monsters and unique artifact items
- add robots that heal the player, in particular as a mid-game reset for HP
- move spaceship airlock to level 10 and beef up spaceship crew
- let AI gang up, attempt stealth and react to player aggressiveness
- spawn actors fast, close to the enemy and in large numbers
- spawn actors less and less often on a given level, but with growing depth
- prefer weapons with effects, if recharged
- make the bracing melee bonus additive, not multiplicative
- let explosions buffet actors around
- make braced actors immune to translocation effects
- make actor domination yet less common and deadly
- use mouse for movement, actor selection, aiming
- don't run straight with selected actors, but go-to cross-hair with them
- speed up default frame rate, slow down projectiles visually
- rework item manipulation UI
- you can pick up many items at once and it costs only one turn
- allow actors to apply and project from the shared stash
- reverse messages shown in player diary
- display actor organs and stats
- split highscore tables wrt game modes
- move score calculation formula to content
- don't keep the default/example config file commented out; was misleading
- update vs the naughtily changed v0.5.0.0 of LambdaHack content API
## [v0.4.100.0, aka 'The last interstellar thaw'](https://github.com/AllureOfTheStars/Allure/compare/v0.4.99.0...v0.4.100.0)
- update vs the unexpectedly thawed v0.5.0.0 of LambdaHack content API
- unexpectedly add items with timeouts and temporary effects
- start campaign on level 3 and don't spawn aliens until level 4
- rebalance campaign (probably still too hard)
- tweak skills of some factions and actors
- rename tablets to chips to make their vanishing easier to understand
- make colorful characters bold (if it resizes your fonts, turn off via colorIsBold = False in config file or --noColorIsBold on commandline)
- start the game with a screensaver safari mode
- improve keyboard handling on Windows
- add i386 Linux and Windows compilation targets to Makefile
## [v0.4.99.0, aka 'Player escapes through airlock'](https://github.com/AllureOfTheStars/Allure/compare/v0.4.14...v0.4.99.0)
- balance game content a bit (campaign still unbalanced)
- fix a bug where doors can't be closed
- assign AI tactics to players, in particular use follow-the-leader in safari
- specify monster spawn rate per-cave
- generally update content to the new v0.5.0.0 of LambdaHack content API
## [v0.4.14, aka 'Out of cosmic balance'](https://github.com/AllureOfTheStars/Allure/compare/v0.4.12...v0.4.14)
- add tons of new (unbalanced) items, actors and descriptions
- add a simple cabal test in addition to make-test and travis-test
- add items of Wonder and of Marvel
- add game mechanics, items and places to enable stealthy tactics
- add lots of shrapnel (explosions) and organs (body parts)
- expose a bit of the plot via new game modes and their order
## [v0.4.12](https://github.com/AllureOfTheStars/Allure/compare/v0.4.10...v0.4.12)
- make walls lit by default to simplify exploration
- improve and simplify dungeon generation
- simplify running and permit multi-actor runs
- let items explode and generate shrapnel projectiles
- add game difficulty setting (initial HP scaling right now)
- allow recording, playing back and looping commands
- implement pathfinding via per-actor BFS over the whole level
- extend setting targets for actors in UI tremendously
- implement autoexplore, go-to-target, etc., as macros
- let AI use pathfinding, switch leaders, pick levels to swarm to
- force level/leader changes on spawners (even when played by humans)
- extend and redesign UI bottom status lines
## [v0.4.10](https://github.com/AllureOfTheStars/Allure/compare/v0.4.8...v0.4.10)
- screensaver game modes (AI vs AI)
- improved AI (can now climbs stairs, etc.)
- multiple, multi-floor staircases
- multiple savefiles
- configurable framerate and combat animations
## [v0.4.8](https://github.com/AllureOfTheStars/Allure/compare/v0.4.6.5...v0.4.8)
- experimental multiplayer modes
- a lot of gameplay changes induced by the engine overhaul and in particular the client-server rewrite
## [v0.4.6.5](https://github.com/AllureOfTheStars/Allure/compare/v0.4.6...v0.4.6.5)
- this is a minor release, primarily intended to fix the broken compilation on Hackage
- changes since 0.4.6 are mostly unrelated to gameplay:
- strictly typed config files split into UI and rules
- a switch from Text to String throughout the codebase
- use of the external library miniutter for English sentence generation
## [v0.4.6](https://github.com/AllureOfTheStars/Allure/compare/v0.4.4...v0.4.6)
- the Main Menu
- improved and configurable mode of squad combat
## [v0.4.4](https://github.com/AllureOfTheStars/Allure/compare/v0.4.3...v0.4.4)
- missiles flying for three turns (by an old kosmikus' idea)
- visual feedback for targeting
- animations of combat and individual monster moves
## [v0.4.3](https://github.com/AllureOfTheStars/Allure/compare/v0.4.2...v0.4.3)
- the Allure of the Stars game depends on the LambdaHack engine library
Allure-0.5.0.0/CREDITS 0000644 0000000 0000000 00000000276 12555263417 012323 0 ustar 00 0000000 0000000 All kinds of contributions to Allure of the Stars are gratefully welcome!
Some of the contributors are listed below, in chronological order.
Andres Loeh
Mikolaj Konarski
Krzysztof Pławski
Allure-0.5.0.0/LICENSE 0000644 0000000 0000000 00000103330 12555263417 012303 0 ustar 00 0000000 0000000 GNU AFFERO GENERAL PUBLIC LICENSE
Version 3, 19 November 2007
Copyright (C) 2007 Free Software Foundation, Inc.
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU Affero General Public License is a free, copyleft license for
software and other kinds of works, specifically designed to ensure
cooperation with the community in the case of network server software.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
our General Public Licenses are intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
Developers that use our General Public Licenses protect your rights
with two steps: (1) assert copyright on the software, and (2) offer
you this License which gives you legal permission to copy, distribute
and/or modify the software.
A secondary benefit of defending all users' freedom is that
improvements made in alternate versions of the program, if they
receive widespread use, become available for other developers to
incorporate. Many developers of free software are heartened and
encouraged by the resulting cooperation. However, in the case of
software used on network servers, this result may fail to come about.
The GNU General Public License permits making a modified version and
letting the public access it on a server without ever releasing its
source code to the public.
The GNU Affero General Public License is designed specifically to
ensure that, in such cases, the modified source code becomes available
to the community. It requires the operator of a network server to
provide the source code of the modified version running there to the
users of that server. Therefore, public use of a modified version, on
a publicly accessible server, gives the public access to the source
code of the modified version.
An older license, called the Affero General Public License and
published by Affero, was designed to accomplish similar goals. This is
a different license, not a version of the Affero GPL, but Affero has
released a new version of the Affero GPL which permits relicensing under
this license.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU Affero General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Remote Network Interaction; Use with the GNU General Public License.
Notwithstanding any other provision of this License, if you modify the
Program, your modified version must prominently offer all users
interacting with it remotely through a computer network (if your version
supports such interaction) an opportunity to receive the Corresponding
Source of your version by providing access to the Corresponding Source
from a network server at no charge, through some standard or customary
means of facilitating copying of software. This Corresponding Source
shall include the Corresponding Source for any work covered by version 3
of the GNU General Public License that is incorporated pursuant to the
following paragraph.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the work with which it is combined will remain governed by version
3 of the GNU General Public License.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU Affero General Public License from time to time. Such new versions
will be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU Affero General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU Affero General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU Affero General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
Copyright (C)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see .
Also add information on how to contact you by electronic and paper mail.
If your software can interact with users remotely through a computer
network, you should also make sure that it provides a way for users to
get its source. For example, if your program is a web application, its
interface could display a "Source" link that leads users to an archive
of the code. There are many ways you could offer source, and different
solutions will be better for different programs; see section 13 for the
specific requirements.
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU AGPL, see
.
Allure-0.5.0.0/Setup.hs 0000644 0000000 0000000 00000000057 12555263417 012734 0 ustar 00 0000000 0000000 import Distribution.Simple
main = defaultMain
Allure-0.5.0.0/README.md 0000644 0000000 0000000 00000015222 12555263417 012557 0 ustar 00 0000000 0000000 Allure of the Stars [](https://travis-ci.org/AllureOfTheStars/Allure)[](https://drone.io/github.com/AllureOfTheStars/Allure/latest)
===================
[Allure of the Stars] [6] is a near-future Sci-Fi [roguelike] [2]
and tactical squad game. Have a look at [PLAYING.md](GameDefinition/PLAYING.md)
or jump straight into the fray.

The game is written in [Haskell] [1] using the [LambdaHack] [10]
roguelike game engine. Long-term goals of the project are high
replayability and auto-balancing through procedural content generation
and persistent content modification based on player behaviour.
Installation from binary archives
---------------------------------
Pre-compiled game binaries for some platforms are available through
the [release page] [11] and from the [Nix Packages Collection] [12].
To manually install a binary archive, make sure you have the GTK
libraries suite on your system, unpack the Allure archive
and run the executable in the unpacked directory.
On Windows, if you don't already have GTK installed (e.g., for the GIMP
picture editor) please download and run (with default settings)
the GTK installer from
http://sourceforge.net/projects/gtk-win/
Screen and keyboard configuration
---------------------------------
The game UI can be configured via a config file.
A file with the default settings, the same as built into the binary, is in
[GameDefinition/config.ui.default](GameDefinition/config.ui.default).
When the game is run for the first time, the file is copied to the official
location, which is `~/.Allure/config.ui.ini` on Linux and
`C:\Users\\AppData\Roaming\Allure\config.ui.ini`
(or `C:\Documents And Settings\user\Application Data\Allure\config.ui.ini`
or something else altogether) on Windows.
Screen font can be changed and enlarged by editing the config file
at its official location or by CTRL-right-clicking on the game window.
If you use the numeric keypad, use the NumLock key on your keyboard
to toggle the game keyboard mode. With NumLock off, you walk with the numeric
keys and run with SHIFT (or CONTROL) and the keys. This mode is probably
the best if you use mouse for running. When you turn NumLock on,
the reversed key setup enforces good playing habits by setting as the default
the run command (which automatically stops at threats, keeping you safe)
and requiring SHIFT (or CONTROL) for the error-prone step by step walking.
If you don't have the numeric keypad, you can use laptop keys (uk8o79jl)
or you can enable the Vi keys (aka roguelike keys) in the config file.
Compilation from source
-----------------------
If you want to compile your own binaries from the source code,
use Cabal (already a part of your OS distribution, or available within
[The Haskell Platform] [7]), which also takes care of all the dependencies.
You also need the GTK libraries for your OS. On Linux, remember to install
the -dev versions as well. On Windows follow [the same steps as for Wine] [13].
On OSX, if you encounter problems, you may want to
[compile the GTK libraries from sources] [14].
The latest official version of the game can be downloaded,
compiled and installed automatically by Cabal from [Hackage] [3] as follows
cabal update
cabal install gtk2hs-buildtools
cabal install Allure --force-reinstalls
For a newer version, install a matching LambdaHack library snapshot
from a development branch, download the game source from [github] [5]
and run `cabal install` from the main directory.
Compatibility notes
-------------------
If you are using a terminal frontend, numeric keypad may not work
correctly depending on versions of the libraries, terminfo and terminal
emulators. The curses frontend is not fully supported due to the limitations
of the curses library. With the vty frontend started in an xterm,
CTRL-keypad keys for running seem to work OK, but on rxvt they do not.
The commands that require pressing CTRL and SHIFT together won't
work either, but fortunately they are not crucial to gameplay.
For movement, laptop (uk8o79jl) and Vi keys (hjklyubn, if enabled
in config.ui.ini) should work everywhere. GTK works fine, too, both
with numeric keypad and with mouse.
Testing and debugging
---------------------
The [Makefile](Makefile) contains many sample test commands.
Numerous tests that use the screensaver game modes (AI vs. AI)
and the dumb `stdout` frontend are gathered in `make test`.
Of these, travis runs `test-travis-*` on each push to the repo.
Test commands with prefix `frontend` start AI vs. AI games
with the standard, user-friendly gtk frontend.
Run `Allure --help` to see a brief description of all debug options.
Of these, `--sniffIn` and `--sniffOut` are very useful (though verbose
and initially cryptic), for monitoring the traffic between clients
and the server. Some options in the config file may prove useful too,
though they mostly overlap with commandline options (and will be totally
merged at some point).
Further information
-------------------
For more information, visit the [wiki] [4]
and see [PLAYING.md](GameDefinition/PLAYING.md), [CREDITS](CREDITS)
and [LICENSE](LICENSE).
Have fun!
Copyright
---------
Copyright (c) 2008--2011 Andres Loeh, 2010--2015 Mikolaj Konarski
Allure of the Stars is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program in file LICENSE.
If not, see .
[1]: http://www.haskell.org/
[2]: http://roguebasin.roguelikedevelopment.org/index.php?title=Berlin_Interpretation
[3]: http://hackage.haskell.org/package/Allure
[4]: https://github.com/AllureOfTheStars/Allure/wiki
[5]: http://github.com/AllureOfTheStars/Allure
[6]: http://allureofthestars.com
[7]: http://www.haskell.org/platform
[10]: http://github.com/LambdaHack/LambdaHack
[11]: https://github.com/AllureOfTheStars/Allure/releases/latest
[12]: http://hydra.cryp.to/search?query=Allure
[13]: http://www.haskell.org/haskellwiki/GHC_under_Wine#Code_that_uses_gtk2hs
[14]: http://www.edsko.net/2014/04/27/haskell-including-gtk-on-mavericks
Allure-0.5.0.0/Makefile 0000644 0000000 0000000 00000042711 12555263417 012743 0 ustar 00 0000000 0000000 # Copyright (c) 2008--2011 Andres Loeh, 2010--2015 Mikolaj Konarski
# This file is a part of the computer game Allure of the Stars
# and is released under the terms of the GNU Affero General Public License.
# For license and copyright information, see the file LICENSE.
#
# All xc* tests assume a profiling build (for stack traces).
# See the install-debug target below.
install-debug:
cabal install --enable-library-profiling --enable-executable-profiling --ghc-options="-fprof-auto-calls" --disable-optimization
configure-debug:
cabal configure --enable-library-profiling --enable-executable-profiling --ghc-options="-fprof-auto-calls" --disable-optimization
xcplay:
dist/build/Allure/Allure +RTS -xc -RTS --dbgMsgSer --dumpInitRngs
xcfrontendCampaign:
dist/build/Allure/Allure +RTS -xc -RTS --dbgMsgSer --savePrefix test --newGame 1 --maxFps 60 --dumpInitRngs --automateAll --gameMode campaign
xcfrontendRaid:
dist/build/Allure/Allure +RTS -xc -RTS --dbgMsgSer --savePrefix test --newGame 5 --maxFps 60 --dumpInitRngs --automateAll --gameMode raid
xcfrontendSkirmish:
dist/build/Allure/Allure +RTS -xc -RTS --dbgMsgSer --savePrefix test --newGame 5 --maxFps 60 --dumpInitRngs --automateAll --gameMode skirmish
xcfrontendAmbush:
dist/build/Allure/Allure +RTS -xc -RTS --dbgMsgSer --savePrefix test --newGame 5 --maxFps 60 --dumpInitRngs --automateAll --gameMode ambush
xcfrontendBattle:
dist/build/Allure/Allure +RTS -xc -RTS --dbgMsgSer --savePrefix test --newGame 2 --maxFps 60 --dumpInitRngs --automateAll --gameMode battle
xcfrontendBattleSurvival:
dist/build/Allure/Allure +RTS -xc -RTS --dbgMsgSer --savePrefix test --newGame 8 --maxFps 60 --dumpInitRngs --automateAll --gameMode "battle survival"
xcfrontendSafari:
dist/build/Allure/Allure +RTS -xc -RTS --dbgMsgSer --savePrefix test --newGame 2 --maxFps 60 --dumpInitRngs --automateAll --gameMode safari
xcfrontendSafariSurvival:
dist/build/Allure/Allure +RTS -xc -RTS --dbgMsgSer --savePrefix test --newGame 8 --maxFps 60 --dumpInitRngs --automateAll --gameMode "safari survival"
xcfrontendDefense:
dist/build/Allure/Allure +RTS -xc -RTS --dbgMsgSer --savePrefix test --newGame 9 --maxFps 60 --dumpInitRngs --automateAll --gameMode defense
play:
dist/build/Allure/Allure --dbgMsgSer --dumpInitRngs
frontendCampaign:
dist/build/Allure/Allure --dbgMsgSer --savePrefix test --newGame 1 --maxFps 60 --dumpInitRngs --automateAll --gameMode campaign
frontendRaid:
dist/build/Allure/Allure --dbgMsgSer --savePrefix test --newGame 5 --maxFps 60 --dumpInitRngs --automateAll --gameMode raid
frontendSkirmish:
dist/build/Allure/Allure --dbgMsgSer --savePrefix test --newGame 5 --maxFps 60 --dumpInitRngs --automateAll --gameMode skirmish
frontendAmbush:
dist/build/Allure/Allure --dbgMsgSer --savePrefix test --newGame 5 --maxFps 60 --dumpInitRngs --automateAll --gameMode ambush
frontendBattle:
dist/build/Allure/Allure --dbgMsgSer --savePrefix test --newGame 2 --maxFps 60 --dumpInitRngs --automateAll --gameMode battle
frontendBattleSurvival:
dist/build/Allure/Allure --dbgMsgSer --savePrefix test --newGame 8 --maxFps 60 --dumpInitRngs --automateAll --gameMode "battle survival"
frontendSafari:
dist/build/Allure/Allure --dbgMsgSer --savePrefix test --newGame 2 --maxFps 60 --dumpInitRngs --automateAll --gameMode safari
frontendSafariSurvival:
dist/build/Allure/Allure --dbgMsgSer --savePrefix test --newGame 8 --maxFps 60 --dumpInitRngs --automateAll --gameMode "safari survival"
frontendDefense:
dist/build/Allure/Allure --dbgMsgSer --savePrefix test --newGame 9 --maxFps 60 --dumpInitRngs --automateAll --gameMode defense
benchCampaign:
dist/build/Allure/Allure --dbgMsgSer --savePrefix test --newGame 1 --noDelay --noAnim --maxFps 100000 --frontendNull --benchmark --stopAfter 60 --automateAll --keepAutomated --gameMode campaign --setDungeonRng 42 --setMainRng 42 +RTS -N1 -RTS
benchBattle:
dist/build/Allure/Allure --dbgMsgSer --savePrefix test --newGame 2 --noDelay --noAnim --maxFps 100000 --frontendNull --benchmark --stopAfter 60 --automateAll --keepAutomated --gameMode battle --setDungeonRng 42 --setMainRng 42 +RTS -N1 -RTS
benchFrontendCampaign:
dist/build/Allure/Allure --dbgMsgSer --savePrefix test --newGame 1 --maxFps 100000 --benchmark --stopAfter 60 --automateAll --keepAutomated --gameMode campaign --setDungeonRng 42 --setMainRng 42 +RTS -N1 -RTS
benchFrontendBattle:
dist/build/Allure/Allure --dbgMsgSer --savePrefix test --newGame 2 --maxFps 100000 --benchmark --stopAfter 60 --automateAll --keepAutomated --gameMode battle --setDungeonRng 42 --setMainRng 42 +RTS -N1 -RTS
benchNull: benchCampaign benchBattle
bench: benchCampaign benchFrontendCampaign benchBattle benchFrontendBattle
test-travis-short: test-short
test-travis-medium: test-short test-medium
test-travis-medium-no-safari: test-short test-medium-no-safari
test-travis-long: test-short test-long
test-travis-long-no-safari: test-short test-long-no-safari
test: test-short test-medium test-long
test-short: test-short-new test-short-load
test-medium: testCampaign-medium testRaid-medium testSkirmish-medium testAmbush-medium testBattle-medium testBattleSurvival-medium testSafari-medium testSafariSurvival-medium testPvP-medium testCoop-medium testDefense-medium
test-medium-no-safari: testCampaign-medium testRaid-medium testSkirmish-medium testAmbush-medium testBattle-medium testBattleSurvival-medium testPvP-medium testCoop-medium testDefense-medium
test-long: testCampaign-long testRaid-medium testSkirmish-medium testAmbush-medium testBattle-long testBattleSurvival-long testSafari-long testSafariSurvival-long testPvP-medium testDefense-long
test-long-no-safari: testCampaign-long testRaid-medium testSkirmish-medium testAmbush-medium testBattle-long testBattleSurvival-long testPvP-medium testDefense-long
testCampaign-long:
dist/build/Allure/Allure --dbgMsgSer --savePrefix test --newGame 1 --noDelay --noAnim --maxFps 100000 --frontendStd --benchmark --stopAfter 500 --dumpInitRngs --automateAll --keepAutomated --gameMode campaign > /tmp/stdtest.log
testCampaign-medium:
dist/build/Allure/Allure --dbgMsgSer --savePrefix test --newGame 1 --noDelay --noAnim --maxFps 100000 --frontendStd --benchmark --stopAfter 400 --dumpInitRngs --automateAll --keepAutomated --gameMode campaign > /tmp/stdtest.log
testRaid-long:
dist/build/Allure/Allure --dbgMsgSer --savePrefix test --newGame 5 --maxFps 100000 --frontendStd --benchmark --stopAfter 60 --dumpInitRngs --automateAll --keepAutomated --gameMode raid > /tmp/stdtest.log
testRaid-medium:
dist/build/Allure/Allure --dbgMsgSer --savePrefix test --newGame 5 --maxFps 100000 --frontendStd --benchmark --stopAfter 30 --dumpInitRngs --automateAll --keepAutomated --gameMode raid > /tmp/stdtest.log
testSkirmish-long:
dist/build/Allure/Allure --dbgMsgSer --savePrefix test --newGame 5 --maxFps 100000 --frontendStd --benchmark --stopAfter 60 --dumpInitRngs --automateAll --keepAutomated --gameMode skirmish > /tmp/stdtest.log
testSkirmish-medium:
dist/build/Allure/Allure --dbgMsgSer --savePrefix test --newGame 5 --maxFps 100000 --frontendStd --benchmark --stopAfter 30 --dumpInitRngs --automateAll --keepAutomated --gameMode skirmish > /tmp/stdtest.log
testAmbush-long:
dist/build/Allure/Allure --dbgMsgSer --savePrefix test --newGame 5 --noDelay --noAnim --maxFps 100000 --frontendStd --benchmark --stopAfter 60 --dumpInitRngs --automateAll --keepAutomated --gameMode ambush > /tmp/stdtest.log
testAmbush-medium:
dist/build/Allure/Allure --dbgMsgSer --savePrefix test --newGame 5 --noDelay --noAnim --maxFps 100000 --frontendStd --benchmark --stopAfter 30 --dumpInitRngs --automateAll --keepAutomated --gameMode ambush > /tmp/stdtest.log
testBattle-long:
dist/build/Allure/Allure --dbgMsgSer --savePrefix test --newGame 2 --noDelay --noAnim --maxFps 100000 --frontendStd --benchmark --stopAfter 100 --dumpInitRngs --automateAll --keepAutomated --gameMode battle > /tmp/stdtest.log
testBattle-medium:
dist/build/Allure/Allure --dbgMsgSer --savePrefix test --newGame 2 --noDelay --noAnim --maxFps 100000 --frontendStd --benchmark --stopAfter 50 --dumpInitRngs --automateAll --keepAutomated --gameMode battle > /tmp/stdtest.log
testBattleSurvival-long:
dist/build/Allure/Allure --dbgMsgSer --savePrefix test --newGame 8 --noDelay --noAnim --maxFps 100000 --frontendStd --benchmark --stopAfter 100 --dumpInitRngs --automateAll --keepAutomated --gameMode "battle survival" > /tmp/stdtest.log
testBattleSurvival-medium:
dist/build/Allure/Allure --dbgMsgSer --savePrefix test --newGame 8 --noDelay --noAnim --maxFps 100000 --frontendStd --benchmark --stopAfter 50 --dumpInitRngs --automateAll --keepAutomated --gameMode "battle survival" > /tmp/stdtest.log
testSafari-long:
dist/build/Allure/Allure --dbgMsgSer --savePrefix test --newGame 2 --noDelay --noAnim --maxFps 100000 --frontendStd --benchmark --stopAfter 250 --dumpInitRngs --automateAll --keepAutomated --gameMode safari > /tmp/stdtest.log
testSafari-medium:
dist/build/Allure/Allure --dbgMsgSer --savePrefix test --newGame 2 --noDelay --noAnim --maxFps 100000 --frontendStd --benchmark --stopAfter 200 --dumpInitRngs --automateAll --keepAutomated --gameMode safari > /tmp/stdtest.log
testSafariSurvival-long:
dist/build/Allure/Allure --dbgMsgSer --savePrefix test --newGame 8 --noDelay --noAnim --maxFps 100000 --frontendStd --benchmark --stopAfter 250 --dumpInitRngs --automateAll --keepAutomated --gameMode "safari survival" > /tmp/stdtest.log
testSafariSurvival-medium:
dist/build/Allure/Allure --dbgMsgSer --savePrefix test --newGame 8 --noDelay --noAnim --maxFps 100000 --frontendStd --benchmark --stopAfter 200 --dumpInitRngs --automateAll --keepAutomated --gameMode "safari survival" > /tmp/stdtest.log
testPvP-long:
dist/build/Allure/Allure --dbgMsgSer --savePrefix test --newGame 5 --noDelay --noAnim --maxFps 100000 --frontendStd --benchmark --stopAfter 60 --dumpInitRngs --automateAll --keepAutomated --gameMode PvP > /tmp/stdtest.log
testPvP-medium:
dist/build/Allure/Allure --dbgMsgSer --savePrefix test --newGame 5 --noDelay --noAnim --maxFps 100000 --frontendStd --benchmark --stopAfter 30 --dumpInitRngs --automateAll --keepAutomated --gameMode PvP > /tmp/stdtest.log
testCoop-long:
dist/build/Allure/Allure --dbgMsgSer --savePrefix test --newGame 2 --noDelay --noAnim --maxFps 100000 --frontendStd --benchmark --stopAfter 500 --dumpInitRngs --automateAll --keepAutomated --gameMode Coop > /tmp/stdtest.log
testCoop-medium:
dist/build/Allure/Allure --dbgMsgSer --savePrefix test --newGame 2 --noDelay --noAnim --maxFps 100000 --frontendStd --benchmark --stopAfter 300 --dumpInitRngs --automateAll --keepAutomated --gameMode Coop > /tmp/stdtest.log
testDefense-long:
dist/build/Allure/Allure --dbgMsgSer --savePrefix test --newGame 9 --noDelay --noAnim --maxFps 100000 --frontendStd --benchmark --stopAfter 500 --dumpInitRngs --automateAll --keepAutomated --gameMode defense > /tmp/stdtest.log
testDefense-medium:
dist/build/Allure/Allure --dbgMsgSer --savePrefix test --newGame 9 --noDelay --noAnim --maxFps 100000 --frontendStd --benchmark --stopAfter 300 --dumpInitRngs --automateAll --keepAutomated --gameMode defense > /tmp/stdtest.log
test-short-new:
dist/build/Allure/Allure --dbgMsgSer --newGame 5 --savePrefix campaign --dumpInitRngs --automateAll --keepAutomated --gameMode campaign --frontendStd --stopAfter 2 > /tmp/stdtest.log
dist/build/Allure/Allure --dbgMsgSer --newGame 5 --savePrefix raid --dumpInitRngs --automateAll --keepAutomated --gameMode raid --frontendStd --stopAfter 2 > /tmp/stdtest.log
dist/build/Allure/Allure --dbgMsgSer --newGame 5 --savePrefix skirmish --dumpInitRngs --automateAll --keepAutomated --gameMode skirmish --frontendStd --stopAfter 2 > /tmp/stdtest.log
dist/build/Allure/Allure --dbgMsgSer --newGame 5 --savePrefix ambush --dumpInitRngs --automateAll --keepAutomated --gameMode ambush --frontendStd --stopAfter 2 > /tmp/stdtest.log
dist/build/Allure/Allure --dbgMsgSer --newGame 5 --savePrefix battle --dumpInitRngs --automateAll --keepAutomated --gameMode battle --frontendStd --stopAfter 2 > /tmp/stdtest.log
dist/build/Allure/Allure --dbgMsgSer --newGame 5 --savePrefix battleSurvival --dumpInitRngs --automateAll --keepAutomated --gameMode "battle survival" --frontendStd --stopAfter 2 > /tmp/stdtest.log
dist/build/Allure/Allure --dbgMsgSer --newGame 5 --savePrefix safari --dumpInitRngs --automateAll --keepAutomated --gameMode safari --frontendStd --stopAfter 2 > /tmp/stdtest.log
dist/build/Allure/Allure --dbgMsgSer --newGame 5 --savePrefix safariSurvival --dumpInitRngs --automateAll --keepAutomated --gameMode "safari survival" --frontendStd --stopAfter 2 > /tmp/stdtest.log
dist/build/Allure/Allure --dbgMsgSer --newGame 5 --savePrefix PvP --dumpInitRngs --automateAll --keepAutomated --gameMode PvP --frontendStd --stopAfter 2 > /tmp/stdtest.log
dist/build/Allure/Allure --dbgMsgSer --newGame 5 --savePrefix Coop --dumpInitRngs --automateAll --keepAutomated --gameMode Coop --frontendStd --stopAfter 2 > /tmp/stdtest.log
dist/build/Allure/Allure --dbgMsgSer --newGame 5 --savePrefix defense --dumpInitRngs --automateAll --keepAutomated --gameMode defense --frontendStd --stopAfter 2 > /tmp/stdtest.log
test-short-load:
dist/build/Allure/Allure --dbgMsgSer --savePrefix campaign --dumpInitRngs --automateAll --keepAutomated --gameMode campaign --frontendStd --stopAfter 2 > /tmp/stdtest.log
dist/build/Allure/Allure --dbgMsgSer --savePrefix raid --dumpInitRngs --automateAll --keepAutomated --gameMode raid --frontendStd --stopAfter 2 > /tmp/stdtest.log
dist/build/Allure/Allure --dbgMsgSer --savePrefix skirmish --dumpInitRngs --automateAll --keepAutomated --gameMode skirmish --frontendStd --stopAfter 2 > /tmp/stdtest.log
dist/build/Allure/Allure --dbgMsgSer --savePrefix ambush --dumpInitRngs --automateAll --keepAutomated --gameMode ambush --frontendStd --stopAfter 2 > /tmp/stdtest.log
dist/build/Allure/Allure --dbgMsgSer --savePrefix battle --dumpInitRngs --automateAll --keepAutomated --gameMode battle --frontendStd --stopAfter 2 > /tmp/stdtest.log
dist/build/Allure/Allure --dbgMsgSer --savePrefix battleSurvival --dumpInitRngs --automateAll --keepAutomated --gameMode "battle survival" --frontendStd --stopAfter 2 > /tmp/stdtest.log
dist/build/Allure/Allure --dbgMsgSer --savePrefix safari --dumpInitRngs --automateAll --keepAutomated --gameMode safari --frontendStd --stopAfter 2 > /tmp/stdtest.log
dist/build/Allure/Allure --dbgMsgSer --savePrefix safariSurvival --dumpInitRngs --automateAll --keepAutomated --gameMode "safari survival" --frontendStd --stopAfter 2 > /tmp/stdtest.log
dist/build/Allure/Allure --dbgMsgSer --savePrefix PvP --dumpInitRngs --automateAll --keepAutomated --gameMode PvP --frontendStd --stopAfter 2 > /tmp/stdtest.log
dist/build/Allure/Allure --dbgMsgSer --savePrefix Coop --dumpInitRngs --automateAll --keepAutomated --gameMode Coop --frontendStd --stopAfter 2 > /tmp/stdtest.log
dist/build/Allure/Allure --dbgMsgSer --savePrefix defense --dumpInitRngs --automateAll --keepAutomated --gameMode defense --frontendStd --stopAfter 2 > /tmp/stdtest.log
build-binary:
cabal configure -frelease --prefix=/
cabal build Allure
rm -rf /tmp/Allure_x_ubuntu-12.04-amd64.tar.gz
rm -rf /tmp/AllureOfTheStarsInstall
rm -rf /tmp/AllureOfTheStars
mkdir -p /tmp/AllureOfTheStars/GameDefinition
cabal copy --destdir=/tmp/AllureOfTheStarsInstall
cp /tmp/AllureOfTheStarsInstall/bin/Allure /tmp/AllureOfTheStars
cp GameDefinition/PLAYING.md /tmp/AllureOfTheStars/GameDefinition
cp GameDefinition/scores /tmp/AllureOfTheStars/GameDefinition
cp GameDefinition/config.ui.default /tmp/AllureOfTheStars/GameDefinition
cp CHANGELOG.md /tmp/AllureOfTheStars
cp CREDITS /tmp/AllureOfTheStars
cp LICENSE /tmp/AllureOfTheStars
cp README.md /tmp/AllureOfTheStars
tar -czf /tmp/Allure_x_ubuntu-12.04-amd64.tar.gz -C /tmp AllureOfTheStars
build-binary-i386:
cabal configure -frelease --prefix=/ --ghc-option="-optc-m32" --ghc-option="-opta-m32" --ghc-option="-optl-m32" --ld-option="-melf_i386"
cabal build Allure
rm -rf /tmp/Allure_x_ubuntu-12.04-i386.tar.gz
rm -rf /tmp/AllureOfTheStarsInstall
rm -rf /tmp/AllureOfTheStars
mkdir -p /tmp/AllureOfTheStars/GameDefinition
cabal copy --destdir=/tmp/AllureOfTheStarsInstall
cp /tmp/AllureOfTheStarsInstall/bin/Allure /tmp/AllureOfTheStars
cp GameDefinition/PLAYING.md /tmp/AllureOfTheStars/GameDefinition
cp GameDefinition/scores /tmp/AllureOfTheStars/GameDefinition
cp GameDefinition/config.ui.default /tmp/AllureOfTheStars/GameDefinition
cp CHANGELOG.md /tmp/AllureOfTheStars
cp CREDITS /tmp/AllureOfTheStars
cp LICENSE /tmp/AllureOfTheStars
cp README.md /tmp/AllureOfTheStars
tar -czf /tmp/Allure_x_ubuntu-12.04-i386.tar.gz -C /tmp AllureOfTheStars
# TODO: figure out, whey this must be so different from Linux
build-binary-windows-i386:
wine cabal configure -frelease
wine cabal build exe:Allure
rm -rf /tmp/Allure_x_windows-i386.zip
rm -rf /tmp/AllureOfTheStarsInstall
rm -rf /tmp/AllureOfTheStars
mkdir -p /tmp/AllureOfTheStars/GameDefinition
wine cabal copy --destdir=Z:/tmp/AllureOfTheStarsInstall
cp /tmp/AllureOfTheStarsInstall/users/mikolaj/Application\ Data/cabal/bin/Allure.exe /tmp/AllureOfTheStars
cp GameDefinition/PLAYING.md /tmp/AllureOfTheStars/GameDefinition
cp GameDefinition/scores /tmp/AllureOfTheStars/GameDefinition
cp GameDefinition/config.ui.default /tmp/AllureOfTheStars/GameDefinition
cp CHANGELOG.md /tmp/AllureOfTheStars
cp CREDITS /tmp/AllureOfTheStars
cp LICENSE /tmp/AllureOfTheStars
cp README.md /tmp/AllureOfTheStars
cp /home/mikolaj/.wine/drive_c/users/mikolaj/gtk/bin/zlib1.dll /tmp/AllureOfTheStars
wine Z:/home/mikolaj/.local/share/wineprefixes/7zip/drive_c/Program\ Files/7-Zip/7z.exe a -ssc -sfx Z:/tmp/Allure_x_windows-i386.exe Z:/tmp/AllureOfTheStars
Allure-0.5.0.0/Allure.cabal 0000644 0000000 0000000 00000011742 12555263417 013513 0 ustar 00 0000000 0000000 name: Allure
-- The package version. See the Haskell package versioning policy (PVP)
-- for standards guiding when and how versions should be incremented.
-- http://www.haskell.org/haskellwiki/Package_versioning_policy
-- PVP summary:+-+------- breaking API changes
-- | | +----- non-breaking API additions
-- | | | +--- code changes with no API change
version: 0.5.0.0
synopsis: Near-future Sci-Fi roguelike and tactical squad game
description: Allure of the Stars
is a near-future Sci-Fi roguelike and tactical squad game.
See the wiki for design notes and contribute.
.
<>
.
Please see the changelog file for recent improvements
and the issue tracker for short-term plans. Long term goals
are high replayability and auto-balancing through procedural
content generation and persistent content modification
based on player behaviour.
.
The game is written using the LambdaHack roguelike game engine
available at .
homepage: http://allureofthestars.com
bug-reports: http://github.com/AllureOfTheStars/Allure/issues
license: AGPL-3
license-file: LICENSE
tested-with: GHC == 7.6, GHC == 7.8, GHC == 7.10
data-files: GameDefinition/config.ui.default, GameDefinition/scores,
GameDefinition/PLAYING.md, README.md, LICENSE, CREDITS,
CHANGELOG.md
extra-source-files: GameDefinition/MainMenu.ascii, Makefile
author: Andres Loeh, Mikolaj Konarski and others
maintainer: Mikolaj Konarski
category: Game
build-type: Simple
cabal-version: >= 1.10
source-repository head
type: git
location: git://github.com/AllureOfTheStars/Allure.git
flag release
description: prepare for a release (expose, optimize, etc.)
default: True
manual: True
executable Allure
hs-source-dirs: GameDefinition
main-is: Main.hs
other-modules: Client.UI.Content.KeyKind,
Content.CaveKind,
Content.ItemKind,
Content.ItemKindActor,
Content.ItemKindOrgan,
Content.ItemKindBlast,
Content.ItemKindTemporary,
Content.ModeKind,
Content.ModeKindPlayer,
Content.PlaceKind,
Content.RuleKind,
Content.TileKind,
TieKnot,
Paths_Allure
build-depends: LambdaHack >= 0.5.0.0 && < 0.5.1.0,
template-haskell >= 2.6 && < 3,
base >= 4 && < 5,
containers >= 0.5.3.0 && < 1,
enummapset-th >= 0.6.0.0 && < 1,
filepath >= 1.2.0.1 && < 2,
text >= 0.11.2.3 && < 2
default-language: Haskell2010
default-extensions: MonoLocalBinds, ScopedTypeVariables, OverloadedStrings
BangPatterns, RecordWildCards, NamedFieldPuns
other-extensions: TemplateHaskell
ghc-options: -Wall -fwarn-orphans -fwarn-tabs -fwarn-incomplete-uni-patterns -fwarn-incomplete-record-updates -fwarn-monomorphism-restriction -fwarn-unrecognised-pragmas
ghc-options: -fno-warn-auto-orphans -fno-warn-implicit-prelude
ghc-options: -fno-ignore-asserts -funbox-strict-fields
ghc-options: -threaded "-with-rtsopts=-C0.005" -rtsopts
if flag(release)
ghc-options: -O2 -fno-ignore-asserts "-with-rtsopts=-N1"
-- TODO: -N
test-suite test
type: exitcode-stdio-1.0
hs-source-dirs: GameDefinition, test
main-is: test.hs
build-depends: LambdaHack,
template-haskell >= 2.6 && < 3,
base >= 4 && < 5,
containers >= 0.5.3.0 && < 1,
enummapset-th >= 0.6.0.0 && < 1,
filepath >= 1.2.0.1 && < 2,
text >= 0.11.2.3 && < 2
default-language: Haskell2010
default-extensions: MonoLocalBinds, ScopedTypeVariables, OverloadedStrings
BangPatterns, RecordWildCards, NamedFieldPuns
other-extensions: TemplateHaskell
ghc-options: -Wall -fwarn-orphans -fwarn-tabs -fwarn-incomplete-uni-patterns -fwarn-incomplete-record-updates -fwarn-monomorphism-restriction -fwarn-unrecognised-pragmas
ghc-options: -fno-warn-auto-orphans -fno-warn-implicit-prelude
ghc-options: -fno-ignore-asserts -funbox-strict-fields
ghc-options: -threaded "-with-rtsopts=-C0.005" -rtsopts
if flag(release)
ghc-options: -O2 -fno-ignore-asserts "-with-rtsopts=-N1"
-- TODO: -N
Allure-0.5.0.0/GameDefinition/ 0000755 0000000 0000000 00000000000 12555263417 014160 5 ustar 00 0000000 0000000 Allure-0.5.0.0/GameDefinition/MainMenu.ascii 0000644 0000000 0000000 00000004156 12555263417 016711 0 ustar 00 0000000 0000000 ----------------------------------------------------------------------------------
| |
| >> Allure of the Stars << |
| |
| |
| {{{{{{{{{{{{{{{{{{{{{{{{{ |
| |
| {{{{{{{{{{{{{{{{{{{{{{{{{ |
| |
| {{{{{{{{{{{{{{{{{{{{{{{{{ |
| |
| {{{{{{{{{{{{{{{{{{{{{{{{{ |
| |
| {{{{{{{{{{{{{{{{{{{{{{{{{ |
| |
| {{{{{{{{{{{{{{{{{{{{{{{{{ |
| |
| {{{{{{{{{{{{{{{{{{{{{{{{{ |
| |
| {{{{{{{{{{{{{{{{{{{{{{{{{ |
| |
| {{{{{{{{{{{{{{{{{{{{{{{{{ |
| |
| |
| Version X.X.X (frontend: gtk, engine: LambdaHack X.X.X) |
----------------------------------------------------------------------------------
Allure-0.5.0.0/GameDefinition/Main.hs 0000644 0000000 0000000 00000001224 12555263417 015377 0 ustar 00 0000000 0000000 -- Copyright (c) 2008--2011 Andres Loeh, 2010--2015 Mikolaj Konarski
-- This file is a part of the computer game Allure of the Stars
-- and is released under the terms of the GNU Affero General Public License.
-- For license and copyright information, see the file LICENSE.
--
-- | The main source code file of Allure of the Stars.
-- Module "TieKnot" is separated to make it usable in tests.
module Main ( main ) where
import System.Environment (getArgs)
import TieKnot
-- | Tie the LambdaHack engine client, server and frontend code
-- with the game-specific content definitions, and run the game.
main :: IO ()
main = do
args <- getArgs
tieKnot args
Allure-0.5.0.0/GameDefinition/scores 0000644 0000000 0000000 00000001702 12555263417 015401 0 ustar 00 0000000 0000000 xœ¥VMLAÝ™ÝþHBD=¨±‰QÆ„‹!ñ" ‰#R‰‰*,¸¡\0¨!áàI=y1‰0Ñ(PÑJñÿDE8y0CEÄÝ2oºvS[ã\æíîÌ|ß{󿛄`³¬‰‹]\`AkµÃ§Ówît!ì³¥.scëU‰=Åa–…õK÷Vx
åb*«®mª\Í^“N(ë×øpÞg ¾K°=Àì>DégÀþ³ö#±ò~Ê@Â3€A¬üD^`ð+|z
0„à 1Â@Ò¬o1ø>bå÷,ù cÌúq]êÁ##~ÁÝž6fº)óRŠ6X°±>‚Ô´ºð†õ‰~¼€æšK ,…°zÈH #1ÉH #DHÄ•‘ éôç{Ú\šÓfCô…¡Škå
Qé‡[Žš2ᡘçé=“o)M‚[¹‘k؈/ƒ
x}´LМp/YâÚ´Ä$2åJ¾à†Dþ"”á1d\™RtI“ç
D
ê×"±X‰p%¹YÛ®Gùuj•&W¡(éõŸ®ülÛG{Ôx£Njþ€Á'ÙÎÙ$ñÃñ ‘üBÖëá~ÌmÖNeKÉ AÆT÷»(§R¼i¢‰ã‰…©yëÛ‚¶¼§•ŸüæÙ†LNÖ_/Û|8ñø‚ÃJ•ìÚá©,•½^9Ð_È hŠ
h
n þ(¸óÄC5[èN†±n ¹Å “’Úõ(³_'4Wµ|¶\Õ°u5fñ(¸·"¹*lõиëXT÷”NJj4¸*mò„)\4GGð†Åu´ãÙ+Ïy.׿0Zt(¢˜Ë3Ô2¹È!z7 ëyÅw â[QñpËJ¼<¡ôóòDPžD”'Ê“„;€×)ŠªdGU¢¨J"n>hÞ,%‰uwû”a‹›W‚²-ÄÆJI lã—(‡n2+ ëÏê‰}ŸÒj‚;¯Öp=5W"ÓOOr†W‘}®üò£ªRYåÊ).V
ep÷3`E>ù€—•üÛ‚à÷å)Co Ó‘d¯žûôd@ϽÚeÈ]ÍM=ƒ”M†Z—áSÊ<^×nO‰OÑóöUi
Ë…J™ÆhŸGUäªãl¨W¬» ¦«í/™s§à$pi¨IÑñ'¹¸9ܤe“ö7ªô©†ÒÓ•ÕïŒø7ÓÆX]Dt¸Â‰»Æ@˜šþD%H`ÁŸ(?>V+?>èsvýíñ¤Y Allure-0.5.0.0/GameDefinition/PLAYING.md 0000644 0000000 0000000 00000025740 12555263417 015615 0 ustar 00 0000000 0000000 Playing Allure of the Stars
===========================
Your party of trusted crew-members is about to test their fortune
by exploring an abandoned Solar System passenger cruiser.
You are going to set up ambushes for it's feral denizens, hide in shadows,
cover tracks, bump into unspeakable horrors, hidden mechanisms
and astounding technical treasures and make creative use of it all.
The mysterious inhabitants of the gigantic spaceship are bound
to welcome intruders with bloody surprises of their own.
As soon as you turn your back in fear, expect to be chased tirelessly
throughout all the decks, by sight, sound and smell.
Once the few basic command keys and on-screen symbols are learned,
mastery and enjoyment of the game is the matter of tactical skill
and literary imagination. To be honest, a lot of imagination is required
at this stage of game development, but the game is already playable
and winnable. Contributions are welcome.
Heroes
------
The heroes are marked on the map with symbols `@` and `1` through `9`.
Their goal is to explore a warped, old, once luxurious space liner,
battle the horrors within, gather as much gold and precious gems
as possible, and escape to tell the tale.
The currently chosen party leader is highlighted on the screen
and his attributes are displayed at the bottommost status line,
which in its most complex form may look as follows.
*@12 Adventurer 4d1+5% Calm: 20/60 HP: 33/50 Target: basilisk [**__]
The line starts with the list of party members (unless there's only one member)
and the shortened name of the team. Clicking on the list selects heroes and
the selected run together when `:` or `SHIFT`-left mouse button is pressed.
Then comes the damage of the highest damage dice weapon the leader can use,
then his current and maximum Calm (composure, focus, attentiveness), then
his current and maximum HP (hit points, health). At the end, the personal
target of the leader is described, in this case a basilisk monster,
with hit points drawn as a bar. Weapon damage and other item stats
are displayed using the dice notation `XdY`, which means X rolls
of Y-sided dice. A variant denoted `XdsY` is additionally
scaled by the level depth in proportion to the maximal spaceship depth.
You can read more about combat resolution in section Monsters below.
The second status line describes the current level in relation
to the party.
5 Lofty hall [33% seen] X-hair: exact spot (71,12) p15 l10
First comes the depth of the current level and its name.
Then the percentage of its explorable tiles already seen by the heroes.
The 'X-hair' (meaning 'crosshair') is the common focus of the whole party,
denoted on the map by a white box and manipulated with movement keys
in aiming mode. At the end of the status line comes the length of the shortest
path from the leader to the crosshair position and the straight-line distance
between the two points.
Spaceship
---------
The spaceship and other scenario locations consist of one or many
levels or decks and each deck consists of a large number of tiles.
The basic tile kinds are as follows.
terrain type on-screen symbol
floor .
wall #
rock or tree O
cache &
stairs up <
stairs down >
open door '
closed door +
The game world is persistent, i.e., every time the player visits a deck
during a single game, its layout is the same.
Commands
--------
You walk throughout a level using the left mouse button or the numeric
keypad (left diagram) or its compact laptop replacement (middle)
or Vi text editor keys (right, also known as "Rogue-like keys",
which have to be enabled in config.ui.ini).
7 8 9 7 8 9 y k u
\|/ \|/ \|/
4-5-6 u-i-o h-.-l
/|\ /|\ /|\
1 2 3 j k l b j n
In aiming mode (`KEYPAD_*` or `\`) the same keys (or the middle and right
mouse buttons) move the crosshair (the white box). In normal mode,
`SHIFT` (or `CTRL`) and a movement key make the current party leader
run in the indicated direction, until anything of interest is spotted.
The `5` keypad key and the `i` and `.` keys consume a turn and make you
brace for combat, which reduces any damage taken for a turn and makes it
impossible for foes to displace you. You displace enemies or friends
by bumping into them with `SHIFT` (or `CTRL`).
Melee, searching for secret doors, looting and opening closed doors
can be done by bumping into a monster, a wall and a door, respectively.
Few commands other than movement, 'g'etting an item from the floor,
'a'pplying an item and 'f'linging an item are necessary for casual play.
Some are provided only as specialized versions of the more general
commands or as building blocks for more complex convenience macros.
E.g., the autoexplore command (key `X`) could be defined
by the player as a macro using `CTRL-?`, `CTRL-.` and `V`.
The following minimal command set lets you accomplish almost anything
in the game, though not necessarily with the fewest number of keystrokes.
The full list of commands can be seen in the in-game help accessible
from the Main Menu.
keys command
< ascend a level
> descend a level
c close door
E manage equipment of the leader
g or , get items
a apply consumable
f fling projectile
+ swerve the aiming line
D display player diary
T toggle suspect terrain display
SHIFT-TAB cycle among all party members
ESC cancel action, open Main Menu
The only activity not possible with the commands above is the management
of non-leader party members. You don't need it, unless your non-leader actors
can move or fire opportunistically (via innate skills or rare equipment).
If really needed, you can manually set party tactics with `CTRL-T`
and you can assign individual targets to party members using the aiming
and targeting commands listed below.
keys command
KEYPAD_* or \ aim at an enemy
KEYPAD_/ or | cycle aiming styles
+ swerve the aiming line
- unswerve the aiming line
CTRL-? set crosshair to the closest unknown spot
CTRL-I set crosshair to the closest item
CTRL-{ set crosshair to the closest stairs up
CTRL-} set crosshair to the closest stairs down
BACKSPACE reset target/crosshair
RET or INSERT accept target/choice
For ranged attacks, setting the crosshair or individual targets
beforehand is not mandatory, because the crosshair is set automatically
as soon as a monster comes into view and can still be adjusted while
in the missile choice menu. However, if you want to assign persistent
personal targets or just inspect the level map closely, you can enter
the detailed aiming mode with the right mouse button or with
the `*` keypad key that selects enemies or the `/` keypad key that
marks a tile. You can move the aiming crosshair with direction keys
and assign a personal target to the leader with `RET`.
The details of the shared crosshair position and of the personal target
are described in the status lines at the bottom of the screen.
Commands for saving and exiting the current game, starting a new game, etc.,
are listed in the Main Menu, brought up by the `ESC` key.
Game difficulty setting affects hitpoints at birth for any actors
of any UI-using faction. For a person new to roguelikes, the Raid scenario
offers a gentle introduction. The subsequent game modes gradually introduce
squad combat, stealth, opportunity fire, asymmetric battles and more.
Monsters
--------
Heroes are not alone in the spaceship. Monstrosities, natural
and out of this world, roam the dark halls and crawl from damp air-ducts
day and night. While heroes pay attention to all other party members
and take care to move one at a time, monsters don't care about each other
and all move at once, sometimes brutally colliding by accident.
When the hero bumps into a monster or a monster attacks the hero,
melee combat occurs. Heroes and monsters running into one another
(with the `SHIFT` key) do not inflict damage, but change places.
This gives the opponent a free blow, but can improve the tactical situation
or aid escape. In some circumstances actors are immune to the displacing,
e.g., when both parties form a continuous front-line.
In melee combat, the best equipped weapon (or the best fighting organ)
of each opponent is taken into account for determining the damage
and any extra effects of the blow. If a recharged weapon with a non-trivial
effect is in the equipment, it is preferred for combat. Otherwise combat
involves the weapon with the highest raw damage dice (the same as displayed
at bottommost status line).
To determine the damage dealt, the outcome of the weapon's damage dice roll
is multiplied by the melee damage bonus (summed from the equipped items
of the attacker) minus the melee armor modifier of the defender.
Regardless of the calculation, each attack inflicts at least 1 damage.
The current leader's melee bonus, armor modifier and other detailed
stats can be viewed via the `!` command.
In ranged combat, the missile is assumed to be attacking the defender
in melee, using itself as the weapon, but the ranged damage bonus
and the ranged armor modifier are taken into account for calculations.
You may propel any item in your equipment, inventory pack and on the ground
(by default you are offered only the appropriate items; press `?`
to cycle item menu modes). Only items of a few kinds inflict any damage,
but some have other effects, beneficial, detrimental or mixed.
Whenever the monster's or hero's hit points reach zero, the combatant dies.
When the last hero dies, the scenario ends in defeat.
On Winning and Dying
--------------------
You win the scenario if you escape the spaceship alive or, in scenarios with
no exit locations, if you eliminate all opposition. In the former case,
your score is based on the gold and precious gems you've plundered.
In the latter case, your score is based on the number of turns you spent
overcoming your foes (the quicker the victory, the better; the slower
the demise, the better). Bonus points, based on the number of heroes lost,
are awarded if you win.
When all your heroes fall, you are going to invariably see a new foolhardy
party of adventurers clamoring to be led into the spaceship. They start
their conquest from a new entrance, with no experience and no equipment,
and new, undaunted enemies bar their way. Lead the new hopeful explorers
to fame, wealth and glory!
Allure-0.5.0.0/GameDefinition/TieKnot.hs 0000644 0000000 0000000 00000005031 12555263417 016070 0 ustar 00 0000000 0000000 -- Copyright (c) 2008--2011 Andres Loeh, 2010--2015 Mikolaj Konarski
-- This file is a part of the computer game Allure of the Stars
-- and is released under the terms of the GNU Affero General Public License.
-- For license and copyright information, see the file LICENSE.
--
-- | Here the knot of engine code pieces and the game-specific
-- content definitions is tied, resulting in an executable game.
module TieKnot ( tieKnot ) where
import qualified Client.UI.Content.KeyKind as Content.KeyKind
import qualified Content.CaveKind
import qualified Content.ItemKind
import qualified Content.ModeKind
import qualified Content.PlaceKind
import qualified Content.RuleKind
import qualified Content.TileKind
import Game.LambdaHack.Client
import qualified Game.LambdaHack.Common.Kind as Kind
import Game.LambdaHack.SampleImplementation.SampleMonadClient (executorCli)
import Game.LambdaHack.SampleImplementation.SampleMonadServer (executorSer)
import Game.LambdaHack.Server
-- | Tie the LambdaHack engine client, server and frontend code
-- with the game-specific content definitions, and run the game.
tieKnot :: [String] -> IO ()
tieKnot args = do
let -- Common content operations, created from content definitions.
-- Evaluated fully to discover errors ASAP and free memory.
!copsSlow = Kind.COps
{ cocave = Kind.createOps Content.CaveKind.cdefs
, coitem = Kind.createOps Content.ItemKind.cdefs
, comode = Kind.createOps Content.ModeKind.cdefs
, coplace = Kind.createOps Content.PlaceKind.cdefs
, corule = Kind.createOps Content.RuleKind.cdefs
, cotile = Kind.createOps Content.TileKind.cdefs
}
!copsShared = speedupCOps False copsSlow
-- Client content operations.
copsClient = Content.KeyKind.standardKeys
sdebugNxt <- debugArgs args
-- Fire up the frontend with the engine fueled by content.
-- The action monad types to be used are determined by the 'exeSer'
-- and 'executorCli' calls. If other functions are used in their place
-- the types are different and so the whole pattern of computation
-- is different. Which of the frontends is run depends on the flags supplied
-- when compiling the engine library.
let exeServer executorUI executorAI =
executorSer $ loopSer copsShared sdebugNxt executorUI executorAI
-- Currently a single frontend is started by the server,
-- instead of each client starting it's own.
srtFrontend (executorCli . loopUI)
(executorCli . loopAI)
copsClient copsShared (sdebugCli sdebugNxt) exeServer
Allure-0.5.0.0/GameDefinition/config.ui.default 0000644 0000000 0000000 00000003500 12555263417 017405 0 ustar 00 0000000 0000000 ; Copyright (c) 2008--2011 Andres Loeh, 2010--2015 Mikolaj Konarski
; This file is a part of the computer game Allure of the Stars
; and is released under the terms of the GNU Affero General Public License.
; For license and copyright information, see the file LICENSE.
;
; This is a copy of the default UI settings config file
; that is embedded in the game binary. A user config file can override
; these options. Option names are case-sensitive and only ';' for comments
; is permitted.
;
; The game looks for the config file at the same path where saved games
; directory is located. E.g. on Linux the file is at
; ~/.Allure/config.ui.ini
; and on Windows it can be at
; C:\Documents And Settings\user\Application Data\Allure\config.ui.ini
; or at
; C:\Users\\AppData\Roaming\Allure\config.ui.ini
; or elsewhere.
[extra_commands]
; A handy shorthand with Vi keys
Macro_1 = ("comma", ([CmdItem], Macro "" ["g"]))
; Angband compatibility (accept target)
Macro_2 = ("KP_Insert", ([CmdMeta], Macro "" ["Return"]))
[hero_names]
HeroName_0 = ("Haskell Alvin", "he")
HeroName_1 = ("Alonzo Barkley", "he")
HeroName_2 = ("Ines Galenti", "she")
HeroName_3 = ("Ernst Abraham", "he")
HeroName_4 = ("Samuel Saunders", "he")
HeroName_5 = ("Roger Robin", "he")
HeroName_6 = ("Christopher Flatt", "he")
[ui]
movementViKeys_hjklyubn = False
movementLaptopKeys_uk8o79jl = True
; Monospace fonts that have fixed size regardless of boldness (on some OSes)
font = "Terminus,DejaVu Sans Mono,Consolas,Courier New,Liberation Mono,Courier,FreeMono,Monospace normal normal normal normal 14"
;font = "Terminus,DejaVu Sans Mono,Consolas,Courier New,Liberation Mono,Courier,FreeMono,Monospace normal normal normal normal 18"
colorIsBold = True
; New historyMax takes effect after removal of savefiles.
historyMax = 5000
maxFps = 30
noAnim = False
runStopMsgs = False
Allure-0.5.0.0/GameDefinition/Content/ 0000755 0000000 0000000 00000000000 12555263417 015572 5 ustar 00 0000000 0000000 Allure-0.5.0.0/GameDefinition/Content/ItemKindBlast.hs 0000644 0000000 0000000 00000034707 12555263417 020633 0 ustar 00 0000000 0000000 -- Copyright (c) 2008--2011 Andres Loeh, 2010--2015 Mikolaj Konarski
-- This file is a part of the computer game Allure of the Stars
-- and is released under the terms of the GNU Affero General Public License.
-- For license and copyright information, see the file LICENSE.
--
-- | Blast definitions.
module Content.ItemKindBlast ( blasts ) where
import Game.LambdaHack.Common.Color
import Game.LambdaHack.Common.Dice
import Game.LambdaHack.Common.Flavour
import Game.LambdaHack.Common.Misc
import Game.LambdaHack.Common.Msg
import Game.LambdaHack.Content.ItemKind
blasts :: [ItemKind]
blasts =
[burningOil2, burningOil3, burningOil4, explosionBlast2, explosionBlast10, explosionBlast20, firecracker2, firecracker3, firecracker4, firecracker5, firecracker6, firecracker7, fragrance, pheromone, mistCalming, odorDistressing, mistHealing, mistHealing2, mistWounding, distortion, waste, glassPiece, smoke, boilingWater, glue, spark, mistAntiSlow, mistAntidote, mistStrength, mistWeakness, protectingBalm, vulnerabilityBalm, hasteSpray, slownessSpray, eyeDrop, smellyDroplet, whiskeySpray]
burningOil2, burningOil3, burningOil4, explosionBlast2, explosionBlast10, explosionBlast20, firecracker2, firecracker3, firecracker4, firecracker5, firecracker6, firecracker7, fragrance, pheromone, mistCalming, odorDistressing, mistHealing, mistHealing2, mistWounding, distortion, waste, glassPiece, smoke, boilingWater, glue, spark, mistAntiSlow, mistAntidote, mistStrength, mistWeakness, protectingBalm, vulnerabilityBalm, hasteSpray, slownessSpray, eyeDrop, smellyDroplet, whiskeySpray :: ItemKind
-- * Parameterized immediate effect blasts
burningOil :: Int -> ItemKind
burningOil n = ItemKind
{ isymbol = '*'
, iname = "burning oil"
, ifreq = [(toGroupName $ "burning oil" <+> tshow n, 1)]
, iflavour = zipFancy [BrYellow]
, icount = intToDice (n * 5)
, irarity = [(1, 1)]
, iverbHit = "burn"
, iweight = 1
, iaspects = [AddLight 2]
, ieffects = [Burn 1, Paralyze 1] -- tripping on oil
, ifeature = [ toVelocity (min 100 $ n * 7)
, Fragile, Identified ]
, idesc = "Sticky oil, burning brightly."
, ikit = []
}
burningOil2 = burningOil 2
burningOil3 = burningOil 3
burningOil4 = burningOil 4
explosionBlast :: Int -> ItemKind
explosionBlast n = ItemKind
{ isymbol = '*'
, iname = "blast"
, ifreq = [(toGroupName $ "blast" <+> tshow n, 1)]
, iflavour = zipPlain [BrRed]
, icount = 15 -- strong, but few, so not always hits target
, irarity = [(1, 1)]
, iverbHit = "tear apart"
, iweight = 1
, iaspects = [AddLight $ intToDice n]
, ieffects = [RefillHP (- n `div` 2)]
++ [PushActor (ThrowMod (100 * (n `div` 5)) 50)]
++ [DropItem COrgan "temporary conditions" True | n >= 10]
, ifeature = [Fragile, toLinger 20, Identified]
, idesc = ""
, ikit = []
}
explosionBlast2 = explosionBlast 2
explosionBlast10 = explosionBlast 10
explosionBlast20 = explosionBlast 20
firecracker :: Int -> ItemKind
firecracker n = ItemKind
{ isymbol = '*'
, iname = "firecracker"
, ifreq = [(toGroupName $ "firecracker" <+> tshow n, 1)]
, iflavour = zipPlain [brightCol !! (n `mod` length brightCol)]
, icount = intToDice (n `div` 6) + d (n `div` 2)
, irarity = [(1, 1)]
, iverbHit = "crack"
, iweight = 1
, iaspects = [AddLight $ intToDice $ n `div` 2]
, ieffects = [ RefillCalm (-1) | n >= 5 ]
++ [ DropBestWeapon | n >= 5]
++ [ OnSmash (Explode $ toGroupName
$ "firecracker" <+> tshow (n - 1))
| n > 2 ]
, ifeature = [ ToThrow $ ThrowMod (10 + 3 * n) (10 + 100 `div` n)
, Fragile, Identified ]
, idesc = ""
, ikit = []
}
firecracker7 = firecracker 7
firecracker6 = firecracker 6
firecracker5 = firecracker 5
firecracker4 = firecracker 4
firecracker3 = firecracker 3
firecracker2 = firecracker 2
-- * Assorted immediate effect blasts
fragrance = ItemKind
{ isymbol = '\''
, iname = "fragrance"
, ifreq = [("fragrance", 1)]
, iflavour = zipFancy [Magenta]
, icount = 20
, irarity = [(1, 1)]
, iverbHit = "engulf"
, iweight = 1
, iaspects = []
, ieffects = [Impress]
-- Linger 10, because sometimes it takes 2 turns due to starting just
-- before actor turn's end (e.g., via a necklace).
, ifeature = [ ToThrow $ ThrowMod 28 10 -- 2 steps, one turn
, Fragile, Identified ]
, idesc = ""
, ikit = []
}
pheromone = ItemKind
{ isymbol = '\''
, iname = "musky whiff"
, ifreq = [("pheromone", 1)]
, iflavour = zipFancy [BrMagenta]
, icount = 18
, irarity = [(1, 1)]
, iverbHit = "tempt"
, iweight = 1
, iaspects = []
, ieffects = [Impress, OverfillCalm (-20)]
, ifeature = [ toVelocity 13 -- the slowest that travels at least 2 steps
, Fragile, Identified ]
, idesc = ""
, ikit = []
}
mistCalming = ItemKind
{ isymbol = '\''
, iname = "mist"
, ifreq = [("calming mist", 1)]
, iflavour = zipFancy [White]
, icount = 19
, irarity = [(1, 1)]
, iverbHit = "sooth"
, iweight = 1
, iaspects = []
, ieffects = [RefillCalm 2]
, ifeature = [ toVelocity 13 -- the slowest that travels at least 2 steps
, Fragile, Identified ]
, idesc = ""
, ikit = []
}
odorDistressing = ItemKind
{ isymbol = '\''
, iname = "distressing whiff"
, ifreq = [("distressing odor", 1)]
, iflavour = zipFancy [BrRed]
, icount = 10
, irarity = [(1, 1)]
, iverbHit = "distress"
, iweight = 1
, iaspects = []
, ieffects = [OverfillCalm (-20)]
, ifeature = [ toVelocity 13 -- the slowest that travels at least 2 steps
, Fragile, Identified ]
, idesc = ""
, ikit = []
}
mistHealing = ItemKind
{ isymbol = '\''
, iname = "mist"
, ifreq = [("healing mist", 1)]
, iflavour = zipFancy [White]
, icount = 9
, irarity = [(1, 1)]
, iverbHit = "revitalize"
, iweight = 1
, iaspects = [AddLight 1]
, ieffects = [RefillHP 2]
, ifeature = [ toVelocity 7 -- the slowest that gets anywhere (1 step only)
, Fragile, Identified ]
, idesc = ""
, ikit = []
}
mistHealing2 = ItemKind
{ isymbol = '\''
, iname = "mist"
, ifreq = [("healing mist 2", 1)]
, iflavour = zipFancy [White]
, icount = 8
, irarity = [(1, 1)]
, iverbHit = "revitalize"
, iweight = 1
, iaspects = [AddLight 2]
, ieffects = [RefillHP 4]
, ifeature = [ toVelocity 7 -- the slowest that gets anywhere (1 step only)
, Fragile, Identified ]
, idesc = ""
, ikit = []
}
mistWounding = ItemKind
{ isymbol = '\''
, iname = "mist"
, ifreq = [("wounding mist", 1)]
, iflavour = zipFancy [White]
, icount = 7
, irarity = [(1, 1)]
, iverbHit = "devitalize"
, iweight = 1
, iaspects = []
, ieffects = [RefillHP (-2)]
, ifeature = [ toVelocity 7 -- the slowest that gets anywhere (1 step only)
, Fragile, Identified ]
, idesc = ""
, ikit = []
}
distortion = ItemKind
{ isymbol = 'v'
, iname = "vortex"
, ifreq = [("distortion", 1)]
, iflavour = zipFancy [White]
, icount = 6
, irarity = [(1, 1)]
, iverbHit = "engulf"
, iweight = 1
, iaspects = []
, ieffects = [Teleport $ 15 + d 10]
, ifeature = [ toVelocity 7 -- the slowest that gets anywhere (1 step only)
, Fragile, Identified ]
, idesc = ""
, ikit = []
}
waste = ItemKind
{ isymbol = '*'
, iname = "waste"
, ifreq = [("waste", 1)]
, iflavour = zipPlain [Brown]
, icount = 18
, irarity = [(1, 1)]
, iverbHit = "splosh"
, iweight = 50
, iaspects = []
, ieffects = [RefillHP (-1)]
, ifeature = [ ToThrow $ ThrowMod 28 10 -- 2 steps, one turn
, Fragile, Identified ]
, idesc = ""
, ikit = []
}
glassPiece = ItemKind -- when blowing up windows
{ isymbol = '*'
, iname = "glass piece"
, ifreq = [("glass piece", 1)]
, iflavour = zipPlain [BrBlue]
, icount = 18
, irarity = [(1, 1)]
, iverbHit = "cut"
, iweight = 10
, iaspects = []
, ieffects = [Hurt (1 * d 1)]
, ifeature = [toLinger 20, Fragile, Identified]
, idesc = ""
, ikit = []
}
smoke = ItemKind -- when stuff burns out
{ isymbol = '\''
, iname = "smoke"
, ifreq = [("smoke", 1)]
, iflavour = zipPlain [BrBlack]
, icount = 19
, irarity = [(1, 1)]
, iverbHit = "choke"
, iweight = 1
, iaspects = []
, ieffects = []
, ifeature = [ toVelocity 21, Fragile, Identified ]
, idesc = ""
, ikit = []
}
boilingWater = ItemKind
{ isymbol = '*'
, iname = "boiling water"
, ifreq = [("boiling water", 1)]
, iflavour = zipPlain [BrWhite]
, icount = 21
, irarity = [(1, 1)]
, iverbHit = "boil"
, iweight = 5
, iaspects = []
, ieffects = [Burn 1]
, ifeature = [toVelocity 50, Fragile, Identified]
, idesc = ""
, ikit = []
}
glue = ItemKind
{ isymbol = '*'
, iname = "sticky foam"
, ifreq = [("glue", 1)]
, iflavour = zipPlain [BrYellow]
, icount = 20
, irarity = [(1, 1)]
, iverbHit = "glue"
, iweight = 20
, iaspects = []
, ieffects = [Paralyze (3 + d 3)]
, ifeature = [toVelocity 40, Fragile, Identified]
, idesc = ""
, ikit = []
}
spark = ItemKind
{ isymbol = '\''
, iname = "spark"
, ifreq = [("spark", 1)]
, iflavour = zipPlain [BrYellow]
, icount = 17
, irarity = [(1, 1)]
, iverbHit = "burn"
, iweight = 1
, iaspects = [AddLight 4]
, ieffects = [Burn 1]
, ifeature = [Fragile, toLinger 10, Identified]
, idesc = ""
, ikit = []
}
mistAntiSlow = ItemKind
{ isymbol = '\''
, iname = "mist"
, ifreq = [("anti-slow mist", 1)]
, iflavour = zipPlain [BrRed]
, icount = 7
, irarity = [(1, 1)]
, iverbHit = "propel"
, iweight = 1
, iaspects = []
, ieffects = [DropItem COrgan "slow 10" True]
, ifeature = [ toVelocity 7 -- the slowest that gets anywhere (1 step only)
, Fragile, Identified ]
, idesc = ""
, ikit = []
}
mistAntidote = ItemKind
{ isymbol = '\''
, iname = "mist"
, ifreq = [("antidote mist", 1)]
, iflavour = zipPlain [BrBlue]
, icount = 8
, irarity = [(1, 1)]
, iverbHit = "cure"
, iweight = 1
, iaspects = []
, ieffects = [DropItem COrgan "poisoned" True]
, ifeature = [ toVelocity 7 -- the slowest that gets anywhere (1 step only)
, Fragile, Identified ]
, idesc = ""
, ikit = []
}
-- * Assorted temporary condition blasts
mistStrength = ItemKind
{ isymbol = '\''
, iname = "mist"
, ifreq = [("strength mist", 1)]
, iflavour = zipFancy [Red]
, icount = 6
, irarity = [(1, 1)]
, iverbHit = "strengthen"
, iweight = 1
, iaspects = []
, ieffects = [toOrganActorTurn "strengthened" (3 + d 3)]
, ifeature = [ toVelocity 7 -- the slowest that gets anywhere (1 step only)
, Fragile, Identified ]
, idesc = ""
, ikit = []
}
mistWeakness = ItemKind
{ isymbol = '\''
, iname = "mist"
, ifreq = [("weakness mist", 1)]
, iflavour = zipFancy [Blue]
, icount = 5
, irarity = [(1, 1)]
, iverbHit = "weaken"
, iweight = 1
, iaspects = []
, ieffects = [toOrganGameTurn "weakened" (3 + d 3)]
, ifeature = [ toVelocity 7 -- the slowest that gets anywhere (1 step only)
, Fragile, Identified ]
, idesc = ""
, ikit = []
}
protectingBalm = ItemKind
{ isymbol = '\''
, iname = "balm droplet"
, ifreq = [("protecting balm", 1)]
, iflavour = zipPlain [Brown]
, icount = 13
, irarity = [(1, 1)]
, iverbHit = "balm"
, iweight = 1
, iaspects = []
, ieffects = [toOrganActorTurn "protected" (3 + d 3)]
, ifeature = [ toVelocity 13 -- the slowest that travels at least 2 steps
, Fragile, Identified ]
, idesc = ""
, ikit = []
}
vulnerabilityBalm = ItemKind
{ isymbol = '\''
, iname = "red paint"
, ifreq = [("red paint", 1)]
, iflavour = zipPlain [BrRed]
, icount = 14
, irarity = [(1, 1)]
, iverbHit = "paint"
, iweight = 1
, iaspects = []
, ieffects = [toOrganGameTurn "painted red" (3 + d 3)]
, ifeature = [ toVelocity 13 -- the slowest that travels at least 2 steps
, Fragile, Identified ]
, idesc = ""
, ikit = []
}
hasteSpray = ItemKind
{ isymbol = '\''
, iname = "haste spray"
, ifreq = [("haste spray", 1)]
, iflavour = zipPlain [BrRed]
, icount = 15
, irarity = [(1, 1)]
, iverbHit = "haste"
, iweight = 1
, iaspects = []
, ieffects = [toOrganActorTurn "fast 20" (3 + d 3)]
, ifeature = [ toVelocity 13 -- the slowest that travels at least 2 steps
, Fragile, Identified ]
, idesc = ""
, ikit = []
}
slownessSpray = ItemKind
{ isymbol = '\''
, iname = "slowness spray"
, ifreq = [("slowness spray", 1)]
, iflavour = zipPlain [BrBlue]
, icount = 16
, irarity = [(1, 1)]
, iverbHit = "slow"
, iweight = 1
, iaspects = []
, ieffects = [toOrganGameTurn "slow 10" (3 + d 3)]
, ifeature = [ toVelocity 13 -- the slowest that travels at least 2 steps
, Fragile, Identified ]
, idesc = ""
, ikit = []
}
eyeDrop = ItemKind
{ isymbol = '\''
, iname = "eye drop"
, ifreq = [("eye drop", 1)]
, iflavour = zipPlain [BrGreen]
, icount = 17
, irarity = [(1, 1)]
, iverbHit = "cleanse"
, iweight = 1
, iaspects = []
, ieffects = [toOrganActorTurn "far-sighted" (3 + d 3)]
, ifeature = [ toVelocity 13 -- the slowest that travels at least 2 steps
, Fragile, Identified ]
, idesc = ""
, ikit = []
}
smellyDroplet = ItemKind
{ isymbol = '\''
, iname = "smelly droplet"
, ifreq = [("smelly droplet", 1)]
, iflavour = zipPlain [Blue]
, icount = 18
, irarity = [(1, 1)]
, iverbHit = "sensitize"
, iweight = 1
, iaspects = []
, ieffects = [toOrganActorTurn "keen-smelling" (3 + d 3)]
, ifeature = [ toVelocity 13 -- the slowest that travels at least 2 steps
, Fragile, Identified ]
, idesc = ""
, ikit = []
}
whiskeySpray = ItemKind
{ isymbol = '\''
, iname = "whiskey spray"
, ifreq = [("whiskey spray", 1)]
, iflavour = zipPlain [Brown]
, icount = 19
, irarity = [(1, 1)]
, iverbHit = "inebriate"
, iweight = 1
, iaspects = []
, ieffects = [toOrganActorTurn "drunk" (3 + d 3)]
, ifeature = [ toVelocity 13 -- the slowest that travels at least 2 steps
, Fragile, Identified ]
, idesc = ""
, ikit = []
}
Allure-0.5.0.0/GameDefinition/Content/ItemKindOrgan.hs 0000644 0000000 0000000 00000027161 12555263417 020630 0 ustar 00 0000000 0000000 -- Copyright (c) 2008--2011 Andres Loeh, 2010--2015 Mikolaj Konarski
-- This file is a part of the computer game Allure of the Stars
-- and is released under the terms of the GNU Affero General Public License.
-- For license and copyright information, see the file LICENSE.
--
-- | Organ definitions.
module Content.ItemKindOrgan ( organs ) where
import qualified Data.EnumMap.Strict as EM
import Game.LambdaHack.Common.Ability
import Game.LambdaHack.Common.Color
import Game.LambdaHack.Common.Dice
import Game.LambdaHack.Common.Flavour
import Game.LambdaHack.Common.Misc
import Game.LambdaHack.Common.Msg
import Game.LambdaHack.Content.ItemKind
organs :: [ItemKind]
organs =
[fist, foot, claw, smallClaw, snout, smallJaw, jaw, largeJaw, horn, tentacle, razor, thorn, boilingFissure, biogasFissure, medbotFissure, insectMortality, beeSting, sting, venomTooth, venomFang, screechingBeak, largeTail, liveWire, armoredSkin, eye2, eye3, eye4, eye5, eye6, eye7, eye8, vision4, vision6, vision8, vision10, vision12, vision14, vision16, nostril, sapientBrain, animalBrain, robotBrain, speedGland2, speedGland4, speedGland6, speedGland8, speedGland10, scentGland, boilingVent, biogasVent, medbotVent, wasteContainer, spotlight, bonusHP]
fist, foot, claw, smallClaw, snout, smallJaw, jaw, largeJaw, horn, tentacle, razor, thorn, boilingFissure, biogasFissure, medbotFissure, insectMortality, beeSting, sting, venomTooth, venomFang, screechingBeak, largeTail, liveWire, armoredSkin, eye2, eye3, eye4, eye5, eye6, eye7, eye8, vision4, vision6, vision8, vision10, vision12, vision14, vision16, nostril, sapientBrain, animalBrain, robotBrain, speedGland2, speedGland4, speedGland6, speedGland8, speedGland10, scentGland, boilingVent, biogasVent, medbotVent, wasteContainer, spotlight, bonusHP :: ItemKind
-- Weapons
-- * Human weapon organs
fist = ItemKind
{ isymbol = '%'
, iname = "fist"
, ifreq = [("fist", 100)]
, iflavour = zipPlain [Red]
, icount = 2
, irarity = [(1, 1)]
, iverbHit = "punch"
, iweight = 2000
, iaspects = []
, ieffects = [Hurt (4 * d 1)]
, ifeature = [Durable, Identified]
, idesc = ""
, ikit = []
}
foot = fist
{ iname = "foot"
, ifreq = [("foot", 50)]
, icount = 2
, iverbHit = "kick"
, ieffects = [Hurt (4 * d 1)]
, idesc = ""
}
-- * Universal weapon organs
claw = fist
{ iname = "claw"
, ifreq = [("claw", 50)]
, icount = 2 -- even if more, only the fore claws used for fighting
, iverbHit = "hook"
, iaspects = [Timeout $ 4 + d 4]
, ieffects = [Hurt (2 * d 1), Recharging (toOrganGameTurn "slow 10" 2)]
, idesc = ""
}
smallClaw = fist
{ iname = "small claw"
, ifreq = [("small claw", 50)]
, icount = 2
, iverbHit = "slash"
, ieffects = [Hurt (2 * d 1)]
, idesc = ""
}
snout = fist
{ iname = "snout"
, ifreq = [("snout", 10)]
, iverbHit = "bite"
, ieffects = [Hurt (2 * d 1)]
, idesc = ""
}
smallJaw = fist
{ iname = "small jaw"
, ifreq = [("small jaw", 20)]
, icount = 1
, iverbHit = "rip"
, ieffects = [Hurt (3 * d 1)]
, idesc = ""
}
jaw = fist
{ iname = "jaw"
, ifreq = [("jaw", 20)]
, icount = 1
, iverbHit = "rip"
, ieffects = [Hurt (5 * d 1)]
, idesc = ""
}
largeJaw = fist
{ iname = "large jaw"
, ifreq = [("large jaw", 100)]
, icount = 1
, iverbHit = "crush"
, ieffects = [Hurt (12 * d 1)]
, idesc = ""
}
horn = fist
{ iname = "horn"
, ifreq = [("horn", 20)]
, icount = 2
, iverbHit = "impale"
, ieffects = [Hurt (8 * d 1)]
, idesc = ""
}
-- * Monster weapon organs
tentacle = fist
{ iname = "tentacle"
, ifreq = [("tentacle", 50)]
, icount = 4
, iverbHit = "slap"
, ieffects = [Hurt (4 * d 1)]
, idesc = ""
}
-- * Special weapon organs
razor = fist
{ iname = "razor"
, ifreq = [("razor", 100)]
, icount = 7
, iverbHit = "slice"
, ieffects = [Hurt (2 * d 1)]
, idesc = ""
}
thorn = fist
{ iname = "thorn"
, ifreq = [("thorn", 100)]
, icount = 2 + d 3
, iverbHit = "impale"
, ieffects = [Hurt (2 * d 1)]
, ifeature = [Identified] -- not Durable
, idesc = ""
}
boilingFissure = fist
{ iname = "fissure"
, ifreq = [("boiling fissure", 100)]
, icount = 5 + d 5
, iverbHit = "hiss at"
, ieffects = [Burn $ 1 * d 1]
, ifeature = [Identified] -- not Durable
, idesc = ""
}
biogasFissure = boilingFissure
{ iname = "fissure"
, ifreq = [("biogas fissure", 100)]
, icount = 2 + d 2
, ieffects = [Burn $ 1 * d 1, toOrganGameTurn "weakened" (2 + d 2)]
}
medbotFissure = boilingFissure
{ iname = "fissure"
, ifreq = [("medbot fissure", 100)]
, icount = 2 + d 2
, ieffects = [Burn $ 1 * d 1, RefillHP 6]
}
beeSting = fist
{ iname = "bee sting"
, ifreq = [("bee sting", 100)]
, icount = 1
, iverbHit = "sting"
, iaspects = [AddArmorMelee 90, AddArmorRanged 90]
, ieffects = [Burn $ 2 * d 1, Paralyze 3, RefillHP 5]
, ifeature = [Identified] -- not Durable
, idesc = "Painful, but beneficial."
}
sting = fist
{ iname = "sting"
, ifreq = [("sting", 100)]
, icount = 1
, iverbHit = "sting"
, iaspects = [Timeout $ 1 + d 5]
, ieffects = [Burn $ 2 * d 1, Recharging (Paralyze 2)]
, idesc = "Painful, debilitating and harmful."
}
venomTooth = fist
{ iname = "venom tooth"
, ifreq = [("venom tooth", 100)]
, icount = 2
, iverbHit = "bite"
, iaspects = [Timeout $ 5 + d 3]
, ieffects = [ Hurt (2 * d 1)
, Recharging (toOrganGameTurn "slow 10" (3 + d 3)) ]
, idesc = ""
}
-- TODO: should also confer poison resistance, but current implementation
-- is too costly (poison removal each turn)
venomFang = fist
{ iname = "venom fang"
, ifreq = [("venom fang", 100)]
, icount = 2
, iverbHit = "bite"
, iaspects = [Timeout $ 7 + d 5]
, ieffects = [ Hurt (2 * d 1)
, Recharging (toOrganNone "poisoned") ]
, idesc = ""
}
screechingBeak = armoredSkin
{ iname = "screeching beak"
, ifreq = [("screeching beak", 100)]
, icount = 1
, iverbHit = "peck"
, iaspects = [Timeout $ 5 + d 5]
, ieffects = [ Recharging (Summon [("scavenger", 1)] $ 1 + dl 2)
, Hurt (2 * d 1) ]
, idesc = ""
}
largeTail = fist
{ iname = "large tail"
, ifreq = [("large tail", 50)]
, icount = 1
, iverbHit = "knock"
, iaspects = [Timeout $ 1 + d 3]
, ieffects = [Hurt (8 * d 1), Recharging (PushActor (ThrowMod 400 25))]
, idesc = ""
}
liveWire = fist
{ iname = "live wire"
, ifreq = [("live wire", 100)]
, icount = 1
, iverbHit = "shock"
, iaspects = [Timeout $ 3 + d 3]
, ieffects = [ Hurt (1 * d 1)
, Recharging (DropItem COrgan "temporary conditions" True)
, Recharging $ RefillHP (-2)
]
, idesc = ""
}
-- Non-weapons
-- * Armor organs
armoredSkin = ItemKind
{ isymbol = '%'
, iname = "armored skin"
, ifreq = [("armored skin", 100)]
, iflavour = zipPlain [Red]
, icount = 1
, irarity = [(1, 1)]
, iverbHit = "bash"
, iweight = 2000
, iaspects = [AddArmorMelee 30, AddArmorRanged 30]
, ieffects = []
, ifeature = [Durable, Identified]
, idesc = ""
, ikit = []
}
-- * Sense organs
eye :: Int -> ItemKind
eye n = armoredSkin
{ iname = "eye"
, ifreq = [(toGroupName $ "eye" <+> tshow n, 100)]
, icount = 2
, iverbHit = "glare at"
, iaspects = [AddSight (intToDice n)]
, idesc = ""
}
eye2 = eye 2
eye3 = eye 3
eye4 = eye 4
eye5 = eye 5
eye6 = eye 6
eye7 = eye 7
eye8 = eye 8
vision :: Int -> ItemKind
vision n = armoredSkin
{ iname = "vision"
, ifreq = [(toGroupName $ "vision" <+> tshow n, 100)]
, icount = 1
, iverbHit = "visualize"
, iaspects = [AddSight (intToDice n)]
, idesc = ""
}
vision4 = vision 4
vision6 = vision 6
vision8 = vision 8
vision10 = vision 10
vision12 = vision 12
vision14 = vision 14
vision16 = vision 16
nostril = armoredSkin
{ iname = "nostril"
, ifreq = [("nostril", 100)]
, icount = 2
, iverbHit = "snuff"
, iaspects = [AddSmell 1] -- times 2, from icount
, idesc = ""
}
-- * Assorted
insectMortality = fist
{ iname = "insect mortality"
, ifreq = [("insect mortality", 100)]
, icount = 1
, iverbHit = "age"
, iaspects = [Periodic, Timeout $ 40 + d 10]
, ieffects = [Recharging (RefillHP (-1))]
, idesc = ""
}
sapientBrain = armoredSkin
{ iname = "sapient brain"
, ifreq = [("sapient brain", 100)]
, icount = 1
, iverbHit = "outbrain"
, iaspects = [AddSkills unitSkills]
, idesc = ""
}
animalBrain = armoredSkin
{ iname = "animal brain"
, ifreq = [("animal brain", 100)]
, icount = 1
, iverbHit = "blank"
, iaspects = [let absNo = [AbDisplace, AbMoveItem, AbProject, AbApply]
sk = EM.fromList $ zip absNo [-1, -1..]
in AddSkills $ addSkills unitSkills sk]
, idesc = ""
}
robotBrain = armoredSkin
{ iname = "robot brain"
, ifreq = [("robot brain", 100)]
, icount = 1
, iverbHit = "outcompute"
, iaspects = [let absNo = [AbApply]
sk = EM.fromList $ zip absNo [-1, -1..]
in AddSkills $ addSkills unitSkills sk]
, idesc = ""
}
speedGland :: Int -> ItemKind
speedGland n = armoredSkin
{ iname = "speed gland"
, ifreq = [(toGroupName $ "speed gland" <+> tshow n, 100)]
, icount = 1
, iverbHit = "spit at"
, iaspects = [ AddSpeed $ intToDice n
, Periodic
, Timeout $ intToDice $ 100 `div` n ]
, ieffects = [Recharging (RefillHP 1)]
, idesc = ""
}
speedGland2 = speedGland 2
speedGland4 = speedGland 4
speedGland6 = speedGland 6
speedGland8 = speedGland 8
speedGland10 = speedGland 10
scentGland = armoredSkin -- TODO: cone attack, 3m away, project? apply?
{ iname = "scent gland"
, ifreq = [("scent gland", 100)]
, icount = 1
, iverbHit = "spray at"
, iaspects = [Periodic, Timeout $ 10 + d 2 |*| 5 ]
, ieffects = [ Recharging (Explode "distressing odor")
, Recharging ApplyPerfume ]
, idesc = ""
}
boilingVent = armoredSkin
{ iname = "vent"
, ifreq = [("boiling vent", 100)]
, iflavour = zipPlain [BrBlue]
, icount = 1
, iverbHit = "menace"
, iaspects = [Periodic, Timeout $ 2 + d 2 |*| 5]
, ieffects = [Recharging (Explode "boiling water")]
, idesc = ""
}
biogasVent = armoredSkin
{ iname = "vent"
, ifreq = [("biogas vent", 100)]
, iflavour = zipPlain [BrGreen]
, icount = 1
, iverbHit = "menace"
, iaspects = [Periodic, Timeout $ 2 + d 2 |*| 5]
, ieffects = [Recharging (Explode "weakness mist")]
, idesc = ""
}
medbotVent = armoredSkin
{ iname = "vent"
, ifreq = [("medbot vent", 100)]
, iflavour = zipPlain [BrYellow]
, icount = 1
, iverbHit = "menace"
, iaspects = [Periodic, Timeout $ 2 + d 2 |*| 5]
, ieffects = [Recharging (Explode "protecting balm")]
, idesc = ""
}
wasteContainer = armoredSkin
{ iname = "waste container"
, ifreq = [("waste container", 100)]
, icount = 1
, iverbHit = "spill over"
, iaspects = [Periodic, Timeout $ 5 + d 5 |*| 10]
, ieffects = [ Recharging (Summon [("mobile animal", 1)] $ 1 + dl 2)
, Recharging (RefillHP 1)
, Recharging (Explode "waste") ]
, idesc = ""
}
spotlight = armoredSkin
{ iname = "spotlight"
, ifreq = [("spotlight", 100)]
, icount = 1
, iverbHit = "blind"
, iaspects = [AddLight 3]
, idesc = ""
}
bonusHP = armoredSkin
{ iname = "bonus HP"
, ifreq = [("bonus HP", 100)]
, icount = 1
, iverbHit = "intimidate"
, iweight = 0
, iaspects = [AddMaxHP 1]
, idesc = ""
}
Allure-0.5.0.0/GameDefinition/Content/ItemKind.hs 0000644 0000000 0000000 00000115254 12555263417 017642 0 ustar 00 0000000 0000000 -- Copyright (c) 2008--2011 Andres Loeh, 2010--2015 Mikolaj Konarski
-- This file is a part of the computer game Allure of the Stars
-- and is released under the terms of the GNU Affero General Public License.
-- For license and copyright information, see the file LICENSE.
--
-- | Item and treasure definitions.
module Content.ItemKind ( cdefs ) where
import qualified Data.EnumMap.Strict as EM
import Data.List
import Content.ItemKindActor
import Content.ItemKindBlast
import Content.ItemKindOrgan
import Content.ItemKindTemporary
import Game.LambdaHack.Common.Ability
import Game.LambdaHack.Common.Color
import Game.LambdaHack.Common.ContentDef
import Game.LambdaHack.Common.Dice
import Game.LambdaHack.Common.Flavour
import Game.LambdaHack.Common.Misc
import Game.LambdaHack.Content.ItemKind
cdefs :: ContentDef ItemKind
cdefs = ContentDef
{ getSymbol = isymbol
, getName = iname
, getFreq = ifreq
, validateSingle = validateSingleItemKind
, validateAll = validateAllItemKind
, content = items ++ organs ++ blasts ++ actors ++ temporaries
}
items :: [ItemKind]
items =
[dart, dart200, paralizingProj, harpoon, net, needle, jumpingPole, sharpeningTool, seeingItem, light1, light2, light3, gorget, necklace1, necklace2, necklace3, necklace4, necklace5, necklace6, necklace7, necklace8, necklace9, sightSharpening, ring1, ring2, ring3, ring4, ring5, ring6, ring7, ring8, potion1, potion2, potion3, potion4, potion5, potion6, potion7, potion8, potion9, flask1, flask2, flask3, flask4, flask5, flask6, flask7, flask8, flask9, flask10, flask11, flask12, flask13, flask14, constructionHooter, scroll1, scroll2, scroll3, scroll4, scroll5, scroll6, scroll7, scroll8, scroll9, scroll10, scroll11, armorLeather, armorMail, gloveFencing, gloveGauntlet, gloveJousting, buckler, shield, dagger, daggerDropBestWeapon, hammer, hammerParalyze, hammerSpark, sword, swordImpress, swordNullify, halberd, halberdPushActor, wand1, wand2, gem1, gem2, gem3, gem4, currency]
dart, dart200, paralizingProj, harpoon, net, needle, jumpingPole, sharpeningTool, seeingItem, light1, light2, light3, gorget, necklace1, necklace2, necklace3, necklace4, necklace5, necklace6, necklace7, necklace8, necklace9, sightSharpening, ring1, ring2, ring3, ring4, ring5, ring6, ring7, ring8, potion1, potion2, potion3, potion4, potion5, potion6, potion7, potion8, potion9, flask1, flask2, flask3, flask4, flask5, flask6, flask7, flask8, flask9, flask10, flask11, flask12, flask13, flask14, constructionHooter, scroll1, scroll2, scroll3, scroll4, scroll5, scroll6, scroll7, scroll8, scroll9, scroll10, scroll11, armorLeather, armorMail, gloveFencing, gloveGauntlet, gloveJousting, buckler, shield, dagger, daggerDropBestWeapon, hammer, hammerParalyze, hammerSpark, sword, swordImpress, swordNullify, halberd, halberdPushActor, wand1, wand2, gem1, gem2, gem3, gem4, currency :: ItemKind
necklace, ring, potion, flask, scroll, wand, gem :: ItemKind -- generic templates
-- * Item group symbols, from Angband and variants
symbolProjectile, _symbolLauncher, symbolLight, symbolTool, symbolGem, symbolGold, symbolNecklace, symbolRing, symbolPotion, symbolFlask, symbolScroll, symbolTorsoArmor, symbolMiscArmor, _symbolClothes, symbolShield, symbolPolearm, symbolEdged, symbolHafted, symbolWand, _symbolStaff, _symbolFood :: Char
symbolProjectile = '{'
_symbolLauncher = '}'
symbolLight = '~'
symbolTool = '~'
symbolGem = '*'
symbolGold = '$'
symbolNecklace = '"'
symbolRing = '='
symbolPotion = '!' -- concoction, bottle, jar, vial, canister
symbolFlask = '!'
symbolScroll = '?' -- book, note, tablet, remote, chip, card
symbolTorsoArmor = '['
symbolMiscArmor = ']'
_symbolClothes = '('
symbolShield = ')'
symbolPolearm = '/'
symbolEdged = '|'
symbolHafted = '\\'
symbolWand = '-' -- magical rod, transmitter, pistol, rifle
_symbolStaff = '_' -- scanner
_symbolFood = ',' -- too easy to miss?
-- * Thrown weapons
dart = ItemKind
{ isymbol = symbolProjectile
, iname = "steak knife"
, ifreq = [("useful", 100), ("any arrow", 100)]
, iflavour = zipPlain [BrCyan]
, icount = 4 * d 3
, irarity = [(1, 10), (10, 20)]
, iverbHit = "nick"
, iweight = 100
, iaspects = [AddHurtRanged (d 3 + dl 6 |*| 20)]
, ieffects = [Hurt (2 * d 1)]
, ifeature = [toVelocity 75, Identified] -- no fins, no special balance
, idesc = "Not particularly well balanced, but with a laser-sharpened titanium tip and blade."
, ikit = []
}
dart200 = ItemKind
{ isymbol = symbolProjectile
, iname = "billiard ball"
, ifreq = [("useful", 100), ("any arrow", 50)] -- TODO: until arrows added
, iflavour = zipPlain [BrWhite]
, icount = 4 * d 3
, irarity = [(1, 20), (10, 10)]
, iverbHit = "strike"
, iweight = 300
, iaspects = [AddHurtRanged (d 3 + dl 6 |*| 20)]
, ieffects = [Hurt (1 * d 1)]
, ifeature = [toVelocity 150, Identified]
, idesc = "Ideal shape, size and weight for throwing."
, ikit = []
}
-- * Exotic thrown weapons
paralizingProj = ItemKind
{ isymbol = symbolProjectile
, iname = "can"
, ifreq = [("useful", 100), ("can of sticky foam", 1)]
, iflavour = zipPlain [Magenta]
, icount = dl 3
, irarity = [(5, 5), (10, 20)]
, iverbHit = "glue"
, iweight = 1500
, iaspects = []
, ieffects = [ NoEffect "of sticky foam", Paralyze (5 + d 7)
, OnSmash (Explode "glue")]
, ifeature = [toVelocity 50, Identified, Fragile] -- unwieldy
, idesc = "A can of liquid, fast-setting, construction foam."
, ikit = []
}
harpoon = ItemKind
{ isymbol = symbolProjectile
, iname = "harpoon"
, ifreq = [("useful", 100)]
, iflavour = zipPlain [Brown]
, icount = dl 5
, irarity = [(5, 5), (10, 5)]
, iverbHit = "hook"
, iweight = 4000
, iaspects = [AddHurtRanged (d 2 + dl 5 |*| 20)]
, ieffects = [Hurt (4 * d 1), PullActor (ThrowMod 200 50)]
, ifeature = [Identified]
, idesc = "A display piece harking back to the Earth's oceanic tourism hayday. The cruel, barbed head lodges in its victim so painfully that the weakest tug of the thin line sends the victim flying."
, ikit = []
}
net = ItemKind
{ isymbol = symbolProjectile
, iname = "net"
, ifreq = [("useful", 100)]
, iflavour = zipPlain [White]
, icount = dl 3
, irarity = [(3, 5), (10, 4)]
, iverbHit = "entangle"
, iweight = 1000
, iaspects = []
, ieffects = [ toOrganGameTurn "slow 10" (3 + d 3)
, DropItem CEqp "torso armor" False ]
, ifeature = [Identified]
, idesc = "A large synthetic fibre net with weights affixed along the edges. Entangles armor and restricts movement."
, ikit = []
}
needle = ItemKind
{ isymbol = symbolProjectile
, iname = "needle"
, ifreq = [("needle", 1)] -- special
, iflavour = zipPlain [BrBlue]
, icount = 9 * d 3
, irarity = [(1, 1)]
, iverbHit = "prick"
, iweight = 1
, iaspects = [AddHurtRanged (d 3 + dl 3 |*| 10)]
, ieffects = [Hurt (1 * d 1)]
, ifeature = [toVelocity 200, Fragile]
, idesc = "The hypodermic needle part of a micro-syringe. Without the payload, it flies far and penetrates deeply, causing intense pain on movement."
, ikit = []
}
-- * Assorted tools
jumpingPole = ItemKind
{ isymbol = symbolTool
, iname = "jumping pole"
, ifreq = [("useful", 100)]
, iflavour = zipPlain [White]
, icount = 1
, irarity = [(1, 2)]
, iverbHit = "prod"
, iweight = 10000
, iaspects = [Timeout $ d 2 + 2 - dl 2 |*| 10]
, ieffects = [Recharging (toOrganActorTurn "fast 20" 1)]
, ifeature = [Durable, Applicable, Identified]
, idesc = "Makes you vulnerable at take-off, but then you are free like a bird."
, ikit = []
}
sharpeningTool = ItemKind
{ isymbol = symbolTool
, iname = "honing steel"
, ifreq = [("useful", 100)]
, iflavour = zipPlain [Blue]
, icount = 1
, irarity = [(10, 10)]
, iverbHit = "smack"
, iweight = 400
, iaspects = [AddHurtMelee $ d 10 |*| 3]
, ieffects = []
, ifeature = [EqpSlot EqpSlotAddHurtMelee "", Identified]
, idesc = "Originally used for realigning the bent or buckled edges of kitchen knives in the local bars. Now it saves lives by letting you fix your weapons between or even during fights, without the need to set up camp, fish out tools and assemble a proper sharpening workshop."
, ikit = []
}
seeingItem = ItemKind
{ isymbol = '%'
, iname = "visual sensor"
, ifreq = [("useful", 100)]
, iflavour = zipPlain [Red]
, icount = 1
, irarity = [(1, 1)]
, iverbHit = "gaze at"
, iweight = 500
, iaspects = [ AddSight 10, AddMaxCalm 60, AddLight 2
, Periodic, Timeout $ 1 + d 2 ]
, ieffects = [ Recharging (toOrganNone "poisoned")
, Recharging (Summon [("mobile robot", 1)] 1) ]
, ifeature = [Identified]
, idesc = "A functioning visual sensor torn out from some giant robot. The circuitry is too big to serve just the basic signal processing. Watch out for the sharp edges and the seeping coolant liquid."
, ikit = []
}
-- * Lights
light1 = ItemKind
{ isymbol = symbolLight
, iname = "candle"
, ifreq = [("useful", 100), ("light source", 100)]
, iflavour = zipPlain [Brown]
, icount = d 2
, irarity = [(1, 10)]
, iverbHit = "scorch"
, iweight = 500
, iaspects = [ AddLight 3
, AddSight (-2) ]
, ieffects = [Burn 2]
, ifeature = [ toVelocity 50 -- easy to break when throwing
, Fragile, EqpSlot EqpSlotAddLight "", Identified ]
, idesc = "A smoking, thick candle with an unsteady fire."
, ikit = []
}
light2 = ItemKind
{ isymbol = symbolLight
, iname = "oil lamp"
, ifreq = [("useful", 100), ("light source", 100)]
, iflavour = zipPlain [BrYellow]
, icount = 1
, irarity = [(6, 7)]
, iverbHit = "burn"
, iweight = 1000
, iaspects = [AddLight 3, AddSight (-1)]
, ieffects = [Burn 3, Paralyze 3, OnSmash (Explode "burning oil 3")]
, ifeature = [ toVelocity 70 -- hard not to spill the oil while throwing
, Fragile, EqpSlot EqpSlotAddLight "", Identified ]
, idesc = "A sizable glass lamp filled with plant oil feeding a wick."
, ikit = []
}
light3 = ItemKind
{ isymbol = symbolLight
, iname = "crank spotlight"
, ifreq = [("useful", 100), ("light source", 100)]
, iflavour = zipPlain [BrWhite]
, icount = 1
, irarity = [(10, 5)]
, iverbHit = "snag"
, iweight = 2400
, iaspects = [AddLight 4, AddArmorRanged $ - d 3] -- noise and busy hands
, ieffects = []
, ifeature = [ EqpSlot EqpSlotAddLight "", Identified ]
, idesc = "Powerful, wide-beam spotlight, powered by a hand-crank. Requires noisy two-handed recharging every few minutes."
, ikit = []
}
-- * Periodic jewelry
gorget = ItemKind
{ isymbol = symbolNecklace
, iname = "Old Gorget"
, ifreq = [("useful", 100)]
, iflavour = zipFancy [BrCyan]
, icount = 1
, irarity = [(4, 3), (10, 3)] -- weak, shallow
, iverbHit = "whip"
, iweight = 30
, iaspects = [ Unique
, Periodic
, Timeout $ 1 + d 2
, AddArmorMelee $ 2 + d 3
, AddArmorRanged $ 2 + d 3 ]
, ieffects = [Recharging (RefillCalm 1)]
, ifeature = [ Durable, Precious, EqpSlot EqpSlotPeriodic ""
, Identified, toVelocity 50 ] -- not dense enough
, idesc = "Highly ornamental, cold, large, steel medallion on a chain. Unlikely to offer much protection as an armor piece, but the old, worn engraving reassures you."
, ikit = []
}
necklace = ItemKind
{ isymbol = symbolNecklace
, iname = "necklace"
, ifreq = [("useful", 100)]
, iflavour = zipFancy stdCol ++ zipPlain brightCol
, icount = 1
, irarity = [(10, 2)]
, iverbHit = "whip"
, iweight = 30
, iaspects = [Periodic]
, ieffects = []
, ifeature = [ Precious, EqpSlot EqpSlotPeriodic ""
, toVelocity 50 ] -- not dense enough
, idesc = "Tingling, rattling chain of flat encrusted links. Eccentric millionaires are known to hide their highly personalized body augmentation packs in such large jewelry pieces."
, ikit = []
}
necklace1 = necklace
{ ifreq = [("treasure", 100)]
, irarity = [(3, 0), (4, 1), (10, 2)] -- prevents camping on lvl 3
, iaspects = [Unique, Timeout $ d 3 + 4 - dl 3 |*| 10]
++ iaspects necklace
, ieffects = [NoEffect "of Trickle Life", Recharging (RefillHP 1)]
, ifeature = Durable : ifeature necklace
}
necklace2 = necklace
{ ifreq = [("treasure", 100)] -- just too nasty to call it useful
, irarity = [(1, 1)]
, iaspects = (Timeout $ d 3 + 3 - dl 3 |*| 10) : iaspects necklace
, ieffects = [ Recharging Impress
, Recharging (DropItem COrgan "temporary conditions" True)
, Recharging (Summon [("mobile animal", 1)] $ 1 + dl 2)
, Recharging (Explode "waste") ]
}
necklace3 = necklace
{ iaspects = (Timeout $ d 3 + 3 - dl 3 |*| 10) : iaspects necklace
, ieffects = [Recharging (Paralyze $ 5 + d 5 + dl 5)]
}
necklace4 = necklace
{ iaspects = (Timeout $ d 4 + 4 - dl 4 |*| 2) : iaspects necklace
, ieffects = [Recharging (Teleport $ d 2 * 3)]
}
necklace5 = necklace
{ iaspects = (Timeout $ d 3 + 4 - dl 3 |*| 10) : iaspects necklace
, ieffects = [Recharging (Teleport $ 14 + d 3 * 3)]
}
necklace6 = necklace
{ iaspects = (Timeout $ d 4 |*| 10) : iaspects necklace
, ieffects = [Recharging (PushActor (ThrowMod 100 50))]
}
necklace7 = necklace -- TODO: teach AI to wear only for fight
{ ifreq = [("treasure", 100)]
, iaspects = [ Unique, AddMaxHP $ 10 + d 10
, AddArmorMelee 20, AddArmorRanged 20
, Timeout $ d 2 + 5 - dl 3 ]
++ iaspects necklace
, ieffects = [ NoEffect "of Overdrive"
, Recharging (InsertMove $ 1 + d 2)
, Recharging (RefillHP (-1))
, Recharging (RefillCalm (-1)) ]
, ifeature = Durable : ifeature necklace
}
necklace8 = necklace
{ iaspects = (Timeout $ d 3 + 3 - dl 3 |*| 5) : iaspects necklace
, ieffects = [Recharging $ Explode "spark"]
}
necklace9 = necklace
{ iaspects = (Timeout $ d 3 + 3 - dl 3 |*| 5) : iaspects necklace
, ieffects = [Recharging $ Explode "fragrance"]
}
-- * Non-periodic jewelry
sightSharpening = ItemKind
{ isymbol = symbolRing
, iname = "Autozoom Contact Lens"
, ifreq = [("treasure", 100)]
, iflavour = zipPlain [White]
, icount = 1
, irarity = [(7, 3), (10, 3)] -- medium weak, medium shallow
, iverbHit = "rap"
, iweight = 50
, iaspects = [Unique, AddSight $ 1 + d 2, AddHurtMelee $ d 2 |*| 3]
, ieffects = []
, ifeature = [ Precious, Identified, Durable
, EqpSlot EqpSlotAddSight "" ]
, idesc = "Zooms on any movement, distant or close. Requires some getting used to. Never needs to be taken off."
, ikit = []
}
-- Don't add standard effects to rings, because they go in and out
-- of eqp and so activating them would require UI tedium: looking for
-- them in eqp and inv or even activating a wrong item via letter by mistake.
ring = ItemKind
{ isymbol = symbolRing
, iname = "ring"
, ifreq = [("useful", 100)]
, iflavour = zipPlain stdCol ++ zipFancy darkCol
, icount = 1
, irarity = [(10, 3)]
, iverbHit = "knock"
, iweight = 15
, iaspects = []
, ieffects = [Explode "blast 20"]
, ifeature = [Precious, Identified]
, idesc = "A sturdy ring with a softly shining eye. If it contains a body booster unit, beware of the side-effects."
, ikit = []
}
ring1 = ring
{ irarity = [(10, 2)]
, iaspects = [AddSpeed $ 1 + d 2, AddMaxHP $ dl 7 - 7 - d 7]
, ieffects = [Explode "distortion"] -- strong magic
, ifeature = ifeature ring ++ [EqpSlot EqpSlotAddSpeed ""]
}
ring2 = ring
{ irarity = [(10, 5)]
, iaspects = [AddMaxHP $ 10 + dl 10, AddMaxCalm $ dl 5 - 20 - d 5]
, ifeature = ifeature ring ++ [EqpSlot EqpSlotAddMaxHP ""]
}
ring3 = ring
{ irarity = [(10, 5)]
, iaspects = [AddMaxCalm $ 29 + dl 10]
, ifeature = ifeature ring ++ [EqpSlot EqpSlotAddMaxCalm ""]
, idesc = "Cold, solid to the touch, perfectly round, engraved with solemn, strangely comforting, worn out words."
}
ring4 = ring
{ irarity = [(3, 3), (10, 5)]
, iaspects = [AddHurtMelee $ d 5 + dl 5 |*| 3, AddMaxHP $ dl 3 - 5 - d 3]
, ifeature = ifeature ring ++ [EqpSlot EqpSlotAddHurtMelee ""]
}
ring5 = ring -- by the time it's found, probably no space in eqp
{ irarity = [(5, 0), (10, 2)]
, iaspects = [AddLight $ d 2]
, ieffects = [Explode "distortion"] -- strong magic
, ifeature = ifeature ring ++ [EqpSlot EqpSlotAddLight ""]
, idesc = "A sturdy ring with a large, shining stone."
}
ring6 = ring
{ ifreq = [("treasure", 100)]
, irarity = [(10, 2)]
, iaspects = [ Unique, AddSpeed $ 3 + d 4
, AddMaxCalm $ - 20 - d 20, AddMaxHP $ - 20 - d 20 ]
, ieffects = [NoEffect "of Rush"] -- no explosion, because Durable
, ifeature = ifeature ring ++ [Durable, EqpSlot EqpSlotAddSpeed ""]
}
ring7 = ring
{ ifreq = [("useful", 100), ("ring of opportunity sniper", 1) ]
, irarity = [(1, 1)]
, iaspects = [AddSkills $ EM.fromList [(AbProject, 8)]]
, ieffects = [ NoEffect "of opportunity sniper"
, Explode "distortion" ] -- strong magic
, ifeature = ifeature ring ++ [EqpSlot (EqpSlotAddSkills AbProject) ""]
}
ring8 = ring
{ ifreq = [("useful", 1), ("ring of opportunity grenadier", 1) ]
, irarity = [(1, 1)]
, iaspects = [AddSkills $ EM.fromList [(AbProject, 11)]]
, ieffects = [ NoEffect "of opportunity grenadier"
, Explode "distortion" ] -- strong magic
, ifeature = ifeature ring ++ [EqpSlot (EqpSlotAddSkills AbProject) ""]
}
-- * Ordinary exploding consumables, often intended to be thrown
potion = ItemKind
{ isymbol = symbolPotion
, iname = "vial"
, ifreq = [("useful", 100)]
, iflavour = zipLiquid brightCol ++ zipPlain brightCol ++ zipFancy brightCol
, icount = 1
, irarity = [(1, 12), (10, 9)]
, iverbHit = "splash"
, iweight = 200
, iaspects = []
, ieffects = []
, ifeature = [ toVelocity 50 -- oily, bad grip
, Applicable, Fragile ]
, idesc = "A vial of bright, frothing concoction." -- purely natural; no nano, no alien tech
, ikit = []
}
potion1 = potion
{ ieffects = [ NoEffect "of rose water", Impress, RefillCalm (-3)
, OnSmash ApplyPerfume, OnSmash (Explode "fragrance") ]
}
potion2 = potion
{ ifreq = [("treasure", 100)]
, irarity = [(6, 10), (10, 10)]
, iaspects = [Unique]
, ieffects = [ NoEffect "of Attraction", Impress, OverfillCalm (-20)
, OnSmash (Explode "pheromone") ]
}
potion3 = potion
{ irarity = [(1, 10)]
, ieffects = [ RefillHP 5, DropItem COrgan "poisoned" True
, OnSmash (Explode "healing mist") ]
}
potion4 = potion
{ irarity = [(10, 10)]
, ieffects = [ RefillHP 10, DropItem COrgan "poisoned" True
, OnSmash (Explode "healing mist 2") ]
}
potion5 = potion
{ ieffects = [ OneOf [ OverfillHP 10, OverfillHP 5, Burn 5
, toOrganActorTurn "strengthened" (20 + d 5) ]
, OnSmash (OneOf [ Explode "healing mist"
, Explode "wounding mist"
, Explode "fragrance"
, Explode "smelly droplet"
, Explode "blast 10" ]) ]
}
potion6 = potion
{ irarity = [(3, 3), (10, 6)]
, ieffects = [ Impress
, OneOf [ OverfillCalm (-60)
, OverfillHP 20, OverfillHP 10, Burn 10
, toOrganActorTurn "fast 20" (20 + d 5) ]
, OnSmash (OneOf [ Explode "healing mist 2"
, Explode "calming mist"
, Explode "distressing odor"
, Explode "eye drop"
, Explode "blast 20" ]) ]
}
potion7 = potion
{ irarity = [(1, 15), (10, 5)]
, ieffects = [ DropItem COrgan "poisoned" True
, OnSmash (Explode "antidote mist") ]
}
potion8 = potion
{ irarity = [(1, 5), (10, 15)]
, ieffects = [ DropItem COrgan "temporary conditions" True
, OnSmash (Explode "blast 10") ]
}
potion9 = potion
{ ifreq = [("treasure", 100)]
, irarity = [(10, 5)]
, iaspects = [Unique]
, ieffects = [ NoEffect "of Love", OverfillHP 60
, Impress, OverfillCalm (-60)
, OnSmash (Explode "healing mist 2")
, OnSmash (Explode "pheromone") ]
}
-- * Exploding consumables with temporary aspects, can be thrown
-- TODO: dip projectiles in those
-- TODO: add flavour and realism as in, e.g., "flask of whiskey",
-- which is more flavourful and believable than "flask of strength"
flask = ItemKind
{ isymbol = symbolFlask
, iname = "flask"
, ifreq = [("useful", 100), ("flask", 100)]
, iflavour = zipLiquid darkCol ++ zipPlain darkCol ++ zipFancy darkCol
, icount = 1
, irarity = [(1, 9), (10, 6)]
, iverbHit = "splash"
, iweight = 500
, iaspects = []
, ieffects = []
, ifeature = [ toVelocity 50 -- oily, bad grip
, Applicable, Fragile ]
, idesc = "A flask of oily liquid of a suspect color."
, ikit = []
}
flask1 = flask
{ irarity = [(10, 5)]
, ieffects = [ NoEffect "of strength brew"
, toOrganActorTurn "strengthened" (20 + d 5)
, toOrganNone "regenerating"
, OnSmash (Explode "strength mist") ]
}
flask2 = flask
{ ieffects = [ NoEffect "of weakness brew"
, toOrganGameTurn "weakened" (20 + d 5)
, OnSmash (Explode "weakness mist") ]
}
flask3 = flask
{ ieffects = [ NoEffect "of protecting balm"
, toOrganActorTurn "protected" (20 + d 5)
, OnSmash (Explode "protecting balm") ]
}
flask4 = flask
{ ieffects = [ NoEffect "of red paint"
, toOrganGameTurn "painted red" (20 + d 5)
, OnSmash (Explode "red paint") ]
}
flask5 = flask
{ irarity = [(10, 5)]
, ieffects = [ NoEffect "of haste brew"
, toOrganActorTurn "fast 20" (20 + d 5)
, OnSmash (Explode "haste spray") ]
}
flask6 = flask
{ ieffects = [ NoEffect "of lethargy brew"
, toOrganGameTurn "slow 10" (20 + d 5)
, toOrganNone "regenerating"
, RefillCalm 3
, OnSmash (Explode "slowness spray") ]
}
flask7 = flask -- sight can be reduced from Calm, drunk, etc.
{ irarity = [(10, 7)]
, ieffects = [ NoEffect "of eye drops"
, toOrganActorTurn "far-sighted" (20 + d 5)
, OnSmash (Explode "blast 10") ]
}
flask8 = flask
{ irarity = [(10, 3)]
, ieffects = [ NoEffect "of smelly concoction"
, toOrganActorTurn "keen-smelling" (20 + d 5)
, OnSmash (Explode "blast 10") ]
}
flask9 = flask
{ ieffects = [ NoEffect "of bait cocktail"
, toOrganActorTurn "drunk" (5 + d 5)
, OnSmash (Summon [("mobile animal", 1)] $ 1 + dl 2)
, OnSmash (Explode "waste") ]
}
flask10 = flask
{ ieffects = [ NoEffect "of whiskey"
, toOrganActorTurn "drunk" (20 + d 5)
, Impress, Burn 2, RefillHP 4
, OnSmash (Explode "whiskey spray") ]
}
flask11 = flask
{ irarity = [(1, 20), (10, 10)]
, ieffects = [ NoEffect "of regeneration brew"
, toOrganNone "regenerating"
, OnSmash (Explode "healing mist") ]
}
flask12 = flask -- but not flask of Calm depletion, since Calm reduced often
{ ieffects = [ NoEffect "of poison"
, toOrganNone "poisoned"
, OnSmash (Explode "wounding mist") ]
}
flask13 = flask
{ irarity = [(10, 5)]
, ieffects = [ NoEffect "of slow resistance"
, toOrganNone "slow resistant"
, OnSmash (Explode "anti-slow mist") ]
}
flask14 = flask
{ irarity = [(10, 5)]
, ieffects = [ NoEffect "of poison resistance"
, toOrganNone "poison resistant"
, OnSmash (Explode "antidote mist") ]
}
-- * Non-exploding consumables, not specifically designed for throwing
constructionHooter = scroll
{ iname = "construction hooter"
, ifreq = [("useful", 1), ("construction hooter", 1)] -- extremely rare
, iflavour = zipPlain [BrRed]
, irarity = [(1, 1)]
, iaspects = []
, ieffects = [Summon [("construction robot", 1)] $ 1 + dl 2]
, ifeature = ifeature scroll ++ [Identified]
, idesc = "The single-use electronic overdrive hooter that construction robots use to warn about danger and call help in extreme emergency."
, ikit = []
}
scroll = ItemKind
{ isymbol = symbolScroll
, iname = "chip"
, ifreq = [("useful", 100), ("any scroll", 100)]
, iflavour = zipFancy stdCol ++ zipPlain darkCol -- arcane and old
, icount = 1
, irarity = [(1, 15), (10, 12)]
, iverbHit = "thump"
, iweight = 20
, iaspects = []
, ieffects = []
, ifeature = [ toVelocity 25 -- too little
, Applicable ]
, idesc = "A generic, diposable chip, capable of a one-time holo-display. Some of these also contain a one-time password authorizing a particular spaceship's infrastructure transition. It is unknown how the infrastructure might respond after so many years."
, ikit = []
}
scroll1 = scroll
{ ifreq = [("treasure", 100)]
, irarity = [(5, 10), (10, 10)] -- mixed blessing, so available early
, iaspects = [Unique]
, ieffects = [ NoEffect "of Reckless Beacon"
, CallFriend 1, Summon standardSummon (2 + d 2) ]
}
scroll2 = scroll
{ irarity = []
, ieffects = []
}
scroll3 = scroll
{ irarity = [(1, 5), (10, 3)]
, ieffects = [Ascend 1]
}
scroll4 = scroll
{ ieffects = [OneOf [ Teleport 5, RefillCalm 5, RefillCalm (-5)
, InsertMove 5, Paralyze 10 ]]
}
scroll5 = scroll
{ irarity = [(10, 15)]
, ieffects = [ Impress
, OneOf [ Teleport 20, Ascend (-1), Ascend 1
, Summon standardSummon 2, CallFriend 1
, RefillCalm 5, OverfillCalm (-60)
, CreateItem CGround "useful" TimerNone ] ]
}
scroll6 = scroll
{ ieffects = [Teleport 5]
}
scroll7 = scroll
{ ieffects = [Teleport 20]
}
scroll8 = scroll
{ irarity = [(10, 3)]
, ieffects = [InsertMove $ 1 + d 2 + dl 2]
}
scroll9 = scroll -- TODO: remove Calm when server can tell if anything IDed
{ irarity = [(1, 15), (10, 10)]
, ieffects = [ NoEffect "of scientific explanation"
, Identify, OverfillCalm 3 ]
}
scroll10 = scroll -- TODO: firecracker only if an item really polymorphed?
-- But currently server can't tell.
{ irarity = [(10, 10)]
, ieffects = [ NoEffect "molecular reconfiguration"
, PolyItem, Explode "firecracker 7" ]
}
scroll11 = scroll
{ ifreq = [("treasure", 100)]
, irarity = [(6, 10), (10, 10)]
, iaspects = [Unique]
, ieffects = [NoEffect "of Prisoner Release", CallFriend 1]
}
standardSummon :: Freqs ItemKind
standardSummon = [ ("mobile alien", 20)
, ("mobile animal", 50)
, ("mobile robot", 30) ]
-- * Armor
armorLeather = ItemKind
{ isymbol = symbolTorsoArmor
, iname = "spacesuit breastplate"
, ifreq = [("useful", 100)]
, iflavour = zipPlain [Brown]
, icount = 1
, irarity = [(1, 9), (10, 3)]
, iverbHit = "thud"
, iweight = 7000
, iaspects = [ AddHurtMelee (-3)
, AddArmorMelee $ 1 + d 2 + dl 2 |*| 5
, AddArmorRanged $ 1 + d 2 + dl 2 |*| 5 ]
, ieffects = []
, ifeature = [ toVelocity 30 -- unwieldy to throw and blunt
, Durable, EqpSlot EqpSlotAddArmorMelee "", Identified ]
, idesc = "A hard-shell torso segment cut from a disposed off spacesuit."
, ikit = []
}
armorMail = armorLeather
{ iname = "bulletproof vest"
, iflavour = zipPlain [Cyan]
, irarity = [(6, 9), (10, 3)]
, iweight = 12000
, iaspects = [ AddHurtMelee (-3)
, AddArmorMelee $ 2 + d 2 + dl 3 |*| 5
, AddArmorRanged $ 2 + d 2 + dl 3 |*| 5 ]
, idesc = "A civilian bulletproof vest. Discourages foes from attacking your torso, making it harder for them to land a blow."
}
gloveFencing = ItemKind
{ isymbol = symbolMiscArmor
, iname = "construction glove"
, ifreq = [("useful", 100)]
, iflavour = zipPlain [BrYellow]
, icount = 1
, irarity = [(5, 9), (10, 9)]
, iverbHit = "flap"
, iweight = 100
, iaspects = [ AddHurtMelee $ (d 2 + dl 10) |*| 3
, AddArmorRanged $ d 2 |*| 5 ]
, ieffects = []
, ifeature = [ toVelocity 30 -- flaps and flutters
, Durable, EqpSlot EqpSlotAddArmorRanged "", Identified ]
, idesc = "A flexible construction glove from rough leather ensuring a good grip. Also, quite effective in deflecting or even catching slow projectiles."
, ikit = []
}
gloveGauntlet = gloveFencing
{ iname = "spacesuit glove"
, iflavour = zipPlain [BrCyan]
, irarity = [(1, 9), (10, 3)]
, iweight = 300
, iaspects = [ AddArmorMelee $ 1 + dl 2 |*| 5
, AddArmorRanged $ 1 + dl 2 |*| 5 ]
, idesc = "A piece of a hull maintenance spacesuit, padded and reinforced with carbon fibre."
}
gloveJousting = gloveFencing
{ iname = "Welding Handgear"
, iflavour = zipFancy [BrRed]
, irarity = [(1, 3), (10, 3)]
, iweight = 500
, iaspects = [ Unique
, AddHurtMelee $ dl 4 - 6 |*| 3
, AddArmorMelee $ 2 + dl 2 |*| 5
, AddArmorRanged $ 2 + dl 2 |*| 5 ]
, idesc = "Rigid, bulky handgear embedding a welding equipment, complete with an affixed small shield and a darkened visor. Awe-inspiring."
}
-- * Shields
-- Shield doesn't protect against ranged attacks to prevent
-- micromanagement: walking with shield, melee without.
buckler = ItemKind
{ isymbol = symbolShield
, iname = "buckler"
, ifreq = [("useful", 100)]
, iflavour = zipPlain [Blue]
, icount = 1
, irarity = [(4, 6)]
, iverbHit = "bash"
, iweight = 2000
, iaspects = [ AddArmorMelee 40
, AddHurtMelee (-30)
, Timeout $ d 3 + 3 - dl 3 |*| 2 ]
, ieffects = [ Hurt (1 * d 1) -- to display xdy everywhre in Hurt
, Recharging (PushActor (ThrowMod 200 50)) ]
, ifeature = [ toVelocity 40 -- unwieldy to throw
, Durable, EqpSlot EqpSlotAddArmorMelee "", Identified ]
, idesc = "Heavy and unwieldy arm protection made from an outer airlock panel. Absorbs a percentage of melee damage, both dealt and sustained. Too small to intercept projectiles with."
, ikit = []
}
shield = buckler
{ iname = "shield"
, irarity = [(8, 3)]
, iflavour = zipPlain [Green]
, iweight = 3000
, iaspects = [ AddArmorMelee 80
, AddHurtMelee (-70)
, Timeout $ d 6 + 6 - dl 6 |*| 2 ]
, ieffects = [Hurt (1 * d 1), Recharging (PushActor (ThrowMod 400 50))]
, ifeature = [ toVelocity 30 -- unwieldy to throw
, Durable, EqpSlot EqpSlotAddArmorMelee "", Identified ]
, idesc = "Large and unwieldy rectangle made of anti-meteorite ceramic sheet. Absorbs a percentage of melee damage, both dealt and sustained. Too heavy to intercept projectiles with."
}
-- * Weapons
dagger = ItemKind
{ isymbol = symbolEdged
, iname = "cleaver"
, ifreq = [("useful", 100), ("starting weapon", 100)]
, iflavour = zipPlain [BrCyan]
, icount = 1
, irarity = [(1, 20)]
, iverbHit = "stab"
, iweight = 1000
, iaspects = [ AddHurtMelee $ d 3 + dl 3 |*| 3
, AddArmorMelee $ d 2 |*| 5
, AddHurtRanged (-60) ] -- as powerful as a dart
, ieffects = [Hurt (6 * d 1)]
, ifeature = [ toVelocity 40 -- ensuring it hits with the tip costs speed
, Durable, EqpSlot EqpSlotWeapon "", Identified ]
, idesc = "A heavy professional kitchen blade. Will do fine cutting any kind of meat and bone, as well as parrying blows. Does not penetrate deeply, but is hard to block. Especially useful in conjunction with a larger weapon."
, ikit = []
}
daggerDropBestWeapon = dagger
{ iname = "Double Dagger"
, ifreq = [("treasure", 20)]
, irarity = [(1, 2), (10, 4)]
-- The timeout has to be small, so that the player can count on the effect
-- occuring consistently in any longer fight. Otherwise, the effect will be
-- absent in some important fights, leading to the feeling of bad luck,
-- but will manifest sometimes in fights where it doesn't matter,
-- leading to the feeling of wasted power.
-- If the effect is very powerful and so the timeout has to be significant,
-- let's make it really large, for the effect to occur only once in a fight:
-- as soon as the item is equipped, or just on the first strike.
, iaspects = [Unique, Timeout $ d 3 + 4 - dl 3 |*| 2]
, ieffects = ieffects dagger
++ [Recharging DropBestWeapon, Recharging $ RefillCalm (-3)]
, idesc = "A knife with a forked blade that a focused fencer can use to catch and twist an opponent's weapon occasionally."
}
hammer = ItemKind
{ isymbol = symbolHafted
, iname = "demolition hammer"
, ifreq = [("useful", 100), ("starting weapon", 100)]
, iflavour = zipPlain [BrMagenta]
, icount = 1
, irarity = [(5, 15)]
, iverbHit = "club"
, iweight = 1500
, iaspects = [ AddHurtMelee $ d 2 + dl 2 |*| 3
, AddHurtRanged (-80) ] -- as powerful as a dart
, ieffects = [Hurt (8 * d 1)]
, ifeature = [ toVelocity 20 -- ensuring it hits with the sharp tip costs
, Durable, EqpSlot EqpSlotWeapon "", Identified ]
, idesc = "A hammer on a long handle used for construction work. It may not cause grave wounds, but neither does it ricochet or glance off armor. Great sidearm for opportunistic blows against armored foes."
, ikit = []
}
hammerParalyze = hammer
{ iname = "Concussion Hammer"
, ifreq = [("treasure", 20)]
, irarity = [(5, 2), (10, 4)]
, iaspects = [Unique, Timeout $ d 2 + 3 - dl 2 |*| 2]
, ieffects = ieffects hammer ++ [Recharging $ Paralyze 5]
}
hammerSpark = hammer
{ iname = "Grand Smithhammer"
, ifreq = [("treasure", 20)]
, irarity = [(5, 2), (10, 4)]
, iaspects = [Unique, Timeout $ d 4 + 4 - dl 4 |*| 2]
, ieffects = ieffects hammer ++ [Recharging $ Explode "spark"]
}
sword = ItemKind
{ isymbol = symbolPolearm
, iname = "sharpened pipe"
, ifreq = [("useful", 100), ("starting weapon", 100)]
, iflavour = zipPlain [BrBlue]
, icount = 1
, irarity = [(4, 1), (5, 15)]
, iverbHit = "slash"
, iweight = 2000
, iaspects = []
, ieffects = [Hurt (10 * d 1)]
, ifeature = [ toVelocity 5 -- ensuring it hits with the tip costs speed
, Durable, EqpSlot EqpSlotWeapon "", Identified ]
, idesc = "A makeshift weapon of simple design, but great potential. Hard to master, though."
, ikit = []
}
swordImpress = sword
{ isymbol = symbolEdged
, iname = "Master's Sword"
, ifreq = [("treasure", 20)]
, irarity = [(5, 1), (10, 4)]
, iaspects = [Unique, Timeout $ d 4 + 5 - dl 4 |*| 2]
, ieffects = ieffects sword ++ [Recharging Impress]
, idesc = "An old, dull, but well-balance blade, lending itself to impressive shows of fencing skill."
}
swordNullify = sword
{ isymbol = symbolEdged
, iname = "Gutting Sword"
, ifreq = [("treasure", 20)]
, irarity = [(5, 1), (10, 4)]
, iaspects = [Unique, Timeout $ d 4 + 5 - dl 4 |*| 2]
, ieffects = ieffects sword
++ [ Recharging $ DropItem COrgan "temporary conditions" True
, Recharging $ RefillHP (-2) ]
, idesc = "Cold, thin, ancient blade that pierces deeply and sends its victim into abrupt, sobering shock."
}
halberd = ItemKind
{ isymbol = symbolPolearm
, iname = "pole cleaver"
, ifreq = [("useful", 100), ("starting weapon", 1)]
, iflavour = zipPlain [BrYellow]
, icount = 1
, irarity = [(7, 1), (10, 10)]
, iverbHit = "impale"
, iweight = 3000
, iaspects = [AddArmorMelee $ 1 + dl 3 |*| 5]
, ieffects = [Hurt (12 * d 1)]
, ifeature = [ toVelocity 5 -- not balanced
, Durable, EqpSlot EqpSlotWeapon "", Identified ]
, idesc = "An improvised but deadly weapon made of a long, sharp kitchen knife glued and bound to a long pole."
, ikit = []
}
halberdPushActor = halberd
{ iname = "Swiss Halberd"
, ifreq = [("treasure", 20)]
, irarity = [(7, 1), (10, 4)]
, iaspects = [Unique, Timeout $ d 5 + 5 - dl 5 |*| 2]
, ieffects = ieffects halberd ++ [Recharging (PushActor (ThrowMod 400 25))]
, idesc = "A perfect replica made for a reenactor troupe, missing only some sharpening. Versatile, with great reach and leverage. Foes are held at a distance."
}
-- * Wands
wand = ItemKind
{ isymbol = symbolWand
, iname = "injector"
, ifreq = [("useful", 100)]
, iflavour = zipFancy brightCol
, icount = 1
, irarity = [] -- TODO: add charges, etc.
, iverbHit = "club"
, iweight = 300
, iaspects = [AddLight 1, AddSpeed (-1)] -- pulsing with power, distracts
, ieffects = []
, ifeature = [ toVelocity 125 -- sufficiently advanced tech
, Applicable, Durable ]
, idesc = "Buzzing with dazzling light that shines even through appendages that handle it."
, ikit = []
}
wand1 = wand
{ ieffects = [] -- TODO: emit a cone of sound shrapnel that makes enemy cover his ears and so drop '{'
}
wand2 = wand
{ ieffects = []
}
-- * Treasure
gem = ItemKind
{ isymbol = symbolGem
, iname = "gem"
, ifreq = [("treasure", 100), ("gem", 100)]
, iflavour = zipPlain $ delete BrYellow brightCol -- natural, so not fancy
, icount = 1
, irarity = []
, iverbHit = "tap"
, iweight = 50
, iaspects = [AddLight 1, AddSpeed (-1)]
-- reflects strongly, distracts; so it glows in the dark,
-- is visible on dark floor, but not too tempting to wear
, ieffects = []
, ifeature = [Precious]
, idesc = "Precious, though useless. Worth around 100 gold grains."
, ikit = []
}
gem1 = gem
{ irarity = [(3 * 10/12, 0), (10, 12)]
}
gem2 = gem
{ irarity = [(5 * 10/12, 0), (10, 14)]
}
gem3 = gem
{ irarity = [(7 * 10/12, 0), (10, 16)]
}
gem4 = gem
{ iname = "stimpack"
, iflavour = zipPlain [BrYellow]
, irarity = [(1, 40), (10, 40)]
, iaspects = []
, ieffects = [NoEffect "of youth", OverfillCalm 5, OverfillHP 15]
, ifeature = [Identified, Applicable, Precious] -- TODO: only heal humans
, idesc = "Calms, heals, invigorates and rejuvenates at the same time. No side-effects. As valuable as precious gems, at 100 gold grains each."
}
currency = ItemKind
{ isymbol = symbolGold
, iname = "gold grain"
, ifreq = [("treasure", 100), ("currency", 100)]
, iflavour = zipPlain [BrYellow]
, icount = 10 + d 20 + dl 20
, irarity = [(1, 25), (10, 10)]
, iverbHit = "tap"
, iweight = 1
, iaspects = []
, ieffects = []
, ifeature = [Identified, Precious]
, idesc = "Reliably valuable in every civilized place."
, ikit = []
}
Allure-0.5.0.0/GameDefinition/Content/ModeKind.hs 0000644 0000000 0000000 00000034242 12555263417 017625 0 ustar 00 0000000 0000000 -- Copyright (c) 2008--2011 Andres Loeh, 2010--2015 Mikolaj Konarski
-- This file is a part of the computer game Allure of the Stars
-- and is released under the terms of the GNU Affero General Public License.
-- For license and copyright information, see the file LICENSE.
--
-- | Game mode definitions.
module Content.ModeKind ( cdefs ) where
import qualified Data.IntMap.Strict as IM
import Content.ModeKindPlayer
import Game.LambdaHack.Common.ContentDef
import Game.LambdaHack.Common.Dice
import Game.LambdaHack.Common.Misc
import Game.LambdaHack.Content.ModeKind
cdefs :: ContentDef ModeKind
cdefs = ContentDef
{ getSymbol = msymbol
, getName = mname
, getFreq = mfreq
, validateSingle = validateSingleModeKind
, validateAll = validateAllModeKind
, content =
[campaign, raid, skirmish, ambush, battle, battleSurvival, safari, safariSurvival, pvp, coop, defense, screensaver]
}
campaign, raid, skirmish, ambush, battle, battleSurvival, safari, safariSurvival, pvp, coop, defense, screensaver :: ModeKind
campaign = ModeKind
{ msymbol = 'c'
, mname = "campaign"
, mfreq = [("campaign", 1)]
, mroster = rosterCampaign
, mcaves = cavesCampaign
, mdesc = "You got stranded looting the blasted bridge of a once luxurious cruise liner. Your current plan is to fight through, gathering your spoils, to the shuttle airlock somewhere among the giant spaceship's uppermost decks. There are animal cries down below and ominous silence up above."
}
raid = ModeKind
{ msymbol = 'r'
, mname = "raid"
, mfreq = [("raid", 1)]
, mroster = rosterRaid
, mcaves = cavesRaid
, mdesc = "The Triton City sewers need purging. The first person to break through to the other end will be paid 100 gold grains. Please don't fight."
}
skirmish = ModeKind
{ msymbol = 'k'
, mname = "skirmish"
, mfreq = [("skirmish", 1)]
, mroster = rosterSkirmish
, mcaves = cavesSkirmish
, mdesc = "You cheated. Come alone to the woody biosphere behind the saloon at noon, if you dare. The winner takes all the spoils, including the keys and the papers of the decrepit giant spaceship."
}
ambush = ModeKind
{ msymbol = 'm'
, mname = "ambush"
, mfreq = [("ambush", 1)]
, mroster = rosterAmbush
, mcaves = cavesAmbush
, mdesc = "Conveniently, on the path to the Triton's spaceport, passengers can relax in a shady park."
}
battle = ModeKind
{ msymbol = 'b'
, mname = "battle"
, mfreq = [("battle", 1)]
, mroster = rosterBattle
, mcaves = cavesBattle
, mdesc = "Not even the unexplained ruin of the largest and tightest security Neptune's moon spaceport will prevent you from claiming your prize."
}
battleSurvival = ModeKind
{ msymbol = 'i'
, mname = "battle survival"
, mfreq = [("battle survival", 1)]
, mroster = rosterBattleSurvival
, mcaves = cavesBattle
, mdesc = "Odds are stacked for those that breathe mathematics."
}
safari = ModeKind
{ msymbol = 'f'
, mname = "safari"
, mfreq = [("safari", 1)]
, mroster = rosterSafari
, mcaves = cavesSafari
, mdesc = "In this simulation you'll discover the joys of hunting the most exquisite of Earth's flora and fauna, both animal and semi-intelligent (exit at the uppermost level)."
}
safariSurvival = ModeKind
{ msymbol = 'u'
, mname = "safari survival"
, mfreq = [("safari survival", 1)]
, mroster = rosterSafariSurvival
, mcaves = cavesSafari
, mdesc = "In this simulation you'll discover the joys of being hunted among the most exquisite of Earth's flora and fauna, both animal and semi-intelligent."
}
pvp = ModeKind
{ msymbol = 'v'
, mname = "PvP"
, mfreq = [("PvP", 1)]
, mroster = rosterPvP
, mcaves = cavesSkirmish
, mdesc = "(Not usable right now.) This is a fight to the death between two human-controlled teams."
}
coop = ModeKind
{ msymbol = 'o'
, mname = "Coop"
, mfreq = [("Coop", 1)]
, mroster = rosterCoop
, mcaves = cavesCampaign
, mdesc = "(This mode is intended solely for automated testing.)"
}
defense = ModeKind
{ msymbol = 'e'
, mname = "defense"
, mfreq = [("defense", 1)]
, mroster = rosterDefense
, mcaves = cavesCampaign
, mdesc = "Don't let the half-witted humans derail your operation and flee, like the puny, naked, tentacle-less beasts that they are!"
}
screensaver = safari
{ mname = "safari screensaver"
, mfreq = [("starting", 1)]
, mroster = rosterSafari
{ rosterList = (head (rosterList rosterSafari))
-- changing leader by client needed, because of TFollow
-- changing level by client enabled for UI
{fleaderMode = LeaderAI $ AutoLeader False False}
: tail (rosterList rosterSafari)
}
}
rosterCampaign, rosterRaid, rosterSkirmish, rosterAmbush, rosterBattle, rosterBattleSurvival, rosterSafari, rosterSafariSurvival, rosterPvP, rosterCoop, rosterDefense :: Roster
rosterCampaign = Roster
{ rosterList = [ playerHero
, playerMonster
, playerAnimal
, playerRobot ]
, rosterEnemy = [ ("Spacefarer Crew", "Alien Hierarchy")
, ("Spacefarer Crew", "Animal Kingdom")
, ("Spacefarer Crew", "Robot Anarchy") ]
, rosterAlly = [ ("Alien Hierarchy", "Animal Kingdom")
, ("Alien Hierarchy", "Robot Anarchy")
, ("Robot Anarchy", "Animal Kingdom") ] }
rosterRaid = Roster
{ rosterList = [ playerHero { fname = "Spacefarer Crew"
, fhiCondPoly = hiRaid
, fentryLevel = 4
, finitialActors = 1 }
, playerAntiHero { fname = "Red Collars"
, fhiCondPoly = hiRaid
, fentryLevel = 4
, finitialActors = 1 }
, playerAnimal { fentryLevel = 4
, finitialActors = 1 }
, playerRobot { fentryLevel = 4
, finitialActors = 1 } ]
, rosterEnemy = [ ("Spacefarer Crew", "Animal Kingdom")
, ("Spacefarer Crew", "Robot Anarchy")
, ("Red Collars", "Animal Kingdom")
, ("Red Collars", "Robot Anarchy") ]
, rosterAlly = [("Robot Anarchy", "Animal Kingdom")] }
rosterSkirmish = Roster
{ rosterList = [ playerHero { fname = "Spacefarer Crew"
, fhiCondPoly = hiDweller
, fentryLevel = 4 }
, playerAntiHero { fname = "Red Collars"
, fhiCondPoly = hiDweller
, fentryLevel = 4 }
, playerHorror ]
, rosterEnemy = [ ("Spacefarer Crew", "Red Collars")
, ("Spacefarer Crew", "Horror Den")
, ("Red Collars", "Horror Den") ]
, rosterAlly = [] }
rosterAmbush = rosterSkirmish
{ rosterList = [ playerSniper { fname = "Spacefarer Crew"
, fhiCondPoly = hiDweller
, fentryLevel = 7
, finitialActors = 4 }
, playerAntiSniper { fname = "Red Collars"
, fhiCondPoly = hiDweller
, fentryLevel = 7
, finitialActors = 4 }
, playerHorror {fentryLevel = 7} ] }
rosterBattle = Roster
{ rosterList = [ playerSoldier { fhiCondPoly = hiDweller
, fentryLevel = 7
, finitialActors = 5 }
, playerMobileMonster { fentryLevel = 7
, finitialActors = 35
, fneverEmpty = True }
, playerMobileAnimal { fentryLevel = 7
, finitialActors = 20
, fneverEmpty = True }
, playerMobileRobot { fentryLevel = 7
, finitialActors = 15
, fneverEmpty = True } ]
, rosterEnemy = [ ("Armed Spacefarer Crew", "Alien Hierarchy")
, ("Armed Spacefarer Crew", "Animal Kingdom")
, ("Armed Spacefarer Crew", "Robot Anarchy") ]
, rosterAlly = [ ("Alien Hierarchy", "Animal Kingdom")
, ("Alien Hierarchy", "Robot Anarchy")
, ("Robot Anarchy", "Animal Kingdom") ] }
rosterBattleSurvival = rosterBattle
{ rosterList = [ playerSoldier { fhiCondPoly = hiDweller
, fentryLevel = 7
, finitialActors = 5
, fleaderMode =
LeaderAI $ AutoLeader True False
, fhasUI = False }
, playerMobileMonster { fentryLevel = 7
, finitialActors = 35
, fneverEmpty = True }
, playerMobileAnimal { fentryLevel = 7
, finitialActors = 20
, fneverEmpty = True }
, playerMobileRobot { fentryLevel = 7
, finitialActors = 15
, fneverEmpty = True
, fhasUI = True } ] }
playerMonsterTourist, playerHunamConvict, playerAnimalMagnificent, playerAnimalExquisite :: Player Dice
playerMonsterTourist =
playerAntiMonster { fname = "Alien Tourist Office"
, fcanEscape = True
, fneverEmpty = True -- no spawning
-- Follow-the-guide, as tourists do.
, ftactic = TFollow
, fentryLevel = 4
, finitialActors = 15
, fleaderMode =
LeaderUI $ AutoLeader False False }
playerHunamConvict =
playerCivilian { fname = "Hunam Convict Pack"
, fentryLevel = 4 }
playerAnimalMagnificent =
playerMobileAnimal { fname = "Animal Magnificent Specimen Variety"
, fneverEmpty = True
, fentryLevel = 7
, finitialActors = 10
, fleaderMode = -- move away from stairs
LeaderAI $ AutoLeader True False }
playerAnimalExquisite =
playerMobileAnimal { fname = "Animal Exquisite Herds and Packs"
, fneverEmpty = True
, fentryLevel = 10
, finitialActors = 30 }
rosterSafari = Roster
{ rosterList = [ playerMonsterTourist
, playerHunamConvict
, playerAnimalMagnificent
, playerAnimalExquisite
]
, rosterEnemy = [ ( "Alien Tourist Office", "Hunam Convict Pack")
, ( "Alien Tourist Office"
, "Animal Magnificent Specimen Variety" )
, ( "Alien Tourist Office"
, "Animal Exquisite Herds and Packs" ) ]
, rosterAlly = [ ( "Animal Magnificent Specimen Variety"
, "Animal Exquisite Herds and Packs" )
, ( "Animal Magnificent Specimen Variety"
, "Hunam Convict Pack" )
, ( "Hunam Convict Pack"
, "Animal Exquisite Herds and Packs" ) ] }
rosterSafariSurvival = rosterSafari
{ rosterList = [ playerMonsterTourist
{ fleaderMode = LeaderAI $ AutoLeader True False
, fhasUI = False }
, playerHunamConvict
, playerAnimalMagnificent
{ fleaderMode = LeaderUI $ AutoLeader False False
, fhasUI = True }
, playerAnimalExquisite
] }
rosterPvP = Roster
{ rosterList = [ playerHero { fname = "Red"
, fhiCondPoly = hiDweller
, fentryLevel = 4 }
, playerHero { fname = "Blue"
, fhiCondPoly = hiDweller
, fentryLevel = 4 }
, playerHorror ]
, rosterEnemy = [ ("Red", "Blue")
, ("Red", "Horror Den")
, ("Blue", "Horror Den") ]
, rosterAlly = [] }
rosterCoop = Roster
{ rosterList = [ playerAntiHero { fname = "Coral" }
, playerAntiHero { fname = "Amber"
, fleaderMode = LeaderNull }
, playerAnimal { fhasUI = True }
, playerAnimal
, playerMonster { fname = "Alien Hierarchy"
, finitialActors = 3 }
, playerMonster { fname = "Leaderless Alien Hierarchy"
, finitialActors = 1
, fleaderMode = LeaderNull }
, playerRobot ]
, rosterEnemy = [ ("Coral", "Alien Hierarchy")
, ("Amber", "Alien Hierarchy") ]
, rosterAlly = [ ("Coral", "Amber") ] }
rosterDefense = rosterCampaign
{ rosterList = [ playerAntiHero
, playerAntiMonster
, playerAnimal
, playerRobot ] }
cavesCampaign, cavesRaid, cavesSkirmish, cavesAmbush, cavesBattle, cavesSafari :: Caves
cavesCampaign = IM.fromList
$ [(1, ("shallow random 1", Nothing))]
++ [(2, ("shallow random 2", Nothing))]
++ [(3, ("caveBridge", Nothing))]
++ [(4, ("caveNoise", Nothing))]
++ zip [5..9] (repeat ("campaign random", Nothing))
++ [(10, ("caveEmpty", Just False))]
++ [(11, ("campaign random", Nothing))]
++ [(12, ("caveNoise", Nothing))]
cavesRaid = IM.fromList [(4, ("caveRogueLit", Just True))]
cavesSkirmish = IM.fromList [(4, ("caveSkirmish", Nothing))]
cavesAmbush = IM.fromList [(7, ("caveAmbush", Nothing))]
cavesBattle = IM.fromList [(7, ("caveBattle", Nothing))]
cavesSafari = IM.fromList [ (4, ("caveSafari1", Nothing))
, (7, ("caveSafari2", Nothing))
, (10, ("caveSafari3", Just False)) ]
Allure-0.5.0.0/GameDefinition/Content/CaveKind.hs 0000644 0000000 0000000 00000022144 12555263417 017615 0 ustar 00 0000000 0000000 -- Copyright (c) 2008--2011 Andres Loeh, 2010--2015 Mikolaj Konarski
-- This file is a part of the computer game Allure of the Stars
-- and is released under the terms of the GNU Affero General Public License.
-- For license and copyright information, see the file LICENSE.
--
-- | Cave layouts.
module Content.CaveKind ( cdefs ) where
import Data.Ratio
import Game.LambdaHack.Common.ContentDef
import Game.LambdaHack.Common.Dice
import Game.LambdaHack.Common.Misc
import Game.LambdaHack.Content.CaveKind
cdefs :: ContentDef CaveKind
cdefs = ContentDef
{ getSymbol = csymbol
, getName = cname
, getFreq = cfreq
, validateSingle = validateSingleCaveKind
, validateAll = validateAllCaveKind
, content =
[rogue, arena, empty, noise, battle, skirmish, ambush, safari1, safari2, safari3, rogueLit, bridge, shallow2rogue, shallow2arena, shallow2empty, shallow1arena]
}
rogue, arena, empty, noise, battle, skirmish, ambush, safari1, safari2, safari3, rogueLit, bridge, shallow2rogue, shallow2arena, shallow2empty, shallow1arena :: CaveKind
rogue = CaveKind
{ csymbol = 'R'
, cname = "Storage area"
, cfreq = [("campaign random", 100), ("caveRogue", 1)]
, cxsize = fst normalLevelBound + 1
, cysize = snd normalLevelBound + 1
, cgrid = DiceXY (3 * d 2) (d 2 + 2)
, cminPlaceSize = DiceXY (2 * d 2 + 2) 4
, cmaxPlaceSize = DiceXY 15 10
, cdarkChance = d 54 + dl 20
, cnightChance = 51 -- always night
, cauxConnects = 1%3
, cmaxVoid = 1%6
, cminStairDist = 30
, cdoorChance = 1%2
, copenChance = 1%10
, chidden = 8
, cactorCoeff = 150 -- the maze requires time to explore
, cactorFreq = [("alien", 50), ("animal", 25), ("robot", 25)]
, citemNum = 10 * d 2
, citemFreq = [("useful", 50), ("treasure", 50)]
, cplaceFreq = [("rogue", 100)]
, cpassable = False
, cdefTile = "fillerWall"
, cdarkCorTile = "floorCorridorDark"
, clitCorTile = "floorCorridorLit"
, cfillerTile = "fillerWall"
, couterFenceTile = "basic outer fence"
, clegendDarkTile = "legendDark"
, clegendLitTile = "legendLit"
}
arena = rogue
{ csymbol = 'A'
, cname = "Recreational deck"
, cfreq = [("campaign random", 50), ("caveArena", 1)]
, cgrid = DiceXY (2 * d 2) (2 * d 2)
, cminPlaceSize = DiceXY (2 * d 2 + 3) 4
, cdarkChance = d 100 - dl 50
-- Trails provide enough light for fun stealth. Light is not too deadly,
-- because not many obstructions, so foes visible from far away.
, cnightChance = d 50 + dl 50
, cmaxVoid = 1%4
, chidden = 1000
, cactorCoeff = 100
, cactorFreq = [("alien", 25), ("animal", 70), ("robot", 5)]
, citemNum = 9 * d 2 -- few rooms
, cpassable = True
, cdefTile = "arenaSet"
, cdarkCorTile = "trailLit" -- let trails give off light
, clitCorTile = "trailLit"
}
empty = rogue
{ csymbol = 'E'
, cname = "Construction site"
, cfreq = [("campaign random", 50), ("caveEmpty", 1)]
, cgrid = DiceXY (d 2 + 1) 1
, cminPlaceSize = DiceXY 10 10
, cmaxPlaceSize = DiceXY 24 15
, cdarkChance = d 80 + dl 80
, cnightChance = 0 -- always day
, cauxConnects = 1
, cmaxVoid = 1%2
, cminStairDist = 50
, chidden = 1000
, cactorCoeff = 80
, cactorFreq = [("alien", 25), ("animal", 5), ("robot", 70)]
, citemNum = 7 * d 2 -- few rooms
, cpassable = True
, cdefTile = "emptySet"
, cdarkCorTile = "floorArenaDark"
, clitCorTile = "floorArenaLit"
}
noise = rogue
{ csymbol = 'N'
, cname = "Machine rooms"
, cfreq = [("caveNoise", 1)]
, cgrid = DiceXY (2 + d 2) 3
, cminPlaceSize = DiceXY 12 5
, cmaxPlaceSize = DiceXY 24 15
, cdarkChance = 0 -- few rooms, so all lit
-- Light is deadly, because nowhere to hide and pillars enable spawning
-- very close to heroes, so deep down light should be rare.
, cnightChance = dl 300
, cauxConnects = 0
, cmaxVoid = 0
, chidden = 1000
, cactorCoeff = 160 -- the maze requires time to explore
, cactorFreq = [("alien", 70), ("animal", 15), ("robot", 15)]
, citemNum = 12 * d 2 -- an incentive to explore the labyrinth
, cpassable = True
, cplaceFreq = [("noise", 100)]
, cdefTile = "noiseSet"
, cdarkCorTile = "floorArenaDark"
, clitCorTile = "floorArenaLit"
}
battle = rogue -- few lights and many solids, to help the less numerous heroes
{ csymbol = 'B'
, cname = "Ravaged spaceport"
, cfreq = [("caveBattle", 1)]
, cgrid = DiceXY (2 * d 2 + 1) 3
, cminPlaceSize = DiceXY 4 4
, cmaxPlaceSize = DiceXY 9 7
, cdarkChance = 0
, cnightChance = 51 -- always night
, cmaxVoid = 0
, cdoorChance = 2%10
, copenChance = 9%10
, chidden = 1000
, cactorFreq = []
, citemNum = 20 * d 2
, citemFreq = [("useful", 100), ("light source", 200)]
, cplaceFreq = [("battle", 50), ("rogue", 50)]
, cpassable = True
, cdefTile = "battleSet"
, cdarkCorTile = "trailLit" -- let trails give off light
, clitCorTile = "trailLit"
}
skirmish = rogue -- many random solid tiles, to break LOS, since it's a day
{ csymbol = 'S'
, cname = "Woodland biosphere"
, cfreq = [("caveSkirmish", 1)]
, cgrid = DiceXY (2 * d 2 + 2) (d 2 + 2)
, cminPlaceSize = DiceXY 3 3
, cmaxPlaceSize = DiceXY 7 5
, cdarkChance = 100
, cnightChance = 0
, cdoorChance = 1
, copenChance = 0
, chidden = 1000
, cactorFreq = []
, citemNum = 20 * d 2
, citemFreq = [("useful", 100)]
, cplaceFreq = [("skirmish", 60), ("rogue", 40)]
, cpassable = True
, cdefTile = "skirmishSet"
, cdarkCorTile = "floorArenaLit"
, clitCorTile = "floorArenaLit"
}
ambush = rogue -- lots of lights, to give a chance to snipe
{ csymbol = 'M'
, cname = "Public garden"
, cfreq = [("caveAmbush", 1)]
, cgrid = DiceXY (2 * d 2 + 3) (d 2 + 2)
, cminPlaceSize = DiceXY 3 3
, cmaxPlaceSize = DiceXY 5 5
, cdarkChance = 0
, cnightChance = 51 -- always night
, cauxConnects = 1
, cdoorChance = 1%10
, copenChance = 9%10
, chidden = 1000
, cactorFreq = []
, citemNum = 22 * d 2
, citemFreq = [("useful", 100)]
, cplaceFreq = [("ambush", 100)]
, cpassable = True
, cdefTile = "ambushSet"
, cdarkCorTile = "trailLit" -- let trails give off light
, clitCorTile = "trailLit"
}
safari1 = ambush {cfreq = [("caveSafari1", 1)]}
safari2 = battle {cfreq = [("caveSafari2", 1)]}
safari3 = skirmish {cfreq = [("caveSafari3", 1)]}
rogueLit = rogue
{ csymbol = 'S'
, cname = "Triton City Sewers"
, cfreq = [("caveRogueLit", 1)]
, cdarkChance = 0
, cmaxVoid = 1%10
, cactorCoeff = 1000 -- deep level with no eqp, so slow spawning
, cactorFreq = [("animal", 50), ("robot", 50)]
, citemNum = 30 * d 2 -- just one level, hard enemies, treasure
, citemFreq = [("useful", 33), ("gem", 33), ("currency", 33)]
, cdarkCorTile = "emergency walkway"
, clitCorTile = "emergency walkway"
}
bridge = rogueLit
{ csymbol = 'B'
, cname = "Captain's bridge"
, cfreq = [("caveBridge", 1)]
, cgrid = DiceXY (d 2 + 1) 2
, cminPlaceSize = DiceXY 10 7
, cmaxPlaceSize = DiceXY 40 14
, cactorFreq = [] -- safe, nothing spawns
, citemNum = 15 * d 2 -- lure them in with loot
, citemFreq = filter ((/= "treasure") . fst) $ citemFreq rogue
}
shallow2rogue = rogue
{ cfreq = [("shallow random 2", 50)]
, cactorCoeff = cactorCoeff rogue `div` 2
, cactorFreq = filter ((/= "alien") . fst) $ cactorFreq rogue
, citemFreq = filter ((/= "treasure") . fst) $ citemFreq rogue
}
shallow2arena = arena
{ cfreq = [("shallow random 2", 100)]
, cnightChance = 0 -- safe and easy
, cactorCoeff = cactorCoeff arena `div` 2
, cactorFreq = filter ((/= "alien") . fst) $ cactorFreq empty
, citemFreq = filter ((/= "treasure") . fst) $ citemFreq empty
}
shallow2empty = empty
{ cfreq = [("shallow random 2", 20)]
, cactorFreq = filter ((/= "alien") . fst) $ cactorFreq empty
, cactorCoeff = cactorCoeff empty `div` 2
, citemFreq = filter ((/= "treasure") . fst) $ citemFreq empty
}
shallow1arena = shallow2empty -- TODO: replace some rooms with oriels?
{ cname = "Outermost deck"
, cfreq = [("shallow random 1", 100)]
, cminPlaceSize = DiceXY (2 * d 2 + 3) 3
, cactorCoeff = 3 -- mostly immobile actors anyway
, cactorFreq = [("animal", 8), ("robot", 2), ("immobile robot", 90)]
-- The medbot faucets on lvl 1 act like HP resets. They are needed to avoid
-- cascading failure, if the particular starting conditions were
-- very hard. The items are not reset, even if the are bad, which provides
-- enough of a continuity. The faucets on lvl 1 are not OP and can't be
-- abused, because they spawn less and less often and they don't heal over
-- max HP.
, couterFenceTile = "oriels fence"
}
Allure-0.5.0.0/GameDefinition/Content/ItemKindActor.hs 0000644 0000000 0000000 00000063524 12555263417 020635 0 ustar 00 0000000 0000000 -- Copyright (c) 2008--2011 Andres Loeh, 2010--2015 Mikolaj Konarski
-- This file is a part of the computer game Allure of the Stars
-- and is released under the terms of the GNU Affero General Public License.
-- For license and copyright information, see the file LICENSE.
--
-- | Actor (or rather actor body trunk) definitions.
module Content.ItemKindActor ( actors ) where
import qualified Data.EnumMap.Strict as EM
import Game.LambdaHack.Common.Ability
import Game.LambdaHack.Common.Color
import Game.LambdaHack.Common.Flavour
import Game.LambdaHack.Common.Misc
import Game.LambdaHack.Content.ItemKind
actors :: [ItemKind]
actors =
[warrior, warrior2, warrior3, warrior4, soldier, sniper, civilian, civilian2, civilian3, civilian4, civilian5, eye, fastEye, nose, elbow, torsor, goldenJackal, griffonVulture, skunk, armadillo, gilaMonster, rattlesnake, komodoDragon, hyena, alligator, rhinoceros, beeSwarm, hornetSwarm, thornbush, razorwireFence, electricFence, activeFence, steamFaucet, biogasFaucet, medbotFaucet, surveillanceDrone, shepherdDrone, huntingDrone, homeRobot, wasteRobot, lightRobot, heavyRobot, cleanerRobot]
warrior, warrior2, warrior3, warrior4, soldier, sniper, civilian, civilian2, civilian3, civilian4, civilian5, eye, fastEye, nose, elbow, torsor, goldenJackal, griffonVulture, skunk, armadillo, gilaMonster, rattlesnake, komodoDragon, hyena, alligator, rhinoceros, beeSwarm, hornetSwarm, thornbush, razorwireFence, electricFence, activeFence, steamFaucet, biogasFaucet, medbotFaucet, surveillanceDrone, shepherdDrone, huntingDrone, homeRobot, wasteRobot, lightRobot, heavyRobot, cleanerRobot :: ItemKind
-- * Hunams
warrior = ItemKind
{ isymbol = '@'
, iname = "mercenary" -- modified if in hero faction
, ifreq = [("hero", 100), ("civilian", 100), ("mobile", 1)]
, iflavour = zipPlain [BrBlack] -- modified if in hero faction
, icount = 1
, irarity = [(1, 5)]
, iverbHit = "thud"
, iweight = 80000
, iaspects = [ AddMaxHP 80 -- partially from clothes and assumed first aid
-- also possibly from artificial skin
, AddMaxCalm 60, AddSpeed 20
, AddSkills $ EM.fromList [(AbProject, 2), (AbApply, 1)] ]
, ieffects = []
, ifeature = [Durable, Identified]
, idesc = ""
, ikit = [ ("fist", COrgan), ("foot", COrgan), ("eye 5", COrgan)
, ("sapient brain", COrgan) ]
}
warrior2 = warrior
{ iname = "pilot" }
warrior3 = warrior
{ iname = "engineer" }
warrior4 = warrior
{ iname = "doctor" }
soldier = warrior
{ iname = "soldier"
, ifreq = [("soldier", 100), ("mobile", 1)]
, ikit = ikit warrior ++ [("starting weapon", CEqp)]
}
sniper = warrior
{ iname = "sniper"
, ifreq = [("sniper", 100), ("mobile", 1)]
, ikit = ikit warrior
++ [ ("ring of opportunity sniper", CEqp)
, ("any arrow", CSha), ("any arrow", CInv)
, ("any arrow", CInv), ("any arrow", CInv)
, ("flask", CInv), ("light source", CSha)
, ("light source", CInv), ("light source", CInv) ]
}
civilian = warrior
{ iname = "clerk"
, ifreq = [("civilian", 100), ("mobile", 1)] }
civilian2 = civilian
{ iname = "hairdresser" }
civilian3 = civilian
{ iname = "lawyer" }
civilian4 = civilian
{ iname = "peddler" }
civilian5 = civilian
{ iname = "tax collector" }
-- * Aliens
eye = ItemKind
{ isymbol = 'w'
, iname = "beckoning walker"
, ifreq = [("alien", 100), ("horror", 100), ("mobile alien", 100)]
, iflavour = zipFancy [BrRed]
, icount = 1
, irarity = [(4, 6), (10, 10)]
, iverbHit = "thud"
, iweight = 80000
, iaspects = [ AddMaxHP 20, AddMaxCalm 60, AddSpeed 20
, AddSkills $ EM.fromList [(AbProject, 2), (AbApply, 1)] ]
, ieffects = []
, ifeature = [Durable, Identified]
, idesc = "Walks with a stately dignity. You read death in the slow beckoning gestures of its revolting upper appendages."
, ikit = [ ("foot", COrgan), ("tentacle", COrgan)
, ("eye 5", COrgan)
, ("sapient brain", COrgan) ]
}
fastEye = ItemKind
{ isymbol = 'b'
, iname = "crawling biter"
, ifreq = [("alien", 100), ("horror", 100), ("mobile alien", 100)]
, iflavour = zipFancy [BrBlue]
, icount = 1
, irarity = [(4, 3), (10, 10)]
, iverbHit = "thud"
, iweight = 80000
, iaspects = [ AddMaxHP 5, AddMaxCalm 60, AddSpeed 30 ]
, ieffects = []
, ifeature = [Durable, Identified]
, idesc = "It bites as blindingly fast as it runs. Or rolls? Or crawls? Also, cuts and pierces."
, ikit = [ ("tentacle", COrgan), ("jaw", COrgan)
, ("eye 4", COrgan), ("speed gland 10", COrgan)
, ("sapient brain", COrgan) ]
}
nose = ItemKind -- depends solely on smell
{ isymbol = 'h'
, iname = "tentacled horror"
, ifreq = [("alien", 100), ("horror", 100), ("mobile alien", 100)]
, iflavour = zipFancy [BrGreen]
, icount = 1
, irarity = [(4, 5), (10, 9)]
, iverbHit = "thud"
, iweight = 80000
, iaspects = [ AddMaxHP 30, AddMaxCalm 30, AddSpeed 18
, AddSkills $ EM.fromList [(AbProject, -1)] ]
, ieffects = []
, ifeature = [Durable, Identified]
, idesc = "A blind, slimy mass of clawing, stinging and burning. You'd think it's powerless, but as soon as it touches your trembling body, it's always one step ahead."
, ikit = [ ("nostril", COrgan), ("small claw", COrgan)
, ("tentacle", COrgan), ("tentacle", COrgan)
, ("thorn", COrgan), ("sting", COrgan)
, ("sapient brain", COrgan) ]
}
elbow = ItemKind
{ isymbol = 's'
, iname = "creepy shooter"
, ifreq = [("alien", 100), ("horror", 100), ("mobile alien", 100)]
, iflavour = zipFancy [BrMagenta]
, icount = 1
, irarity = [(6, 1), (10, 9)]
, iverbHit = "thud"
, iweight = 80000
, iaspects = [ AddMaxHP 12, AddMaxCalm 90, AddSpeed 21
, AddSkills
$ EM.fromList [(AbProject, 2), (AbApply, 1), (AbMelee, -1)] ]
, ieffects = []
, ifeature = [Durable, Identified]
, idesc = "It moves in sudden jerks and never makes a noise. Speaks in hard objects hurled at deadly speeds."
, ikit = [ ("speed gland 4", COrgan)
, ("eye 7", COrgan)
, ("any arrow", CSha), ("any arrow", CInv)
, ("any arrow", CInv), ("any arrow", CInv)
, ("sapient brain", COrgan) ]
}
torsor = ItemKind
{ isymbol = 'M'
, iname = "The Maker of Contact"
, ifreq = [("alien", 100), ("mobile", 1)]
, iflavour = zipFancy [BrCyan]
, icount = 1
, irarity = [(11 * 10/12, 0), (10, 1000)] -- unique
, iverbHit = "thud"
, iweight = 80000
, iaspects = [ Unique, AddMaxHP 300, AddMaxCalm 100, AddSpeed 6
, AddSkills $ EM.fromList
[(AbProject, 2), (AbApply, 1), (AbTrigger, -1)] ]
-- can't switch levels, a miniboss
, ieffects = []
, ifeature = [Durable, Identified]
, idesc = "The mind, the heart behind it all. Warmth and sympathy pour out through the graceful undulation of tentacles, sharp claws, snapping jaw, grinding teeth and tensing fangs."
, ikit = [ ("tentacle", COrgan), ("claw", COrgan), ("large jaw", COrgan)
, ("venom tooth", COrgan), ("venom fang", COrgan)
, ("eye 5", COrgan), ("speed gland 4", COrgan)
, ("gem", CInv), ("gem", CInv), ("gem", CInv), ("gem", CInv)
, ("sapient brain", COrgan) ]
}
-- * Animals
-- They need rather strong melee, because they don't use items.
-- Unless/until they level up.
goldenJackal = ItemKind -- basically a much smaller and slower hyena
{ isymbol = 'j'
, iname = "golden jackal"
, ifreq = [("animal", 100), ("horror", 100), ("mobile animal", 100), ("scavenger", 50)]
, iflavour = zipPlain [BrYellow]
, icount = 1
, irarity = [(1, 5)]
, iverbHit = "thud"
, iweight = 13000
, iaspects = [ AddMaxHP 12, AddMaxCalm 60, AddSpeed 22 ]
, ieffects = []
, ifeature = [Durable, Identified]
, idesc = ""
, ikit = [ ("small jaw", COrgan), ("eye 5", COrgan), ("nostril", COrgan)
, ("animal brain", COrgan) ]
}
griffonVulture = ItemKind
{ isymbol = 'v'
, iname = "griffon vulture"
, ifreq = [("animal", 100), ("horror", 100), ("mobile animal", 100), ("scavenger", 30)]
, iflavour = zipPlain [BrYellow]
, icount = 1
, irarity = [(1, 5)]
, iverbHit = "thud"
, iweight = 13000
, iaspects = [ AddMaxHP 12, AddMaxCalm 60, AddSpeed 20
, AddSkills $ EM.singleton AbAlter (-1) ]
, ieffects = []
, ifeature = [Durable, Identified]
, idesc = ""
, ikit = [ ("screeching beak", COrgan) -- in reality it grunts and hisses
, ("small claw", COrgan), ("eye 6", COrgan)
, ("animal brain", COrgan) ]
}
skunk = ItemKind
{ isymbol = 's'
, iname = "hog-nosed skunk"
, ifreq = [("animal", 100), ("horror", 100), ("mobile animal", 100)]
, iflavour = zipPlain [White]
, icount = 1
, irarity = [(1, 5), (10, 3)]
, iverbHit = "thud"
, iweight = 4000
, iaspects = [ AddMaxHP 10, AddMaxCalm 30, AddSpeed 20
, AddSkills $ EM.singleton AbAlter (-1) ]
, ieffects = []
, ifeature = [Durable, Identified]
, idesc = ""
, ikit = [ ("scent gland", COrgan)
, ("small claw", COrgan), ("snout", COrgan)
, ("nostril", COrgan), ("eye 2", COrgan)
, ("animal brain", COrgan) ]
}
armadillo = ItemKind
{ isymbol = 'a'
, iname = "giant armadillo"
, ifreq = [("animal", 100), ("horror", 100), ("mobile animal", 100)]
, iflavour = zipPlain [Brown]
, icount = 1
, irarity = [(1, 5)]
, iverbHit = "thud"
, iweight = 80000
, iaspects = [ AddMaxHP 20, AddMaxCalm 30, AddSpeed 17
, AddSkills $ EM.singleton AbAlter (-1) ]
, ieffects = []
, ifeature = [Durable, Identified]
, idesc = ""
, ikit = [ ("claw", COrgan), ("snout", COrgan), ("armored skin", COrgan)
, ("nostril", COrgan), ("eye 2", COrgan)
, ("animal brain", COrgan) ]
}
gilaMonster = ItemKind
{ isymbol = 'g'
, iname = "Gila monster"
, ifreq = [("animal", 100), ("horror", 100), ("mobile animal", 100)]
, iflavour = zipPlain [Magenta]
, icount = 1
, irarity = [(2, 5), (10, 3)]
, iverbHit = "thud"
, iweight = 80000
, iaspects = [ AddMaxHP 12, AddMaxCalm 60, AddSpeed 15
, AddSkills $ EM.singleton AbAlter (-1) ]
, ieffects = []
, ifeature = [Durable, Identified]
, idesc = ""
, ikit = [ ("venom tooth", COrgan), ("small claw", COrgan)
, ("eye 2", COrgan), ("nostril", COrgan)
, ("animal brain", COrgan) ]
}
rattlesnake = ItemKind
{ isymbol = 's'
, iname = "rattlesnake"
, ifreq = [("animal", 100), ("horror", 100), ("mobile animal", 100)]
, iflavour = zipPlain [Brown]
, icount = 1
, irarity = [(4, 1), (10, 7)]
, iverbHit = "thud"
, iweight = 80000
, iaspects = [ AddMaxHP 25, AddMaxCalm 60, AddSpeed 15
, AddSkills $ EM.singleton AbAlter (-1) ]
, ieffects = []
, ifeature = [Durable, Identified]
, idesc = ""
, ikit = [ ("venom fang", COrgan)
, ("eye 3", COrgan), ("nostril", COrgan)
, ("animal brain", COrgan) ]
}
komodoDragon = ItemKind -- bad hearing; regeneration makes it very powerful
{ isymbol = 'k'
, iname = "Komodo dragon"
, ifreq = [("animal", 100), ("horror", 100), ("mobile animal", 100)]
, iflavour = zipPlain [Blue]
, icount = 1
, irarity = [(7, 0), (10, 10)]
, iverbHit = "thud"
, iweight = 80000
, iaspects = [ AddMaxHP 41, AddMaxCalm 60, AddSpeed 16 ]
, ieffects = []
, ifeature = [Durable, Identified]
, idesc = ""
, ikit = [ ("large tail", COrgan), ("jaw", COrgan), ("claw", COrgan)
, ("speed gland 4", COrgan), ("armored skin", COrgan)
, ("eye 2", COrgan), ("nostril", COrgan)
, ("animal brain", COrgan) ]
}
hyena = ItemKind
{ isymbol = 'h'
, iname = "spotted hyena"
, ifreq = [("animal", 100), ("horror", 100), ("mobile animal", 100), ("scavenger", 20)]
, iflavour = zipPlain [BrYellow]
, icount = 1
, irarity = [(4, 1), (10, 8)]
, iverbHit = "thud"
, iweight = 60000
, iaspects = [ AddMaxHP 20, AddMaxCalm 60, AddSpeed 30 ]
, ieffects = []
, ifeature = [Durable, Identified]
, idesc = ""
, ikit = [ ("jaw", COrgan), ("eye 5", COrgan), ("nostril", COrgan)
, ("animal brain", COrgan) ]
}
alligator = ItemKind
{ isymbol = 'a'
, iname = "alligator"
, ifreq = [("animal", 100), ("horror", 100), ("mobile animal", 100)]
, iflavour = zipPlain [Blue]
, icount = 1
, irarity = [(6, 1), (10, 9)]
, iverbHit = "thud"
, iweight = 80000
, iaspects = [ AddMaxHP 41, AddMaxCalm 60, AddSpeed 15 ]
, ieffects = []
, ifeature = [Durable, Identified]
, idesc = ""
, ikit = [ ("large jaw", COrgan), ("large tail", COrgan)
, ("small claw", COrgan)
, ("armored skin", COrgan), ("eye 5", COrgan)
, ("animal brain", COrgan) ]
}
rhinoceros = ItemKind
{ isymbol = 'R'
, iname = "The Maddened Rhinoceros"
, ifreq = [("animal", 100), ("mobile", 1)]
, iflavour = zipPlain [Brown]
, icount = 1
, irarity = [(1 * 10/12, 1000000), (2 * 10/12, 0)] -- unique
, iverbHit = "thud"
, iweight = 80000
, iaspects = [ Unique, AddMaxHP 90, AddMaxCalm 60, AddSpeed 25
, AddSkills $ EM.singleton AbTrigger (-1) ]
-- can't switch levels, a miniboss
, ieffects = []
, ifeature = [Durable, Identified]
, idesc = "The last of its kind. Blind with rage. Charges at deadly speed."
, ikit = [ ("armored skin", COrgan), ("eye 2", COrgan)
, ("horn", COrgan), ("snout", COrgan)
, ("animal brain", COrgan) ]
}
-- * Non-animal animals
beeSwarm = ItemKind
{ isymbol = 'b'
, iname = "bee swarm"
, ifreq = [("animal", 100), ("horror", 100)]
, iflavour = zipPlain [Brown]
, icount = 1
, irarity = [(1, 2), (10, 4)]
, iverbHit = "thud"
, iweight = 1000
, iaspects = [ AddMaxHP 8, AddMaxCalm 60, AddSpeed 30
, AddSkills $ EM.singleton AbAlter (-1) ] -- armor in sting
, ieffects = []
, ifeature = [Durable, Identified]
, idesc = ""
, ikit = [ ("bee sting", COrgan), ("vision 4", COrgan)
, ("insect mortality", COrgan), ("animal brain", COrgan) ]
}
hornetSwarm = ItemKind
{ isymbol = 'h'
, iname = "hornet swarm"
, ifreq = [("animal", 100), ("horror", 100), ("mobile animal", 100)]
, iflavour = zipPlain [Magenta]
, icount = 1
, irarity = [(5, 1), (10, 8)]
, iverbHit = "thud"
, iweight = 1000
, iaspects = [ AddMaxHP 8, AddMaxCalm 60, AddSpeed 30
, AddSkills $ EM.singleton AbAlter (-1)
, AddArmorMelee 80, AddArmorRanged 80 ]
, ieffects = []
, ifeature = [Durable, Identified]
, idesc = ""
, ikit = [ ("sting", COrgan), ("vision 4", COrgan)
, ("insect mortality", COrgan), ("animal brain", COrgan) ]
}
thornbush = ItemKind
{ isymbol = 't'
, iname = "thornbush"
, ifreq = [("animal", 50)]
, iflavour = zipPlain [Brown]
, icount = 1
, irarity = [(1, 3)]
, iverbHit = "thud"
, iweight = 80000
, iaspects = [ AddMaxHP 20, AddMaxCalm 999, AddSpeed 20
, AddSkills $ EM.fromList (zip [AbWait, AbMelee] [1, 1..]) ]
, ieffects = []
, ifeature = [Durable, Identified]
, idesc = ""
, ikit = [("thorn", COrgan), ("armored skin", COrgan)]
}
-- * Robots
razorwireFence = ItemKind
{ isymbol = 'f'
, iname = "razorwire fence"
, ifreq = [("robot", 50), ("immobile robot", 50)]
, iflavour = zipPlain [Cyan]
, icount = 1
, irarity = [(3 * 10/12, 0), (4, 2)]
, iverbHit = "thud"
, iweight = 80000
, iaspects = [ AddMaxHP 30, AddMaxCalm 999, AddSpeed 20
, AddSkills $ EM.fromList (zip [AbWait, AbMelee] [1, 1..])
, AddArmorMelee 50, AddArmorRanged 50 ]
, ieffects = []
, ifeature = [Durable, Identified]
, idesc = "Must have been bought by previous ship owners to contain the wild animal infestation."
, ikit = [("razor", COrgan)]
}
electricFence = ItemKind
{ isymbol = 'f'
, iname = "electric fence"
, ifreq = [("robot", 50), ("immobile robot", 50)]
, iflavour = zipPlain [Blue]
, icount = 1
, irarity = [(3 * 10/12, 0), (4, 2)]
, iverbHit = "thud"
, iweight = 80000
, iaspects = [ AddMaxHP 10, AddMaxCalm 999, AddSpeed 40
, AddSkills $ EM.fromList (zip [AbWait, AbMelee] [1, 1..])
, AddArmorMelee 50, AddArmorRanged 50 ]
, ieffects = []
, ifeature = [Durable, Identified]
, idesc = "Marginally intelligent electric shepherd. Originally used in the spaceship's dairy farm and the zoo level."
, ikit = [("live wire", COrgan)]
}
activeFence = ItemKind
{ isymbol = 'f'
, iname = "active fence"
, ifreq = [("robot", 50), ("immobile robot", 100)]
, iflavour = zipPlain [Red]
, icount = 1
, irarity = [(3 * 10/12, 0), (4, 1)]
, iverbHit = "thud"
, iweight = 80000
, iaspects = [ AddMaxHP 20, AddMaxCalm 999, AddSpeed 20
, AddSkills $ EM.fromList [(AbWait, 1), (AbProject, 3)]
, AddArmorMelee 50, AddArmorRanged 50 ]
, ieffects = []
, ifeature = [Durable, Identified]
, idesc = "Makeshift, mostly non-lethal, autonomous perimeter defense outpost."
, ikit = [ ("vision 6", COrgan)
, ("needle", CInv), ("can of sticky foam", CInv) ]
}
steamFaucet = ItemKind
{ isymbol = 'f'
, iname = "steam faucet"
, ifreq = [("robot", 50), ("immobile robot", 50)]
, iflavour = zipPlain [BrWhite]
, icount = 1
, irarity = [(5, 2)]
, iverbHit = "thud"
, iweight = 80000
, iaspects = [ AddMaxHP 10, AddMaxCalm 999, AddSpeed 10
, AddSkills $ EM.fromList (zip [AbWait, AbMelee] [1, 1..])
, AddArmorMelee 80, AddArmorRanged 80 ]
, ieffects = []
, ifeature = [Durable, Identified]
, idesc = "A cracked valve on one of the superheated water pipes spreading radially outward from the tokamak level."
, ikit = [("boiling vent", COrgan), ("boiling fissure", COrgan)]
}
biogasFaucet = ItemKind
{ isymbol = 'f'
, iname = "biogas faucet"
, ifreq = [("robot", 50), ("immobile robot", 100)]
, iflavour = zipPlain [BrGreen]
, icount = 1
, irarity = [(5, 2)]
, iverbHit = "thud"
, iweight = 80000
, iaspects = [ AddMaxHP 30, AddMaxCalm 999, AddSpeed 20, AddLight 3
, AddSkills $ EM.fromList (zip [AbWait, AbMelee] [1, 1..]) ]
, ieffects = []
, ifeature = [Durable, Identified]
, idesc = "An emergency pressure-release vent on a smelly biogas pipe."
, ikit = [("biogas vent", COrgan), ("biogas fissure", COrgan)]
}
medbotFaucet = ItemKind
{ isymbol = 'f'
, iname = "nano medbot faucet"
, ifreq = [("robot", 50), ("immobile robot", 400)]
, iflavour = zipPlain [BrYellow]
, icount = 1
, irarity = [(5, 2)]
, iverbHit = "thud"
, iweight = 80000
, iaspects = [ AddMaxHP 30, AddMaxCalm 999, AddSpeed 20, AddLight 3
, AddSkills $ EM.fromList (zip [AbWait, AbMelee] [1, 1..]) ]
, ieffects = []
, ifeature = [Durable, Identified] -- TODO: only heal humans
, idesc = "A faucet of a malfunctioning nano medical robot dispenser. Let's hope the medbots are still effective."
, ikit = [("medbot vent", COrgan), ("medbot fissure", COrgan)]
}
surveillanceDrone = ItemKind
{ isymbol = 'd'
, iname = "surveillance drone"
, ifreq = [("robot", 100), ("horror", 100), ("mobile robot", 100)]
, iflavour = zipPlain [Blue]
, icount = 1
, irarity = [] -- TODO: too boring
, iverbHit = "thud"
, iweight = 1000
, iaspects = [ AddMaxHP 3, AddMaxCalm 90, AddSpeed 30
, AddSkills
$ EM.fromList
$ zip [AbDisplace, AbMoveItem, AbProject, AbMelee] [-1, -1..]
, AddArmorMelee 80, AddArmorRanged 80 ]
, ieffects = []
, ifeature = [Durable, Identified]
, idesc = "A video camera in each room would violate privacy of passengers, hence surveillance drones. Programmed to be easy to fend off, they keep a respectful distance."
, ikit = [ ("vision 14", COrgan), ("robot brain", COrgan) ]
}
shepherdDrone = ItemKind
{ isymbol = 'd'
, iname = "shepherd drone"
, ifreq = [("robot", 100), ("horror", 100), ("mobile robot", 100)]
, iflavour = zipPlain [BrRed]
, icount = 1
, irarity = [(1, 7)]
, iverbHit = "thud"
, iweight = 1000
, iaspects = [ AddMaxHP 3, AddMaxCalm 60, AddSpeed 30
, AddSkills
$ EM.fromList
$ zip [AbDisplace, AbMoveItem, AbProject] [-1, -1..]
, AddArmorMelee 80, AddArmorRanged 80 ]
, ieffects = []
, ifeature = [Durable, Identified]
, idesc = "A shabby drone for bringing cows home."
, ikit = [ ("eye 4", COrgan), ("live wire", COrgan)
, ("robot brain", COrgan) ]
}
huntingDrone = ItemKind
{ isymbol = 'd'
, iname = "hunting drone"
, ifreq = [("robot", 100), ("horror", 100), ("mobile robot", 100)]
, iflavour = zipPlain [Green]
, icount = 1
, irarity = [(3, 0), (5, 2), (10, 4)]
, iverbHit = "thud"
, iweight = 500
, iaspects = [ AddMaxHP 3, AddMaxCalm 60, AddSpeed 40
, AddSkills
$ EM.fromList
$ zip [AbDisplace, AbMoveItem, AbMelee] [-1, -1..]
, AddArmorMelee 80, AddArmorRanged 80 ]
, ieffects = []
, ifeature = [Durable, Identified]
, idesc = "Originally designed for hunting down and putting to sleep stray animals. The sleeping agent has long since dried up."
, ikit = [ ("eye 5", COrgan), ("needle", CInv)
, ("robot brain", COrgan) ]
}
homeRobot = ItemKind
{ isymbol = 'r'
, iname = "feral home robot"
-- TODO: name another 'deranged', tertiary imperative: survival
, ifreq = [("robot", 100), ("horror", 100), ("mobile robot", 100)]
, iflavour = zipPlain [Magenta]
, icount = 1
, irarity = [(1, 20), (10, 6)]
, iverbHit = "thud"
, iweight = 80000
, iaspects = [ AddMaxHP 10, AddMaxCalm 30, AddSpeed 20
, AddSkills $ EM.singleton AbProject (-1) ]
, ieffects = []
, ifeature = [Durable, Identified]
, idesc = "Once a timid household robot, now sufficiently adapted to survive in the deadly environment."
, ikit = [ ("fist", COrgan), ("eye 2", COrgan), ("nostril", COrgan)
, ("robot brain", COrgan) ]
}
wasteRobot = ItemKind
{ isymbol = 'r'
, iname = "waste disposal robot"
, ifreq = [ ("robot", 100), ("horror", 100), ("mobile robot", 100)
, ("construction robot", 1) ]
, iflavour = zipPlain [Green]
, icount = 1
, irarity = [(1, 10), (10, 6)]
, iverbHit = "thud"
, iweight = 80000
, iaspects = [ AddMaxHP 15, AddMaxCalm 30, AddSpeed 15 ]
, ieffects = []
, ifeature = [Durable, Identified]
, idesc = "You are not in its database, hence you are waste."
, ikit = [ ("jaw", COrgan), ("tentacle", COrgan)
, ("waste container", COrgan), ("armored skin", COrgan)
, ("eye 2", COrgan), ("nostril", COrgan)
, ("robot brain", COrgan) ]
}
lightRobot = ItemKind
{ isymbol = 'r'
, iname = "decoration robot"
, ifreq = [ ("robot", 100), ("horror", 100), ("mobile robot", 100)
, ("construction robot", 1) ]
, iflavour = zipPlain [BrYellow]
, icount = 1
, irarity = [(3, 1), (10, 10)]
, iverbHit = "thud"
, iweight = 80000
, iaspects = [ AddMaxHP 15, AddMaxCalm 60, AddSpeed 30
, AddSkills $ EM.singleton AbProject 2 ]
, ieffects = []
, ifeature = [Durable, Identified]
, idesc = "Interior and exterior decoration robot. Strongly fancies deep reds recently."
, ikit = [ ("claw", COrgan), ("tentacle", COrgan), ("spotlight", COrgan)
, ("armored skin", COrgan), ("eye 5", COrgan)
, ("robot brain", COrgan) ]
}
heavyRobot = ItemKind
{ isymbol = 'r'
, iname = "construction robot"
, ifreq = [ ("robot", 100), ("horror", 100), ("mobile robot", 100)
, ("construction robot", 100) ]
, iflavour = zipPlain [BrRed]
, icount = 1
, irarity = [(6, 0), (10, 10)]
, iverbHit = "thud"
, iweight = 800000
, iaspects = [ AddMaxHP 41, AddMaxCalm 60, AddSpeed 20
, AddSkills $ EM.singleton AbProject 2 ]
, ieffects = []
, ifeature = [Durable, Identified]
, idesc = "Heavy multi-purpose construction robot. Excels at discharging, dismantling and demolition."
, ikit = [ ("large jaw", COrgan), ("small claw", COrgan), ("spotlight", COrgan)
, ("construction hooter", CInv)
, ("armored skin", COrgan), ("eye 4", COrgan)
, ("robot brain", COrgan) ]
}
cleanerRobot = ItemKind
{ isymbol = 'C'
, iname = "The Void Cleaner Robot"
, ifreq = [("robot", 100), ("mobile", 1)]
, iflavour = zipPlain [BrGreen]
, icount = 1
, irarity = [(9 * 10/12, 0), (10 * 10/12, 1000), (11 * 10/12, 0)]
-- unique, appears at 10 of 12
, iverbHit = "thud"
, iweight = 80000
, iaspects = [ Unique, AddMaxHP 120, AddMaxCalm 60, AddSpeed 18
, AddSkills $ EM.singleton AbTrigger (-1) ]
-- can't switch levels, a miniboss
, ieffects = []
, ifeature = [Durable, Identified]
, idesc = "A waste disposal robot repaired with parts from a heavy construction robot, including a scaled up goal matrix. The cosmic void is now the only acceptable model of cleanliness."
, ikit = [ ("waste container", COrgan), ("boiling vent", COrgan)
, ("armored skin", COrgan), ("live wire", COrgan)
, ("jaw", COrgan), ("claw", COrgan)
, ("eye 2", COrgan), ("nostril", COrgan), ("spotlight", COrgan)
, ("currency", CInv), ("currency", CInv), ("currency", CInv)
, ("robot brain", COrgan) ]
}
Allure-0.5.0.0/GameDefinition/Content/RuleKind.hs 0000644 0000000 0000000 00000006013 12555263417 017643 0 ustar 00 0000000 0000000 {-# LANGUAGE TemplateHaskell #-}
-- Copyright (c) 2008--2011 Andres Loeh, 2010--2015 Mikolaj Konarski
-- This file is a part of the computer game Allure of the Stars
-- and is released under the terms of the GNU Affero General Public License.
-- For license and copyright information, see the file LICENSE.
--
-- | Game rules and assorted game setup data.
module Content.RuleKind ( cdefs ) where
import Language.Haskell.TH.Syntax
import System.FilePath
-- Cabal
import qualified Paths_Allure as Self (getDataFileName, version)
import Game.LambdaHack.Common.ContentDef
import Game.LambdaHack.Content.RuleKind
cdefs :: ContentDef RuleKind
cdefs = ContentDef
{ getSymbol = rsymbol
, getName = rname
, getFreq = rfreq
, validateSingle = validateSingleRuleKind
, validateAll = validateAllRuleKind
, content =
[standard]
}
standard :: RuleKind
standard = RuleKind
{ rsymbol = 's'
, rname = "standard Allure of the Stars ruleset"
, rfreq = [("standard", 100)]
-- Check whether one position is accessible from another.
-- Precondition: the two positions are next to each other
-- and the target tile is walkable.
-- TODO: in the future check flying for chasms, swimming for water, etc.
, raccessible = Nothing
, raccessibleDoor = Nothing
, rtitle = "Allure of the Stars"
, rpathsDataFile = Self.getDataFileName
, rpathsVersion = Self.version
-- The strings containing the default configuration file
-- included from config.ui.default.
, rcfgUIName = "config.ui"
, rcfgUIDefault = $(do
let path = "GameDefinition" > "config.ui" <.> "default"
qAddDependentFile path
x <- qRunIO (readFile path)
lift x)
-- ASCII art for the Main Menu. Only pure 7-bit ASCII characters are
-- allowed. The picture should be exactly 24 rows by 80 columns,
-- plus an extra frame (of any characters) that is ignored.
-- For a different screen size, the picture is centered and the outermost
-- rows and columns cloned. When displayed in the Main Menu screen,
-- it's overwritten with the game version string and keybinding strings.
-- The game version string begins and ends with a space and is placed
-- in the very bottom right corner. The keybindings overwrite places
-- marked with 25 left curly brace signs '{' in a row. The sign is forbidden
-- everywhere else. A specific number of such places with 25 left braces
-- are required, at most one per row, and all are overwritten
-- with text that is flushed left and padded with spaces.
-- The Main Menu is displayed dull white on black.
-- TODO: Show highlighted keybinding in inverse video or bright white on grey
-- background. The spaces that pad keybindings are not highlighted.
, rmainMenuArt = $(do
let path = "GameDefinition/MainMenu.ascii"
qAddDependentFile path
x <- qRunIO (readFile path)
lift x)
, rfirstDeathEnds = False
, rfovMode = Digital
, rwriteSaveClips = 500
, rleadLevelClips = 100
, rscoresFile = "scores"
, rsavePrefix = "save"
, rnearby = 20
}
Allure-0.5.0.0/GameDefinition/Content/PlaceKind.hs 0000644 0000000 0000000 00000017643 12555263417 017773 0 ustar 00 0000000 0000000 -- Copyright (c) 2008--2011 Andres Loeh, 2010--2015 Mikolaj Konarski
-- This file is a part of the computer game Allure of the Stars
-- and is released under the terms of the GNU Affero General Public License.
-- For license and copyright information, see the file LICENSE.
--
-- | Room, hall and passage definitions.
module Content.PlaceKind ( cdefs ) where
import Game.LambdaHack.Common.ContentDef
import Game.LambdaHack.Content.PlaceKind
cdefs :: ContentDef PlaceKind
cdefs = ContentDef
{ getSymbol = psymbol
, getName = pname
, getFreq = pfreq
, validateSingle = validateSinglePlaceKind
, validateAll = validateAllPlaceKind
, content =
[rect, ruin, collapsed, collapsed2, collapsed3, collapsed4, pillar, pillar2, pillar3, pillar4, colonnade, colonnade2, colonnade3, colonnade4, colonnadeWide, lampPost, lampPost2, lampPost3, lampPost4, treeShade, treeShade2, treeShade3, oval, ovalFloor, ovalSquare, maze, maze2, maze3, mazeBig, mazeBig2, mazeBig3, cells]
}
rect, ruin, collapsed, collapsed2, collapsed3, collapsed4, pillar, pillar2, pillar3, pillar4, colonnade, colonnade2, colonnade3, colonnade4, colonnadeWide, lampPost, lampPost2, lampPost3, lampPost4, treeShade, treeShade2, treeShade3, oval, ovalFloor, ovalSquare, maze, maze2, maze3, mazeBig, mazeBig2, mazeBig3, cells :: PlaceKind
rect = PlaceKind -- Valid for any nonempty area, hence low frequency.
{ psymbol = 'r'
, pname = "room"
, pfreq = [("rogue", 70), ("ambush", 8), ("noise", 80)]
, prarity = [(1, 10), (10, 8)]
, pcover = CStretch
, pfence = FWall
, ptopLeft = ["."]
, poverride = []
}
ruin = PlaceKind
{ psymbol = 'R'
, pname = "ruin"
, pfreq = [("ambush", 17), ("battle", 100), ("noise", 40)]
, prarity = [(1, 10), (10, 20)]
, pcover = CStretch
, pfence = FWall
, ptopLeft = ["X"]
, poverride = []
}
collapsed = PlaceKind
{ psymbol = 'c'
, pname = "collapsed cavern"
, pfreq = [("noise", 1)]
, prarity = [(1, 10), (10, 10)]
, pcover = CStretch
, pfence = FNone
, ptopLeft = ["#"]
, poverride = [('#', "doorlessWallOver_#")]
}
collapsed2 = collapsed
{ pfreq = [("noise", 100), ("battle", 50)]
, ptopLeft = [ "XX#"
, "X##"
]
}
collapsed3 = collapsed
{ pfreq = [("noise", 200), ("battle", 50)]
, ptopLeft = [ "XXX#"
, "X###"
]
}
collapsed4 = collapsed
{ pfreq = [("noise", 400), ("battle", 200)]
, ptopLeft = [ "XXX#"
, "XXX#"
, "X###"
]
}
pillar = PlaceKind
{ psymbol = 'p'
, pname = "pillar room"
, pfreq = [("rogue", 1000), ("noise", 50)]
, prarity = [(1, 10), (10, 10)]
, pcover = CStretch
, pfence = FWall
-- Larger rooms require support pillars.
, ptopLeft = [ "...."
, ".O.."
, "...."
, "...."
]
, poverride = []
}
pillar2 = pillar
{ prarity = [(1, 5), (10, 5)]
, ptopLeft = [ ".#.."
, "#..."
, "...."
, "...."
]
}
pillar3 = pillar
{ prarity = [(1, 5), (10, 5)]
, ptopLeft = [ "#..."
, "..#."
, ".#.."
, "...."
]
}
pillar4 = pillar
{ prarity = [(10, 7)]
, ptopLeft = [ "&.#."
, "...."
, "#..."
, "...."
]
}
colonnade = PlaceKind
{ psymbol = 'c'
, pname = "colonnade"
, pfreq = [("rogue", 70), ("noise", 2000)]
, prarity = [(1, 10), (10, 10)]
, pcover = CAlternate
, pfence = FFloor
, ptopLeft = [ ".#"
, "#."
]
, poverride = []
}
colonnade2 = colonnade
{ prarity = [(1, 2), (10, 4)]
, pfence = FGround
, ptopLeft = [ ".."
, ".O"
]
}
colonnade3 = colonnade
{ prarity = [(1, 4), (10, 6)]
, ptopLeft = [ "#.."
, "..#"
]
}
colonnade4 = colonnade
{ ptopLeft = [ "#."
, ".."
, ".#"
]
}
colonnadeWide = colonnade
{ prarity = [(1, 3), (10, 3)]
, pfence = FWall
, ptopLeft = [ ".."
, ".#"
]
}
lampPost = PlaceKind
{ psymbol = 'l'
, pname = "lamp post"
, pfreq = [("ambush", 30), ("battle", 10)]
, prarity = [(1, 10), (10, 10)]
, pcover = CVerbatim
, pfence = FNone
, ptopLeft = [ "X.X"
, ".O."
, "X.X"
]
, poverride = [('O', "lampPostOver_O")]
}
lampPost2 = lampPost
{ ptopLeft = [ "..."
, ".O."
, "..."
]
}
lampPost3 = lampPost
{ ptopLeft = [ "XX.XX"
, "X...X"
, "..O.."
, "X...X"
, "XX.XX"
]
}
lampPost4 = lampPost
{ ptopLeft = [ "X...X"
, "....."
, "..O.."
, "....."
, "X...X"
]
}
treeShade = PlaceKind
{ psymbol = 't'
, pname = "tree shade"
, pfreq = [("skirmish", 100)]
, prarity = [(1, 10), (10, 10)]
, pcover = CVerbatim
, pfence = FNone
, ptopLeft = [ "sss"
, "XOs"
, "XXs"
]
, poverride = [('O', "treeShadeOver_O"), ('s', "treeShadeOver_s")]
}
treeShade2 = treeShade
{ ptopLeft = [ "sss"
, "XOs"
, "Xss"
]
}
treeShade3 = treeShade
{ ptopLeft = [ "sss"
, "sOs"
, "XXs"
]
}
oval = PlaceKind
{ psymbol = 'o'
, pname = "oval room"
, pfreq = [("rogue", 1000)]
, prarity = [(1, 10), (10, 10)]
, pcover = CStretch
, pfence = FWall
, ptopLeft = [ "####."
, "##..."
, "#...."
, "#...."
, "....."
]
, poverride = []
}
ovalFloor = oval -- Without outer solid fence, visible from outside.
{ pfreq = [("rogue", 10000)]
, pfence = FGround
, ptopLeft = [ "XXXX+#"
, "XX###."
, "X##..."
, "X#...."
, "+#...."
, "#....."
]
}
ovalSquare = ovalFloor
{ pfreq = [("rogue", 3000)]
, ptopLeft = [ "X###+"
, "##..."
, "#...."
, "#...."
, "+...."
]
}
maze = PlaceKind
{ psymbol = 'm'
, pname = "maze"
, pfreq = [("rogue", 20)]
, prarity = [(1, 10), (10, 10)]
, pcover = CStretch
, pfence = FNone
, ptopLeft = [ "#.#.##"
, "##.#.."
, "#.##.#"
, "#.#.#."
]
, poverride = []
}
maze2 = maze
{ ptopLeft = [ "###.##"
, ".###.."
, "..#..#"
, ".#..#."
]
}
maze3 = maze
{ ptopLeft = [ "###.##"
, ".##.#."
, "..##.#"
, ".#..#."
]
}
mazeBig = maze
{ pfreq = [("rogue", 1000)]
, ptopLeft = [ "#.#.##"
, ".#.#.."
, "#.&.##"
, ".#.#.."
, "#.#..#"
, "#.#.#."
]
}
mazeBig2 = mazeBig
{ ptopLeft = [ "##..##"
, "#.##.."
, ".#.###"
, ".##.#."
, "#.#&.#"
, "#.#.#."
]
}
mazeBig3 = mazeBig
{ ptopLeft = [ "##..##"
, "#.###."
, ".#...#"
, ".#.##."
, "##.#.#"
, "#.#.#."
]
}
cells = PlaceKind
{ psymbol = '#'
, pname = "cells"
, pfreq = [("rogue", 100), ("noise", 100)]
, prarity = [(1, 10), (10, 10)]
, pcover = CReflect
, pfence = FWall
, ptopLeft = [ "..#"
, "..#"
, "##."
]
, poverride = []
}
-- TODO: obtain all the rest as places nested within places.
-- 3 places are enough, with 1 or 2 tiles between places,
-- on all sides, only vertical, only horizontal,
Allure-0.5.0.0/GameDefinition/Content/TileKind.hs 0000644 0000000 0000000 00000021561 12555263417 017636 0 ustar 00 0000000 0000000 -- Copyright (c) 2008--2011 Andres Loeh, 2010--2015 Mikolaj Konarski
-- This file is a part of the computer game Allure of the Stars
-- and is released under the terms of the GNU Affero General Public License.
-- For license and copyright information, see the file LICENSE.
--
-- | Terrain tile definitions.
module Content.TileKind ( cdefs ) where
import Control.Arrow (first)
import Data.Maybe
import qualified Data.Text as T
import Game.LambdaHack.Common.Color
import Game.LambdaHack.Common.ContentDef
import Game.LambdaHack.Common.Misc
import Game.LambdaHack.Common.Msg
import qualified Game.LambdaHack.Content.ItemKind as IK
import Game.LambdaHack.Content.TileKind
cdefs :: ContentDef TileKind
cdefs = ContentDef
{ getSymbol = tsymbol
, getName = tname
, getFreq = tfreq
, validateSingle = validateSingleTileKind
, validateAll = validateAllTileKind
, content =
[wall, wallCache, hardRock, doorlessWall, oriel, pillar, lampPost, burningBush, bush, tree, wallSuspect, doorClosed, doorOpen, stairsUp, stairsDown, escapeUp, escapeDown, liftUp, lift, liftDown, unknown, floorCorridorLit, floorActorLit, floorItemLit, floorActorItemLit, floorArenaShade, floorRedLit, floorBlueLit, floorGreenLit]
++ map makeDarkColor [floorCorridorLit, floorActorLit, floorItemLit, floorActorItemLit]
}
wall, wallCache, hardRock, doorlessWall, oriel, pillar, lampPost, burningBush, bush, tree, wallSuspect, doorClosed, doorOpen, stairsUp, stairsDown, escapeUp, escapeDown, liftUp, lift, liftDown, unknown, floorCorridorLit, floorActorLit, floorItemLit, floorActorItemLit, floorArenaShade, floorRedLit, floorBlueLit, floorGreenLit :: TileKind
oriel = TileKind
{ tsymbol = '\''
, tname = "oriel"
, tfreq = [("oriels fence", 4)]
, tcolor = White
, tcolor2 = Black
, tfeature = [Dark, Impenetrable]
}
wall = TileKind
{ tsymbol = '#'
, tname = "granite wall"
, tfreq = [ ("fillerWall", 1), ("legendLit", 100), ("legendDark", 100)
, ("cachable", 70)
, ("noiseSet", 100), ("battleSet", 250) ]
, tcolor = BrWhite
, tcolor2 = defFG
, tfeature = [HideAs "suspect wall"]
}
hardRock = TileKind
{ tsymbol = '#'
, tname = "outer hull"
, tfreq = [("basic outer fence", 100), ("oriels fence", 96)]
, tcolor = BrBlack
, tcolor2 = BrBlack
, tfeature = [Impenetrable]
}
doorlessWall = TileKind
{ tsymbol = '#'
, tname = "granite wall"
, tfreq = [("doorlessWallOver_#", 100)]
, tcolor = BrWhite
, tcolor2 = defFG
, tfeature = []
}
pillar = TileKind
{ tsymbol = 'O'
, tname = "rock"
, tfreq = [ ("legendLit", 100), ("legendDark", 100)
, ("skirmishSet", 5) ]
, tcolor = BrWhite
, tcolor2 = defFG
, tfeature = []
}
wallCache = TileKind
{ tsymbol = '&'
, tname = "cache"
, tfreq = [ ("cachable", 30)
, ("legendLit", 100), ("legendDark", 100) ]
, tcolor = BrWhite
, tcolor2 = defFG
, tfeature = [ Cause $ IK.CreateItem CGround "useful" IK.TimerNone
, ChangeTo "cachable" ]
}
lampPost = TileKind
{ tsymbol = 'O'
, tname = "lamp post"
, tfreq = [("lampPostOver_O", 90)]
, tcolor = BrYellow
, tcolor2 = Brown
, tfeature = []
}
burningBush = TileKind
{ tsymbol = 'O'
, tname = "burning bush"
, tfreq = [("lampPostOver_O", 10), ("ambushSet", 3), ("battleSet", 2)]
, tcolor = BrRed
, tcolor2 = Red
, tfeature = []
}
bush = TileKind
{ tsymbol = 'O'
, tname = "bush"
, tfreq = [("ambushSet", 100) ]
, tcolor = Green
, tcolor2 = BrBlack
, tfeature = [Dark]
}
tree = TileKind
{ tsymbol = 'O'
, tname = "tree"
, tfreq = [("skirmishSet", 14), ("battleSet", 20), ("treeShadeOver_O", 1)]
, tcolor = BrGreen
, tcolor2 = Green
, tfeature = []
}
wallSuspect = TileKind
{ tsymbol = '#'
, tname = "moldy wall"
, tfreq = [("suspect wall", 1)]
, tcolor = BrWhite
, tcolor2 = defFG
, tfeature = [Suspect, RevealAs "closed door"]
}
doorClosed = TileKind
{ tsymbol = '+'
, tname = "closed door"
, tfreq = [("legendLit", 100), ("legendDark", 100), ("closed door", 1)]
, tcolor = Brown
, tcolor2 = BrBlack
, tfeature = [OpenTo "open door", HideAs "suspect wall"]
}
doorOpen = TileKind
{ tsymbol = '\''
, tname = "open door"
, tfreq = [("legendLit", 100), ("legendDark", 100), ("open door", 1)]
, tcolor = Brown
, tcolor2 = BrBlack
, tfeature = [Walkable, Clear, NoItem, NoActor, CloseTo "closed door"]
}
stairsUp = TileKind
{ tsymbol = '<'
, tname = "staircase up"
, tfreq = [] -- TODO: [("legendLit", 100), ("legendDark", 100)]
, tcolor = BrWhite
, tcolor2 = defFG
, tfeature = [Walkable, Clear, NoItem, NoActor, Cause $ IK.Ascend 1]
}
stairsDown = TileKind
{ tsymbol = '>'
, tname = "staircase down"
, tfreq = [] -- TODO: [("legendLit", 100), ("legendDark", 100)]
, tcolor = BrWhite
, tcolor2 = defFG
, tfeature = [Walkable, Clear, NoItem, NoActor, Cause $ IK.Ascend (-1)]
}
escapeUp = TileKind
{ tsymbol = '<'
, tname = "airlock to the shuttle"
, tfreq = [("legendLit", 100), ("legendDark", 100)]
, tcolor = BrYellow
, tcolor2 = BrYellow
, tfeature = [Walkable, Clear, NoItem, NoActor, Cause $ IK.Escape 1]
}
escapeDown = TileKind
{ tsymbol = '>'
, tname = "airlock to the shuttle"
, tfreq = [("legendLit", 100), ("legendDark", 100)]
, tcolor = BrYellow
, tcolor2 = BrYellow
, tfeature = [Walkable, Clear, NoItem, NoActor, Cause $ IK.Escape (-1)]
}
liftUp = TileKind
{ tsymbol = '<'
, tname = "lift up"
, tfreq = [("legendLit", 100), ("legendDark", 100)]
, tcolor = BrCyan
, tcolor2 = BrCyan
, tfeature = [Walkable, Clear, NoItem, NoActor, Cause $ IK.Ascend 1]
}
lift = TileKind
{ tsymbol = '<'
, tname = "lift"
, tfreq = [("legendLit", 100), ("legendDark", 100)]
, tcolor = BrBlue
, tcolor2 = BrBlue
, tfeature = [ Walkable, Clear, NoItem, NoActor
, Cause $ IK.Ascend 1
, Cause $ IK.Ascend (-1) ]
}
liftDown = TileKind
{ tsymbol = '>'
, tname = "lift down"
, tfreq = [("legendLit", 100), ("legendDark", 100)]
, tcolor = BrCyan
, tcolor2 = BrCyan
, tfeature = [Walkable, Clear, NoItem, NoActor, Cause $ IK.Ascend (-1)]
}
unknown = TileKind
{ tsymbol = ' '
, tname = "unknown space"
, tfreq = [("unknown space", 1)]
, tcolor = defFG
, tcolor2 = defFG
, tfeature = [Dark]
}
floorCorridorLit = TileKind
{ tsymbol = '.'
, tname = "floor"
, tfreq = [ ("floorCorridorLit", 1), ("floorArenaLit", 1)
, ("arenaSet", 1), ("emptySet", 1), ("noiseSet", 50)
, ("battleSet", 1000), ("skirmishSet", 100)
, ("ambushSet", 1000) ]
, tcolor = BrWhite
, tcolor2 = defFG
, tfeature = [Walkable, Clear]
}
floorActorLit = floorCorridorLit
{ tfreq = [("floorActorLit", 1)]
, tfeature = OftenActor : tfeature floorCorridorLit
}
floorItemLit = floorCorridorLit
{ tfreq = []
, tfeature = OftenItem : tfeature floorCorridorLit
}
floorActorItemLit = floorItemLit
{ tfreq = [("legendLit", 100)]
, tfeature = OftenActor : tfeature floorItemLit
}
floorArenaShade = floorActorLit
{ tname = "floor" -- TODO: "shaded ground"
, tfreq = [("treeShadeOver_s", 1)]
, tcolor2 = BrBlack
, tfeature = Dark : tfeature floorActorLit -- no OftenItem
}
floorRedLit = floorCorridorLit
{ tname = "emergency walkway"
, tfreq = [("emergency walkway", 1), ("trailLit", 20)]
, tcolor = BrRed
, tcolor2 = Red
, tfeature = Trail : tfeature floorCorridorLit
}
floorBlueLit = floorRedLit
{ tname = "transport route"
, tfreq = [("trailLit", 100)]
, tcolor = BrBlue
, tcolor2 = Blue
}
floorGreenLit = floorRedLit
{ tname = "greenery trail"
, tfreq = [("trailLit", 100)]
, tcolor = BrGreen
, tcolor2 = Green
}
makeDark :: TileKind -> TileKind
makeDark k = let darkText :: GroupName TileKind -> GroupName TileKind
darkText t = maybe t (toGroupName . (<> "Dark"))
$ T.stripSuffix "Lit" $ tshow t
darkFrequency = map (first darkText) $ tfreq k
darkFeat (OpenTo t) = Just $ OpenTo $ darkText t
darkFeat (CloseTo t) = Just $ CloseTo $ darkText t
darkFeat (ChangeTo t) = Just $ ChangeTo $ darkText t
darkFeat (HideAs t) = Just $ HideAs $ darkText t
darkFeat (RevealAs t) = Just $ RevealAs $ darkText t
darkFeat OftenItem = Nothing -- items not common in the dark
darkFeat feat = Just feat
in k { tfreq = darkFrequency
, tfeature = Dark : mapMaybe darkFeat (tfeature k)
}
makeDarkColor :: TileKind -> TileKind
makeDarkColor k = (makeDark k) { tcolor = BrYellow
, tcolor2 = BrBlack
}
Allure-0.5.0.0/GameDefinition/Content/ItemKindTemporary.hs 0000644 0000000 0000000 00000006245 12555263417 021544 0 ustar 00 0000000 0000000 -- Copyright (c) 2008--2011 Andres Loeh, 2010--2015 Mikolaj Konarski
-- This file is a part of the computer game Allure of the Stars
-- and is released under the terms of the GNU Affero General Public License.
-- For license and copyright information, see the file LICENSE.
--
-- | Temporary aspect pseudo-item definitions.
module Content.ItemKindTemporary ( temporaries ) where
import Data.Text (Text)
import Game.LambdaHack.Common.Color
import Game.LambdaHack.Common.Dice
import Game.LambdaHack.Common.Flavour
import Game.LambdaHack.Common.Misc
import Game.LambdaHack.Common.Msg
import Game.LambdaHack.Content.ItemKind
temporaries :: [ItemKind]
temporaries =
[tmpStrengthened, tmpWeakened, tmpProtected, tmpVulnerable, tmpFast20, tmpSlow10, tmpFarSighted, tmpKeenSmelling, tmpDrunk, tmpRegenerating, tmpPoisoned, tmpSlow10Resistant, tmpPoisonResistant]
tmpStrengthened, tmpWeakened, tmpProtected, tmpVulnerable, tmpFast20, tmpSlow10, tmpFarSighted, tmpKeenSmelling, tmpDrunk, tmpRegenerating, tmpPoisoned, tmpSlow10Resistant, tmpPoisonResistant :: ItemKind
-- The @name@ is be used in item description, so it should be an adjective
-- describing the temporary set of aspects.
tmpAs :: Text -> [Aspect Dice] -> ItemKind
tmpAs name aspects = ItemKind
{ isymbol = '+'
, iname = name
, ifreq = [(toGroupName name, 1), ("temporary conditions", 1)]
, iflavour = zipPlain [BrWhite]
, icount = 1
, irarity = [(1, 1)]
, iverbHit = "affect"
, iweight = 0
, iaspects = [Periodic, Timeout 0] -- activates and vanishes soon,
-- depending on initial timer setting
++ aspects
, ieffects = let tmp = Temporary $ "be no longer" <+> name
in [Recharging tmp, OnSmash tmp]
, ifeature = [Identified]
, idesc = ""
, ikit = []
}
tmpStrengthened = tmpAs "strengthened" [AddHurtMelee 20]
tmpWeakened = tmpAs "weakened" [AddHurtMelee (-20)]
tmpProtected = tmpAs "protected" [ AddArmorMelee 30
, AddArmorRanged 30 ]
tmpVulnerable = tmpAs "painted red" [ AddArmorMelee (-30)
, AddArmorRanged (-30) ]
tmpFast20 = tmpAs "fast 20" [AddSpeed 20]
tmpSlow10 = tmpAs "slow 10" [AddSpeed (-10)]
tmpFarSighted = tmpAs "far-sighted" [AddSight 5]
tmpKeenSmelling = tmpAs "keen-smelling" [AddSmell 2]
tmpDrunk = tmpAs "drunk" [ AddHurtMelee 30 -- fury
, AddArmorMelee (-20)
, AddArmorRanged (-20)
, AddSight (-7)
]
tmpRegenerating =
let tmp = tmpAs "regenerating" []
in tmp { icount = 7 + d 5
, ieffects = Recharging (RefillHP 1) : ieffects tmp
}
tmpPoisoned =
let tmp = tmpAs "poisoned" []
in tmp { icount = 7 + d 5
, ieffects = Recharging (RefillHP (-1)) : ieffects tmp
}
tmpSlow10Resistant =
let tmp = tmpAs "slow resistant" []
in tmp { icount = 7 + d 5
, ieffects = Recharging (DropItem COrgan "slow 10" True) : ieffects tmp
}
tmpPoisonResistant =
let tmp = tmpAs "poison resistant" []
in tmp { icount = 7 + d 5
, ieffects = Recharging (DropItem COrgan "poisoned" True) : ieffects tmp
}
Allure-0.5.0.0/GameDefinition/Content/ModeKindPlayer.hs 0000644 0000000 0000000 00000012476 12555263417 021007 0 ustar 00 0000000 0000000 -- Copyright (c) 2008--2011 Andres Loeh, 2010--2015 Mikolaj Konarski
-- This file is a part of the computer game Allure of the Stars
-- and is released under the terms of the GNU Affero General Public License.
-- For license and copyright information, see the file LICENSE.
--
-- | Basic players definitions.
module Content.ModeKindPlayer
( playerHero, playerSoldier, playerSniper
, playerAntiHero, playerAntiSniper, playerCivilian
, playerMonster, playerMobileMonster, playerAntiMonster
, playerAnimal, playerMobileAnimal
, playerRobot, playerMobileRobot
, playerHorror
, hiHero, hiDweller, hiRaid
) where
import Data.List
import Game.LambdaHack.Common.Ability
import Game.LambdaHack.Common.Dice
import Game.LambdaHack.Common.Misc
import Game.LambdaHack.Content.ModeKind
playerHero, playerSoldier, playerSniper, playerAntiHero, playerAntiSniper, playerCivilian, playerMonster, playerMobileMonster, playerAntiMonster, playerAnimal, playerMobileAnimal, playerRobot, playerMobileRobot, playerHorror :: Player Dice
playerHero = Player
{ fname = "Spacefarer Crew"
, fgroup = "hero"
, fskillsOther = meleeAdjacent
, fcanEscape = True
, fneverEmpty = True
, fhiCondPoly = hiHero
, fhasNumbers = True
, fhasGender = True
, ftactic = TExplore
, fentryLevel = 3
, finitialActors = 3
, fleaderMode = LeaderUI $ AutoLeader False False
, fhasUI = True
}
playerSoldier = playerHero
{ fname = "Armed Spacefarer Crew"
, fgroup = "soldier"
}
playerSniper = playerHero
{ fname = "Sniper Adventurer Party"
, fgroup = "sniper"
}
playerAntiHero = playerHero
{ fleaderMode = LeaderAI $ AutoLeader True False
, fhasUI = False
}
playerAntiSniper = playerSniper
{ fleaderMode = LeaderAI $ AutoLeader True False
, fhasUI = False
}
playerCivilian = Player
{ fname = "Civilian Crowd"
, fgroup = "civilian"
, fskillsOther = zeroSkills -- not coordinated by any leadership
, fcanEscape = False
, fneverEmpty = True
, fhiCondPoly = hiDweller
, fhasNumbers = False
, fhasGender = True
, ftactic = TPatrol
, fentryLevel = 1
, finitialActors = d 2 + 1
, fleaderMode = LeaderNull -- unorganized
, fhasUI = False
}
playerMonster = Player
{ fname = "Alien Hierarchy"
, fgroup = "alien"
, fskillsOther = zeroSkills
, fcanEscape = False
, fneverEmpty = False
, fhiCondPoly = hiDweller
, fhasNumbers = False
, fhasGender = False
, ftactic = TExplore
, fentryLevel = 4
, finitialActors = 0
, fleaderMode =
-- No point changing leader on level, since all move and they
-- don't follow the leader.
LeaderAI $ AutoLeader True True
, fhasUI = False
}
playerMobileMonster = playerMonster
playerAntiMonster = playerMonster
{ fhasUI = True
, fleaderMode = LeaderUI $ AutoLeader True True
}
playerAnimal = Player
{ fname = "Animal Kingdom"
, fgroup = "animal"
, fskillsOther = zeroSkills
, fcanEscape = False
, fneverEmpty = False
, fhiCondPoly = hiDweller
, fhasNumbers = False
, fhasGender = False
, ftactic = TRoam -- can't pick up, so no point exploring
, fentryLevel = 3
, finitialActors = 2 + d 2 -- many, because no spawning
, fleaderMode = LeaderNull
, fhasUI = False
}
playerMobileAnimal = playerAnimal
{ fgroup = "mobile animal" }
playerRobot = Player
{ fname = "Robot Anarchy"
, fgroup = "robot"
, fskillsOther = zeroSkills
, fcanEscape = False
, fneverEmpty = False
, fhiCondPoly = hiDweller
, fhasNumbers = False
, fhasGender = False
, ftactic = TRoam -- TODO:TFollow -- coordinated via net, follow alien leader
, fentryLevel = 3
, finitialActors = 2 + d 2 -- many, because no spawning
, fleaderMode = LeaderNull
, fhasUI = False
}
playerMobileRobot = playerRobot
{ fgroup = "mobile robot" }
-- | A special player, for summoned actors that don't belong to any
-- of the main players of a given game. E.g., animals summoned during
-- a duel game between two hero players land in the horror faction.
-- In every game, either all factions for which summoning items exist
-- should be present or a horror player should be added to host them.
-- Actors that can be summoned should have "horror" in their @ifreq@ set.
playerHorror = Player
{ fname = "Horror Den"
, fgroup = "horror"
, fskillsOther = zeroSkills
, fcanEscape = False
, fneverEmpty = False
, fhiCondPoly = []
, fhasNumbers = False
, fhasGender = False
, ftactic = TPatrol -- disoriented
, fentryLevel = 4
, finitialActors = 0
, fleaderMode = LeaderNull
, fhasUI = False
}
victoryOutcomes :: [Outcome]
victoryOutcomes = [Conquer, Escape]
hiHero, hiDweller, hiRaid :: HiCondPoly
-- Heroes rejoice in loot.
hiHero = [ ( [(HiLoot, 1)]
, [minBound..maxBound] )
, ( [(HiConst, 1000), (HiLoss, -100)]
, victoryOutcomes )
]
-- Spawners or skirmishers get no points from loot, but try to kill
-- all opponents fast or at least hold up for long.
hiDweller = [ ( [(HiConst, 1000)] -- no loot
, victoryOutcomes )
, ( [(HiConst, 1000), (HiLoss, -10)]
, victoryOutcomes )
, ( [(HiBlitz, -100)]
, victoryOutcomes )
, ( [(HiSurvival, 100)]
, [minBound..maxBound] \\ victoryOutcomes )
]
hiRaid = [ ( [(HiLoot, 1)]
, [minBound..maxBound] )
, ( [(HiConst, 100)]
, victoryOutcomes )
]
Allure-0.5.0.0/GameDefinition/Client/ 0000755 0000000 0000000 00000000000 12555263417 015376 5 ustar 00 0000000 0000000 Allure-0.5.0.0/GameDefinition/Client/UI/ 0000755 0000000 0000000 00000000000 12555263417 015713 5 ustar 00 0000000 0000000 Allure-0.5.0.0/GameDefinition/Client/UI/Content/ 0000755 0000000 0000000 00000000000 12555263417 017325 5 ustar 00 0000000 0000000 Allure-0.5.0.0/GameDefinition/Client/UI/Content/KeyKind.hs 0000644 0000000 0000000 00000023115 12555263417 021221 0 ustar 00 0000000 0000000 -- Copyright (c) 2008--2011 Andres Loeh, 2010--2015 Mikolaj Konarski
-- This file is a part of the computer game Allure of the Stars
-- and is released under the terms of the GNU Affero General Public License.
-- For license and copyright information, see the file LICENSE.
--
-- | The default game key-command mapping to be used for UI. Can be overridden
-- via macros in the config file.
module Client.UI.Content.KeyKind ( standardKeys ) where
import Control.Arrow (first)
import qualified Game.LambdaHack.Client.Key as K
import Game.LambdaHack.Client.UI.Content.KeyKind
import Game.LambdaHack.Client.UI.HumanCmd
import Game.LambdaHack.Common.Misc
import qualified Game.LambdaHack.Content.ItemKind as IK
import qualified Game.LambdaHack.Content.TileKind as TK
standardKeys :: KeyKind
standardKeys = KeyKind
{ rhumanCommands = map (first K.mkKM)
-- All commands are defined here, except some movement and leader picking
-- commands. All commands are shown on help screens except debug commands
-- and macros with empty descriptions.
-- The order below determines the order on the help screens.
-- Remember to put commands that show information (e.g., enter targeting
-- mode) first.
-- Main Menu, which apart of these includes a few extra commands
[ ("CTRL-x", ([CmdMenu], GameExit))
, ("CTRL-r", ([CmdMenu], GameRestart "raid"))
, ("CTRL-k", ([CmdMenu], GameRestart "skirmish"))
, ("CTRL-m", ([CmdMenu], GameRestart "ambush"))
, ("CTRL-b", ([CmdMenu], GameRestart "battle"))
, ("CTRL-c", ([CmdMenu], GameRestart "campaign"))
, ("CTRL-i", ([CmdDebug], GameRestart "battle survival"))
, ("CTRL-f", ([CmdDebug], GameRestart "safari"))
, ("CTRL-u", ([CmdDebug], GameRestart "safari survival"))
, ("CTRL-e", ([CmdDebug], GameRestart "defense"))
, ("CTRL-d", ([CmdMenu], GameDifficultyCycle))
-- Movement and terrain alteration
, ("less", ([CmdMove, CmdMinimal], TriggerTile
[ TriggerFeature { verb = "ascend"
, object = "a level"
, feature = TK.Cause (IK.Ascend 1) }
, TriggerFeature { verb = "escape"
, object = "spaceship"
, feature = TK.Cause (IK.Escape 1) } ]))
, ("CTRL-less", ([CmdMove], TriggerTile
[ TriggerFeature { verb = "ascend"
, object = "10 levels"
, feature = TK.Cause (IK.Ascend 10) } ]))
, ("greater", ([CmdMove, CmdMinimal], TriggerTile
[ TriggerFeature { verb = "descend"
, object = "a level"
, feature = TK.Cause (IK.Ascend (-1)) }
, TriggerFeature { verb = "escape"
, object = "spaceship"
, feature = TK.Cause (IK.Escape (-1)) } ]))
, ("CTRL-greater", ([CmdMove], TriggerTile
[ TriggerFeature { verb = "descend"
, object = "10 levels"
, feature = TK.Cause (IK.Ascend (-10)) } ]))
, ("semicolon",
( [CmdMove]
, Macro "go to crosshair for 100 steps"
["CTRL-semicolon", "CTRL-period", "V"] ))
, ("colon",
( [CmdMove]
, Macro "run selected to crosshair for 100 steps"
["CTRL-colon", "CTRL-period", "V"] ))
, ("x",
( [CmdMove]
, Macro "explore the closest unknown spot"
[ "CTRL-question" -- no semicolon
, "CTRL-period", "V" ] ))
, ("X",
( [CmdMove]
, Macro "autoexplore 100 times"
["'", "CTRL-question", "CTRL-period", "'", "V"] ))
, ("CTRL-X",
( [CmdMove]
, Macro "autoexplore 25 times"
["'", "CTRL-question", "CTRL-period", "'", "CTRL-V"] ))
, ("R", ([CmdMove], Macro "rest (wait 100 times)"
["KP_Begin", "V"]))
, ("CTRL-R", ([CmdMove], Macro "rest (wait 25 times)"
["KP_Begin", "CTRL-V"]))
, ("c", ([CmdMove, CmdMinimal], AlterDir
[ AlterFeature { verb = "close"
, object = "door"
, feature = TK.CloseTo "closed door" }
]))
-- Item use
--
-- For later:
-- ApplyItem {verb = "eat", object = "food", symbol = ','}
-- ApplyItem {verb = "apply", object = "emitter", symbol = '_'}
-- ApplyItem {verb = "use", object = "tool", symbol = '~'}
--
, ("E", ([CmdItem, CmdMinimal], DescribeItem $ MStore CEqp))
, ("P", ([CmdItem], DescribeItem $ MStore CInv))
, ("S", ([CmdItem], DescribeItem $ MStore CSha))
, ("A", ([CmdItem], DescribeItem MOwned))
, ("G", ([CmdItem], DescribeItem $ MStore CGround))
, ("@", ([CmdItem], DescribeItem $ MStore COrgan))
, ("exclam", ([CmdItem], DescribeItem MStats))
, ("g", ([CmdItem, CmdMinimal],
MoveItem [CGround] CEqp (Just "get") "items" True))
, ("d", ([CmdItem], MoveItem [CEqp, CInv, CSha] CGround
Nothing "items" False))
, ("e", ([CmdItem], MoveItem [CGround, CInv, CSha] CEqp
Nothing "items" False))
, ("p", ([CmdItem], MoveItem [CGround, CEqp, CSha] CInv
Nothing "items into inventory"
False))
, ("s", ([CmdItem], MoveItem [CGround, CInv, CEqp] CSha
Nothing "and share items" False))
, ("a", ([CmdItem, CmdMinimal], Apply
[ ApplyItem { verb = "apply"
, object = "consumable"
, symbol = ' ' }
, ApplyItem { verb = "quaff"
, object = "drink"
, symbol = '!' }
, ApplyItem { verb = "read"
, object = "chip"
, symbol = '?' }
]))
, ("q", ([CmdItem], Apply [ApplyItem { verb = "quaff"
, object = "drink"
, symbol = '!' }]))
, ("r", ([CmdItem], Apply [ApplyItem { verb = "read"
, object = "chip"
, symbol = '?' }]))
, ("f", ([CmdItem, CmdMinimal], Project
[ApplyItem { verb = "fling"
, object = "projectile"
, symbol = ' ' }]))
, ("t", ([CmdItem], Project [ ApplyItem { verb = "throw"
, object = "missile"
, symbol = '}' }
, ApplyItem { verb = "throw"
, object = "missile"
, symbol = '{' } ]))
-- , ("z", ([CmdItem], Project [ApplyItem { verb = "zap"
-- , object = "mechanism"
-- , symbol = '-' }]))
-- Targeting
, ("KP_Multiply", ([CmdTgt], TgtEnemy))
, ("backslash", ([CmdTgt], Macro "" ["KP_Multiply"]))
, ("KP_Divide", ([CmdTgt], TgtFloor))
, ("bar", ([CmdTgt], Macro "" ["KP_Divide"]))
, ("plus", ([CmdTgt, CmdMinimal], EpsIncr True))
, ("minus", ([CmdTgt], EpsIncr False))
, ("CTRL-question", ([CmdTgt], CursorUnknown))
, ("CTRL-I", ([CmdTgt], CursorItem))
, ("CTRL-braceleft", ([CmdTgt], CursorStair True))
, ("CTRL-braceright", ([CmdTgt], CursorStair False))
, ("BackSpace", ([CmdTgt], TgtClear))
-- Automation
, ("equal", ([CmdAuto], SelectActor))
, ("underscore", ([CmdAuto], SelectNone))
, ("v", ([CmdAuto], Repeat 1))
, ("V", ([CmdAuto], Repeat 100))
, ("CTRL-v", ([CmdAuto], Repeat 1000))
, ("CTRL-V", ([CmdAuto], Repeat 25))
, ("apostrophe", ([CmdAuto], Record))
, ("CTRL-T", ([CmdAuto], Tactic))
, ("CTRL-A", ([CmdAuto], Automate))
-- Assorted
, ("question", ([CmdMeta], Help))
, ("D", ([CmdMeta, CmdMinimal], History))
, ("T", ([CmdMeta, CmdMinimal], MarkSuspect))
, ("Z", ([CmdMeta], MarkVision))
, ("C", ([CmdMeta], MarkSmell))
, ("Tab", ([CmdMeta], MemberCycle))
, ("ISO_Left_Tab", ([CmdMeta, CmdMinimal], MemberBack))
, ("space", ([CmdMeta], Clear))
, ("Escape", ([CmdMeta, CmdMinimal], Cancel))
, ("Return", ([CmdMeta, CmdTgt], Accept))
-- Mouse
, ("LeftButtonPress",
([CmdMouse], macroLeftButtonPress))
, ("SHIFT-LeftButtonPress",
([CmdMouse], macroShiftLeftButtonPress))
, ("MiddleButtonPress", ([CmdMouse], CursorPointerEnemy))
, ("SHIFT-MiddleButtonPress", ([CmdMouse], CursorPointerFloor))
, ("CTRL-MiddleButtonPress",
([CmdInternal], Macro "" ["SHIFT-MiddleButtonPress"]))
, ("RightButtonPress", ([CmdMouse], TgtPointerEnemy))
-- Debug and others not to display in help screens
, ("CTRL-S", ([CmdDebug], GameSave))
, ("CTRL-semicolon", ([CmdInternal], MoveOnceToCursor))
, ("CTRL-colon", ([CmdInternal], RunOnceToCursor))
, ("CTRL-period", ([CmdInternal], ContinueToCursor))
, ("CTRL-comma", ([CmdInternal], RunOnceAhead))
, ("CTRL-LeftButtonPress",
([CmdInternal], Macro "" ["SHIFT-LeftButtonPress"]))
, ("CTRL-MiddleButtonPress",
([CmdInternal], Macro "" ["SHIFT-MiddleButtonPress"]))
, ("ALT-space", ([CmdInternal], StopIfTgtMode))
, ("ALT-minus", ([CmdInternal], SelectWithPointer))
]
}
Allure-0.5.0.0/test/ 0000755 0000000 0000000 00000000000 12555263417 012255 5 ustar 00 0000000 0000000 Allure-0.5.0.0/test/test.hs 0000644 0000000 0000000 00000001064 12555263417 013571 0 ustar 00 0000000 0000000 import TieKnot
main :: IO ()
main =
tieKnot $ tail $ words "dist/build/LambdaHack/LambdaHack --dbgMsgSer --savePrefix test --newGame 2 --noDelay --noAnim --maxFps 100000 --frontendNull --benchmark --stopAfter 6 --automateAll --keepAutomated --gameMode campaign --setDungeonRng 42 --setMainRng 42"
-- tieKnot $ tail $ words "dist/build/LambdaHack/LambdaHack --dbgMsgSer --savePrefix test --newGame 2 --noDelay --noAnim --maxFps 100000 --frontendNull --benchmark --stopAfter 6 --automateAll --keepAutomated --gameMode battle --setDungeonRng 42 --setMainRng 42"