diff --git a/COPYING b/COPYING deleted file mode 100644 index f6cdd22..0000000 --- a/COPYING +++ /dev/null @@ -1,232 +0,0 @@ -GNU GENERAL PUBLIC LICENSE -Version 3, 29 June 2007 - -Copyright © 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 General Public License is a free, copyleft license for software and other kinds of works. - -The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is 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. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. - -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. - -To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. - -For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. - -Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. - -For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. - -Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. - -Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. - -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 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. Use with the GNU Affero General Public License. -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 Affero 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 special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. - -14. Revised Versions of this License. -The Free Software Foundation may publish revised and/or new versions of the GNU 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 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 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 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 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 General Public License for more details. - - You should have received a copy of the GNU General Public License along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - -If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: - - Copyright (C) - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an “about box”. - -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 GPL, see . - -The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . diff --git a/LICENSE-NOTICE.md b/LICENSE-NOTICE.md new file mode 100644 index 0000000..10bc7b7 --- /dev/null +++ b/LICENSE-NOTICE.md @@ -0,0 +1,187 @@ +# License Notice + +This document explains the legal framework for the multi-component Conquer repository and how different licenses interact. + +## Repository Structure + +This repository follows the proven dual-licensing structure established in [conquerv5](https://github.com/vejeta/conquerv5): + +- **`gpl-release/`** - Clean GPL v3 distribution for modern development +- **`original/`** - Complete historical preservation of original distribution +- **`richard-caley-utilities/`** - Detailed documentation of Richard Caley's contributions +- **Root level** - Licensing documentation and prominent attribution + +## Component Details + +### Core Game (GPL v3) +- **Location**: `gpl-release/` folder +- **License**: GNU General Public License v3.0+ +- **Authors**: Edward M. Barlow and Adam Bryant (original), Juan Manuel Méndez Rey (GPL coordination) +- **Usage**: Free to use, modify, and distribute under GPL terms + +**Legal Basis**: +- Explicit written permission obtained from both original authors +- Relicensing process completed in 2025 +- All copyright holders have agreed to GPL terms + +**Rights Granted**: +- ✅ Use for any purpose (including commercial) +- ✅ Modify and create derivative works +- ✅ Distribute original and modified versions +- ✅ Charge fees for distribution +- ✅ Private use and modification + +**Obligations**: +- 📋 Provide source code with distribution +- 📋 Preserve copyright notices +- 📋 Include GPL license text +- 📋 Document modifications +- 📋 License derivatives under GPL + +### Richard Caley Map Utility (Custom License) +- **Location**: `original/utilities/` folder (original code), `richard-caley-utilities/` folder (documentation) +- **License**: Custom permissive license (see `richard-caley-utilities/LICENSE`) +- **Author**: Richard Caley (deceased 2006) +- **Usage**: Free to copy, distribute, and modify with restrictions (no charging, must include source) + +**Legal Basis**: +- Original author's published license terms +- Permissive license allows copying and modification +- Used under original terms as published + +**Rights Granted**: +- ✅ Copy and distribute +- ✅ Modify ("do what you will") +- ✅ Use for any non-commercial purpose +- ✅ Create derivative works + +**Obligations**: +- 📋 Preserve license notice in all copies +- 📋 Distribute source code with program +- ❌ Cannot charge money for the software + +**Restrictions**: +- ❌ No commercial distribution (charging fees) +- ❌ Cannot distribute without source code + +## License Interaction + +### Compatibility Analysis + +The two licenses are **NOT directly compatible** for code merging due to conflicting terms: + +- **GPL v3**: Permits charging fees (essential freedom) +- **Caley License**: Prohibits charging fees (explicit restriction) + +### Safe Usage Patterns + +✅ **ALLOWED**: +- Distribute both components in the same repository +- Use both components in the same project +- Document both components together +- Link to both from the same website +- Include both in the same documentation + +✅ **ALLOWED with care**: +- Create wrapper scripts that use both (keep components separate) +- Build systems that compile both (as separate executables) +- Configuration that coordinates both (without code merging) + +❌ **NOT ALLOWED**: +- Merge Caley code directly into GPL components +- Include Caley code in GPL-licensed files +- Create combined works under single license +- Sublicense Caley code under GPL terms + +### Distribution Guidelines + +When distributing this software: + +1. **Preserve both license texts** in their respective locations (`gpl-release/LICENSE` and `richard-caley-utilities/LICENSE`) +2. **Document the dual licensing** clearly (this document serves that purpose) +3. **Separate the components** in distribution packages: + - `gpl-release/` contains clean GPL code + - `original/` preserves complete historical distribution + - `richard-caley-utilities/` provides documentation context +4. **Inform users** about different terms for each component + +## Legal Precedents + +This approach follows established patterns: + +- **Debian**: Multi-license packages with clear component separation +- **GNU/Linux**: Combines GPL and non-GPL components (kernel modules, firmware) +- **Web browsers**: Bundle components under different licenses +- **Academic software**: Preserves historical code with original licenses + +## Contribution Guidelines + +### For Core Game (GPL Components) + +- Submit contributions under GPL v3+ terms +- Ensure new code is compatible with GPL +- Follow GPL requirements for derivative works +- Can freely modify and enhance + +### For Richard Caley Components + +- **Cannot accept contributions** to original code (author deceased) +- Can document bugs or historical behavior +- Can create separate derivative works under different licenses +- Original code preserved as historical artifact + +## Future Considerations + +### Modern Ports + +Developers wishing to create modern versions of Richard Caley's map utility can: + +1. **Study the original** for reference (educational use) +2. **Implement from scratch** under new license +3. **Create inspired-by versions** under GPL or other licenses +4. **Document historical techniques** for educational purposes + +### License Evolution + +- **Core Game**: Can be upgraded to future GPL versions +- **Caley Code**: Frozen at original 1989 terms (cannot be changed) + +## Quick Reference + +| Component | Location | License | Can Charge? | Source Required? | Modifications OK? | +|-----------|----------|---------|-------------|------------------|-------------------| +| Core Game | `gpl-release/` | GPL v3 | ✅ Yes | ✅ Yes | ✅ Yes | +| Map Utility | `original/utilities/` | Custom | ❌ No | ✅ Yes | ✅ Yes* | + +*Modifications to Richard Caley's code are permitted by his license but preserved historically in `original/`. + +## FAQ + +**Q: Can I charge for the complete package?** +A: No, because it includes Richard Caley's component which prohibits charging. + +**Q: Can I charge for just the GPL component?** +A: Yes, if distributed separately from the Caley component. + +**Q: Can I modify Richard Caley's code?** +A: Yes, his license explicitly permits modification. + +**Q: Can I contribute improvements to Richard Caley's code?** +A: No, we preserve it as a historical artifact in its original form. + +**Q: Are the licenses compatible for linking?** +A: No, they cannot be directly linked into a single executable under unified terms. + +**Q: Can I create a GUI that uses both?** +A: Yes, as long as you keep the components separate and respect both license terms. + +## Contact + +For legal questions about this licensing framework: +- Create an issue in the GitHub repository +- Consult with legal counsel for commercial use cases +- Reference this document in license discussions + +--- + +*This document provides guidance but is not legal advice. Consult qualified legal counsel for specific situations.* diff --git a/LICENSES/GPL-3.0-or-later.txt b/LICENSES/GPL-3.0-or-later.txt index f6cdd22..f288702 100644 --- a/LICENSES/GPL-3.0-or-later.txt +++ b/LICENSES/GPL-3.0-or-later.txt @@ -1,232 +1,674 @@ -GNU GENERAL PUBLIC LICENSE -Version 3, 29 June 2007 - -Copyright © 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 General Public License is a free, copyleft license for software and other kinds of works. - -The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is 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. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. - -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. - -To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. - -For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. - -Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. - -For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. - -Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. - -Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. - -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 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. Use with the GNU Affero General Public License. -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 Affero 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 special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. - -14. Revised Versions of this License. -The Free Software Foundation may publish revised and/or new versions of the GNU 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 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 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 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 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 General Public License for more details. - - You should have received a copy of the GNU General Public License along with this program. If not, see . + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 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 General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is 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. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + 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. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + 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 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. Use with the GNU Affero General Public License. + + 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 Affero 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 special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU 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 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 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 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 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . Also add information on how to contact you by electronic and paper mail. -If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: - - Copyright (C) - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an “about box”. - -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 GPL, see . - -The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + 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 GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/LICENSES/LicenseRef-Original-Restrictive.txt b/LICENSES/LicenseRef-Original-Restrictive.txt new file mode 100644 index 0000000..08b7a6a --- /dev/null +++ b/LICENSES/LicenseRef-Original-Restrictive.txt @@ -0,0 +1,45 @@ +Conquer Original License +Copyright (c) 1988, 1989 by Ed Barlow. + + MODIFICATION OF THIS FILE IMPLIES THAT THE MODIFIER WILL ACCEPT + A LIMITED USE COPYRIGHT AS FOLLOWS: + + + 1) This software is copyrighted and protected by law. The + sole owner of this software, which hereafter is known as + "conquer" is Edward M. Barlow, who hereby grants you a + personal, non-exclusive right to use this software. + All rights on this software are reserved. + 2) conquer may not be redistributed in any form. Any requests for + new software shall, for now, be the perogative of the author. + 3) loss or damage caused by this software shall not be + the responsibility of the author. + 4) Ed Barlow or Adam Bryant shall be notified of enhancements to this + software via electronic mail and, if there is no response, via + US mail to: + + Ed Barlow + 115 E 34ths St. + NY, NY 10016 + + My home phone is 212-679-1439. Use it sparingly and call + before 11PM if it is important. Note that I no longer have + access to the arpanet and cant really support conquer like + I used to. If somebody knows of a cheap (free) way of getting + a login somewhere where there is network access - HELP ME!!!! + Since i am "volunteering" my time for this project, I am not + about to spend millions of dollars to buy network access... + I can get a modem for my PC if somebody will help me get + something to call into. -ED- + 5) no attempt shall be made to make any money from this game or to + use any portion of this code to make any money without the + authors permission. + 6) no attempt shall be made to port this software to any form of + personal computer without the permission of Ed Barlow. + 7) you agree to use your best efforts to see that any user + of conquer complies with the terms and conditions stated above. + 8) The above copyright agreement will not be tampered with in any form. + + + Special thanks to Brian Beuning, Adam Bryant, and any others who helped + me by making enhancements and bug reports diff --git a/LICENSES/LicenseRef-Richard-Caley.txt b/LICENSES/LicenseRef-Richard-Caley.txt new file mode 100644 index 0000000..67282ac --- /dev/null +++ b/LICENSES/LicenseRef-Richard-Caley.txt @@ -0,0 +1,16 @@ +Richard Caley Map Drawing Utility License + +This program draws a map of the conquer world on a bitmap system + +Written by Richard Caley July 1989 and hacked extensively thereafter. + +You may copy, distribute, modify or do what you will with this code so long as +this message remains in it and so long as you do not charge for it, nor +distribute the program without the source. + +There is a horrid hack for getpass - to make this read the password from +standard in one has to disconnect from the control terminal. GAG! It should +be possible to disconnect just the conquer from the control terminal . . . +someday. + +See Readme for more details. diff --git a/README.md b/README.md index 7e9512d..90518ea 100644 --- a/README.md +++ b/README.md @@ -1,36 +1,20 @@ -[![License: GPL v3](https://img.shields.io/badge/License-GPLv3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0) -[![Relicensed: 2025](https://img.shields.io/badge/Relicensed-2025-green.svg)](./RELICENSING-PERMISSIONS.md) -********************************************************* -* README FILE FOR THE INSTALLER OF CONQUER * -********************************************************* +# Conquer - Classic Unix Strategy Game -CONQUER - Classic Multi-Player Strategy Game +**Conquer** is the classic multi-player strategy game originally created by Edward M. Barlow and Adam Bryant in the late 1980s. This repository preserves both the historical distribution and provides a modern GPL-licensed version for continued development. -What you have here is a GPL v3 licensed version of the classic CONQUER game, -originally created by Edward M. Barlow and Adam Bryant. This version has been -relicensed to GPL v3 in 2025 by Juan Manuel Méndez Rey (Vejeta) with explicit -permission from the original authors. +## 🗺️ Special Recognition: Richard Caley's Map Utility -LICENSING INFORMATION: -====================== -- Originally Copyright (C) 1988-1989 by Edward M. Barlow and Adam Bryant -- Copyright (C) 2025 Juan Manuel Méndez Rey (Vejeta) -- Licensed under GPL v3 with permission from original authors +This repository includes a significant historical contribution: **Richard Caley's map drawing utility** from 1989. Richard Caley, a researcher at the University of Edinburgh's Centre for Speech Technology Research and contributor to the Festival Speech Synthesis System, created a bitmap visualization tool for Conquer game worlds. -This program is free software: you can redistribute it and/or modify it under -the terms of the GNU General Public License as published by the Free Software -Foundation, either version 3 of the License, or (at your option) any later -version. See the COPYING file for the complete GPL v3 license text. +His work represents an early example of game data visualization, created with the generous spirit typical of the late 1980s Unix computing community. Richard wrote: *"You may copy, distribute, modify or do what you will with this code"* - embodying the collaborative ethos that shaped early computer gaming. +**📖 Learn more about Richard Caley's contributions**: See [`richard-caley-utilities/`](richard-caley-utilities/) for detailed biographical information, technical context, and links to his archived research and personal materials. -### Relicensing Documentation +*Richard Caley passed away in 2006. This code is preserved in his memory and as a testament to the early Unix gaming community's collaborative spirit.* -This game has been successfully relicensed from its original restrictive license to GPL v3 through a **15-year effort** (2006-2025) with explicit written permission from all copyright holders: +## Relicensing Achievement -📄 **[Full Legal Documentation](./RELICENSING-PERMISSIONS.md)** - Complete email permissions with headers -📄 **[Authors & Attribution](./AUTHORS.md)** - All contributors and their roles -📄 **[Project History](./HISTORY.md)** - Timeline from 1987 USENET release to present -📄 **[License Text](./COPYING)** - Full GPL v3 license +This repository represents a successful **15-year relicensing effort** (2006-2025) that transformed Conquer from a restrictively licensed game into a modern GPL v3 project. All original copyright holders provided explicit written permission: ### Summary of Permissions @@ -44,7 +28,7 @@ This game has been successfully relicensed from its original restrictive license > *"Yes i delegated it all to adam aeons ago. Im easy on it all.... copyleft didnt exist when i wrote it and it was all for fun so..."* - Ed Barlow, 2016 -> *""Oh, that was a long time ago. But yes, that was me. And I have no problem with relicensing it to GPL."* - Martin Forssen, 2025 +> *"Oh, that was a long time ago. But yes, that was me. And I have no problem with relicensing it to GPL."* - Martin Forssen, 2025 ### Legal Validation @@ -54,207 +38,104 @@ This relicensing effort has been: - ✅ Documented at [vejeta.com](http://vejeta.com/historia-del-conquer/) - ✅ Preserved with complete email headers for authentication -### What This Means For You +📄 **Complete legal documentation**: See [`gpl-release/RELICENSING-PERMISSIONS.md`](gpl-release/RELICENSING-PERMISSIONS.md) for full email permissions with headers. -- ✅ **Free to use, modify, and distribute** under GPL v3 terms -- ✅ **No legal concerns** - all permissions properly obtained -- ✅ **Contribute with confidence** - clear legal foundation -- ✅ **Fork freely** - create your own versions under GPL v3 +## Repository Structure -For questions about the relicensing process: vejeta@gmail.com +This repository uses a dual-licensing approach to balance historical preservation with modern development: ---- +### 🚀 For Modern Development +- **[`gpl-release/`](gpl-release/)** - Clean GPL v3 licensed distribution + - Free to use, modify, and distribute commercially + - Relicensed with explicit permission from all original authors + - Recommended for new projects and contributions + +### 📚 For Historical Research +- **[`original/`](original/)** - Complete original distribution preserved + - Original restrictive licensing (personal use only) + - Includes Richard Caley's map utility in `original/utilities/` + - Historical accuracy for researchers and gaming archaeologists + +### 🎯 Documentation & Attribution +- **[`richard-caley-utilities/`](richard-caley-utilities/)** - Detailed documentation of Richard Caley's contributions +- **[`LICENSES/`](LICENSES/)** - All license texts for REUSE compliance +- **[`LICENSE-NOTICE.md`](LICENSE-NOTICE.md)** - Comprehensive licensing framework explanation + +## Quick Start + +### Playing the Game +Use the modern GPL version for the best experience: + +```bash +cd gpl-release/ +# See gpl-release/README.md for complete build and setup instructions +``` +### Historical Research +Explore the original distribution exactly as it was shared in the late 1980s: -HISTORICAL NOTE: -================ -This is based on the original release 4 version of CONQUER. The original -authors made no guarantees to the sanity or style of this code, but believed -that it should work as documented. It included numerous bugfixes from previous -releases and various enhancements. - -The original development team included Edward M. Barlow and Adam Bryant, who -set up mailing lists and provided community support in the late 1980s. Their -innovative work created one of the early multi-player strategy games that -influenced many later games in the genre. - -CURRENT STATUS: -=============== -This version maintains the original gameplay and functionality while being -made available under modern open-source licensing terms. Bug reports, feature -requests, and contributions are welcome through the project's repository. - -INCLUDED IN THIS DISTRIBUTION: -=============================== - 1) A Brief Description of Conquer - 2) Installation (unpacking) Instructions - 3) Configuration Instructions - 4) Compilation Instructions - 5) Administration instructions - 6) GPL v3 License Information - ------------------------------------------------------------ -I A Brief Description of Conquer ------------------------------------------------------------ -A complete description of Conquer v4 is contained in "man.pag" and can be -generated in "conquer.docs". The game is a multi-player strategy simulation -where players control nations, managing resources, armies, diplomacy, and -territorial expansion. - -Key features include: -- Multi-player strategy gameplay -- Resource management (food, gold, metal, jewels) -- Military units and naval fleets -- Magic system and special powers -- Diplomatic relations between nations +```bash +cd original/ +# See original README and build instructions for historical reference +``` + +## About Conquer + +Conquer is a turn-based strategy game where players control nations in a fantasy world, managing resources, armies, diplomacy, and territorial expansion. Key features include: + +- Multi-player strategy gameplay with up to 50+ nations +- Resource management (food, gold, metal, jewels) +- Military units, naval fleets, and siege warfare +- Magic system with spells and artifacts +- Diplomatic relations and trade between nations - NPC nations with AI behavior -- Random events and world dynamics +- Random events and dynamic world systems - Customizable world generation -The documentation files txt[0-5] contain help information that is customized -from data in the header files and converted to help[0-5] files during -compilation. "make docs" will create documentation from current data. - ------------------------------------------------------------ -II Installation Instructions ------------------------------------------------------------ -SYSTEM REQUIREMENTS: -- Unix-like operating system (Linux, BSD, macOS) -- C compiler (gcc recommended) -- make utility -- curses library (ncurses) -- Standard Unix utilities - -COMPILATION: -1. Extract the source code to a directory -2. Review and modify configuration files (see Configuration section) -3. Compile: `make` -4. Install and set up new game: `make new_game` - -If curses linking fails, you may need to add "-ltermcap" or "-lncurses" -to the library flags in the Makefile. - ------------------------------------------------------------ -III Configuration ------------------------------------------------------------ -THE FOLLOWING FILES SHOULD BE MODIFIED TO REFLECT YOUR ENVIRONMENT -AND THE TYPE OF GAME YOU WISH TO PLAY: - -REQUIRED MODIFICATIONS: -- header.h: Game configuration constants and settings -- Makefile: Build configuration and paths - -OPTIONAL MODIFICATIONS: -- rules: Grammar rules for NPC message generation -- nations: NPC nation configurations for world creation - -The options specified in these files will be reflected in the documentation -and help files when the program is compiled. - -IMPORTANT: Edit the following defines in header.h: -- OWNER: Administrator name -- LOGIN: Administrator login ID -- Directory paths for game data and executables -- System-specific settings (BSD vs SYSV) - -The "rules" file contains grammar rules for random messages generated by -NPCs. You may customize this with local names or creative content following -the format: %CLASS declares a class, with %MAIN being the top level. - ------------------------------------------------------------ -IV Compilation Instructions ------------------------------------------------------------ -After configuring header.h and Makefile: - -Basic compilation: - make # Compile the game - make clean # Clean up object files - make clobber # Remove all generated files - -Game setup: - make new_game # Build and install a complete new game - make install # Install executables only - make docs # Generate documentation - -TROUBLESHOOTING: -- If linking fails with curses errors, add "-ltermcap" to LIBRARIES in Makefile -- If make gives "command not found" errors, try: setenv SHELL /bin/sh -- Ensure all directory paths in header.h exist and are writable - ------------------------------------------------------------ -V Administration Instructions ------------------------------------------------------------ -COMMAND LINE ADMINISTRATION: - -conqrun options: - -m Create/make a new world - -a Add new player to existing world - -x Execute update (process turn) - -d DIR Use specified game directory - -r SCENARIO Read map from scenario files during world creation - -GAME ADMINISTRATION LEVELS: -1. God: Primary administrator (defined by LOGIN in header.h) -2. Demi-God: World-specific administrator (can be changed during game) - -During world creation, you'll be prompted to designate a demi-god for the -world, or you can serve as demi-god yourself. - -SETUP PROCEDURE: -1. Create world: `conqrun -m` - - Sets up the game world and NPC nations per the nations file - - NPCs use the same password as god initially - -2. Add players: `conqrun -a` - - Interactive player addition - - Won't work if world is full from scenario loading - -3. Alternative - Scenario-based: `conqrun -r SCENARIO` - - Uses SCENARIO.ele, SCENARIO.veg, and SCENARIO.ntn files - - Pre-configured world setup - -GOD FUNCTIONS: -Access god functions by logging in with: `conquer -n god` -- Modify terrain and sectors -- Manage nations (create/destroy) -- Adjust game balance -- Administrative oversight - -GAME BALANCE: -The world generation is not perfectly balanced. Some players may start in -difficult positions. As god, you can: -- Redesignate terrain to improve starting positions -- Destroy and recreate nations in better locations -- Modify surrounding terrain for fairness -- Use the change nation command to adjust player situations - -REGULAR OPERATION: -- Players connect: `conquer` -- Process turns: `conqrun -x` (typically automated via cron) -- Monitor via god login for administrative needs - -AUTOMATED UPDATES: -Use the included "run" script as a template for automated turn processing. -Modify it for your preferred update schedule and system configuration. - -For detailed gameplay help, use the '?' command within the game. - ------------------------------------------------------------ -VI Contributing and Support ------------------------------------------------------------ -This open-source version welcomes contributions: +## Contributors & History + +- **Edward M. Barlow** (1987-1988) - Original creator and core engine +- **Adam Bryant** (1987-1988) - Co-author, maintainer, and enhancements +- **Richard Caley** (1989) - Map drawing utility for world visualization +- **Martin Forssen** (1989) - PostScript utilities and enhancements +- **Juan Manuel Méndez Rey** (2006-2025) - Historical preservation and GPL relicensing coordination + +## Licensing + +This repository contains software under multiple licenses: + +| Component | Location | License | Commercial Use | +|-----------|----------|---------|----------------| +| **Modern Game** | `gpl-release/` | GPL v3+ | ✅ Allowed | +| **Original Distribution** | `original/` | Restrictive | ❌ Personal use only | +| **Richard Caley Utility** | `original/utilities/` | Custom permissive | ❌ No charging allowed | + +**📋 See [`LICENSE-NOTICE.md`](LICENSE-NOTICE.md)** for complete licensing details and legal framework. + +## Contributing + +Contributions are welcome for the GPL-licensed components in [`gpl-release/`](gpl-release/): + - Bug reports and fixes -- Feature enhancements +- Feature enhancements - Documentation improvements -- Platform compatibility updates +- Modern platform support - Translation efforts -Please maintain the spirit of the original game while modernizing the codebase -for current systems and development practices. +Please maintain the spirit of the original game while modernizing for current systems. + +## Historical Significance + +This preservation effort maintains one of the early examples of: +- Unix-based multiplayer gaming (1987-1988) +- Community-driven game development via USENET +- Early game world visualization tools (Richard Caley's work) +- Collaborative open-source game development principles + +The generous code-sharing philosophy of contributors like Richard Caley helped establish the collaborative culture that continues in modern open-source gaming. + +--- -The original creators, Edward M. Barlow and Adam Bryant, laid the foundation -for this classic strategy game. This GPL v3 version ensures it remains -available for future generations of strategy game enthusiasts. +**🎮 Ready to conquer?** Start with [`gpl-release/`](gpl-release/) for the modern experience, or explore [`original/`](original/) for historical gaming archaeology. ------------------------------------------------------------ -For more information, see the man page (man.pag) and in-game help system. +**📖 Learn about the people behind the code:** Visit [`richard-caley-utilities/`](richard-caley-utilities/) to discover the fascinating individuals who created this classic game. \ No newline at end of file diff --git a/REUSE.toml b/REUSE.toml index 9153e74..36e87e4 100644 --- a/REUSE.toml +++ b/REUSE.toml @@ -16,3 +16,63 @@ precedence = "aggregate" SPDX-FileCopyrightText = ["1987-1989 Original Authors (see headers)", "2006-2025 Juan Manuel Méndez Rey "] SPDX-License-Identifier = "GPL-3.0-or-later" SPDX-FileComment = "Fallback rule for all other files not covered above." +version = 1 +SPDX-PackageName = "conquer" +SPDX-PackageSupplier = "Juan Manuel Méndez Rey " +SPDX-PackageDownloadLocation = "https://github.com/vejeta/conquer" + +# Richard Caley's specific contribution (highest precedence) +[[annotations]] +path = ["original/utilities/xconqrast.h"] +precedence = "override" +SPDX-FileCopyrightText = "1989 Richard Caley " +SPDX-License-Identifier = "LicenseRef-Richard-Caley" +SPDX-FileComment = "Map drawing utility for Conquer worlds. Written by Richard Caley July 1989. Original permissive license allows copying, distribution, and modification but prohibits charging fees." + +# GPL release folder - clean modern distribution +[[annotations]] +path = ["gpl-release/**"] +precedence = "aggregate" +SPDX-FileCopyrightText = ["1987-1988 Ed Barlow ", "1987-1988 Adam Bryant ", "2006-2025 Juan Manuel Méndez Rey "] +SPDX-License-Identifier = "GPL-3.0-or-later" +SPDX-FileComment = "Core Conquer game - relicensed to GPL with explicit permission from all original authors. Ed Barlow: Original creator, core engine. Adam Bryant: Co-author, maintainer. Juan Manuel Méndez Rey: Relicensing coordinator and current maintainer." + +# Original folder - preserves historical restrictive licensing (except Richard Caley's file) +[[annotations]] +path = ["original/**.c", "original/**.h"] +precedence = "aggregate" +SPDX-FileCopyrightText = ["1987-1988 Ed Barlow ", "1987-1988 Adam Bryant "] +SPDX-License-Identifier = "LicenseRef-Original-Restrictive" +SPDX-FileComment = "Original Conquer distribution preserved with historical restrictive licensing. Cannot be redistributed without author permission. Relicensed version available in gpl-release/ folder." + +# Original folder non-source files +[[annotations]] +path = ["original/**"] +precedence = "aggregate" +SPDX-FileCopyrightText = ["1987-1988 Ed Barlow ", "1987-1988 Adam Bryant "] +SPDX-License-Identifier = "LicenseRef-Original-Restrictive" +SPDX-FileComment = "Original Conquer distribution preserved with historical restrictive licensing." + +# Richard Caley utilities documentation folder +[[annotations]] +path = ["richard-caley-utilities/**"] +precedence = "aggregate" +SPDX-FileCopyrightText = "2025 Juan Manuel Méndez Rey " +SPDX-License-Identifier = "CC0-1.0" +SPDX-FileComment = "Documentation and preservation materials for Richard Caley's contributions. Released as public domain documentation." + +# Root level documentation and build files +[[annotations]] +path = ["README.md", "LICENSE-NOTICE.md", "Makefile*", "*.toml"] +precedence = "aggregate" +SPDX-FileCopyrightText = "2006-2025 Juan Manuel Méndez Rey " +SPDX-License-Identifier = "CC0-1.0" +SPDX-FileComment = "Repository documentation, build configuration, and licensing framework." + +# Fallback rule for any remaining files +[[annotations]] +path = "**" +precedence = "aggregate" +SPDX-FileCopyrightText = ["1987-1989 Original Authors (see specific file headers)", "2006-2025 Juan Manuel Méndez Rey "] +SPDX-License-Identifier = "LicenseRef-Original-Restrictive" +SPDX-FileComment = "Fallback rule - preserves original restrictive licensing unless explicitly overridden. See LICENSE-NOTICE.md for detailed licensing framework." diff --git a/.indent.pro b/gpl-release/.indent.pro similarity index 100% rename from .indent.pro rename to gpl-release/.indent.pro diff --git a/AUTHORS.md b/gpl-release/AUTHORS.md similarity index 100% rename from AUTHORS.md rename to gpl-release/AUTHORS.md diff --git a/CONQPS.INFO b/gpl-release/CONQPS.INFO similarity index 100% rename from CONQPS.INFO rename to gpl-release/CONQPS.INFO diff --git a/gpl-release/COPYING b/gpl-release/COPYING new file mode 100644 index 0000000..f288702 --- /dev/null +++ b/gpl-release/COPYING @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 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 General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is 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. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + 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. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + 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 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. Use with the GNU Affero General Public License. + + 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 Affero 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 special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU 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 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 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 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 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + 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 GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/HISTORY.md b/gpl-release/HISTORY.md similarity index 100% rename from HISTORY.md rename to gpl-release/HISTORY.md diff --git a/LICENSE.md b/gpl-release/LICENSE.md similarity index 100% rename from LICENSE.md rename to gpl-release/LICENSE.md diff --git a/MANIFEST b/gpl-release/MANIFEST similarity index 100% rename from MANIFEST rename to gpl-release/MANIFEST diff --git a/Makefile b/gpl-release/Makefile similarity index 100% rename from Makefile rename to gpl-release/Makefile diff --git a/gpl-release/Makefile.orig b/gpl-release/Makefile.orig new file mode 100644 index 0000000..e400fcd --- /dev/null +++ b/gpl-release/Makefile.orig @@ -0,0 +1,361 @@ +# +# Makefile - Build configuration and compilation rules +# +# This file is part of Conquer. +# Originally Copyright (C) 1988-1989 by Edward M. Barlow and Adam Bryant +# Copyright (C) 2025 Juan Manuel Méndez Rey (Vejeta) - Licensed under GPL v3 with permission from original authors +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + + +MAKE = /usr/bin/make +CC = /usr/bin/gcc +RM = /bin/rm -f + +# LN must be "ln -s" if source and default directories span disks +LN = /bin/ln +CP = /bin/cp +NULL = 2>/dev/null + +# Flags to lint +LTFLG = -h -lcurses + +# Options for the postscript map printing program. +# The file 'conqps.ps' will be installed in the EXEDIR +# directory which is determined below. +# +# To avoid building this program, remove $(PSPROG) from +# both the 'all:' list and the 'install:' list +PSPROG = conqps +PSSRC = psmap.c +PSHEAD = psmap.h +PSDATA = psmap.ps +# Default Pagesize Setting: +# A4 for European page size. +# LETTER for American page size. +# OTHER for Local page size. [edit conqps.h] +PSPAGE = LETTER + +# Options for shar program, SHARLIM is limit of each shar +# file created in kilobytes and SHARNAM is the prefix for +# SHARFILE name. +# [This is for a public domain shar from USENET, I can send +# copies if you wish - adb@bu-cs.bu.edu] +SHAR = /usr/bin/shar +SHARLIM = 50 +SHARNAM = shar. +SHARFLG = -D -c -l$(SHARLIM) -o$(SHARNAM) + +# This should be installed by whomever you want to own the game. +# I recommend "games" or "root". + +# uncomment the next line if you dont have getopt in your library +# (eg you are on a pc, or a non unix system). getopt.c is a +# public domain software, and has not been tested by the authors +# of conquer. [not distributed with conquer V4] +#GETOPT = getopt.o + +# +# libraries for BSD systems: +LIBRARIES = -lcurses -ltermcap -lcrypt +# +# libraries for SYSV systems: +#LIBRARIES = -lcurses +# +# libraries for Xenix systems: +#LIBRARIES = -ltermlib -ltcap -lcrypt + +# CURRENT is this directory. The directory where the source +# and Makefile are located +CURRENT = /home/conquer/src + +# DEFAULT is the directory where default nations & help files will be +# stored. It is also the default directory = where players will play +# if they do not use the -d option. +DEFAULT = /home/conquer/lib + +# This directory is where the executables will be stored +EXEDIR = /home/conquer/bin + +# Definitions used for compiling conquer +CDEFS = -DDEFAULTDIR=\"$(DEFAULT)\" -DEXEDIR=\"$(EXEDIR)\" + +# Options flag used for normal compilation +OPTFLG = -O + +# Options flag used for debugging purposes +# [make sure to comment out 'strip' commands in install section] +#OPTFLG = -DDEBUG -g + +# this is the name of the user executable +# the user executable contains commands for the games players +GAME = conquer +# this is the name of the administrative executable +# the administrative executable contains commands for the game super user +ADMIN = conqrun +# this is the name of the sorting program which conquer uses +SORT = conqsort + +# GAME IDENTIFICATION +# +# Set this to some unique identifier for each game you wish +# to create via 'make new_game'. It will make a subdirectory +# $(GAMEID) to the DEFAULT data directory where it will store +# data for the new game. [Leave it blank to create the default +# game] +GAMEID = + +# AFILS are files needed for game updating... +AFILS = combat.c cexecute.c io.c admin.c makeworl.c navy.c spew.c \ +newlogin.c update.c magic.c npc.c misc.c randeven.c data.c trade.c check.c +AOBJS = combat.o cexecuteA.o ioA.o admin.o makeworl.o navyA.o spew.o \ +newlogin.o update.o magicA.o npc.o miscA.o randeven.o dataA.o \ +tradeA.o $(GETOPT) check.o + +# GFILS are files needed to run a normal interactive game +GFILS = commands.c cexecute.c forms.c io.c main.c move.c navy.c \ +magic.c misc.c reports.c data.c display.c extcmds.c trade.c check.c +GOBJS = commands.o cexecuteG.o forms.o ioG.o main.o move.o navyG.o \ +magicG.o miscG.o reports.o dataG.o display.o extcmds.o tradeG.o \ +$(GETOPT) check.o + +# List of temporary C files +DAFILS = cexecuteA.c ioA.c miscA.c navyA.c magicA.c dataA.c tradeA.c +DGFILS = cexecuteG.c ioG.c miscG.c navyG.c magicG.c dataG.c tradeG.c + +#txt[0-4] are input help files. help[0-4] are output. HELPSCR is sed script. +HELP=txt +HELPOUT=help +HELPSCR=sed + +HEADERS=header.h data.h newlogin.h patchlevel.h +SUPT1=nations Makefile $(HELP)[0-5] README run man.pag rules +SUPT2=execute messages news commerce CONQPS.INFO +ALLFILS=$(SUPT1) $(HEADERS) $(AFILS) commands.c forms.c main.c move.c \ +reports.c display.c extcmds.c newhelp.c sort.c getopt.c \ +$(PSSRC) $(PSHEAD) $(PSDATA) + +all: $(ADMIN) $(GAME) $(SORT) $(PSPROG) helpfile + @echo YAY! make new_game to set up permissions, zero appropriate + @echo initial files, move $(GAME) and $(ADMIN) to + @echo $(EXEDIR), and set up the world. + @echo If a game is in progress, make install will just move $(GAME) + @echo and $(ADMIN) to $(EXEDIR). + @echo + +$(ADMIN): $(AOBJS) + @echo phew... + -$(RM) $(DAFILS) $(NULL) + @echo if the next command does not work you might also need -ltermcap + @echo === compiling administrative functions + $(CC) $(OPTFLG) -o $(ADMIN) $(AOBJS) $(LIBRARIES) +# comment out the next line during debugging + strip $(ADMIN) + +$(GAME): $(GOBJS) + @echo phew... + -$(RM) $(DGFILS) $(NULL) + @echo if the next command does not work you might also need -ltermcap + @echo === compiling user interface + $(CC) $(OPTFLG) -o $(GAME) $(GOBJS) $(LIBRARIES) +# comment out the next line during debugging + strip $(GAME) + +$(SORT): sort.c + $(CC) $(OPTFLG) -o $(SORT) sort.c +# comment out the next line if debugging + strip $(SORT) + +clobber: + -$(RM) *.o $(HELPOUT)[0-5] $(PSPROG) $(SORT) insthelp helpfile $(NULL) + -$(RM) newhelp in$(GAME) in$(SORT) in$(ADMIN) in$(PSPROG) $(NULL) + -$(RM) $(HELPSCR).[12] lint[ag] conquer.doc $(GAME) $(ADMIN) $(NULL) + +clean: + $(RM) *.o lint[ag] conquer.doc $(NULL) + +in$(GAME): $(GAME) + -$(RM) $(EXEDIR)/$(GAME) + mv $(GAME) $(EXEDIR) + chmod 4751 $(EXEDIR)/$(GAME) + touch $(GAME) + touch in$(GAME) + +in$(ADMIN): $(ADMIN) + -$(RM) $(EXEDIR)/$(ADMIN) + mv $(ADMIN) $(EXEDIR) + chmod 4751 $(EXEDIR)/$(ADMIN) + touch $(ADMIN) + touch in$(ADMIN) + +in$(SORT): $(SORT) + -$(RM) $(EXEDIR)/$(SORT) + mv $(SORT) $(EXEDIR) + chmod 751 $(EXEDIR)/$(SORT) + touch $(SORT) + touch in$(SORT) + +in$(PSPROG): $(PSPROG) + -$(RM) $(EXEDIR)/$(PSPROG) + mv $(PSPROG) $(EXEDIR) + $(CP) $(PSDATA) $(EXEDIR) + chmod 751 $(EXEDIR)/$(PSPROG) + chmod 644 $(EXEDIR)/$(PSDATA) + touch $(PSPROG) + touch in$(PSPROG) + +install: in$(GAME) in$(ADMIN) in$(SORT) in$(PSPROG) insthelp instman + @echo "" + @echo "Installation complete" + +new_game: all insthelp + @echo Installing new game + -mkdir $(EXEDIR) $(NULL) + -mkdir $(DEFAULT) $(NULL) + -mkdir $(DEFAULT)/$(GAMEID) $(NULL) + chmod 755 $(EXEDIR) + chmod 750 $(DEFAULT)/$(GAMEID) $(DEFAULT) + $(CP) $(GAME) $(ADMIN) $(SORT) $(PSPROG) $(PSDATA) $(EXEDIR) + chmod 4755 $(EXEDIR)/$(GAME) $(EXEDIR)/$(ADMIN) + chmod 0755 $(EXEDIR)/$(SORT) $(EXEDIR)/$(PSPROG) + chmod 0644 $(EXEDIR)/$(PSDATA) + chmod 0600 nations + chmod 0700 run + $(CP) nations rules $(DEFAULT)/$(GAMEID) + $(CP) nations rules $(DEFAULT) + @echo now making the world + $(EXEDIR)/$(ADMIN) -d "$(GAMEID)" -m + $(EXEDIR)/$(ADMIN) -d "$(GAMEID)" -a + +insthelp: helpfile + @echo Installing helpfiles + -$(RM) $(DEFAULT)/$(HELPOUT)0 + -$(LN) $(CURRENT)/$(HELPOUT)0 $(DEFAULT)/$(HELPOUT)0 + -$(RM) $(DEFAULT)/$(HELPOUT)1 + -$(LN) $(CURRENT)/$(HELPOUT)1 $(DEFAULT)/$(HELPOUT)1 + -$(RM) $(DEFAULT)/$(HELPOUT)2 + -$(LN) $(CURRENT)/$(HELPOUT)2 $(DEFAULT)/$(HELPOUT)2 + -$(RM) $(DEFAULT)/$(HELPOUT)3 + -$(LN) $(CURRENT)/$(HELPOUT)3 $(DEFAULT)/$(HELPOUT)3 + -$(RM) $(DEFAULT)/$(HELPOUT)4 + -$(LN) $(CURRENT)/$(HELPOUT)4 $(DEFAULT)/$(HELPOUT)4 + -$(RM) $(DEFAULT)/$(HELPOUT)5 + -$(LN) $(CURRENT)/$(HELPOUT)5 $(DEFAULT)/$(HELPOUT)5 + touch insthelp + +instman: + @echo Installing man pages + $(CP) man.pag $(EXEDIR) + +helpfile: $(HELPOUT)0 $(HELPOUT)1 $(HELPOUT)2 $(HELPOUT)3 $(HELPOUT)4 $(HELPOUT)5 + @echo Helpfiles built + touch helpfile + +$(HELPOUT)0: $(HELP)0 $(HELPSCR).1 $(HELPSCR).2 + @echo building $(HELPOUT)0 + cat $(HELP)0 | sed -f $(HELPSCR).1 | sed -f $(HELPSCR).2 > $(HELPOUT)0 + +$(HELPOUT)1: $(HELP)1 $(HELPSCR).1 $(HELPSCR).2 + @echo building $(HELPOUT)1 + cat $(HELP)1 | sed -f $(HELPSCR).1 | sed -f $(HELPSCR).2 > $(HELPOUT)1 + +$(HELPOUT)2: $(HELP)2 $(HELPSCR).1 $(HELPSCR).2 + @echo building $(HELPOUT)2 + cat $(HELP)2 | sed -f $(HELPSCR).1 | sed -f $(HELPSCR).2 > $(HELPOUT)2 + +$(HELPOUT)3: $(HELP)3 $(HELPSCR).1 $(HELPSCR).2 + @echo building $(HELPOUT)3 + cat $(HELP)3 | sed -f $(HELPSCR).1 | sed -f $(HELPSCR).2 > $(HELPOUT)3 + +$(HELPOUT)4: $(HELP)4 $(HELPSCR).1 $(HELPSCR).2 + @echo building $(HELPOUT)4 + cat $(HELP)4 | sed -f $(HELPSCR).1 | sed -f $(HELPSCR).2 > $(HELPOUT)4 + +$(HELPOUT)5: $(HELP)5 $(HELPSCR).1 $(HELPSCR).2 + @echo building $(HELPOUT)5 + cat $(HELP)5 | sed -f $(HELPSCR).1 | sed -f $(HELPSCR).2 > $(HELPOUT)5 + +$(HELPSCR).1: newhelp + newhelp + +$(HELPSCR).2: newhelp + newhelp + +newhelp: dataG.o newhelp.o + $(CC) $(OPTFLG) dataG.o newhelp.o -o newhelp + strip newhelp +# +# postscript map program +PSOPTS = -DPSFILE=\"$(EXEDIR)/$(PSDATA)\" -D$(PSPAGE) +# +$(PSPROG): $(PSSRC) $(PSDATA) $(PSHEAD) + $(CC) $(OPTFLG) $(PSOPTS) $(PSSRC) -o $(PSPROG) +# comment out the next line if debugging + strip $(PSPROG) + +lint: + lint $(LTFLG) $(CDEFS) -DCONQUER $(GFILS) > lintg + lint $(LTFLG) $(CDEFS) -DADMIN $(AFILS) > linta + +docs: conquer.doc + +conquer.doc: $(HELPOUT)0 $(HELPOUT)1 $(HELPOUT)2 $(HELPOUT)3 $(HELPOUT)4 $(HELPOUT)5 + cat $(HELPOUT)? |sed -e "s/^DONE/ /g"|sed -e "s/^END//g" >conquer.doc + +cpio: + -$(RM) core + find . -name '*[CrpsEech]' -print | cpio -ocBv > cpiosv + +shar: + echo " lines words chars FILENAME" > MANIFEST + wc $(ALLFILS) >> MANIFEST + $(SHAR) $(SHARFLG) $(ALLFILS) MANIFEST + +.cA.o: $< + ( trap "" 0 1 2 3 4 ; $(LN) $*.c $*A.c ;\ + $(CC) $(OPTFLG) $(CDEFS) -DADMIN -c $*A.c ;\ + $(RM) $*A.c ) + +.cG.o: $< + ( trap "" 0 1 2 3 4 ; $(LN) $*.c $*G.c ;\ + $(CC) $(OPTFLG) $(CDEFS) -DCONQUER -c $*G.c ;\ + $(RM) $*G.c ) + +.c.o: $< +# compiles using both defines since they +# are needed for the data.h definitions for +# each file... but should not be needed for +# the actual C source file being compiled + $(CC) $(OPTFLG) $(CDEFS) -DADMIN -DCONQUER -c $*.c + +$(GOBJS): data.h header.h + +$(AOBJS): data.h header.h + +ioG.o: data.h header.h patchlevel.h io.c + +ioA.o: data.h header.h patchlevel.h io.c + +newlogin.o: data.h header.h newlogin.h patchlevel.h newlogin.c + +main.o: data.h header.h patchlevel.h main.c + +newhelp.o: data.h header.h patchlevel.h newhelp.c + +# Clear suffixes +# Commented out for problems with newer versions of make +#.SUFFIXES: + +# Suffixes for conquer files. +#.SUFFIXES: .c .o .cA.o .cG.o A.o G.o diff --git a/gpl-release/Makefile.txt b/gpl-release/Makefile.txt new file mode 100644 index 0000000..e400fcd --- /dev/null +++ b/gpl-release/Makefile.txt @@ -0,0 +1,361 @@ +# +# Makefile - Build configuration and compilation rules +# +# This file is part of Conquer. +# Originally Copyright (C) 1988-1989 by Edward M. Barlow and Adam Bryant +# Copyright (C) 2025 Juan Manuel Méndez Rey (Vejeta) - Licensed under GPL v3 with permission from original authors +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + + +MAKE = /usr/bin/make +CC = /usr/bin/gcc +RM = /bin/rm -f + +# LN must be "ln -s" if source and default directories span disks +LN = /bin/ln +CP = /bin/cp +NULL = 2>/dev/null + +# Flags to lint +LTFLG = -h -lcurses + +# Options for the postscript map printing program. +# The file 'conqps.ps' will be installed in the EXEDIR +# directory which is determined below. +# +# To avoid building this program, remove $(PSPROG) from +# both the 'all:' list and the 'install:' list +PSPROG = conqps +PSSRC = psmap.c +PSHEAD = psmap.h +PSDATA = psmap.ps +# Default Pagesize Setting: +# A4 for European page size. +# LETTER for American page size. +# OTHER for Local page size. [edit conqps.h] +PSPAGE = LETTER + +# Options for shar program, SHARLIM is limit of each shar +# file created in kilobytes and SHARNAM is the prefix for +# SHARFILE name. +# [This is for a public domain shar from USENET, I can send +# copies if you wish - adb@bu-cs.bu.edu] +SHAR = /usr/bin/shar +SHARLIM = 50 +SHARNAM = shar. +SHARFLG = -D -c -l$(SHARLIM) -o$(SHARNAM) + +# This should be installed by whomever you want to own the game. +# I recommend "games" or "root". + +# uncomment the next line if you dont have getopt in your library +# (eg you are on a pc, or a non unix system). getopt.c is a +# public domain software, and has not been tested by the authors +# of conquer. [not distributed with conquer V4] +#GETOPT = getopt.o + +# +# libraries for BSD systems: +LIBRARIES = -lcurses -ltermcap -lcrypt +# +# libraries for SYSV systems: +#LIBRARIES = -lcurses +# +# libraries for Xenix systems: +#LIBRARIES = -ltermlib -ltcap -lcrypt + +# CURRENT is this directory. The directory where the source +# and Makefile are located +CURRENT = /home/conquer/src + +# DEFAULT is the directory where default nations & help files will be +# stored. It is also the default directory = where players will play +# if they do not use the -d option. +DEFAULT = /home/conquer/lib + +# This directory is where the executables will be stored +EXEDIR = /home/conquer/bin + +# Definitions used for compiling conquer +CDEFS = -DDEFAULTDIR=\"$(DEFAULT)\" -DEXEDIR=\"$(EXEDIR)\" + +# Options flag used for normal compilation +OPTFLG = -O + +# Options flag used for debugging purposes +# [make sure to comment out 'strip' commands in install section] +#OPTFLG = -DDEBUG -g + +# this is the name of the user executable +# the user executable contains commands for the games players +GAME = conquer +# this is the name of the administrative executable +# the administrative executable contains commands for the game super user +ADMIN = conqrun +# this is the name of the sorting program which conquer uses +SORT = conqsort + +# GAME IDENTIFICATION +# +# Set this to some unique identifier for each game you wish +# to create via 'make new_game'. It will make a subdirectory +# $(GAMEID) to the DEFAULT data directory where it will store +# data for the new game. [Leave it blank to create the default +# game] +GAMEID = + +# AFILS are files needed for game updating... +AFILS = combat.c cexecute.c io.c admin.c makeworl.c navy.c spew.c \ +newlogin.c update.c magic.c npc.c misc.c randeven.c data.c trade.c check.c +AOBJS = combat.o cexecuteA.o ioA.o admin.o makeworl.o navyA.o spew.o \ +newlogin.o update.o magicA.o npc.o miscA.o randeven.o dataA.o \ +tradeA.o $(GETOPT) check.o + +# GFILS are files needed to run a normal interactive game +GFILS = commands.c cexecute.c forms.c io.c main.c move.c navy.c \ +magic.c misc.c reports.c data.c display.c extcmds.c trade.c check.c +GOBJS = commands.o cexecuteG.o forms.o ioG.o main.o move.o navyG.o \ +magicG.o miscG.o reports.o dataG.o display.o extcmds.o tradeG.o \ +$(GETOPT) check.o + +# List of temporary C files +DAFILS = cexecuteA.c ioA.c miscA.c navyA.c magicA.c dataA.c tradeA.c +DGFILS = cexecuteG.c ioG.c miscG.c navyG.c magicG.c dataG.c tradeG.c + +#txt[0-4] are input help files. help[0-4] are output. HELPSCR is sed script. +HELP=txt +HELPOUT=help +HELPSCR=sed + +HEADERS=header.h data.h newlogin.h patchlevel.h +SUPT1=nations Makefile $(HELP)[0-5] README run man.pag rules +SUPT2=execute messages news commerce CONQPS.INFO +ALLFILS=$(SUPT1) $(HEADERS) $(AFILS) commands.c forms.c main.c move.c \ +reports.c display.c extcmds.c newhelp.c sort.c getopt.c \ +$(PSSRC) $(PSHEAD) $(PSDATA) + +all: $(ADMIN) $(GAME) $(SORT) $(PSPROG) helpfile + @echo YAY! make new_game to set up permissions, zero appropriate + @echo initial files, move $(GAME) and $(ADMIN) to + @echo $(EXEDIR), and set up the world. + @echo If a game is in progress, make install will just move $(GAME) + @echo and $(ADMIN) to $(EXEDIR). + @echo + +$(ADMIN): $(AOBJS) + @echo phew... + -$(RM) $(DAFILS) $(NULL) + @echo if the next command does not work you might also need -ltermcap + @echo === compiling administrative functions + $(CC) $(OPTFLG) -o $(ADMIN) $(AOBJS) $(LIBRARIES) +# comment out the next line during debugging + strip $(ADMIN) + +$(GAME): $(GOBJS) + @echo phew... + -$(RM) $(DGFILS) $(NULL) + @echo if the next command does not work you might also need -ltermcap + @echo === compiling user interface + $(CC) $(OPTFLG) -o $(GAME) $(GOBJS) $(LIBRARIES) +# comment out the next line during debugging + strip $(GAME) + +$(SORT): sort.c + $(CC) $(OPTFLG) -o $(SORT) sort.c +# comment out the next line if debugging + strip $(SORT) + +clobber: + -$(RM) *.o $(HELPOUT)[0-5] $(PSPROG) $(SORT) insthelp helpfile $(NULL) + -$(RM) newhelp in$(GAME) in$(SORT) in$(ADMIN) in$(PSPROG) $(NULL) + -$(RM) $(HELPSCR).[12] lint[ag] conquer.doc $(GAME) $(ADMIN) $(NULL) + +clean: + $(RM) *.o lint[ag] conquer.doc $(NULL) + +in$(GAME): $(GAME) + -$(RM) $(EXEDIR)/$(GAME) + mv $(GAME) $(EXEDIR) + chmod 4751 $(EXEDIR)/$(GAME) + touch $(GAME) + touch in$(GAME) + +in$(ADMIN): $(ADMIN) + -$(RM) $(EXEDIR)/$(ADMIN) + mv $(ADMIN) $(EXEDIR) + chmod 4751 $(EXEDIR)/$(ADMIN) + touch $(ADMIN) + touch in$(ADMIN) + +in$(SORT): $(SORT) + -$(RM) $(EXEDIR)/$(SORT) + mv $(SORT) $(EXEDIR) + chmod 751 $(EXEDIR)/$(SORT) + touch $(SORT) + touch in$(SORT) + +in$(PSPROG): $(PSPROG) + -$(RM) $(EXEDIR)/$(PSPROG) + mv $(PSPROG) $(EXEDIR) + $(CP) $(PSDATA) $(EXEDIR) + chmod 751 $(EXEDIR)/$(PSPROG) + chmod 644 $(EXEDIR)/$(PSDATA) + touch $(PSPROG) + touch in$(PSPROG) + +install: in$(GAME) in$(ADMIN) in$(SORT) in$(PSPROG) insthelp instman + @echo "" + @echo "Installation complete" + +new_game: all insthelp + @echo Installing new game + -mkdir $(EXEDIR) $(NULL) + -mkdir $(DEFAULT) $(NULL) + -mkdir $(DEFAULT)/$(GAMEID) $(NULL) + chmod 755 $(EXEDIR) + chmod 750 $(DEFAULT)/$(GAMEID) $(DEFAULT) + $(CP) $(GAME) $(ADMIN) $(SORT) $(PSPROG) $(PSDATA) $(EXEDIR) + chmod 4755 $(EXEDIR)/$(GAME) $(EXEDIR)/$(ADMIN) + chmod 0755 $(EXEDIR)/$(SORT) $(EXEDIR)/$(PSPROG) + chmod 0644 $(EXEDIR)/$(PSDATA) + chmod 0600 nations + chmod 0700 run + $(CP) nations rules $(DEFAULT)/$(GAMEID) + $(CP) nations rules $(DEFAULT) + @echo now making the world + $(EXEDIR)/$(ADMIN) -d "$(GAMEID)" -m + $(EXEDIR)/$(ADMIN) -d "$(GAMEID)" -a + +insthelp: helpfile + @echo Installing helpfiles + -$(RM) $(DEFAULT)/$(HELPOUT)0 + -$(LN) $(CURRENT)/$(HELPOUT)0 $(DEFAULT)/$(HELPOUT)0 + -$(RM) $(DEFAULT)/$(HELPOUT)1 + -$(LN) $(CURRENT)/$(HELPOUT)1 $(DEFAULT)/$(HELPOUT)1 + -$(RM) $(DEFAULT)/$(HELPOUT)2 + -$(LN) $(CURRENT)/$(HELPOUT)2 $(DEFAULT)/$(HELPOUT)2 + -$(RM) $(DEFAULT)/$(HELPOUT)3 + -$(LN) $(CURRENT)/$(HELPOUT)3 $(DEFAULT)/$(HELPOUT)3 + -$(RM) $(DEFAULT)/$(HELPOUT)4 + -$(LN) $(CURRENT)/$(HELPOUT)4 $(DEFAULT)/$(HELPOUT)4 + -$(RM) $(DEFAULT)/$(HELPOUT)5 + -$(LN) $(CURRENT)/$(HELPOUT)5 $(DEFAULT)/$(HELPOUT)5 + touch insthelp + +instman: + @echo Installing man pages + $(CP) man.pag $(EXEDIR) + +helpfile: $(HELPOUT)0 $(HELPOUT)1 $(HELPOUT)2 $(HELPOUT)3 $(HELPOUT)4 $(HELPOUT)5 + @echo Helpfiles built + touch helpfile + +$(HELPOUT)0: $(HELP)0 $(HELPSCR).1 $(HELPSCR).2 + @echo building $(HELPOUT)0 + cat $(HELP)0 | sed -f $(HELPSCR).1 | sed -f $(HELPSCR).2 > $(HELPOUT)0 + +$(HELPOUT)1: $(HELP)1 $(HELPSCR).1 $(HELPSCR).2 + @echo building $(HELPOUT)1 + cat $(HELP)1 | sed -f $(HELPSCR).1 | sed -f $(HELPSCR).2 > $(HELPOUT)1 + +$(HELPOUT)2: $(HELP)2 $(HELPSCR).1 $(HELPSCR).2 + @echo building $(HELPOUT)2 + cat $(HELP)2 | sed -f $(HELPSCR).1 | sed -f $(HELPSCR).2 > $(HELPOUT)2 + +$(HELPOUT)3: $(HELP)3 $(HELPSCR).1 $(HELPSCR).2 + @echo building $(HELPOUT)3 + cat $(HELP)3 | sed -f $(HELPSCR).1 | sed -f $(HELPSCR).2 > $(HELPOUT)3 + +$(HELPOUT)4: $(HELP)4 $(HELPSCR).1 $(HELPSCR).2 + @echo building $(HELPOUT)4 + cat $(HELP)4 | sed -f $(HELPSCR).1 | sed -f $(HELPSCR).2 > $(HELPOUT)4 + +$(HELPOUT)5: $(HELP)5 $(HELPSCR).1 $(HELPSCR).2 + @echo building $(HELPOUT)5 + cat $(HELP)5 | sed -f $(HELPSCR).1 | sed -f $(HELPSCR).2 > $(HELPOUT)5 + +$(HELPSCR).1: newhelp + newhelp + +$(HELPSCR).2: newhelp + newhelp + +newhelp: dataG.o newhelp.o + $(CC) $(OPTFLG) dataG.o newhelp.o -o newhelp + strip newhelp +# +# postscript map program +PSOPTS = -DPSFILE=\"$(EXEDIR)/$(PSDATA)\" -D$(PSPAGE) +# +$(PSPROG): $(PSSRC) $(PSDATA) $(PSHEAD) + $(CC) $(OPTFLG) $(PSOPTS) $(PSSRC) -o $(PSPROG) +# comment out the next line if debugging + strip $(PSPROG) + +lint: + lint $(LTFLG) $(CDEFS) -DCONQUER $(GFILS) > lintg + lint $(LTFLG) $(CDEFS) -DADMIN $(AFILS) > linta + +docs: conquer.doc + +conquer.doc: $(HELPOUT)0 $(HELPOUT)1 $(HELPOUT)2 $(HELPOUT)3 $(HELPOUT)4 $(HELPOUT)5 + cat $(HELPOUT)? |sed -e "s/^DONE/ /g"|sed -e "s/^END//g" >conquer.doc + +cpio: + -$(RM) core + find . -name '*[CrpsEech]' -print | cpio -ocBv > cpiosv + +shar: + echo " lines words chars FILENAME" > MANIFEST + wc $(ALLFILS) >> MANIFEST + $(SHAR) $(SHARFLG) $(ALLFILS) MANIFEST + +.cA.o: $< + ( trap "" 0 1 2 3 4 ; $(LN) $*.c $*A.c ;\ + $(CC) $(OPTFLG) $(CDEFS) -DADMIN -c $*A.c ;\ + $(RM) $*A.c ) + +.cG.o: $< + ( trap "" 0 1 2 3 4 ; $(LN) $*.c $*G.c ;\ + $(CC) $(OPTFLG) $(CDEFS) -DCONQUER -c $*G.c ;\ + $(RM) $*G.c ) + +.c.o: $< +# compiles using both defines since they +# are needed for the data.h definitions for +# each file... but should not be needed for +# the actual C source file being compiled + $(CC) $(OPTFLG) $(CDEFS) -DADMIN -DCONQUER -c $*.c + +$(GOBJS): data.h header.h + +$(AOBJS): data.h header.h + +ioG.o: data.h header.h patchlevel.h io.c + +ioA.o: data.h header.h patchlevel.h io.c + +newlogin.o: data.h header.h newlogin.h patchlevel.h newlogin.c + +main.o: data.h header.h patchlevel.h main.c + +newhelp.o: data.h header.h patchlevel.h newhelp.c + +# Clear suffixes +# Commented out for problems with newer versions of make +#.SUFFIXES: + +# Suffixes for conquer files. +#.SUFFIXES: .c .o .cA.o .cG.o A.o G.o diff --git a/RELICENSING-PERMISSIONS.md b/gpl-release/RELICENSING-PERMISSIONS.md similarity index 100% rename from RELICENSING-PERMISSIONS.md rename to gpl-release/RELICENSING-PERMISSIONS.md diff --git a/WARNING.p11 b/gpl-release/WARNING.p11 similarity index 100% rename from WARNING.p11 rename to gpl-release/WARNING.p11 diff --git a/admin.c b/gpl-release/admin.c similarity index 100% rename from admin.c rename to gpl-release/admin.c diff --git a/cexecute.c b/gpl-release/cexecute.c similarity index 100% rename from cexecute.c rename to gpl-release/cexecute.c diff --git a/check.c b/gpl-release/check.c similarity index 100% rename from check.c rename to gpl-release/check.c diff --git a/combat.c b/gpl-release/combat.c similarity index 100% rename from combat.c rename to gpl-release/combat.c diff --git a/commands.c b/gpl-release/commands.c similarity index 100% rename from commands.c rename to gpl-release/commands.c diff --git a/data.c b/gpl-release/data.c similarity index 100% rename from data.c rename to gpl-release/data.c diff --git a/data.h b/gpl-release/data.h similarity index 100% rename from data.h rename to gpl-release/data.h diff --git a/display.c b/gpl-release/display.c similarity index 100% rename from display.c rename to gpl-release/display.c diff --git a/extcmds.c b/gpl-release/extcmds.c similarity index 100% rename from extcmds.c rename to gpl-release/extcmds.c diff --git a/forms.c b/gpl-release/forms.c similarity index 100% rename from forms.c rename to gpl-release/forms.c diff --git a/header.h b/gpl-release/header.h similarity index 100% rename from header.h rename to gpl-release/header.h diff --git a/io.c b/gpl-release/io.c similarity index 100% rename from io.c rename to gpl-release/io.c diff --git a/magic.c b/gpl-release/magic.c similarity index 100% rename from magic.c rename to gpl-release/magic.c diff --git a/main.c b/gpl-release/main.c similarity index 100% rename from main.c rename to gpl-release/main.c diff --git a/makeworl.c b/gpl-release/makeworl.c similarity index 100% rename from makeworl.c rename to gpl-release/makeworl.c diff --git a/man.pag b/gpl-release/man.pag similarity index 100% rename from man.pag rename to gpl-release/man.pag diff --git a/misc.c b/gpl-release/misc.c similarity index 100% rename from misc.c rename to gpl-release/misc.c diff --git a/move.c b/gpl-release/move.c similarity index 100% rename from move.c rename to gpl-release/move.c diff --git a/nations b/gpl-release/nations similarity index 100% rename from nations rename to gpl-release/nations diff --git a/navy.c b/gpl-release/navy.c similarity index 100% rename from navy.c rename to gpl-release/navy.c diff --git a/newhelp.c b/gpl-release/newhelp.c similarity index 100% rename from newhelp.c rename to gpl-release/newhelp.c diff --git a/newlogin.c b/gpl-release/newlogin.c similarity index 100% rename from newlogin.c rename to gpl-release/newlogin.c diff --git a/newlogin.h b/gpl-release/newlogin.h similarity index 100% rename from newlogin.h rename to gpl-release/newlogin.h diff --git a/notes.v4 b/gpl-release/notes.v4 similarity index 100% rename from notes.v4 rename to gpl-release/notes.v4 diff --git a/npc.c b/gpl-release/npc.c similarity index 100% rename from npc.c rename to gpl-release/npc.c diff --git a/patchlevel.h b/gpl-release/patchlevel.h similarity index 100% rename from patchlevel.h rename to gpl-release/patchlevel.h diff --git a/psmap.c b/gpl-release/psmap.c similarity index 100% rename from psmap.c rename to gpl-release/psmap.c diff --git a/psmap.h b/gpl-release/psmap.h similarity index 100% rename from psmap.h rename to gpl-release/psmap.h diff --git a/psmap.ps b/gpl-release/psmap.ps similarity index 100% rename from psmap.ps rename to gpl-release/psmap.ps diff --git a/randeven.c b/gpl-release/randeven.c similarity index 100% rename from randeven.c rename to gpl-release/randeven.c diff --git a/reports.c b/gpl-release/reports.c similarity index 100% rename from reports.c rename to gpl-release/reports.c diff --git a/rules b/gpl-release/rules similarity index 100% rename from rules rename to gpl-release/rules diff --git a/run b/gpl-release/run similarity index 100% rename from run rename to gpl-release/run diff --git a/sort.c b/gpl-release/sort.c similarity index 100% rename from sort.c rename to gpl-release/sort.c diff --git a/spew.c b/gpl-release/spew.c similarity index 100% rename from spew.c rename to gpl-release/spew.c diff --git a/trade.c b/gpl-release/trade.c similarity index 100% rename from trade.c rename to gpl-release/trade.c diff --git a/trade.h b/gpl-release/trade.h similarity index 100% rename from trade.h rename to gpl-release/trade.h diff --git a/txt0 b/gpl-release/txt0 similarity index 100% rename from txt0 rename to gpl-release/txt0 diff --git a/txt1 b/gpl-release/txt1 similarity index 100% rename from txt1 rename to gpl-release/txt1 diff --git a/txt2 b/gpl-release/txt2 similarity index 100% rename from txt2 rename to gpl-release/txt2 diff --git a/txt3 b/gpl-release/txt3 similarity index 100% rename from txt3 rename to gpl-release/txt3 diff --git a/txt4 b/gpl-release/txt4 similarity index 100% rename from txt4 rename to gpl-release/txt4 diff --git a/txt5 b/gpl-release/txt5 similarity index 100% rename from txt5 rename to gpl-release/txt5 diff --git a/update.c b/gpl-release/update.c similarity index 100% rename from update.c rename to gpl-release/update.c diff --git a/utilities/.gitignore b/gpl-release/utilities/.gitignore similarity index 100% rename from utilities/.gitignore rename to gpl-release/utilities/.gitignore diff --git a/utilities/.indent.pro b/gpl-release/utilities/.indent.pro similarity index 100% rename from utilities/.indent.pro rename to gpl-release/utilities/.indent.pro diff --git a/utilities/Makefile b/gpl-release/utilities/Makefile similarity index 100% rename from utilities/Makefile rename to gpl-release/utilities/Makefile diff --git a/utilities/README b/gpl-release/utilities/README similarity index 100% rename from utilities/README rename to gpl-release/utilities/README diff --git a/gpl-release/utilities/backup/Makefile.backup b/gpl-release/utilities/backup/Makefile.backup new file mode 100644 index 0000000..d0a8535 --- /dev/null +++ b/gpl-release/utilities/backup/Makefile.backup @@ -0,0 +1,132 @@ +# +SHELL=/bin/sh +SHAR=/usr/bin/shar +MAKE=/usr/bin/make + +# +# Will most likely have to edit the location of the +# X Libraries. +# +Libs_sun= -lpixrect +Libs_x= -L/usr/lib -lX11 + +WHICHconqrast: WHICHconqrast.o error.o WHICHstuff.o file.o util.o + cc $(CFLAGS) -o WHICHconqrast WHICHconqrast.o WHICHstuff.o file.o\ + util.o error.o $(Libs_WHICH) + +error.o: error.c +file.o: file.c +util.o:util.c + +WHICHconqrast.o: conqrast.c WHICHconqrast.h file.h ../header.h + $(CC) $(CFLAGS) -c conqrast.c -DHEADERFILE=\"WHICHconqrast.h\" + mv conqrast.o WHICHconqrast.o + +WHICHstuff.o: WHICHstuff.c WHICHconqrast.h + +lint.WHICH: + lint -abchx -DHEADERFILE=\"WHICHconqrast.h\" \ + conqrast.c WHICHstuff.c error.c file.c util.c $(Libs_WHICH) + +### don't delete this line! + +all: sunconqrast xconqrast + +lint: lint.sun lint.x + +lint.sun: makefile.sun + $(MAKE) $(MFLAGS) -f makefile.sun lint.sun + +lint.x: makefile.x + $(MAKE) $(MFLAGS) -f makefile.x lint.x + +sun sunconqrast: makefile.sun conqrast.c sunstuff.c sunconqrast.h file.c\ + file.h util.c + $(MAKE) $(MFLAGS) -f makefile.sun sunconqrast + +makefile.sun : Makefile + sed -e '/^###/q' -e '/WHICH/s//sun/g' Makefile > makefile.sun + +x xconqrast: makefile.x conqrast.c xstuff.c xconqrast.h file.c file.h util.c + $(MAKE) $(MFLAGS) -f makefile.x xconqrast + +makefile.x : Makefile + sed -e '/^###/q' -e '/WHICH/s//x/g' Makefile > makefile.x + +shar.core: conqrast.c + shar -c -v conqrast.c > shar.core + +shar.sun: sunstuff.c sunconqrast.h + shar -c -v sunstuff.c sunconqrast.h > shar.sun + +shar.x: xstuff.c xconqrast.h + shar -c -v xstuff.c xconqrast.h > shar.x + +shar.general: Makefile README error.c file.c file.h util.c conqrast.man + shar -c -v Makefile README conqrast.man error.c file.c file.h util.c > shar.general + +shar: shar.general shar.sun shar.x shar.core + +checkpoint: + cp Makefile README *.[ch] *.man old + /bin/rm *.diff newfiles difffiles + +clean: + /bin/rm -f *.o *.diff patch shar.* *~ "#*" makefile.* newfiles difffiles + +diffs: + echo -n >patch + -for i in old/* ; do \ + j=`basename $$i` ;\ + if diff -c $$i $$j > $$j.diff ;\ + then \ + /bin/rm $$j.diff ;\ + else \ + cat $$j.diff >> patch ;\ + wc $$j.diff ;\ + fi ;\ + done + +newfiles: + echo -n > newfiles + -for i in *.[ch1] ; do\ + if test -f old/$$i ; then\ + : ;\ + else \ + echo $$i >> newfiles ;\ + fi ;\ + done + +difffiles: newfiles diffs + echo -n > difffiles + -for i in *.diff ; do\ + j=`basename $$i .diff` ;\ + echo -n $$j ;\ + is=`wc $$i |colrm 9`;\ + js=`wc $$j |colrm 9`;\ + echo " " $$js $$is ;\ + if test $$is -gt $$js ; then \ + echo is very new! ;\ + echo $$j >> newfiles ;\ + else \ + echo is changed ;\ + echo $$i >> difffiles ;\ + fi ;\ + done + +update: newfiles difffiles + -n=1;for i in `cat difffiles` `cat newfiles` ; do \ + lines=`wc $$them $$i| tail -1 | colrm 9` ;\ + echo $$them $$i $$lines ;\ + if test $$lines -gt 800 ; then\ + echo chop! ;\ + $(SHAR) -c -v $$them > shar.$$n ;\ + n=`expr $$n + 1` ;\ + them="$$i" ;\ + else \ + them="$$them $$i" ;\ + fi ;\ + done ;\ + $(SHAR) -c -v $$them > shar.$$n + /bin/rm newfiles difffiles + diff --git a/gpl-release/utilities/backup/conqrast.c.backup b/gpl-release/utilities/backup/conqrast.c.backup new file mode 100644 index 0000000..1841507 --- /dev/null +++ b/gpl-release/utilities/backup/conqrast.c.backup @@ -0,0 +1,792 @@ +#include +#include +#include +#include "../header.h" +#include "file.h" +#include HEADERFILE + +/********************************************************************* +* * +* This program draws a map of the conquer world on a bitmap system * +* * +* Written by Richard Caley July 1989 and hacked extensively * +* thereafter. * +* * +* You may copy, distribute, modify or do what you will with this * +* code so long as this message remains in it and so long as you do * +* not charge for it, nor distribute the program without the source. * +* * +* There is a horrid hack for getpass - to make this read the * +* password from standard in one has to disconnect from the control * +* terminal. GAG! It should be possible to disconnect just the * +* conquer from the control terminal . . . someday. * +* * +* See Readme for more details. * +* * +*********************************************************************/ + +#define GAP (2) /* fudge factor - space above + * and below titles */ + +#define total_height (height*mag+ (do_title?4*GAP+2*font_height(titlefont):0)) + /* height of map and title bars */ + +#define yoffset(place) ((place)+(do_title?font_height(titlefont)+GAP+GAP:0)) + /* a y position */ + +#define tracef if(trace) printf + +char *getpass(); +void error(), ioerror(); +char *passwd=NULL; +char *nation=NULL; +int turn; +int trace=0; +int bg=0; +char conquer_version[100]; + +#define conqrast_version "1.0" + +#ifndef conqrast_name +# define conqrast_name "Some conqrast" /* this is redefined in the header */ +# define driver_version "unknown driver" +#endif + +#define HEADER_TAG "Conquer Version" /* just before first line of map */ +#define HEADER_TAG_LENGTH (sizeof(HEADER_TAG)/sizeof(char)-1) + +extern struct /* maps from size of map to the font */ + /* to use */ + { /* if size > mag use font */ + int mag; + char *romanfont,*boldfont; + } fonts[]; + +struct /* Maps from terrain to brightness */ + { + char c; + int val; /* must be between 0 and 255 */ + } values[] = + { + ' ', 256, + '~', 0, + '-', 64, + '%', 128, + '^', 192, + '#', 224, + '\0' + }; + +char *mapnames[] = + { + "This should never happen", + "Altitude", + "Vegetation", + "Nation", + "Designation" + }; + +#define num_mapnames (sizeof(mapnames)/sizeof(char *)) + +/********************************************************************* +* * +* Font mapping information. Fonts used by the system have symbolic * +* names so they can be referred to on the commend line. font_table * +* records which fonts go with which name. * +* * +*********************************************************************/ + +enum mapfont + { + f_nation, + f_designation, + f_title, + f_last + }; + +struct + { + char *name; + font romanfont; + font boldfont; + } font_table[(unsigned)f_last+1] = + { + {"nation"}, + {"designation"}, + {"title"}, + {NULL} + }; + +#define MAXDITHER 4 /* don't touch this */ + +short dit[1<= mag ) + break; + else if (fonts[i].mag < mag ) + { + if(bad_font(font_table[(unsigned)f].romanfont= + font_named(fonts[i].romanfont))) + error("Can't get font '%s' as %s font", + fonts[i].romanfont,font_table[(unsigned)f].name); + if ( font_table[(unsigned)f].boldfont==NULL && fonts[i].boldfont !=NULL) + if (bad_font(font_table[(unsigned)f].boldfont= + font_named(fonts[i].boldfont))) + error("Can't get font '%s' as bold %s font", + fonts[i].romanfont,font_table[(unsigned)f].name); + } + } + if(font_table[(unsigned)f].romanfont==NULL) + error("No font small enough for size %d %s",mag,font_table[(unsigned)f].name); + } + + } + +/********************************************************************* +* * +* Set up a single font. if the name is in the table ( or is a prefix * +* ) then insert the name into the font table. If the name begins * +* with 'b' then sets the bold font. * +* * +*********************************************************************/ + +void +set_a_font(name,fontname) + +char *name; +char *fontname; + +{ + int i,bold=0,l; + font thefont; + + if( name[0]=='b') + { + name++; + bold=1; + } + + l=strlen(name); + + for (i=0;i< (int)f_last;i++) + if (!strncmp(name,font_table[i].name,l)) + break; + + if ( i == (int)f_last) + error("Unknown font name '%s'",name); + + thefont=font_named(fontname); + + if ( bad_font(thefont) ) + error("Can't get font '%s'",fontname); + + if (bold) + font_table[i].boldfont=thefont; + else + font_table[i].romanfont=thefont; + } + +/********************************************************************* +* * +* scan over the header of the map. Returns the number of the map, or * +* 0 if the map is bad. If `pipe' is != 0 then the input is a pipe * +* and an eof implies a bad password. * +* * +* Tries to cope with DEBUG and none-DEBUG conquers * +* * +*********************************************************************/ + +scan_header(f,pipe) + +FILE *f; +int pipe; + +{ + char line[1024]; + char which[100]; + static char who[100]; + int mapid; + + while ( fgets(line,1024,f) != NULL) /* scan to top of map */ + { + if (!strncmp(line,HEADER_TAG,HEADER_TAG_LENGTH)) + break; + } + + if (feof(f)) + { + if(pipe) + error("Password incorrect"); + else + error("Unexpected end of map file"); + } + + if (sscanf(line,"Conquer Version %[0-9.] : %s Map %*s %*s %s on Turn %d",conquer_version,which,who,&turn)!=4) + error("Bad title line (wrong version?) '%s'",line); + + for(mapid=1;mapid < num_mapnames;mapid++) + if(!strcmp(mapnames[mapid],which)) + break; + + if ( mapid==num_mapnames) + mapid= 0; + else if ( trace && !pipe) + printf("Found %s map\n", which); + + if(!strcmp(who,"World")) + nation="god"; + else + nation=who; + + tracef("Nation is %s\n",nation); + + return mapid; + } + +/********************************************************************* +* * +* Find maps in a file and store away a file pointer and offset for * +* each * +* * +*********************************************************************/ + +void +process_map_file(name) + +char *name; + +{ + int which; + FILE *f; + char line[1024]; + + tracef("Searching file %s\n",name); + + if ((f=fopen(name,"r"))==NULL) + ioerror("Can't open map file '%s'",name); + + while(1) + { + long top; + + which=scan_header(f,0); + + if(which==0) + error("Bad map file '%s'",name); + + myopen(which,f); + top=ftell(f); + while(fgets(line,1024,f)!=NULL) + { + if (!strncmp(line,HEADER_TAG,HEADER_TAG_LENGTH)) + break; + top=ftell(f); + } + + if(feof(f)) + break; + + fseek(f,top,0); + } + } + +/********************************************************************* +* * +* Get a map. If the map was not in one of the files on the command * +* line it runs conquer -p to get it. * +* * +* Which selects the map. * +* Args are passed to conqrun. * +* Tmpname is the name of a temporary file to use. This is * +* deleted in this routine so you can reuse the name. * +* * +* All except `which' are ignored if the user has given a map * +* file of the correct type as an argumant. * +* * +*********************************************************************/ + +int +get_map_file(which,args,tmpname) + +int which; +char *args; +char *tmpname; + +{ + char command[100]; + FILE *tmp; + + if ( ! myisopen(which)) + { + if (nation==NULL) + { + tracef("Assuming god\n"); + + nation="god"; + } + + tracef("Asking conquer for %s map\n",mapnames[which]); + + if (passwd==NULL) + { + passwd=getpass("Enter conquer password: "); + } + + tracef("Disconnecting ( HACK! ) bye bye\n"); + + disconnect(); /* disconnect from controling tty */ + /* ( hack for getpass ) */ + + if (bg) /* go into background if asked */ + { + tracef("Going into background\n"); + + background(); + } + + sprintf(command,"conquer -p %s > %s 2>/dev/null",args,tmpname); + + if((tmp=popen(command,"w"))==NULL) + ioerror("can't run conquer"); + + if (fprintf(tmp,"%s\n%s\n%c\n",nation,passwd, which+'0')==EOF) + error("Couldn't get map. Conquer may be updating.\n"); + + pclose(tmp); + + if((tmp=fopen(tmpname,"r"))==NULL) + ioerror("can't open %s",tmpname); + + unlink(tmpname); /* delete it */ + + (void)scan_header(tmp,1); + myopen(which,tmp); + } + + return which; + } + +/*ARGSUSED*/ +main(argc,argv) + +int argc; +char *argv[]; + +{ + char line[1024]; + char desline[1024]; + char tmpname[20]; + char args[100]; + char *screen_name=get_default_screen_name(); + screen_type screen=NULL; + int mapfile; + int destmapfile; + int mag=11; + bitmap pr; + int width,height; + extern char *myname; + int x,y,i,j,val; + char c; + char *mapname=NULL; + char *world=NULL; + int do_nations=0,barbarians=0,markbarbs=0; + int all=0,live=0,altitude=1; + int desig=0; + int do_title=1; + font titlefont; + int boldtitle=0; /* indicates that the title font should be + emboldened - ie `titlefont' is roman and + so _we_ must do the bold */ + + + myname=argv[0]; + + strcpy(args,""); + + while(*(++argv)!=NULL) + if (!strncmp(*argv,"-o",2)) + { + mapname= *(++argv); + if ( is_screenname(mapname)) + { + screen_name=mapname; + mapname=NULL; + } + } + else if (!strcmp(*argv,"-l")) + live++; + else if (!strcmp(*argv,"-D")) + sprintf(args,"%s -d %s",args,world= *(++argv)); + else if (!strcmp(*argv,"-N")) + nation= *(++argv); + else if (!strcmp(*argv,"-bg")) + bg++; + else if (!strcmp(*argv,"-a")) + altitude=0; + else if (!strcmp(*argv,"-f")) + { + char *which= *(++argv), *fontname= *(++argv); + set_a_font(which,fontname); + } + else if (!strncmp(*argv,"-b",2)) + { + barbarians++; + if ( (*argv)[2]=='a') + markbarbs++; + } + else if (!strcmp(*argv,"-m")) + mag=atoi(*(++argv)); + else if (!strncmp(*argv,"-c",2)) + { + c=(*argv)[2]; + for (i=0;;i++) + { + if (values[i].c =='\0') + error("Unknown contour '%c'",c); + else if ( values[i].c == c) + { + values[i].val=atoi(*(++argv)); + break; + } + } + } + else if (!strncmp(*argv,"-n",2)) + { + do_nations++; + if ( (*argv)[2]=='a') + ++all; + } + else if (!strncmp(*argv,"-d",2)) + { + desig++; + } + else if (!strcmp(*argv,"-h")) + help_message(myname); + else if (!strcmp(*argv,"-t")) + do_title=0; + else if (!strcmp(*argv,"-v")) + trace++; + else if ( (*argv)[0]=='-') + { + printf("Unknown option '%s'\n",*argv); + help_message(myname); + } + else + process_map_file(*argv); + + if (do_nations) /* if we have to put in nations */ + set_default_fonts(mag,f_nation); + + if (desig) + { + if (all) + error("Only one of -d and -na allowed!"); + + set_default_fonts(mag,f_designation); + } + + if (do_title) + { + set_default_fonts(mag+2,f_title); + if ( (titlefont=font_table[(unsigned)f_title].boldfont)==NULL) + { + boldtitle=1; + titlefont=font_table[(unsigned)f_title].romanfont; + } + + } + + screen=screen_named(screen_name); + + sprintf(tmpname,"/tmp/conq%d",getpid()); + + mapfile=get_map_file(altitude?1:3, /* get a map */ + args,tmpname); + + if(mygets(line,1024,mapfile)==NULL) + error("empty map!"); + + width=strlen(line)-1; /* count height and width */ + + for(height=1;mygets(line,1024,mapfile)!=NULL;height++) + if(!strncmp(line,HEADER_TAG,HEADER_TAG_LENGTH)|| + !strncmp(line,"reading",7)) + break; + + tracef("Size %d X %d, image %d X %d\n",width,height,width*mag,height*mag); + + initialise_bitmaps(); + + if(live) /* if live do it on the screen */ + { + if ((pr=get_screen_bitmap(screen))==(bitmap)NULL) + ioerror("Can't open screen %s",screen_name); + } + else /* otherwise in memory */ + pr=create_bitmap(width*mag,total_height); + + myrewind(mapfile); + + if (altitude) /* if needed do altitude */ + { + int xx,yy; + tracef("Drawing topography\n"); + + build_dither_matrix(MAXDITHER); + + yy=yoffset(0); + for(y=0;y=val?1:0); + } + } + } + + myclose(mapfile); + } + + if(do_nations||desig) /* nations */ + { + font nf, bnf; + font df; + int xx,yy; + char des, + current='\0'; /* keeps track of which nation we are in */ + char last[1024]; /* ditto vertically for each column */ + + tracef("Drawing nations\n"); + + if (do_nations) + { + nf = font_table[(unsigned)f_nation].romanfont; + bnf = font_table[(unsigned)f_nation].boldfont; + } + + if (desig) + { + df = font_table[(unsigned)f_designation].romanfont; + } + + if (altitude) /* if no altitude this was gotten to */ + /* count the size */ + mapfile=get_map_file(3,args,tmpname); + + destmapfile=get_map_file(4,args,tmpname); + + yy=yoffset(mag); + for(y=0;y. + */ + +#include +#include +#include +#include "../header.h" +#include "file.h" +#include HEADERFILE + +/********************************************************************* +* * +* This program draws a map of the conquer world on a bitmap system * +* * +* Written by Richard Caley July 1989 and hacked extensively * +* thereafter. * +* * +* You may copy, distribute, modify or do what you will with this * +* code so long as this message remains in it and so long as you do * +* not charge for it, nor distribute the program without the source. * +* * +* There is a horrid hack for getpass - to make this read the * +* password from standard in one has to disconnect from the control * +* terminal. GAG! It should be possible to disconnect just the * +* conquer from the control terminal . . . someday. * +* * +* See Readme for more details. * +* * +*********************************************************************/ + +#define GAP (2) /* fudge factor - space above + * and below titles */ + +#define total_height (height*mag+ (do_title?4*GAP+2*font_height(titlefont):0)) + /* height of map and title bars */ + +#define yoffset(place) ((place)+(do_title?font_height(titlefont)+GAP+GAP:0)) + /* a y position */ + +#define tracef if(trace) printf + +char *getpass(); +void error(), ioerror(); +char *passwd=NULL; +char *nation=NULL; +int turn; +int trace=0; +int bg=0; +char conquer_version[100]; + +#define conqrast_version "1.0" + +#ifndef conqrast_name +# define conqrast_name "Some conqrast" /* this is redefined in the header */ +# define driver_version "unknown driver" +#endif + +#define HEADER_TAG "Conquer Version" /* just before first line of map */ +#define HEADER_TAG_LENGTH (sizeof(HEADER_TAG)/sizeof(char)-1) + +extern struct /* maps from size of map to the font */ + /* to use */ + { /* if size > mag use font */ + int mag; + char *romanfont,*boldfont; + } fonts[]; + +struct /* Maps from terrain to brightness */ + { + char c; + int val; /* must be between 0 and 255 */ + } values[] = + { + ' ', 256, + '~', 0, + '-', 64, + '%', 128, + '^', 192, + '#', 224, + '\0' + }; + +char *mapnames[] = + { + "This should never happen", + "Altitude", + "Vegetation", + "Nation", + "Designation" + }; + +#define num_mapnames (sizeof(mapnames)/sizeof(char *)) + +/********************************************************************* +* * +* Font mapping information. Fonts used by the system have symbolic * +* names so they can be referred to on the commend line. font_table * +* records which fonts go with which name. * +* * +*********************************************************************/ + +enum mapfont + { + f_nation, + f_designation, + f_title, + f_last + }; + +struct + { + char *name; + font romanfont; + font boldfont; + } font_table[(unsigned)f_last+1] = + { + {"nation"}, + {"designation"}, + {"title"}, + {NULL} + }; + +#define MAXDITHER 4 /* don't touch this */ + +short dit[1<= mag ) + break; + else if (fonts[i].mag < mag ) + { + if(bad_font(font_table[(unsigned)f].romanfont= + font_named(fonts[i].romanfont))) + error("Can't get font '%s' as %s font", + fonts[i].romanfont,font_table[(unsigned)f].name); + if ( font_table[(unsigned)f].boldfont==NULL && fonts[i].boldfont !=NULL) + if (bad_font(font_table[(unsigned)f].boldfont= + font_named(fonts[i].boldfont))) + error("Can't get font '%s' as bold %s font", + fonts[i].romanfont,font_table[(unsigned)f].name); + } + } + if(font_table[(unsigned)f].romanfont==NULL) + error("No font small enough for size %d %s",mag,font_table[(unsigned)f].name); + } + + } + +/********************************************************************* +* * +* Set up a single font. if the name is in the table ( or is a prefix * +* ) then insert the name into the font table. If the name begins * +* with 'b' then sets the bold font. * +* * +*********************************************************************/ + +void +set_a_font(name,fontname) + +char *name; +char *fontname; + +{ + int i,bold=0,l; + font thefont; + + if( name[0]=='b') + { + name++; + bold=1; + } + + l=strlen(name); + + for (i=0;i< (int)f_last;i++) + if (!strncmp(name,font_table[i].name,l)) + break; + + if ( i == (int)f_last) + error("Unknown font name '%s'",name); + + thefont=font_named(fontname); + + if ( bad_font(thefont) ) + error("Can't get font '%s'",fontname); + + if (bold) + font_table[i].boldfont=thefont; + else + font_table[i].romanfont=thefont; + } + +/********************************************************************* +* * +* scan over the header of the map. Returns the number of the map, or * +* 0 if the map is bad. If `pipe' is != 0 then the input is a pipe * +* and an eof implies a bad password. * +* * +* Tries to cope with DEBUG and none-DEBUG conquers * +* * +*********************************************************************/ + +scan_header(f,pipe) + +FILE *f; +int pipe; + +{ + char line[1024]; + char which[100]; + static char who[100]; + int mapid; + + while ( fgets(line,1024,f) != NULL) /* scan to top of map */ + { + if (!strncmp(line,HEADER_TAG,HEADER_TAG_LENGTH)) + break; + } + + if (feof(f)) + { + if(pipe) + error("Password incorrect"); + else + error("Unexpected end of map file"); + } + + if (sscanf(line,"Conquer Version %[0-9.] : %s Map %*s %*s %s on Turn %d",conquer_version,which,who,&turn)!=4) + error("Bad title line (wrong version?) '%s'",line); + + for(mapid=1;mapid < num_mapnames;mapid++) + if(!strcmp(mapnames[mapid],which)) + break; + + if ( mapid==num_mapnames) + mapid= 0; + else if ( trace && !pipe) + printf("Found %s map\n", which); + + if(!strcmp(who,"World")) + nation="god"; + else + nation=who; + + tracef("Nation is %s\n",nation); + + return mapid; + } + +/********************************************************************* +* * +* Find maps in a file and store away a file pointer and offset for * +* each * +* * +*********************************************************************/ + +void +process_map_file(name) + +char *name; + +{ + int which; + FILE *f; + char line[1024]; + + tracef("Searching file %s\n",name); + + if ((f=fopen(name,"r"))==NULL) + ioerror("Can't open map file '%s'",name); + + while(1) + { + long top; + + which=scan_header(f,0); + + if(which==0) + error("Bad map file '%s'",name); + + myopen(which,f); + top=ftell(f); + while(fgets(line,1024,f)!=NULL) + { + if (!strncmp(line,HEADER_TAG,HEADER_TAG_LENGTH)) + break; + top=ftell(f); + } + + if(feof(f)) + break; + + fseek(f,top,0); + } + } + +/********************************************************************* +* * +* Get a map. If the map was not in one of the files on the command * +* line it runs conquer -p to get it. * +* * +* Which selects the map. * +* Args are passed to conqrun. * +* Tmpname is the name of a temporary file to use. This is * +* deleted in this routine so you can reuse the name. * +* * +* All except `which' are ignored if the user has given a map * +* file of the correct type as an argumant. * +* * +*********************************************************************/ + +int +get_map_file(which,args,tmpname) + +int which; +char *args; +char *tmpname; + +{ + char command[100]; + FILE *tmp; + + if ( ! myisopen(which)) + { + if (nation==NULL) + { + tracef("Assuming god\n"); + + nation="god"; + } + + tracef("Asking conquer for %s map\n",mapnames[which]); + + if (passwd==NULL) + { + passwd=getpass("Enter conquer password: "); + } + + tracef("Disconnecting ( HACK! ) bye bye\n"); + + disconnect(); /* disconnect from controling tty */ + /* ( hack for getpass ) */ + + if (bg) /* go into background if asked */ + { + tracef("Going into background\n"); + + background(); + } + + sprintf(command,"conquer -p %s > %s 2>/dev/null",args,tmpname); + + if((tmp=popen(command,"w"))==NULL) + ioerror("can't run conquer"); + + if (fprintf(tmp,"%s\n%s\n%c\n",nation,passwd, which+'0')==EOF) + error("Couldn't get map. Conquer may be updating.\n"); + + pclose(tmp); + + if((tmp=fopen(tmpname,"r"))==NULL) + ioerror("can't open %s",tmpname); + + unlink(tmpname); /* delete it */ + + (void)scan_header(tmp,1); + myopen(which,tmp); + } + + return which; + } + +/*ARGSUSED*/ +main(argc,argv) + +int argc; +char *argv[]; + +{ + char line[1024]; + char desline[1024]; + char tmpname[20]; + char args[100]; + char *screen_name=get_default_screen_name(); + screen_type screen=NULL; + int mapfile; + int destmapfile; + int mag=11; + bitmap pr; + int width,height; + extern char *myname; + int x,y,i,j,val; + char c; + char *mapname=NULL; + char *world=NULL; + int do_nations=0,barbarians=0,markbarbs=0; + int all=0,live=0,altitude=1; + int desig=0; + int do_title=1; + font titlefont; + int boldtitle=0; /* indicates that the title font should be + emboldened - ie `titlefont' is roman and + so _we_ must do the bold */ + + + myname=argv[0]; + + strcpy(args,""); + + while(*(++argv)!=NULL) + if (!strncmp(*argv,"-o",2)) + { + mapname= *(++argv); + if ( is_screenname(mapname)) + { + screen_name=mapname; + mapname=NULL; + } + } + else if (!strcmp(*argv,"-l")) + live++; + else if (!strcmp(*argv,"-D")) + sprintf(args,"%s -d %s",args,world= *(++argv)); + else if (!strcmp(*argv,"-N")) + nation= *(++argv); + else if (!strcmp(*argv,"-bg")) + bg++; + else if (!strcmp(*argv,"-a")) + altitude=0; + else if (!strcmp(*argv,"-f")) + { + char *which= *(++argv), *fontname= *(++argv); + set_a_font(which,fontname); + } + else if (!strncmp(*argv,"-b",2)) + { + barbarians++; + if ( (*argv)[2]=='a') + markbarbs++; + } + else if (!strcmp(*argv,"-m")) + mag=atoi(*(++argv)); + else if (!strncmp(*argv,"-c",2)) + { + c=(*argv)[2]; + for (i=0;;i++) + { + if (values[i].c =='\0') + error("Unknown contour '%c'",c); + else if ( values[i].c == c) + { + values[i].val=atoi(*(++argv)); + break; + } + } + } + else if (!strncmp(*argv,"-n",2)) + { + do_nations++; + if ( (*argv)[2]=='a') + ++all; + } + else if (!strncmp(*argv,"-d",2)) + { + desig++; + } + else if (!strcmp(*argv,"-h")) + help_message(myname); + else if (!strcmp(*argv,"-t")) + do_title=0; + else if (!strcmp(*argv,"-v")) + trace++; + else if ( (*argv)[0]=='-') + { + printf("Unknown option '%s'\n",*argv); + help_message(myname); + } + else + process_map_file(*argv); + + if (do_nations) /* if we have to put in nations */ + set_default_fonts(mag,f_nation); + + if (desig) + { + if (all) + error("Only one of -d and -na allowed!"); + + set_default_fonts(mag,f_designation); + } + + if (do_title) + { + set_default_fonts(mag+2,f_title); + if ( (titlefont=font_table[(unsigned)f_title].boldfont)==NULL) + { + boldtitle=1; + titlefont=font_table[(unsigned)f_title].romanfont; + } + + } + + screen=screen_named(screen_name); + + sprintf(tmpname,"/tmp/conq%d",getpid()); + + mapfile=get_map_file(altitude?1:3, /* get a map */ + args,tmpname); + + if(mygets(line,1024,mapfile)==NULL) + error("empty map!"); + + width=strlen(line)-1; /* count height and width */ + + for(height=1;mygets(line,1024,mapfile)!=NULL;height++) + if(!strncmp(line,HEADER_TAG,HEADER_TAG_LENGTH)|| + !strncmp(line,"reading",7)) + break; + + tracef("Size %d X %d, image %d X %d\n",width,height,width*mag,height*mag); + + initialise_bitmaps(); + + if(live) /* if live do it on the screen */ + { + if ((pr=get_screen_bitmap(screen))==(bitmap)NULL) + ioerror("Can't open screen %s",screen_name); + } + else /* otherwise in memory */ + pr=create_bitmap(width*mag,total_height); + + myrewind(mapfile); + + if (altitude) /* if needed do altitude */ + { + int xx,yy; + tracef("Drawing topography\n"); + + build_dither_matrix(MAXDITHER); + + yy=yoffset(0); + for(y=0;y=val?1:0); + } + } + } + + myclose(mapfile); + } + + if(do_nations||desig) /* nations */ + { + font nf, bnf; + font df; + int xx,yy; + char des, + current='\0'; /* keeps track of which nation we are in */ + char last[1024]; /* ditto vertically for each column */ + + tracef("Drawing nations\n"); + + if (do_nations) + { + nf = font_table[(unsigned)f_nation].romanfont; + bnf = font_table[(unsigned)f_nation].boldfont; + } + + if (desig) + { + df = font_table[(unsigned)f_designation].romanfont; + } + + if (altitude) /* if no altitude this was gotten to */ + /* count the size */ + mapfile=get_map_file(3,args,tmpname); + + destmapfile=get_map_file(4,args,tmpname); + + yy=yoffset(mag); + for(y=0;y +#include +#include + +/* int errno; */ +/* char *sys_errlist[]; */ + +char *myname="Someone"; + +/*VARARGS1*/ +void +ioerror(str,arg1,arg2,arg3) + +char *str; +int arg1, arg2, arg3; + +{ +fprintf(stderr,"%s: ",myname); +fprintf(stderr,str,arg1,arg2,arg3); +fprintf(stderr," - %s\n",sys_errlist[errno]); +exit(1); +} + +/*VARARGS1*/ +void +error(str,arg1,arg2,arg3) + +char *str; +int arg1, arg2, arg3; + +{ +fprintf(stderr,"%s: ",myname); +fprintf(stderr,str,arg1,arg2,arg3); +fputc('\n',stderr); +exit(1); +} + diff --git a/gpl-release/utilities/backup/error.c.bak b/gpl-release/utilities/backup/error.c.bak new file mode 100644 index 0000000..c6ce34f --- /dev/null +++ b/gpl-release/utilities/backup/error.c.bak @@ -0,0 +1,58 @@ +/* + * error.c - Game functionality module + * + * This file is part of Conquer. + * Originally Copyright (C) 1988-1989 by Edward M. Barlow and Adam Bryant + * Copyright (C) 2024 [Your Name] - Licensed under GPL v3 with permission from original authors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include + +/* int errno; */ +/* char *sys_errlist[]; */ + +char *myname="Someone"; + +/*VARARGS1*/ +void +ioerror(str,arg1,arg2,arg3) + +char *str; +int arg1, arg2, arg3; + +{ +fprintf(stderr,"%s: ",myname); +fprintf(stderr,str,arg1,arg2,arg3); +fprintf(stderr," - %s\n",sys_errlist[errno]); +exit(1); +} + +/*VARARGS1*/ +void +error(str,arg1,arg2,arg3) + +char *str; +int arg1, arg2, arg3; + +{ +fprintf(stderr,"%s: ",myname); +fprintf(stderr,str,arg1,arg2,arg3); +fputc('\n',stderr); +exit(1); +} + diff --git a/gpl-release/utilities/backup/file.c.backup b/gpl-release/utilities/backup/file.c.backup new file mode 100644 index 0000000..0f9e948 --- /dev/null +++ b/gpl-release/utilities/backup/file.c.backup @@ -0,0 +1,90 @@ +#include +#include "file.h" + +/********************************************************************* +* * +* All the my* routines mimic stdio routines but manipulate struct * +* file's The point is that we can read from and otherwise manipulate * +* more than one place in a file ( for more than one map ). * +* * +*********************************************************************/ + +/********************************************************************* +* * +* struct file's play the roll of FILE *'s * +* * +*********************************************************************/ + +#define MAX_FILES 10 + +static struct file + { + FILE *fd; /* which file */ + long offset, /* where are we reading from now */ + top; /* where is the notional start */ + } file_table[MAX_FILES]; + + +void +myopen(which,file) + +int which; +FILE *file; + +{ +file_table[which].fd=file; +file_table[which].offset=file_table[which].top=ftell(file); +} + +myisopen(which) + +int which; + +{ +return file_table[which].fd != NULL; +} + +char * +mygets(buffer,num,which) + +char *buffer; +int num; +int which; +{ + fseek(file_table[which].fd,file_table[which].offset,0); + + buffer=fgets(buffer,num,file_table[which].fd); + + file_table[which].offset=ftell(file_table[which].fd); + + return buffer; + } + +void +myrewind(which) + +int which; + +{ + fseek(file_table[which].fd,file_table[which].top,0); + file_table[which].offset=file_table[which].top; + } + +void +myclose(which) + +int which; + +{ + int i; + + for(i=0;i. + */ + +#include +#include "file.h" + +/********************************************************************* +* * +* All the my* routines mimic stdio routines but manipulate struct * +* file's The point is that we can read from and otherwise manipulate * +* more than one place in a file ( for more than one map ). * +* * +*********************************************************************/ + +/********************************************************************* +* * +* struct file's play the roll of FILE *'s * +* * +*********************************************************************/ + +#define MAX_FILES 10 + +static struct file + { + FILE *fd; /* which file */ + long offset, /* where are we reading from now */ + top; /* where is the notional start */ + } file_table[MAX_FILES]; + + +void +myopen(which,file) + +int which; +FILE *file; + +{ +file_table[which].fd=file; +file_table[which].offset=file_table[which].top=ftell(file); +} + +myisopen(which) + +int which; + +{ +return file_table[which].fd != NULL; +} + +char * +mygets(buffer,num,which) + +char *buffer; +int num; +int which; +{ + fseek(file_table[which].fd,file_table[which].offset,0); + + buffer=fgets(buffer,num,file_table[which].fd); + + file_table[which].offset=ftell(file_table[which].fd); + + return buffer; + } + +void +myrewind(which) + +int which; + +{ + fseek(file_table[which].fd,file_table[which].top,0); + file_table[which].offset=file_table[which].top; + } + +void +myclose(which) + +int which; + +{ + int i; + + for(i=0;i + +typedef struct pixrect * bitmap; +typedef char * screen_type; +typedef struct pixfont * font; + +#define initialise_bitmaps() /* EMPTY */ +#define finish_bitmaps() /* EMPTY */ + +#define is_screenname(mapname) (!strncmp(mapname,"/dev/",5)) +#define get_default_screen_name() "/dev/fb" +#define screen_named(name) (name) +#define get_screen_bitmap(screen) (pr_open(screen)) +#define create_bitmap(width,height) (mem_create(width,height,1)) +#define destroy_bitmap(bitmap) pr_close(bitmap) +#define font_named(name) pf_open(name) +#define bad_font(font) ((font)==NULL) +#define font_height(font) ((font->pf_defaultsize).y) +#define font_width(font) ((font->pf_defaultsize).x) +#define font_baseline(font) (0-(font->pf_char)['A'].pc_home.y+1) + +#define BLACK PIX_SET +#define WHITE PIX_CLR +#define DRAW_BLACK (PIX_DST|PIX_SRC) +#define DRAW_WHITE (PIX_DST&PIX_NOT(PIX_SRC)) + +#define set_bit(bitmap,x,y,val) pr_put(bitmap,x,y,val) +#define draw_line(bitmap,x1,y1,x2,y2,colour) pr_vector(bitmap,x1,y1,x2,y2,colour,0) diff --git a/gpl-release/utilities/backup/sunconqrast.h.bak b/gpl-release/utilities/backup/sunconqrast.h.bak new file mode 100644 index 0000000..c4f9e22 --- /dev/null +++ b/gpl-release/utilities/backup/sunconqrast.h.bak @@ -0,0 +1,52 @@ +/* + * sunconqrast.h - Header file with definitions and prototypes + * + * This file is part of Conquer. + * Originally Copyright (C) 1988-1989 by Edward M. Barlow and Adam Bryant + * Copyright (C) 2024 [Your Name] - Licensed under GPL v3 with permission from original authors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#define driver_version "1" +#define conqrast_name "Sunconqrast" + +#include + +typedef struct pixrect * bitmap; +typedef char * screen_type; +typedef struct pixfont * font; + +#define initialise_bitmaps() /* EMPTY */ +#define finish_bitmaps() /* EMPTY */ + +#define is_screenname(mapname) (!strncmp(mapname,"/dev/",5)) +#define get_default_screen_name() "/dev/fb" +#define screen_named(name) (name) +#define get_screen_bitmap(screen) (pr_open(screen)) +#define create_bitmap(width,height) (mem_create(width,height,1)) +#define destroy_bitmap(bitmap) pr_close(bitmap) +#define font_named(name) pf_open(name) +#define bad_font(font) ((font)==NULL) +#define font_height(font) ((font->pf_defaultsize).y) +#define font_width(font) ((font->pf_defaultsize).x) +#define font_baseline(font) (0-(font->pf_char)['A'].pc_home.y+1) + +#define BLACK PIX_SET +#define WHITE PIX_CLR +#define DRAW_BLACK (PIX_DST|PIX_SRC) +#define DRAW_WHITE (PIX_DST&PIX_NOT(PIX_SRC)) + +#define set_bit(bitmap,x,y,val) pr_put(bitmap,x,y,val) +#define draw_line(bitmap,x1,y1,x2,y2,colour) pr_vector(bitmap,x1,y1,x2,y2,colour,0) diff --git a/gpl-release/utilities/backup/sunstuff.c.backup b/gpl-release/utilities/backup/sunstuff.c.backup new file mode 100644 index 0000000..f8a5921 --- /dev/null +++ b/gpl-release/utilities/backup/sunstuff.c.backup @@ -0,0 +1,93 @@ +#include +#include "sunconqrast.h" + +struct /* maps from size of map to the font */ + /* to use */ + { /* if size > mag use font */ + int mag; + char *font,*bold; + } fonts[] = + { + 9, "/usr/lib/fonts/fixedwidthfonts/screen.r.7", NULL, + 11, "/usr/lib/fonts/fixedwidthfonts/cour.r.10", + "/usr/lib/fonts/fixedwidthfonts/cour.b.10", + 12, "/usr/lib/fonts/fixedwidthfonts/cour.r.12", + "/usr/lib/fonts/fixedwidthfonts/cour.b.12", + 14, "/usr/lib/fonts/fixedwidthfonts/cour.r.14", + "/usr/lib/fonts/fixedwidthfonts/cour.b.14", + 16, "/usr/lib/fonts/fixedwidthfonts/cour.r.16", + "/usr/lib/fonts/fixedwidthfonts/cour.b.16", + 18, "/usr/lib/fonts/fixedwidthfonts/cour.r.18", + "/usr/lib/fonts/fixedwidthfonts/cour.b.18", + 22, "/usr/lib/fonts/fixedwidthfonts/cour.r.24", + "/usr/lib/fonts/fixedwidthfonts/cour.b.24", + 999999, NULL + }; + +static int encoding_type = RT_STANDARD ; + +int +argument_parse(argv) + +char *argv[]; + +{ +if ( !strcmp(*argv,"-compact")) + { + encoding_type = RT_BYTE_ENCODED ; + return 1; + } +else + return 0; +} + +/*ARGSUSED*/ +int +write_bitmap(bm,file,width,height) + +bitmap bm; +char *file; +int width,height; + +{ + FILE *f; + + if ((f=fopen(file,"w"))==NULL) + ioerror("Can't open output file %s",file); + + return pr_dump( bm, f, RMT_NONE, encoding_type,0); + } + + + +void +display_bitmap(bm,x,y,w,h) + +bitmap bm; +int x,y,w,h; + +{ + struct pixrect *screen=pr_open("/dev/fb"); + + pr_rop(screen,x,y,w,h,PIX_SRC,bm,0,0); + + } + +bitmap_text(pr,x,y,colour,pf,str) + +bitmap pr; +int x,y; +int colour; +font pf; +char *str; + +{ + struct pr_prpos pos; + + pos.pos.x=x; + pos.pos.y=y; + pos.pr=pr; + + pf_text(pos,colour,pf,str); + } + diff --git a/gpl-release/utilities/backup/sunstuff.c.bak b/gpl-release/utilities/backup/sunstuff.c.bak new file mode 100644 index 0000000..bf86175 --- /dev/null +++ b/gpl-release/utilities/backup/sunstuff.c.bak @@ -0,0 +1,114 @@ +/* + * sunstuff.c - Game functionality module + * + * This file is part of Conquer. + * Originally Copyright (C) 1988-1989 by Edward M. Barlow and Adam Bryant + * Copyright (C) 2024 [Your Name] - Licensed under GPL v3 with permission from original authors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include "sunconqrast.h" + +struct /* maps from size of map to the font */ + /* to use */ + { /* if size > mag use font */ + int mag; + char *font,*bold; + } fonts[] = + { + 9, "/usr/lib/fonts/fixedwidthfonts/screen.r.7", NULL, + 11, "/usr/lib/fonts/fixedwidthfonts/cour.r.10", + "/usr/lib/fonts/fixedwidthfonts/cour.b.10", + 12, "/usr/lib/fonts/fixedwidthfonts/cour.r.12", + "/usr/lib/fonts/fixedwidthfonts/cour.b.12", + 14, "/usr/lib/fonts/fixedwidthfonts/cour.r.14", + "/usr/lib/fonts/fixedwidthfonts/cour.b.14", + 16, "/usr/lib/fonts/fixedwidthfonts/cour.r.16", + "/usr/lib/fonts/fixedwidthfonts/cour.b.16", + 18, "/usr/lib/fonts/fixedwidthfonts/cour.r.18", + "/usr/lib/fonts/fixedwidthfonts/cour.b.18", + 22, "/usr/lib/fonts/fixedwidthfonts/cour.r.24", + "/usr/lib/fonts/fixedwidthfonts/cour.b.24", + 999999, NULL + }; + +static int encoding_type = RT_STANDARD ; + +int +argument_parse(argv) + +char *argv[]; + +{ +if ( !strcmp(*argv,"-compact")) + { + encoding_type = RT_BYTE_ENCODED ; + return 1; + } +else + return 0; +} + +/*ARGSUSED*/ +int +write_bitmap(bm,file,width,height) + +bitmap bm; +char *file; +int width,height; + +{ + FILE *f; + + if ((f=fopen(file,"w"))==NULL) + ioerror("Can't open output file %s",file); + + return pr_dump( bm, f, RMT_NONE, encoding_type,0); + } + + + +void +display_bitmap(bm,x,y,w,h) + +bitmap bm; +int x,y,w,h; + +{ + struct pixrect *screen=pr_open("/dev/fb"); + + pr_rop(screen,x,y,w,h,PIX_SRC,bm,0,0); + + } + +bitmap_text(pr,x,y,colour,pf,str) + +bitmap pr; +int x,y; +int colour; +font pf; +char *str; + +{ + struct pr_prpos pos; + + pos.pos.x=x; + pos.pos.y=y; + pos.pr=pr; + + pf_text(pos,colour,pf,str); + } + diff --git a/gpl-release/utilities/backup/util.c.backup b/gpl-release/utilities/backup/util.c.backup new file mode 100644 index 0000000..54c7548 --- /dev/null +++ b/gpl-release/utilities/backup/util.c.backup @@ -0,0 +1,112 @@ +#include +#include +#include + +/********************************************************************* +* * +* various utility bits split off to try and get conqrast.c down to a * +* reasonable size * +* * +*********************************************************************/ + + +/********************************************************************* +* * +* routine to build the dither matrix used to shade * +* * +*********************************************************************/ + +#define MAXDITHER 4 /* don't touch this */ + +short dit[1<\n",me); + printf("\t\t-N \n"); + printf("\t\t-D \n"); + printf("\t\t-c \n"); + printf("\t\t-f \n"); + printf("\t\t-d -n{a} -b{a} -m -a -bg -l -t -v\n"); + exit(1); + } + diff --git a/gpl-release/utilities/backup/util.c.bak b/gpl-release/utilities/backup/util.c.bak new file mode 100644 index 0000000..7681da2 --- /dev/null +++ b/gpl-release/utilities/backup/util.c.bak @@ -0,0 +1,133 @@ +/* + * util.c - Game functionality module + * + * This file is part of Conquer. + * Originally Copyright (C) 1988-1989 by Edward M. Barlow and Adam Bryant + * Copyright (C) 2024 [Your Name] - Licensed under GPL v3 with permission from original authors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include + +/********************************************************************* +* * +* various utility bits split off to try and get conqrast.c down to a * +* reasonable size * +* * +*********************************************************************/ + + +/********************************************************************* +* * +* routine to build the dither matrix used to shade * +* * +*********************************************************************/ + +#define MAXDITHER 4 /* don't touch this */ + +short dit[1<\n",me); + printf("\t\t-N \n"); + printf("\t\t-D \n"); + printf("\t\t-c \n"); + printf("\t\t-f \n"); + printf("\t\t-d -n{a} -b{a} -m -a -bg -l -t -v\n"); + exit(1); + } + diff --git a/gpl-release/utilities/backup/xconqrast.h.backup b/gpl-release/utilities/backup/xconqrast.h.backup new file mode 100644 index 0000000..adb4744 --- /dev/null +++ b/gpl-release/utilities/backup/xconqrast.h.backup @@ -0,0 +1,37 @@ + +/* header for X */ + +#define driver_version "preliminary" +#define conqrast_name "Xconqrast" + +#include + +typedef Drawable bitmap ; +typedef Display *screen_type; +typedef char *font; /* this needs doing */ + +#define is_screenname(name) (index(name,':')!=NULL) /* I think */ +#define get_default_screen_name() NULL /* I have no idea */ + +screen_type screen_named(); + +bitmap get_screen_bitmap(); +bitmap create_bitmap(); + +#define destroy_bitmap(bm) /* I don't know how to */ +#define font_named(name) (name) /* ditto */ +#define bad_font(font) ((font)==NULL) /* ??? */ +#define font_height(font) (0) /* ??? */ +#define font_width(font) (0) /* ??? */ +#define font_baseline(font) (0) /* ??? */ + +#define BLACK (1) +#define WHITE (0) /* guessing */ +#define DRAW_BLACK (1) /* ?? */ +#define DRAW_WHITE (2) + +void set_bit(); + +#define draw_line(bitmap,x1,y1,x2,y2,colour) /* again no idea! */ + + diff --git a/gpl-release/utilities/backup/xconqrast.h.bak b/gpl-release/utilities/backup/xconqrast.h.bak new file mode 100644 index 0000000..41e926b --- /dev/null +++ b/gpl-release/utilities/backup/xconqrast.h.bak @@ -0,0 +1,55 @@ +/* + * xconqrast.h - Header file with definitions and prototypes + * + * This file is part of Conquer. + * Originally Copyright (C) 1988-1989 by Edward M. Barlow and Adam Bryant + * Copyright (C) 2024 [Your Name] - Licensed under GPL v3 with permission from original authors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#define driver_version "preliminary" +#define conqrast_name "Xconqrast" + +#include + +typedef Drawable bitmap ; +typedef Display *screen_type; +typedef char *font; /* this needs doing */ + +#define is_screenname(name) (index(name,':')!=NULL) /* I think */ +#define get_default_screen_name() NULL /* I have no idea */ + +screen_type screen_named(); + +bitmap get_screen_bitmap(); +bitmap create_bitmap(); + +#define destroy_bitmap(bm) /* I don't know how to */ +#define font_named(name) (name) /* ditto */ +#define bad_font(font) ((font)==NULL) /* ??? */ +#define font_height(font) (0) /* ??? */ +#define font_width(font) (0) /* ??? */ +#define font_baseline(font) (0) /* ??? */ + +#define BLACK (1) +#define WHITE (0) /* guessing */ +#define DRAW_BLACK (1) /* ?? */ +#define DRAW_WHITE (2) + +void set_bit(); + +#define draw_line(bitmap,x1,y1,x2,y2,colour) /* again no idea! */ + + diff --git a/gpl-release/utilities/backup/xstuff.c.backup b/gpl-release/utilities/backup/xstuff.c.backup new file mode 100644 index 0000000..2e61455 --- /dev/null +++ b/gpl-release/utilities/backup/xstuff.c.backup @@ -0,0 +1,154 @@ +#include +#include "xconqrast.h" + +/* utilities for X */ + +Display *display; +Drawable root; +int screen; +GC gc; +short greyscale; + +struct /* maps from size of map to the font */ + /* to use */ + { /* if size > mag use font */ + int mag; + char *font,*bold; + } fonts[] = /* copied from the sun driver! need replacing */ + { + 9, "/usr/lib/fonts/fixedwidthfonts/screen.r.7", NULL, + 11, "/usr/lib/fonts/fixedwidthfonts/cour.r.10", + "/usr/lib/fonts/fixedwidthfonts/cour.b.10", + 12, "/usr/lib/fonts/fixedwidthfonts/cour.r.12", + "/usr/lib/fonts/fixedwidthfonts/cour.b.12", + 14, "/usr/lib/fonts/fixedwidthfonts/cour.r.14", + "/usr/lib/fonts/fixedwidthfonts/cour.b.14", + 16, "/usr/lib/fonts/fixedwidthfonts/cour.r.16", + "/usr/lib/fonts/fixedwidthfonts/cour.b.16", + 18, "/usr/lib/fonts/fixedwidthfonts/cour.r.18", + "/usr/lib/fonts/fixedwidthfonts/cour.b.18", + 22, "/usr/lib/fonts/fixedwidthfonts/cour.r.24", + "/usr/lib/fonts/fixedwidthfonts/cour.b.24", + 999999, NULL + }; + +int +argument_parse(argv) + +char *argv[]; + +{ +return 0; +} + +void +initialise_bitmaps() + + + + +{ + } + +screen_type +screen_named(name) + +char *name; + +{ +int sc; + +if ((display=XOpenDisplay(name)) == NULL) + error("No X server!"); + +root=XDefaultRootWindow(display); +sc=XDefaultScreen(display); +gc=XDefaultGC(display,sc); + +return display; +} + +bitmap +get_screen_bitmap(screen) + +screen_type screen; + +{ +int sc; +return root; +} + +bitmap +create_bitmap(width,height) + +int width,height; + +{ +int depth=1; + +if ( depth != 1 ) + greyscale=1; + +return XCreatePixmap(display,root,width,height,depth); +} + +void +set_bit(bm,x,y,val) + +bitmap bm; +int x,y; +int val; + +{ + +if (!greyscale ) + { + XSetForeground(display,gc,(unsigned long)val); + XDrawPoint(display,bm,gc,x,y); + } +else + if (val) + XDrawPoint(display,bm,gc,x,y); +} + +void +display_bitmap( bm,x,y,width,height) + +bitmap bm; +int x,y,width,height; + +{ +XCopyArea(display,bm,root,gc,0,0,width,height,x,y); + } + +int +write_bitmap(bm,file,width,height) + +bitmap bm; +char *file; +int width,height; +{ + +return XWriteBitmapFile(display,file,bm,width,height,-1,-1); + } + + +void +finish_bitmaps() + +{ +XCloseDisplay(display); +} + +bitmap_text(bm,x,y,colour,pf,str) + +bitmap bm; +int x,y; +int colour; +font pf; +char *str; + +{ + /* ??? */ + } + diff --git a/gpl-release/utilities/backup/xstuff.c.bak b/gpl-release/utilities/backup/xstuff.c.bak new file mode 100644 index 0000000..f8eb7a8 --- /dev/null +++ b/gpl-release/utilities/backup/xstuff.c.bak @@ -0,0 +1,175 @@ +/* + * xstuff.c - Game functionality module + * + * This file is part of Conquer. + * Originally Copyright (C) 1988-1989 by Edward M. Barlow and Adam Bryant + * Copyright (C) 2024 [Your Name] - Licensed under GPL v3 with permission from original authors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include "xconqrast.h" + +/* utilities for X */ + +Display *display; +Drawable root; +int screen; +GC gc; +short greyscale; + +struct /* maps from size of map to the font */ + /* to use */ + { /* if size > mag use font */ + int mag; + char *font,*bold; + } fonts[] = /* copied from the sun driver! need replacing */ + { + 9, "/usr/lib/fonts/fixedwidthfonts/screen.r.7", NULL, + 11, "/usr/lib/fonts/fixedwidthfonts/cour.r.10", + "/usr/lib/fonts/fixedwidthfonts/cour.b.10", + 12, "/usr/lib/fonts/fixedwidthfonts/cour.r.12", + "/usr/lib/fonts/fixedwidthfonts/cour.b.12", + 14, "/usr/lib/fonts/fixedwidthfonts/cour.r.14", + "/usr/lib/fonts/fixedwidthfonts/cour.b.14", + 16, "/usr/lib/fonts/fixedwidthfonts/cour.r.16", + "/usr/lib/fonts/fixedwidthfonts/cour.b.16", + 18, "/usr/lib/fonts/fixedwidthfonts/cour.r.18", + "/usr/lib/fonts/fixedwidthfonts/cour.b.18", + 22, "/usr/lib/fonts/fixedwidthfonts/cour.r.24", + "/usr/lib/fonts/fixedwidthfonts/cour.b.24", + 999999, NULL + }; + +int +argument_parse(argv) + +char *argv[]; + +{ +return 0; +} + +void +initialise_bitmaps() + + + + +{ + } + +screen_type +screen_named(name) + +char *name; + +{ +int sc; + +if ((display=XOpenDisplay(name)) == NULL) + error("No X server!"); + +root=XDefaultRootWindow(display); +sc=XDefaultScreen(display); +gc=XDefaultGC(display,sc); + +return display; +} + +bitmap +get_screen_bitmap(screen) + +screen_type screen; + +{ +int sc; +return root; +} + +bitmap +create_bitmap(width,height) + +int width,height; + +{ +int depth=1; + +if ( depth != 1 ) + greyscale=1; + +return XCreatePixmap(display,root,width,height,depth); +} + +void +set_bit(bm,x,y,val) + +bitmap bm; +int x,y; +int val; + +{ + +if (!greyscale ) + { + XSetForeground(display,gc,(unsigned long)val); + XDrawPoint(display,bm,gc,x,y); + } +else + if (val) + XDrawPoint(display,bm,gc,x,y); +} + +void +display_bitmap( bm,x,y,width,height) + +bitmap bm; +int x,y,width,height; + +{ +XCopyArea(display,bm,root,gc,0,0,width,height,x,y); + } + +int +write_bitmap(bm,file,width,height) + +bitmap bm; +char *file; +int width,height; +{ + +return XWriteBitmapFile(display,file,bm,width,height,-1,-1); + } + + +void +finish_bitmaps() + +{ +XCloseDisplay(display); +} + +bitmap_text(bm,x,y,colour,pf,str) + +bitmap bm; +int x,y; +int colour; +font pf; +char *str; + +{ + /* ??? */ + } + diff --git a/utilities/conqrast.c b/gpl-release/utilities/conqrast.c similarity index 100% rename from utilities/conqrast.c rename to gpl-release/utilities/conqrast.c diff --git a/utilities/conqrast.man b/gpl-release/utilities/conqrast.man similarity index 100% rename from utilities/conqrast.man rename to gpl-release/utilities/conqrast.man diff --git a/utilities/error.c b/gpl-release/utilities/error.c similarity index 100% rename from utilities/error.c rename to gpl-release/utilities/error.c diff --git a/utilities/file.c b/gpl-release/utilities/file.c similarity index 100% rename from utilities/file.c rename to gpl-release/utilities/file.c diff --git a/utilities/file.h b/gpl-release/utilities/file.h similarity index 100% rename from utilities/file.h rename to gpl-release/utilities/file.h diff --git a/utilities/sunconqrast.h b/gpl-release/utilities/sunconqrast.h similarity index 100% rename from utilities/sunconqrast.h rename to gpl-release/utilities/sunconqrast.h diff --git a/utilities/sunstuff.c b/gpl-release/utilities/sunstuff.c similarity index 100% rename from utilities/sunstuff.c rename to gpl-release/utilities/sunstuff.c diff --git a/utilities/util.c b/gpl-release/utilities/util.c similarity index 100% rename from utilities/util.c rename to gpl-release/utilities/util.c diff --git a/utilities/xconqrast.h b/gpl-release/utilities/xconqrast.h similarity index 100% rename from utilities/xconqrast.h rename to gpl-release/utilities/xconqrast.h diff --git a/utilities/xstuff.c b/gpl-release/utilities/xstuff.c similarity index 100% rename from utilities/xstuff.c rename to gpl-release/utilities/xstuff.c diff --git a/original/CONQPS.INFO b/original/CONQPS.INFO new file mode 100644 index 0000000..5a52f57 --- /dev/null +++ b/original/CONQPS.INFO @@ -0,0 +1,88 @@ + + + Description + +The conqps program translates maps from conquer to postscript suitable for +printing on a postscript printer. Conqps can act as a filter, or you +can give filenames to it. There is a lot of options to customise the output. +But the only option you should remember is the h option, which gives +a brief desription of all the options. If you are anxious to try it out +just type 'conquer -p | conqps >psmap' which should give you a file called +psmap, which can be sent to a postscript printer. There is a limitation of how +big the maps may be, this lies in the postscript language. But at our +site I have been able to print 256x256 maps (I haven't tried bigger) on +a LaserWriter II. + + Options + + There is a lot of options, but you don't need to know all of them. Some + options were put in to let advanced users get more control over the output. + Valid options are 'cfghlLnopstuvWXY'. They do the following: + + c Turns off printing of coordinates around the edge of the map. + + f fontname Sets the font to 'fontname', you can use any font that is in your + printer. Default is Times-Roman. The program also looks for + the environment variable CONQ_PSFONT. The f option overrides + both the default and the environment variable. + + g Turns off printing of the grid at the unknown parts of the map. + + h Shows a brief description of the options and some defaults. + + l If you print larger maps it's possible to exhaust the memory of your + printer. This option uses a feature in the Apple LaserWriter which + conserves memory, but gives you a smaller map. This option is not + fully tested, and should probably not be used. + + n Normally the map is centered around the parts of the world you know. + This option turns off this feature, and lets the program do as it + damn well pleases with your map :-) + + o x,y If you want to print just a small part of a bigger map use this + option. It makes conqps just to produce one page centered around + coordinates x,y. + + p type Sets the type of paper you have in the printer. Possible values + today are: A4 (European standard) LETTER (American standard) or + OTHER (should be local standard). You shouldn't have to use this + option since the person who maintains conquer at your site should + have set the right papersize as default (This is done in the + Makefile). + + s size Sets the size of each square of the map. This is useful to get + more map printed on fewer pages, but it will be smaller. + Default value is 9. + + t string Conqps tries to guess a nice title to the map for you. Normally + this is something like 'Designation Map for Nation Midkemia on + Turn 2' (this title is actually provided from the conquer program). + If however you would like to have your own title shown, just use + the t option, which replaces the default title with string. + + u Normally conqps put small pictures in some of your squares instead of + just letters. This option forces conqps not to do this, but instead + print the letters. + + v Puts conqps in verbose mode. For example you will be told how big the map + is and how big it will be on the printer. + + L,W,X,Y If none of the paper types fits your needs you can alter the size + directly with these options. All these options use one postscript + point (1/72 inch) as their unit. L sets the length of the page. + W sets the width. X sets the x coordinate for the leftmost viewable + pixel on the output, and Y sets the y coordinate. These options + are normally never used, instead you should experiment with + the p option. + + Bugs + + Hopefully no. + + + Comments + + If you have any comments or ideas mail them to d8forma@dtek.chalmers.se . + + MaF + diff --git a/original/MANIFEST b/original/MANIFEST new file mode 100644 index 0000000..0b7091d --- /dev/null +++ b/original/MANIFEST @@ -0,0 +1,45 @@ + File Name Archive # Description +----------------------------------------------------------- + MANIFEST 1 This shipping list + Makefile 14 + README 1 + admin.c 9 + cexecute.c 14 + check.c 9 + combat.c 4 + commands.c 6 + data.c 13 + data.h 8 + display.c 11 + extcmds.c 2 + forms.c 13 + header.h 13 + io.c 4 + magic.c 8 + main.c 10 + makeworl.c 9 + man.pag 14 + misc.c 3 + move.c 7 + nations 6 + navy.c 3 + newhelp.c 12 + newlogin.c 7 + newlogin.h 9 + notes.v4 2 + npc.c 5 + patchlevel.h 1 + randeven.c 11 + reports.c 10 + rules 12 + run 4 + sort.c 14 + spew.c 12 + trade.c 12 + txt0 13 + txt1 5 + txt2 6 + txt3 14 + txt4 7 + txt5 11 + update.c 1 diff --git a/original/Makefile b/original/Makefile new file mode 100644 index 0000000..95c7c17 --- /dev/null +++ b/original/Makefile @@ -0,0 +1,359 @@ +# conquer: Copyright (c) 1989 by Edward M Barlow +# +# BY CHANGING THIS FILE, YOU AGREE TO ABIDE BY THE LIMITATIONS STATED IN +# THE LIMITED USE CONTRACT CONTAINED IN THE FILE "header.h" +# +# Make sure to set your desired configuration by +# editing the file "header.h". +# +# This makefile has been modified to allow compilation using +# a parallelized make program. It has been used successfully +# on an Encore Multimax parallel computer with both 4 and +# 6 cpus. +# +# It should pose no problems for non parallel makes. +# +# Please report any problems to adb@bucsf.bu.edu +# or adb@bu-cs.bu.edu +# +# Conquer news mailing list: conquer-news-request@bu-cs.bu.edu. +# +MAKE = /usr/bin/make +CC = /usr/bin/gcc +RM = /bin/rm -f + +# LN must be "ln -s" if source and default directories span disks +LN = /bin/ln +CP = /bin/cp +NULL = 2>/dev/null + +# Flags to lint +LTFLG = -h -lcurses + +# Options for the postscript map printing program. +# The file 'conqps.ps' will be installed in the EXEDIR +# directory which is determined below. +# +# To avoid building this program, remove $(PSPROG) from +# both the 'all:' list and the 'install:' list +PSPROG = conqps +PSSRC = psmap.c +PSHEAD = psmap.h +PSDATA = psmap.ps +# Default Pagesize Setting: +# A4 for European page size. +# LETTER for American page size. +# OTHER for Local page size. [edit conqps.h] +PSPAGE = LETTER + +# Options for shar program, SHARLIM is limit of each shar +# file created in kilobytes and SHARNAM is the prefix for +# SHARFILE name. +# [This is for a public domain shar from USENET, I can send +# copies if you wish - adb@bu-cs.bu.edu] +SHAR = /usr/bin/shar +SHARLIM = 50 +SHARNAM = shar. +SHARFLG = -D -c -l$(SHARLIM) -o$(SHARNAM) + +# This should be installed by whomever you want to own the game. +# I recommend "games" or "root". + +# uncomment the next line if you dont have getopt in your library +# (eg you are on a pc, or a non unix system). getopt.c is a +# public domain software, and has not been tested by the authors +# of conquer. [not distributed with conquer V4] +#GETOPT = getopt.o + +# +# libraries for BSD systems: +LIBRARIES = -lcurses -ltermcap -lcrypt +# +# libraries for SYSV systems: +#LIBRARIES = -lcurses +# +# libraries for Xenix systems: +#LIBRARIES = -ltermlib -ltcap -lcrypt + +# CURRENT is this directory. The directory where the source +# and Makefile are located +CURRENT = /home/conquer/src + +# DEFAULT is the directory where default nations & help files will be +# stored. It is also the default directory = where players will play +# if they do not use the -d option. +DEFAULT = /home/conquer/lib + +# This directory is where the executables will be stored +EXEDIR = /home/conquer/bin + +# Definitions used for compiling conquer +CDEFS = -DDEFAULTDIR=\"$(DEFAULT)\" -DEXEDIR=\"$(EXEDIR)\" + +# Options flag used for normal compilation +OPTFLG = -O + +# Options flag used for debugging purposes +# [make sure to comment out 'strip' commands in install section] +#OPTFLG = -DDEBUG -g + +# this is the name of the user executable +# the user executable contains commands for the games players +GAME = conquer +# this is the name of the administrative executable +# the administrative executable contains commands for the game super user +ADMIN = conqrun +# this is the name of the sorting program which conquer uses +SORT = conqsort + +# GAME IDENTIFICATION +# +# Set this to some unique identifier for each game you wish +# to create via 'make new_game'. It will make a subdirectory +# $(GAMEID) to the DEFAULT data directory where it will store +# data for the new game. [Leave it blank to create the default +# game] +GAMEID = + +# AFILS are files needed for game updating... +AFILS = combat.c cexecute.c io.c admin.c makeworl.c navy.c spew.c \ +newlogin.c update.c magic.c npc.c misc.c randeven.c data.c trade.c check.c +AOBJS = combat.o cexecuteA.o ioA.o admin.o makeworl.o navyA.o spew.o \ +newlogin.o update.o magicA.o npc.o miscA.o randeven.o dataA.o \ +tradeA.o $(GETOPT) check.o + +# GFILS are files needed to run a normal interactive game +GFILS = commands.c cexecute.c forms.c io.c main.c move.c navy.c \ +magic.c misc.c reports.c data.c display.c extcmds.c trade.c check.c +GOBJS = commands.o cexecuteG.o forms.o ioG.o main.o move.o navyG.o \ +magicG.o miscG.o reports.o dataG.o display.o extcmds.o tradeG.o \ +$(GETOPT) check.o + +# List of temporary C files +DAFILS = cexecuteA.c ioA.c miscA.c navyA.c magicA.c dataA.c tradeA.c +DGFILS = cexecuteG.c ioG.c miscG.c navyG.c magicG.c dataG.c tradeG.c + +#txt[0-4] are input help files. help[0-4] are output. HELPSCR is sed script. +HELP=txt +HELPOUT=help +HELPSCR=sed + +HEADERS=header.h data.h newlogin.h patchlevel.h +SUPT1=nations Makefile $(HELP)[0-5] README run man.pag rules +SUPT2=execute messages news commerce CONQPS.INFO +ALLFILS=$(SUPT1) $(HEADERS) $(AFILS) commands.c forms.c main.c move.c \ +reports.c display.c extcmds.c newhelp.c sort.c getopt.c \ +$(PSSRC) $(PSHEAD) $(PSDATA) + +all: $(ADMIN) $(GAME) $(SORT) $(PSPROG) helpfile + @echo YAY! make new_game to set up permissions, zero appropriate + @echo initial files, move $(GAME) and $(ADMIN) to + @echo $(EXEDIR), and set up the world. + @echo If a game is in progress, make install will just move $(GAME) + @echo and $(ADMIN) to $(EXEDIR). + @echo + +$(ADMIN): $(AOBJS) + @echo phew... + -$(RM) $(DAFILS) $(NULL) + @echo if the next command does not work you might also need -ltermcap + @echo === compiling administrative functions + $(CC) $(OPTFLG) -o $(ADMIN) $(AOBJS) $(LIBRARIES) +# comment out the next line during debugging + strip $(ADMIN) + +$(GAME): $(GOBJS) + @echo phew... + -$(RM) $(DGFILS) $(NULL) + @echo if the next command does not work you might also need -ltermcap + @echo === compiling user interface + $(CC) $(OPTFLG) -o $(GAME) $(GOBJS) $(LIBRARIES) +# comment out the next line during debugging + strip $(GAME) + +$(SORT): sort.c + $(CC) $(OPTFLG) -o $(SORT) sort.c +# comment out the next line if debugging + strip $(SORT) + +clobber: + -$(RM) *.o $(HELPOUT)[0-5] $(PSPROG) $(SORT) insthelp helpfile $(NULL) + -$(RM) newhelp in$(GAME) in$(SORT) in$(ADMIN) in$(PSPROG) $(NULL) + -$(RM) $(HELPSCR).[12] lint[ag] conquer.doc $(GAME) $(ADMIN) $(NULL) + +clean: + $(RM) *.o lint[ag] conquer.doc $(NULL) + +in$(GAME): $(GAME) + -$(RM) $(EXEDIR)/$(GAME) + mv $(GAME) $(EXEDIR) + chmod 4751 $(EXEDIR)/$(GAME) + touch $(GAME) + touch in$(GAME) + +in$(ADMIN): $(ADMIN) + -$(RM) $(EXEDIR)/$(ADMIN) + mv $(ADMIN) $(EXEDIR) + chmod 4751 $(EXEDIR)/$(ADMIN) + touch $(ADMIN) + touch in$(ADMIN) + +in$(SORT): $(SORT) + -$(RM) $(EXEDIR)/$(SORT) + mv $(SORT) $(EXEDIR) + chmod 751 $(EXEDIR)/$(SORT) + touch $(SORT) + touch in$(SORT) + +in$(PSPROG): $(PSPROG) + -$(RM) $(EXEDIR)/$(PSPROG) + mv $(PSPROG) $(EXEDIR) + $(CP) $(PSDATA) $(EXEDIR) + chmod 751 $(EXEDIR)/$(PSPROG) + chmod 644 $(EXEDIR)/$(PSDATA) + touch $(PSPROG) + touch in$(PSPROG) + +install: in$(GAME) in$(ADMIN) in$(SORT) in$(PSPROG) insthelp instman + @echo "" + @echo "Installation complete" + +new_game: all insthelp + @echo Installing new game + -mkdir $(EXEDIR) $(NULL) + -mkdir $(DEFAULT) $(NULL) + -mkdir $(DEFAULT)/$(GAMEID) $(NULL) + chmod 755 $(EXEDIR) + chmod 750 $(DEFAULT)/$(GAMEID) $(DEFAULT) + $(CP) $(GAME) $(ADMIN) $(SORT) $(PSPROG) $(PSDATA) $(EXEDIR) + chmod 4755 $(EXEDIR)/$(GAME) $(EXEDIR)/$(ADMIN) + chmod 0755 $(EXEDIR)/$(SORT) $(EXEDIR)/$(PSPROG) + chmod 0644 $(EXEDIR)/$(PSDATA) + chmod 0600 nations + chmod 0700 run + $(CP) nations rules $(DEFAULT)/$(GAMEID) + $(CP) nations rules $(DEFAULT) + @echo now making the world + $(EXEDIR)/$(ADMIN) -d "$(GAMEID)" -m + $(EXEDIR)/$(ADMIN) -d "$(GAMEID)" -a + +insthelp: helpfile + @echo Installing helpfiles + -$(RM) $(DEFAULT)/$(HELPOUT)0 + -$(LN) $(CURRENT)/$(HELPOUT)0 $(DEFAULT)/$(HELPOUT)0 + -$(RM) $(DEFAULT)/$(HELPOUT)1 + -$(LN) $(CURRENT)/$(HELPOUT)1 $(DEFAULT)/$(HELPOUT)1 + -$(RM) $(DEFAULT)/$(HELPOUT)2 + -$(LN) $(CURRENT)/$(HELPOUT)2 $(DEFAULT)/$(HELPOUT)2 + -$(RM) $(DEFAULT)/$(HELPOUT)3 + -$(LN) $(CURRENT)/$(HELPOUT)3 $(DEFAULT)/$(HELPOUT)3 + -$(RM) $(DEFAULT)/$(HELPOUT)4 + -$(LN) $(CURRENT)/$(HELPOUT)4 $(DEFAULT)/$(HELPOUT)4 + -$(RM) $(DEFAULT)/$(HELPOUT)5 + -$(LN) $(CURRENT)/$(HELPOUT)5 $(DEFAULT)/$(HELPOUT)5 + touch insthelp + +instman: + @echo Installing man pages + $(CP) man.pag $(EXEDIR) + +helpfile: $(HELPOUT)0 $(HELPOUT)1 $(HELPOUT)2 $(HELPOUT)3 $(HELPOUT)4 $(HELPOUT)5 + @echo Helpfiles built + touch helpfile + +$(HELPOUT)0: $(HELP)0 $(HELPSCR).1 $(HELPSCR).2 + @echo building $(HELPOUT)0 + cat $(HELP)0 | sed -f $(HELPSCR).1 | sed -f $(HELPSCR).2 > $(HELPOUT)0 + +$(HELPOUT)1: $(HELP)1 $(HELPSCR).1 $(HELPSCR).2 + @echo building $(HELPOUT)1 + cat $(HELP)1 | sed -f $(HELPSCR).1 | sed -f $(HELPSCR).2 > $(HELPOUT)1 + +$(HELPOUT)2: $(HELP)2 $(HELPSCR).1 $(HELPSCR).2 + @echo building $(HELPOUT)2 + cat $(HELP)2 | sed -f $(HELPSCR).1 | sed -f $(HELPSCR).2 > $(HELPOUT)2 + +$(HELPOUT)3: $(HELP)3 $(HELPSCR).1 $(HELPSCR).2 + @echo building $(HELPOUT)3 + cat $(HELP)3 | sed -f $(HELPSCR).1 | sed -f $(HELPSCR).2 > $(HELPOUT)3 + +$(HELPOUT)4: $(HELP)4 $(HELPSCR).1 $(HELPSCR).2 + @echo building $(HELPOUT)4 + cat $(HELP)4 | sed -f $(HELPSCR).1 | sed -f $(HELPSCR).2 > $(HELPOUT)4 + +$(HELPOUT)5: $(HELP)5 $(HELPSCR).1 $(HELPSCR).2 + @echo building $(HELPOUT)5 + cat $(HELP)5 | sed -f $(HELPSCR).1 | sed -f $(HELPSCR).2 > $(HELPOUT)5 + +$(HELPSCR).1: newhelp + newhelp + +$(HELPSCR).2: newhelp + newhelp + +newhelp: dataG.o newhelp.o + $(CC) $(OPTFLG) dataG.o newhelp.o -o newhelp + strip newhelp +# +# postscript map program +PSOPTS = -DPSFILE=\"$(EXEDIR)/$(PSDATA)\" -D$(PSPAGE) +# +$(PSPROG): $(PSSRC) $(PSDATA) $(PSHEAD) + $(CC) $(OPTFLG) $(PSOPTS) $(PSSRC) -o $(PSPROG) +# comment out the next line if debugging + strip $(PSPROG) + +lint: + lint $(LTFLG) $(CDEFS) -DCONQUER $(GFILS) > lintg + lint $(LTFLG) $(CDEFS) -DADMIN $(AFILS) > linta + +docs: conquer.doc + +conquer.doc: $(HELPOUT)0 $(HELPOUT)1 $(HELPOUT)2 $(HELPOUT)3 $(HELPOUT)4 $(HELPOUT)5 + cat $(HELPOUT)? |sed -e "s/^DONE/ /g"|sed -e "s/^END//g" >conquer.doc + +cpio: + -$(RM) core + find . -name '*[CrpsEech]' -print | cpio -ocBv > cpiosv + +shar: + echo " lines words chars FILENAME" > MANIFEST + wc $(ALLFILS) >> MANIFEST + $(SHAR) $(SHARFLG) $(ALLFILS) MANIFEST + +.cA.o: $< + ( trap "" 0 1 2 3 4 ; $(LN) $*.c $*A.c ;\ + $(CC) $(OPTFLG) $(CDEFS) -DADMIN -c $*A.c ;\ + $(RM) $*A.c ) + +.cG.o: $< + ( trap "" 0 1 2 3 4 ; $(LN) $*.c $*G.c ;\ + $(CC) $(OPTFLG) $(CDEFS) -DCONQUER -c $*G.c ;\ + $(RM) $*G.c ) + +.c.o: $< +# compiles using both defines since they +# are needed for the data.h definitions for +# each file... but should not be needed for +# the actual C source file being compiled + $(CC) $(OPTFLG) $(CDEFS) -DADMIN -DCONQUER -c $*.c + +$(GOBJS): data.h header.h + +$(AOBJS): data.h header.h + +ioG.o: data.h header.h patchlevel.h io.c + +ioA.o: data.h header.h patchlevel.h io.c + +newlogin.o: data.h header.h newlogin.h patchlevel.h newlogin.c + +main.o: data.h header.h patchlevel.h main.c + +newhelp.o: data.h header.h patchlevel.h newhelp.c + +# Clear suffixes +.SUFFIXES: + +# Suffixes for conquer files. +.SUFFIXES: A.o G.o .c .h .o diff --git a/original/README b/original/README new file mode 100644 index 0000000..2d137a6 --- /dev/null +++ b/original/README @@ -0,0 +1,202 @@ + ********************************************************* + * README FILE FOR THE INSTALLER OF CONQUER * + ********************************************************* + +What you have here is a copyrighted release 4 version version of CONQUER. +I make no guaranties to the sanity or style of this code, but do believe +that it should work as documented. I have included numerous bugfixes +from previous releases posting, and have added numerous enhancements. +The file notes.v4 details changes between v3.5 and v4, bugs and other things. + +I have no current email address... Too bad. I will post a patch to THIS FILE +when i get a new email address. The hazards of switching jobs. Adam Bryant +has volunteered to take mail for the summer of 1989 at "arpa!bu-cs.bu.edu!adb" +or "adb@bu-cs.bu.edu". He is the co-author of the game... so send comments to +him. We like feedback on the game. Comments and feature requests are very +useful to me as they are my primary method of deciding what to next add to the +code. Your interest is appreciated. + +A mailing list for conquer has been set up to provide a platform for conquer +discussion, and location for conquer test patch releases. The mailing list is +"conquer-news@bu-cs.bu.edu" and addition to or deletions from the mailing +list may be sent to "conquer-news-request@bu-cs.bu.edu". + +NOTE: My new phone number is 212-679-1439. My work has no arpanet. If anybody +knows of a cheap (free??) way of getting an arpanet login I NEED ONE. I +basically can make no more changes to Conquer until I can get a network port, +and since i am "volunteering" my time for this project, I am not about to +spend millions of dollars to buy one... I can get a modem for my PC if +somebody will help me get a port somewhere. -ED- + +Included in this file are the following: + 1) A Brief Description of Conquer + 2) Installation (unpacking) Instructions + 3) Configuration Instructions + 4) Compilation Instructions + 5) Administration instructions + 6) Changes in this version + +This version should not be redistributed without the permission of Edward +Barlow or Adam Bryant ( please read the copyright note in header.h ). + +Again, any comments or bug reports would be greatly appreciated. + +----------------------------------------------------------- +I A Brief Description of Conquer +----------------------------------------------------------- +A complete description of Conquer v4 is contained in "man.page" and +"conquer.docs". "conquer.docs" is created from the files txt[0-5] which are +customized from data in the header files. These txt[] files are then +converted int help[0-5] files, which contain configuration data. "make docs" +will create this file from current data. Note conquer.doc IS NOT created +program is compiled. I have tried to make the documentation as good as +possible, but I guarantee that I have missed a lot. Consider this a feature +and enjoy any (hopefully pleasant) suprises you get. +----------------------------------------------------------- +II Installation (unpacking) Instructions +----------------------------------------------------------- +This program came in several shell archive scripts. They can can be unpacked +by using "sh filename". If you are reading this, you know this. + +If you suspect missing files, please check the MANIFEST. +----------------------------------------------------------- +III Configuration +----------------------------------------------------------- +THE FOLLOWING FILES SHOULD BE MODIFIED TO REFLECT YOUR ENVIRONMENT +AND THE TYPE OF GAME YOU WISH TO PLAY. THE GAME WILL NOT RUN UNLESS +YOU MODIFY THESE FILES APPROPRIATELY. + +header.h modify as per instructions +Makefile modify as per instructions + +I have tried to comment this stuff appropriately. + +The options specified in these files will be reflected +in the conquer.docs and help files when the program is compiled. + +You will probably also want to take a look at the "rules*" file. This +contains the grammar rules for the random mail messages generated by +NPC's. You may wish to insert some local people's names, or think of +some really juicy insults. The format of the file should be obvious; +basically %FOO declares a class FOO and one of the things inside that +class will be selected randomly. Obviously, %MAIN is the top level which +then calls on the subclasses to construct sentences. + +----------------------------------------------------------- +IV Compilation Instructions +----------------------------------------------------------- +This program should be easy to compile. After header.h and Makefile have +been edited properly, you may type 'make' to compile conquer, and +'make new_game' to build and install a new game. + +Note: Sometimes curses does not include termcap or termlib. If all the + '.c' files get compiled, but do not link together, and + unreferenced symbol errors occur, try adding "-ltermcap" after + the "-lcurses" line in the makefile. + +Note2: With some versions of 'make' the SHELL environment variable is + read to determine under what shell jobs should be spawned. The + Makefile for conquer was written with '/bin/sh' in mind, so if + any "command not found" errors appear, doing a: + setenv SHELL /bin/sh + before typing 'make', might alleviate the problem. + +----------------------------------------------------------- +V administration instructions +----------------------------------------------------------- +Now that you have compiled it, this is how you administer/set up/run the game. +I recommend following these instructions once yourself in a mock game +(ie. no other players) for a few turns to get things straight. Then you +can add other players. + +The command line format for the administration commands is + + conqrun [-maxp -dDIR -rSCENARIO]\n",argv[0]); + -m make a world + -a add new player + -x execute program + -d DIR to use play different game + -r SCENARIO read map while making a new world + uses SCENARIO.ele, SCENARIO.veg, & SCENARIO.nat + +Also, some useful god functions are provided through the conquer program +through logging in as 'god' with 'conquer -n god'. + +Conquer now supports two layers of game administration: the god of +conquer, as defined by the LOGIN define in header.h, may allow each +world to have an administrator or demi-god. This demi-god will be able +to perform updates and other god functions for this world only. This +feature allows for multiple worlds, each governed by a different god. +During the creation of a world, god will be prompted for the name of the +demi-god for the new world. Just hitting return will mean that god will +himself act as the demi-god for this world. + +Unlike godship, the demi-god for a world may be changed during the +running of a game, without recompilation of conquer. This is done using +the 'c'hange menu when logged in as god. + +In addition the the conqrun command, the makefile helps you as follows: + +make: Compiles the code. +make clobber: Clobber everything but the source (destroys executables) +make clean: Clean up objects (does not destroy executables) +make new_game: Create a new game, make world, add players... +make install: Install game in appropriate directory +make docs: Creates documentation from help file + +Finally, I have included an 'at' script that permits automatic updating. +run: read this shell script, it permits you to run the update + automatically. It needs to be modified for time to update. + +The command line for the conquer executable can be found by reading +the help files. + +Again, prior to the compile, you should have followed the instructions +in the Makefile and in header.h. + +You can administrate world either via "make new_game" or via: + this will make your world. + This also sets up npc nations as per the nations file + npc stats can be adjusted by editing nations + prior to making the world. Non player nations have + the same password as god. +or this will make your world by using scenarios. + Basically, the scenarios include a nation file and + three map files (elevation, vegetation, and nation + setup). Look at the rome scenario included in the game. + [ this scenario is not finished yet ] + +You can add ( 0 or more ) players via + which should be self explanatory. This wont work if + the world is filled, as it would be if a scenario was + read in and the SCENARIO.ntn file filled the world. + This is because the program wont find spots to place + your players. Adjust the nations file for your + scenario to set up players. When they log in, they + will be asked for a new password. + + +Once you log in as a player or as god, you can get help by +typing '?'. Play around with the commands and get your syntax right. + +Try logging in as either a player or non player nation (they use the super +user password) and noticing any differences. + +IMPORTANT NOTE ON PLAY BALANCE: +The world is not created equal. Some players may start in very bad +positions. You can either start them over (destroy that nation in the +change nation command and create a new one), or modify the surrounding +terain appropriately (god can use the redesignate command to change +elevation and vegetation). + +Now move around on the map and learn where the players are positioned. +If there is a problem (they are surrounded by water...), use the +redesignate command to change elevation or vegetation. In the worst +case, god can destroy a nation with 'c', the change nation command. +Once you think the game will be fair, it is time to allow players to +proceed. + +Now you are all set -- play via + + +and update with via an script similar to "run" diff --git a/original/WARNING.p11 b/original/WARNING.p11 new file mode 100644 index 0000000..a3803ba --- /dev/null +++ b/original/WARNING.p11 @@ -0,0 +1,13 @@ +*** Warning: + +This patch contains the "CHECKUSER" option which will make the data file +incompatible with previous versions of 4.x data files. If you wish to use +this patch with 4.10 data files -=DO NOT=- compile with the CHECKUSER option +enabled. + +-spide + mcy1580@ultb.isc.rit.edu + mcy1580@ritvax.isc.rit.edu + +-adam + adb@cs.bu.edu diff --git a/original/admin.c b/original/admin.c new file mode 100644 index 0000000..ba01fc4 --- /dev/null +++ b/original/admin.c @@ -0,0 +1,658 @@ +/*conquer : Copyright (c) 1988 by Ed Barlow. + * I spent a long time writing this code & I hope that you respect this. + * I give permission to alter the code, but not to copy or redistribute + * it without my explicit permission. If you alter the code, + * please document changes and send me a copy, so all can have it. + * This code, to the best of my knowledge works well, but it is my first + * 'C' program and should be treated as such. I disclaim any + * responsibility for the codes actions (use at your own risk). I guess + * I am saying "Happy gaming", and am trying not to get sued in the process. + * Ed + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "header.h" +#include "data.h" + +/*Declarations*/ +char *getpass(); +struct s_sector **sct; +struct s_nation ntn[NTOTAL]; /* player nation stats */ +struct s_world world; +/*is sector occupied by an army?*/ +char **occ; +short **movecost; +long startgold=0; + +/*offset of upper left hand corner*/ +short xoffset=0,yoffset=0; +/*current cursor postion (relative to 00 in upper corner)*/ +/* position is 2*x,y*/ +short xcurs=0,ycurs=0; +/*display state*/ +short dismode=2; +/* nation id of owner*/ +short country=0; +struct s_nation *curntn; +extern char datadir[]; +#ifdef REMAKE +int remake=FALSE; +#endif /*REMAKE*/ + +FILE *fexe, *fopen(); + +void +main(argc,argv) +int argc; +char **argv; +{ + int geteuid(), getuid(), setuid(), realuser, l; + register int i,j; + char *name; +#ifndef __STDC__ + void srand(); +#endif + int getopt(); + long time(); + /* mflag = make world, a=add player, x=execute, p=print */ + /* rflag = make world from read in files */ + int mflag, aflag, xflag, rflag; + char string[FILELTH]; + extern char *optarg; + char defaultdir[BIGLTH],cq_opts[BIGLTH]; + struct passwd *getpwnam(), *pwent; + + umask (MASK); + mflag = aflag = xflag = rflag = 0; + srand((unsigned) time((long *) 0)); + strcpy(datadir,""); + strcpy(cq_opts,""); + name = string; + *name = 0; + + /* check conquer options */ + if (getenv(ENVIRON_OPTS)!=NULL) { + strncpy(cq_opts, getenv(ENVIRON_OPTS), BIGLTH); + } + if (cq_opts[0] != '\0') { + l = strlen(cq_opts); + for(i=0; i\n"); + exit(FAIL); + } + if (i\n",cq_opts[i]); + exit(FAIL); + break; + } + } + } + + /* process the command line arguments */ + while((i=getopt(argc,argv,"maxr:d:"))!=EOF) switch(i){ + /* process the command line arguments */ + case 'm': /* make a new world*/ + mflag++; + break; + case 'a': /* anyone with password can add player*/ + aflag++; + break; + case 'x': /* execute (update) program*/ + xflag++; + break; + case 'r': /* read map file */ + rflag++; + if(strlen(optarg) > NAMELTH){ + fprintf(stderr,"ERROR: MAPFILE STEM LONGER THAN %d\n",NAMELTH); + exit(FAIL); + } + strcpy(scenario, optarg); + break; + case 'd': + strcpy(datadir, optarg); + break; + case '?': /* print out command line arguments */ + printf("Command line format: %s [-max -dDIR -rSCENARIO]\n",argv[0]); + printf("\t-m make a world\n"); + printf("\t-a add new player\n"); + printf("\t-x execute (update) program\n"); + printf("\t-d DIR to use play different game\n"); + /* printf("\t-r SCENARIO read map while making a new world\n\t\t\tuses SCENARIO.ele, SCENARIO.veg, & SCENARIO.nat\n"); */ + exit(SUCCESS); + }; + + realuser = getuid(); + /* may now replace user identity */ + (void) setuid (geteuid ()) ; + + /* set proper defaultdir */ + if (datadir[0] != '/') { + if (strlen(datadir) > 0) { + sprintf(defaultdir, "%s/%s", DEFAULTDIR, datadir); + } else { + strcpy(defaultdir,DEFAULTDIR); + strcpy(datadir,"[default]"); + } + } else { + strcpy(defaultdir,datadir); + } + + /* now that we have parsed the args, we can got to the + * dir where the files are kept and do some work. + */ + if (chdir(defaultdir)) { + printf("unable to change dir to %s\n",defaultdir); + exit(FAIL); + } + if((mflag)||(rflag)) { +#ifdef REMAKE + /* check if datafile currently exists*/ + if(access(datafile,00) == 0) { + /* read in the data*/ + readdata(); + verifydata( __FILE__, __LINE__ ); + + /* verify ability to remake the world */ + if ((realuser != (getpwnam(LOGIN))->pw_uid ) && + ((pwent=getpwnam(ntn[0].leader)) == NULL || + realuser != pwent->pw_uid )) { + printf("Sorry -- you can not create a world\n"); + printf("you need to be logged in as %s",LOGIN); + if (strcmp(LOGIN, ntn[0].leader)!=0) { + printf(" or %s",ntn[0].leader); + } + printf(".\n"); + exit(FAIL); + } + remake=TRUE; + printf("************* WARNING!!!! *******************\n\n"); + printf(" There is already a game in progress.\n\n"); + printf("*********************************************\n\n"); + printf("Do you wish to destroy the current game? "); + scanf("%s",string); + if (strcmp(string,"yes")!=0 && strcmp(string,"y")!=0) { + printf("Okay... the world is left intact\n"); + exit(FAIL); + } + printf("Are you absolutely certain? "); + scanf("%s",string); + if (strcmp(string,"yes")!=0 && strcmp(string,"y")!=0) { + printf("Okay... the world is left intact\n"); + exit(FAIL); + } + printf("The re-destruction of the world has begun...\n"); + sleep(1); + } +#else + /* check for god permissions */ + if(realuser!=(getpwnam(LOGIN))->pw_uid) { + printf("Sorry -- you can not create a world\n"); + printf("you need to be logged in as %s.\n",LOGIN); + exit(FAIL); + } + + /* check if datafile already exists*/ + if(access(datafile,00) == 0) { + printf("ABORTING: File %s exists\n",datafile); + printf("\tthis means that a game is in progress. To proceed, you must remove \n"); + printf("\tthe existing data file. This will, of course, destroy that game.\n\n"); + exit(FAIL); + } +#endif /* REMAKE */ + + makeworld(rflag); + sprintf(string,"%sup",isonfile); + unlink(string); + exit(SUCCESS); + } + + /* read data*/ + readdata(); + verifydata( __FILE__, __LINE__ ); + + if (aflag) { /* a new player */ + sprintf(string,"%sup",isonfile); + if(check_lock(string,FALSE)==TRUE) { + printf("Conquer is updating\n"); + printf("Please try again later.\n"); + exit(FAIL); + } + + sprintf(string,"%s0",isonfile); + if(check_lock(string,FALSE)==TRUE) { + printf("God is currently logged in.\n"); + printf("Please try again later.\n"); + exit(FAIL); + } + + printf("\n********************************************"); + printf("\n* PREPARING TO ADD NEW PLAYERS *"); + printf("\n********************************************\n"); + if( TURN > LASTADD ){ + printf("more than %d turns have passed since game start!\n", LASTADD); + printf("permission of game administrator required\n"); + if(strncmp(crypt(getpass("\nwhat is conquer super user password:"),SALT),ntn[0].passwd,PASSLTH)!=0) + { + printf("sorry...\n"); + exit(FAIL); + } + } + /* prevent more than one addition */ + sprintf(string,"%sadd",isonfile); + if(check_lock(string,TRUE)==TRUE) { + printf("Someone else is adding\n"); + printf("Please try again later.\n"); + exit(FAIL); + } + + /* disable interrupts */ + signal(SIGINT,SIG_IGN); + signal(SIGQUIT,SIG_IGN); + newlogin(realuser); + unlink(string); + exit(SUCCESS); + } + +#ifdef OGOD + if ((realuser != (getpwnam(LOGIN)->pw_uid) ) && + ((pwent=getpwnam(ntn[0].leader)) == NULL || + realuser != pwent->pw_uid )) { + printf("Sorry -- you can not administrate conquer\n"); + printf("you need to be logged in as %s",LOGIN); + if (strcmp(LOGIN, ntn[0].leader)!=0) { + printf(" or %s",ntn[0].leader); + } + printf("\n"); + exit(FAIL); + } +#endif /* OGOD */ + + if (xflag) { /* update the game */ +#ifndef OGOD + if ((realuser != (getpwnam(LOGIN))->pw_uid ) && + ((pwent=getpwnam(ntn[0].leader)) == NULL || + realuser != pwent->pw_uid )) { + printf("sorry -- your uid is invalid for updating\n"); + printf("you need to be logged in as %s",LOGIN); + if (strcmp(LOGIN, ntn[0].leader)!=0) { + printf(" or %s",ntn[0].leader); + } + printf("\n"); + exit(FAIL); + } +#endif /* OGOD */ +#ifdef RUNSTOP + /* check if any players are on */ + for (i=0;i %s", timefile); + system(string); +#endif /* TIMELOG */ + exit(SUCCESS); + } + printf("error: must specify an option\n"); + + /* print out command line arguments */ + printf("Command line format: %s [-max -dDIR]\n",argv[0]); + printf("\t-a add new player\n"); + printf("\t-d DIR to use play different game\n"); + printf("\t-m make a world\n"); + printf("\t-x execute (update) program\n"); + exit(SUCCESS); +} + +/* if parameter == 0 do for all nations */ +void +att_setup(cntry) +int cntry; +{ + int nat; + for( nat= 0; natactive )) continue; + WORLDNTN++; + WORLDJEWELS+=curntn->jewels; + if(curntn->tgold>0) WORLDGOLD+=curntn->tgold; + WORLDMETAL+=curntn->metals; + WORLDFOOD+=curntn->tfood; + WORLDSCORE+=curntn->score; + WORLDCIV+=curntn->tciv; + WORLDSCT+=curntn->tsctrs; + WORLDMIL+=curntn->tmil; + } + if (WORLDGOLD==0) WORLDGOLD=1; + + /* count the number of sectors */ + for(country=1;countryeatrate<25) curntn->eatrate=25; + if( TURN!= 1) { /* remember eatrate is scaled by 25 */ + switch(SEASON(TURN)) { + case WINTER: /* 7 food/person for each eatrate */ + temp = 180L * curntn->tfood/(curntn->eatrate+25L); + break; + case SPRING: /* 6 food/person for each eatrate */ + temp = 204L * curntn->tfood/(curntn->eatrate+25L); + break; + case SUMMER: /* 5 food/person for each eatrate */ + temp = 250L * curntn->tfood/(curntn->eatrate+25L); + break; + case FALL: /* 4 food/person for each eatrate */ + temp = 312L * curntn->tfood/(curntn->eatrate+25L); + break; + } + if(curntn->tciv>0) x = curntn->eatrate/2 + temp/curntn->tciv; + else x = 25; + if( x < MAXTGVAL ) curntn->eatrate = (char)x; + else curntn->eatrate=MAXTGVAL; + if ( curntn->eatrate < 25 ) curntn->eatrate=25; + + } else { + cityfolk = 10; /* Aproximate steady state */ + } + + if( 30 <= 1+ngrain+ncities ) curntn->spoilrate=1; + else curntn->spoilrate = 30-ngrain-ncities; + if( curntn->tfood > curntn->tciv * 10 ) + curntn->spoilrate = 30; + + /* get number of mercenaries */ + mercs=0; + for(armynum=0;armynumtmil>0 && curntn->tciv>0) temp=(1000*curntn->tmil)/curntn->tciv+(1000*mercs)/curntn->tmil; + else temp=0; + curntn->terror = min( temp/5, MAXTGVAL ); + + temp = (5*townfolk/2+5*cityfolk) + roads*5; + curntn->communications = min( temp,2*MAXTGVAL ); + + temp=1000*curntn->score/WORLDSCORE + 1000*curntn->tmil/WORLDMIL; + curntn->power = min(temp/5,MAXTGVAL); + + /* calculate national wealth */ + temp = curntn->tgold; + if(temp<0) temp=0; + temp = (long)(1000.0*temp/WORLDGOLD + 1000.0*curntn->jewels/WORLDJEWELS + 1000.0*curntn->metals/WORLDMETAL) + cityfolk*5/3 + townfolk*5/6; + if (temp >= curntn->wealth) { + curntn->wealth = min( temp/10,MAXTGVAL ); + } else { + curntn->wealth -= (curntn->wealth - temp)/4; + } + + if( TURN!= 1) { + curntn->reputation += rand()%8-3; + curntn->reputation = min( curntn->reputation,MAXTGVAL ); + + temp = (curntn->prestige + curntn->power + curntn->wealth) / 3; + curntn->prestige = min( temp,MAXTGVAL ); + + if(curntn->tciv>0) temp = foodpts*10 / curntn->tciv; + else temp = 0; + curntn->farm_ability = min( temp,MAXTGVAL ); + } + + /* calcualte mining ability */ + temp = (minepts/3 + cityfolk/2 + townfolk/2 + blksmths); + if( magic(country,MINER) ) + temp += 15; + if( magic(country,STEEL) ) + temp += 15; + if (temp >= curntn->mine_ability) { + curntn->mine_ability = min( temp,MAXTGVAL ); + } else { + curntn->mine_ability -= (curntn->mine_ability - temp)/4; + } + + /* calculate knowledge */ + temp = cityfolk/2 + townfolk/6 + scholars/2; + curntn->knowledge = min( temp,MAXTGVAL ); + + /* find national popularity */ + temp = (curntn->wealth + 10*P_EATRATE + clerics + curntn->popularity)/2; + curntn->popularity = min( temp,MAXTGVAL ); + + if(magic(country,SLAVER)) curntn->terror+=PWR_NA; + if(magic(country,RELIGION)) curntn->popularity+=PWR_NA; + if(magic(country,URBAN)) { + if(curntn->popularity > PWR_NA) + curntn->popularity-=PWR_NA; + else curntn->popularity=0; + } + if(magic(country,DEMOCRACY)) { + curntn->eatrate += 25; + if(curntn->terror > PWR_NA) + curntn->terror-=PWR_NA; + else curntn->terror=0; + if (curntn->charity < 15) { + /* it creeps up */ + curntn->charity+=2; + } + } + if(magic(country,KNOWALL)) curntn->knowledge+=PWR_NA; + if(magic(country,ARCHITECT)){ + if(curntn->spoilrate>=PWR_NA) + curntn->spoilrate-=PWR_NA; + else curntn->spoilrate=1; + } + if(magic(country,ROADS)) curntn->communications+=50; + if(magic(country,DESTROYER)) curntn->terror+=PWR_NA; + if(magic(country,ROADS)) curntn->terror+=PWR_NA; + if(magic(country,VAMPIRE)) curntn->terror+=PWR_NA; + + switch(curntn->class){ + case C_NPC: curntn->popularity+=CLA_NA; + curntn->terror+=CLA_NA; break; + case C_KING: curntn->popularity+=CLA_NA; break; + case C_TRADER: curntn->wealth+=CLA_NA; + curntn->popularity+=CLA_NA; + curntn->prestige+=CLA_NA/3; break; + case C_EMPEROR: curntn->wealth+=CLA_NA; + curntn->popularity+=CLA_NA; + curntn->prestige+=CLA_NA/3; break; + case C_WIZARD: curntn->knowledge+=CLA_NA; break; + case C_PRIEST: curntn->popularity+=CLA_NA; break; + case C_PIRATE: curntn->terror+=CLA_NA; break; + /* for warlord remember it is recursive */ + case C_WARLORD: curntn->prestige+=CLA_NA*2/3; break; + case C_DEMON: curntn->terror+=CLA_NA; break; + case C_DRAGON: curntn->terror+=CLA_NA; break; + case C_SHADOW: curntn->terror+=CLA_NA; break; + } + + curntn->prestige = min( curntn->prestige, MAXTGVAL ); + curntn->popularity = min( curntn->popularity, MAXTGVAL ); + curntn->power = min( curntn->power, MAXTGVAL ); + curntn->communications = min( curntn->communications, 2*MAXTGVAL); + curntn->wealth = min( curntn->wealth, MAXTGVAL ); + curntn->eatrate = min( curntn->eatrate, MAXTGVAL ); + curntn->knowledge = min( curntn->knowledge, MAXTGVAL ); + curntn->farm_ability = min( curntn->farm_ability, MAXTGVAL ); + curntn->mine_ability = min( curntn->mine_ability, MAXTGVAL ); + curntn->terror = min( curntn->terror, MAXTGVAL ); + curntn->reputation = min( curntn->reputation, MAXTGVAL ); + } +} + +/* calculates a nations bonuses due to trade goods */ +void +att_bonus() +{ + short x,y,nation,good; + struct s_sector *sptr; + printf("working on exotic trade goods\n"); + for(x=0;xowner; + curntn = &ntn[nation]; + + if( !tg_ok( nation, sptr) ) continue; + + good = sptr->tradegood; + + if(( *(tg_stype+good)== sptr->designation ) + ||(( *(tg_stype+good)== DTOWN )&&(sptr->designation==DCITY)) + ||(( *(tg_stype+good)== DTOWN )&&(sptr->designation==DCAPITOL)) + ||(( *(tg_stype+good)== DCITY )&&(sptr->designation==DCAPITOL)) + ||(( *(tg_stype+good)== DUNIVERSITY )&&(sptr->designation==DCITY)) + ||(( *(tg_stype+good)== DUNIVERSITY )&&(sptr->designation==DCAPITOL)) + ||( *(tg_stype+good)== 'x' )) + if( good <= END_POPULARITY ) { + curntn->popularity += ( *(tg_value+good) - '0'); + curntn->popularity = min( MAXTGVAL, curntn->popularity ); + } else if( good <= END_COMMUNICATION ) { + if(curntn->communications + (*(tg_value+good) - '0')<2*MAXTGVAL) + curntn->communications += (*(tg_value+good) - '0'); + else curntn->communications = 2*MAXTGVAL; + } else if( good <= END_EATRATE ) { /* eatrate scaled already */ + /* no tradegoods for eatrate */ + curntn->eatrate = min( MAXTGVAL, curntn->eatrate ); + } else if( good <= END_SPOILRATE ) { + if(curntn->spoilrate > (*(tg_value+good) - '0')) + curntn->spoilrate -= (*(tg_value+good)-'0'); + else curntn->spoilrate = 1; + } else if( good <= END_KNOWLEDGE ) { + if(curntn->knowledge + (*(tg_value+good)-'0') < MAXTGVAL) + curntn->knowledge += (*(tg_value+good) - '0'); + else curntn->knowledge = MAXTGVAL; + } else if( good <= END_FARM ) { + if(curntn->farm_ability + (*(tg_value+good) - '0') < MAXTGVAL) + curntn->farm_ability += (*(tg_value+good)-'0'); + else curntn->farm_ability = MAXTGVAL; + } else if( good <= END_SPELL ) { + curntn->spellpts += sptr->people/1000 +1; + } else if( good <= END_TERROR ) { + if(curntn->terror + (*(tg_value+good)-'0')< MAXTGVAL) + curntn->terror += (*(tg_value+good)-'0'); + else curntn->terror = MAXTGVAL; + } + } +} diff --git a/original/cexecute.c b/original/cexecute.c new file mode 100644 index 0000000..8fdc946 --- /dev/null +++ b/original/cexecute.c @@ -0,0 +1,327 @@ +/*conquer : Copyright (c) 1988 by Ed Barlow. + * I spent a long time writing this code & I hope that you respect this. + * I give permission to alter the code, but not to copy or redistribute + * it without my explicit permission. If you alter the code, + * please document changes and send me a copy, so all can have it. + * This code, to the best of my knowledge works well, but it is my first + * 'C' program and should be treated as such. I disclaim any + * responsibility for the codes actions (use at your own risk). I guess + * I am saying "Happy gaming", and am trying not to get sued in the process. + * Ed + */ + +/*EXECUTE THE PROGRAM*/ +#include +#include +#include +#include +#include "header.h" +#include "data.h" +extern long startgold; +extern short country; +extern FILE *fexe, *fnews; +extern char fison[]; + +#ifdef CONQUER +extern int roads_this_turn; +extern int terror_adj; +#endif + +int +execute(isupdate) +int isupdate; /* 0 if not update, 1 if update */ +{ + FILE *fp, *fopen(); + int cmd,savectry; + char comment[LINELTH]; + char temp[LINELTH]; + long longvar,long2var; + int armynum; + short int x,y; + int execed=0; + int done=FALSE; + char line[BIGLTH]; + + /* initialize startgold */ + if( isupdate==0) startgold = curntn->tgold; + + /* initialize i_people */ + for(x=0;x= 32K */ + sct[x][y].i_people = sct[x][y].people/256; + else + sct[x][y].i_people = -1; + + /*open exefile file*/ + sprintf(line,"%s%d",exefile,country); + if ((fp=fopen(line,"r"))==NULL) { + /*THIS MEANS THAT THE NATION HAS NOT MOVED YET*/ + return(0); + } + savectry=country; + + /*read in file*/ + if(fgets(line,80,fp)==NULL) done=TRUE; + while(done==FALSE) { + /*read and parse a new line*/ + /*CODE IF YOU USE LONG VAR IS L_*/ + if( line[0] == 'L' && line[1] == '_' ) { + sscanf(line,"%s %d %hd %ld %ld %hd %s", + temp,&cmd,&country,&longvar,&long2var,&y,comment); + } else { + sscanf(line,"%s %d %hd %d %hd %hd %s", + temp,&cmd,&country,&armynum,&x,&y,comment); + } + curntn = &ntn[country]; + + execed=1; + switch(cmd){ + case XASTAT: /*Aadjstat*/ + if(x>0) P_ASTAT=x; + break; + case XAMEN: /*Aadjmen*/ + armynum= (int) longvar; + P_ASOLD= (int) long2var; + P_ATYPE= y; + break; + case XBRIBE: /* nation has been bribed */ + if(!isupdate) break; /* only work on update */ + ntn[y].tgold += longvar; +#ifdef DEBUG + fprintf(stderr,"DEBUG: BRIBE BY %s of %s\n",ntn[country].name,ntn[y].name); +#endif /* DEBUG */ + /* x represents chance of successful bribe */ + if(npctype(curntn->active)==npctype(ntn[y].active)) + x = 50; + else if(isneutral(ntn[y].active)) x=30; + else if(npctype(ntn[y].active)==ISOLATIONIST) x=15; + else x = 20; + if(curntn->race==ntn[y].race) x+= 20; + if( rand()%100 < x){ +#ifdef DEBUG + fprintf(stderr,"DEBUG: BRIBE IS SUCCESS\n"); +#endif /* DEBUG */ + ntn[y].dstatus[country]--; + } + break; + case XALOC: /*Aadjloc*/ + P_AXLOC=x; + P_AYLOC=y; + break; + case MSETA: /*Aadjmerc*/ +#ifdef CONQUER + mercgot+=armynum; +#endif +#ifdef ADMIN + MERCMEN-=armynum; +#endif + break; + case MSETB: /*Aadjdisb*/ + /* only allow raising of merc bonus */ + if (x>MERCATT) + MERCATT=(MERCMEN*MERCATT+armynum*x)/(MERCMEN+armynum); + if (y>MERCDEF) + MERCDEF=(MERCMEN*MERCDEF+armynum*y)/(MERCMEN+armynum); + MERCMEN+=armynum; + break; + case XNLOC: /*nadjloc*/ + curntn->nvy[armynum].xloc=x; + curntn->nvy[armynum].yloc=y; + break; + case XNACREW: + curntn->nvy[armynum].crew=x; + curntn->nvy[armynum].armynum=y; + break; + case XNAMER: /*nadjmer*/ + curntn->nvy[armynum].merchant=x; + break; + case XNAWAR: /*nadjwar*/ + curntn->nvy[armynum].warships=x; + break; + case XNAGAL: /*nadjgal*/ + curntn->nvy[armynum].galleys=x; + break; + case XNAHOLD: /*nadjhld*/ + curntn->nvy[armynum].people=(unsigned char)y; + curntn->nvy[armynum].armynum=(unsigned char)x; + break; + case XECNAME: /*Nadjname*/ + strcpy(curntn->name,comment); + break; + case XECPAS: /*Nadjpas*/ + strncpy(curntn->passwd,comment,PASSLTH); + break; + case NPOP: /* set various nation attributes */ +#ifdef CONQUER + terror_adj++; +#endif /* CONQUER */ + curntn->popularity = armynum; + curntn->terror = x; + curntn->reputation = y; + break; + case NTAX: /* set nations tax rate */ +#ifdef ADMIN + if (ispc(curntn->active) && !ispc(x)) { + fprintf(fnews, "1.\tNation %s is now being run by the computer.\n", curntn->name); + } + if (ispc(x) && !ispc(curntn->active)) { + fprintf(fnews, "1.\tNation %s is no longer being run by the computer.\n", curntn->name); + } +#endif /*ADMIN*/ + curntn->tax_rate = armynum; + curntn->active = x; + curntn->charity = y; + break; + case EDSPL: /*Edecspl*/ + curntn->spellpts-=armynum; + break; + case XSADES: /*Sadjdes*/ + if((sct[x][y].owner!=country)&&(country!=0)) { + fprintf(stderr,"ERROR: <%s> redesignate sector %d,%d that is not owned\n",curntn->name,x,y); + break; + } + + sct[x][y].designation=comment[0]; + if(sct[x][y].designation==DCAPITOL){ + curntn->capx=x; + curntn->capy=y; + } +#ifdef CONQUER + if (sct[x][y].designation==DROAD) + roads_this_turn++; +#endif + break; + case XSACIV: /*Sadjciv*/ + /* if for some reason you dont own it, put people + back into your capitol */ + if((sct[x][y].owner!=country)&&(country!=0)) { + sct[curntn->capx][curntn->capy].people+=armynum; + break; + } + sct[x][y].people=armynum; + break; + case XSACIV3: /*Sadjciv3 - incremental people adjust */ + /* if you dont own it, put people in your capitol */ + if((sct[x][y].owner!=country)&&(country!=0)) { + sct[curntn->capx][curntn->capy].people+=armynum; + } + else + { + sct[x][y].people+=armynum; + } + break; + case XSIFORT: /*Sincfort*/ + sct[x][y].fortress++; + break; + case XNAGOLD: /*Nadjgold:*/ + curntn->tgold = longvar; + break; + case XAMOV: + P_AMOVE=x; + break; + case XNMOV: + curntn->nvy[armynum].smove=x; + break; + case XSAOWN: + /* if not own it, and if people there, problem */ + if((sct[x][y].owner!=country) + &&( country!=0) + &&( sct[x][y].owner!=0 ) + &&( sct[x][y].people>0 ) + &&( magic(country,SLAVER)==FALSE ) + &&( ntn[sct[x][y].owner].race != curntn->race)){ + sct[ntn[sct[x][y].owner].capx][ntn[sct[x][y].owner].capy].people+= sct[x][y].people; + sct[x][y].people=0; + fprintf(stderr,"ERROR: <%s> taking sector %d %d but civilians exist of other race - puting them in their capitol\n",curntn->name,x,y); + } + if(curntn->popularitypopularity++; + sct[x][y].owner=country; + break; + case EDADJ: + curntn->dstatus[armynum]=x; + break; + case XNARGOLD: + curntn->jewels = longvar; + break; + case XNAMETAL: + curntn->metals = longvar; + break; + case INCAPLUS: + curntn->aplus++; + break; + case INCDPLUS: + curntn->dplus++; + break; + case DESTRY: + sct[ntn[armynum].capx][ntn[armynum].capy].owner=savectry; + country=armynum; + if (isupdate) destroy(country); + country=savectry; + break; + case CHG_MGK: + curntn->powers|=long2var; + if(curntn->powers!=longvar){ + printf("\nERROR ON MAGIC READ country=%d %ld != %ld (or of %ld)",country,longvar,curntn->powers,long2var); + getchar(); + } + for(armynum=0;armynum<=MAXPOWER;armynum++) { + longvar = 1L << armynum; + if (longvar & long2var) + exenewmgk(longvar); + } + long2var=0; + break; + } + if(fgets(line,80,fp)==NULL) done=TRUE; + } + fclose(fp); + /*return 1 if it did something*/ + country=savectry; + curntn = &ntn[country]; + if(execed==1) return(1); + else return(0); +} +#ifdef CONQUER +void +hangup() +{ + char line[LINELTH]; + + if(country==0) writedata(); + else { + fprintf(fexe,"L_NGOLD\t%d \t%d \t%ld \t0 \t0 \t%s\n", + XNAGOLD ,country,curntn->tgold,"null"); + fprintf(fexe,"L_NMETAL\t%d \t%d \t%ld \t0 \t0 \t%s\n", + XNAMETAL ,country,curntn->metals,"null"); + fprintf(fexe,"L_NJWLS\t%d \t%d \t%ld \t0 \t0 \t%s\n", + XNARGOLD ,country,curntn->jewels,"null"); + } + /*close file*/ + fclose(fexe); + + /* remove any existing mail reading/writing file */ + if (mailok!=DONEMAIL) { + extern char tmp_mail_name[]; + unlink(tmp_mail_name); + } + + /* remove the lock file */ + unlink(fison); + sprintf(line,"%s%hd.tmp",msgfile,country); + unlink(line); + + /*send a message to God*/ + if(mailopen( 0 )!=(-1)) { + fprintf(fm,"WARNING: Nation %s hungup on me.\n",curntn->name); + mailclose(0); + } + + /* exit program */ + exit(FAIL); +} +#endif /* CONQUER */ diff --git a/original/check.c b/original/check.c new file mode 100644 index 0000000..6a5ff48 --- /dev/null +++ b/original/check.c @@ -0,0 +1,254 @@ +/* Conquer: Copyright (c) 1988 by Edward M Barlow */ +/* check.c contains checking and debugging functions */ + +#include +#include +#ifndef FILELOCK +#include +#include +#endif +#include "header.h" +#include "data.h" + +void +verify_ntn( __file__, __line__ ) +char __file__[]; +int __line__; +{ + register struct s_nation *nptr; + register int i; + register int country; + int j, k; + struct army *a; + + for( country = 0; country < NTOTAL; country++ ) { + nptr = &ntn[country]; + + if(country !=0 && nptr->active == 0) continue; + if( nptr->metals < 0.0 ) { + fprintf( stderr, "file %s: line %d: nation[%d] metal = %ld\n", + __file__, __line__, country, nptr->metals ); + nptr->metals = 0.0; + } + + if( nptr->jewels < 0 ) { + fprintf( stderr, "file %s: line %d: nation[%d] jewels = %ld\n", + __file__, __line__, country, nptr->jewels ); + nptr->jewels = 0.0; + } + + for( i = 0; i < MAXARM; i++ ) { + a = &nptr->arm[i]; + if( a->sold < 0 ) { + fprintf( stderr, "file %s: line %d: nation[%d] army[%d] sold = %d\n", + __file__, __line__, country, i, a->sold ); + a->sold = 0; + } + if( a->sold==0 ) continue; + if( a->xloc >= MAPX ) { + fprintf( stderr, "file %s: line %d: nation[%d] army[%d] xlocation = %d\n", + __file__, __line__, country, i, a->xloc ); + a->xloc = 0; + } + if( a->yloc >= MAPY ) { + fprintf( stderr, "file %s: line %d: nation[%d] army[%d] ylocation = %d\n", + __file__, __line__, country, i, a->yloc ); + a->yloc = 0; + } + if( a->stat == ONBOARD) { + if (a->smove != 0) { + fprintf( stderr, "file %s: line %d: nation[%d] army[%d] onboard move = %d\n", + __file__, __line__, country, i, a->smove ); + a->smove = 0; + } + k = 0; + for (j = 0; j < MAXNAVY; j++) { + if (nptr->nvy[j].warships == 0 + && nptr->nvy[j].merchant == 0 + && nptr->nvy[j].galleys == 0) + continue; + if (nptr->nvy[j].armynum == i) { + k = 1; + } + } + if (k == 0) { + fprintf(stderr, "files %s: line %d: nation[%d] army[%d] onboard nothing\n", + __file__,__line__,country,i); + a->stat = DEFEND; + } + } + if( a->stat != ONBOARD && sct[a->xloc][a->yloc].altitude==WATER ) { + fprintf( stderr, "file %s: line %d: nation[%d] army[%d] loc=%d,%d (water) men=%d\n", + __file__,__line__,country,i,a->xloc,a->yloc,a->sold); + a->sold = 0; + } + } /* for */ + + for( i = 0; i < MAXNAVY; i++ ) { + if (nptr->nvy[i].warships == 0 + && nptr->nvy[i].merchant == 0 + && nptr->nvy[i].galleys == 0) + continue; + if (nptr->nvy[i].armynum != MAXARM) { + a = &(nptr->arm[nptr->nvy[i].armynum]); + if (a->sold == 0 || a->stat != ONBOARD) { + fprintf(stderr, "file %s: line %d: nation[%d] navy[%d] carrying invalid troop\n", + __file__,__line__,country,i); + nptr->nvy[i].armynum = MAXARM; + } + } + } /* for */ + + for( i = 0; i < NTOTAL; i++ ) { + if( ntn[i].active >= NPC_PEASANT ) { + if ( nptr->dstatus[i] != WAR ) { + nptr->dstatus[i] = WAR; + } + if ( ntn[i].dstatus[country] != WAR ) { + ntn[i].dstatus[country] = WAR; + } + } if( nptr->dstatus[i] > JIHAD ) { + fprintf( stderr, "file %s: line %d: nation[%d] diplomatic status with %d = %d\n", + __file__, __line__, country, i, nptr->dstatus[i] ); + nptr->dstatus[i] = WAR; + } + } /* for */ + } /* for */ +} /* verify_ntn() */ + +void +verify_sct( __file__, __line__ ) +char __file__[]; +int __line__; +{ + register struct s_sector *sptr; + register int x, y; + + for( x = 0; x < MAPX; x++ ) { + for( y = 0; y < MAPY; y++ ) { + sptr = &sct[x][y]; + + if(sptr->tradegood>TG_none) { + fprintf( stderr, "file %s: line %d: sct[%d][%d].tradegood = %d (invalid)\n", __file__, __line__, x, y, sptr->tradegood ); + sptr->tradegood=TG_none; + } + if(( sptr->metal != 0 ) + &&(( sptr->tradegood>END_MINE) + ||(sptr->tradegood<=END_NORMAL))) { + fprintf( stderr, "file %s: line %d: sct[%d][%d].metal = %d with no tradegood\n", __file__, __line__, x, y, sptr->metal ); + sptr->metal = 0; + } + + if(( sptr->jewels != 0 ) + &&((sptr->tradegood>END_WEALTH) + ||(sptr->tradegood<=END_MINE))) { + fprintf( stderr, "file %s: line %d: sct[%d][%d].jewels = %d with no tradegood\n", __file__, __line__, x, y, sptr->jewels ); + sptr->jewels = 0; + } + + if( sptr->people > ABSMAXPEOPLE ) + sptr->people = ABSMAXPEOPLE; + + if( sptr->people < 0 ) { + fprintf( stderr, "file %s: line %d: sct[%d][%d].people = %d\n", __file__, __line__, x, y, sptr->people ); + if( sptr->people < -1*ABSMAXPEOPLE ) + sptr->people = ABSMAXPEOPLE; + else sptr->people = 0; + } + + if( sptr->owner != 0 && sptr->altitude == WATER ) { + fprintf( stderr, "file %s: line %d: sct[%d][%d].owner = %s (a water sector)\n",__file__,__line__, x, y, ntn[sptr->owner].name ); + sptr->owner = 0; + } + if( sptr->fortress > 12 ){ + fprintf( stderr, "file %s: line %d: sct[%d][%d].fortress = %d \n",__file__,__line__, x, y, sptr->fortress ); + sptr->fortress = 12; + } + } /* for */ + } /* for */ +} /* verify_sct() */ + +void +verifydata( __file__, __line__ ) +char __file__[]; +int __line__; +{ + /* check for invalid values */ + verify_ntn( __file__, __line__ ); + verify_sct( __file__, __line__ ); +}/* verifydata() */ + +#ifdef DEBUG +void +checkout(file,line) +int line; +char *file; +{ + fprintf(stderr,"file %s line %d\n",file,line); + verifydata(file,line); +} +#endif /* DEBUG */ + +#include +#ifdef FILELOCK +#ifdef LOCKF +# include +# define do_lock(fd) lockf(fd,F_TLOCK,0) +#else +# include +# include +# define do_lock(fd) flock(fd,LOCK_EX|LOCK_NB) +#endif +#endif /* FILELOCK */ + +/* + * check_lock() -- routine to check if a file is locked. + * - returns true if a lock is active false is not. + * - setting keeplock to true means leaves lock active + * if it is not already active. + */ +int +check_lock(filename,keeplock) + char *filename; + int keeplock; +{ + int hold=FALSE; +#ifdef FILELOCK + int fd; + + if ((fd=open(filename,O_WRONLY|O_CREAT,0600))!=(-1)) { + if(do_lock(fd)==(-1)) { + hold=TRUE; + } + /* remove lock after checking */ + if(keeplock==FALSE && hold==FALSE) { + close(fd); + unlink(filename); + } + } else { + printf("error opening lock file <%s>\n",filename); + exit(FAIL); + } +#else + struct stat fst; + + if( stat( filename, &fst ) == 0 ) { + long now; + now = time(0); + if (now - fst.st_mtime < TIME_DEAD*3) { + hold=TRUE; + } else { + /* remove useless file */ + unlink(filename); + } + } + if (hold==FALSE && keeplock==TRUE) { + /* create lock file */ + if(open(filename,O_CREAT,0600)==(-1)) { + printf("error opening lock file <%s>\n",filename); + exit(FAIL); + } + } +#endif /* FILELOCK */ + return(hold); +} diff --git a/original/combat.c b/original/combat.c new file mode 100644 index 0000000..933a9df --- /dev/null +++ b/original/combat.c @@ -0,0 +1,1377 @@ +/*conquer : Copyright (c) 1988 by Ed Barlow. + * I spent a long time writing this code & I hope that you respect this. + * I give permission to alter the code, but not to copy or redistribute + * it without my explicit permission. If you alter the code, + * please document changes and send me a copy, so all can have it. + * This code, to the best of my knowledge works well, but it is my first + * 'C' program and should be treated as such. I disclaim any + * responsibility for the codes actions (use at your own risk). I guess + * I am saying "Happy gaming", and am trying not to get sued in the process. + * Ed + */ + +#include +#include +#include +#include +#include "header.h" +#include "data.h" + +#define MGKNUM 32 /* number of units possible in battle */ +#define ATKR 2 +#define DFND 1 +#define NTRL 0 +#define WIMP 3 + +extern FILE *fpmsg; +extern FILE *fnews; +extern short country; + +short retreatside; /* ATKR, DFND, or none (0) */ +short retreatx; /* retreat x square */ +short retreaty; /* retreat y square */ + +int unit[MGKNUM]; /*armynum*/ +int owner[MGKNUM]; /*owner*/ +int side[MGKNUM]; /*see definitions->1=units 2=unit*/ +long troops[MGKNUM]; /*starting troops in army */ +int xspot,yspot; /*location of battles*/ +int anation; /*nation attacking in this fight*/ +int dnation; /*one nation defending in this fight*/ +int count=0; /*number of armies or navies in sector*/ + +/* indicators of naval or army combat */ +#define COMBAT_X 0 +#define COMBAT_A 1 +#define COMBAT_N 2 +#define FOUGHT_A 4 +#define FOUGHT_N 8 + +/************************************************************************/ +/* COMBAT() run all combat on the map */ +/* for each sector, determine if armies in with attack mode */ +/************************************************************************/ +void +combat() +{ + register int i,j; + char **fought; /* SET: if already fought in sctr */ + int temp,ctry; + int initialized=FALSE; /* TRUE if arrays initialized */ + short armynum,nvynum; + int valid; + struct s_nation *nptr; + struct army *aptr; + + fought = (char **) m2alloc(MAPX,MAPY,sizeof(char)); + + printf("Run Combat Routines\n"); + fprintf(fnews,"4\tBATTLE SUMMARY STATISTICS\n"); + /*for each nation, if in attack mode run a check*/ + + /* no sectors have been fought in yet */ + for(i=0;i0;ctry--) if(isactive(ntn[ctry].active)) { + + nptr = &ntn[ctry]; + + /*army combat*/ + for(j=0;jarm[j]; + if((aptr->sold>0) + &&(aptr->stat>=ATTACK) + &&(aptr->stat<=SORTIE||aptr->stat>=NUMSTATUS) + &&(!(fought[aptr->xloc][aptr->yloc]&COMBAT_A))){ + + /* someone can initiate combat in xspot,yspot */ + xspot=aptr->xloc; + yspot=aptr->yloc; + fought[xspot][yspot]|=COMBAT_A; + + /*initialize matrix*/ + if( !initialized ) { + for(temp=0;temp0) + &&(ASTAT!=SCOUT) + &&(AXLOC==xspot) + &&(AYLOC==yspot) + &&(countdstatus[country]>HOSTILE)) { + valid=TRUE; + if( sct[xspot][yspot].owner==ctry ) { + dnation=ctry; + anation=country; + } else if(( rand()%2==0 ) + ||( sct[xspot][yspot].owner==country )){ + anation=ctry; + dnation=country; + } else { + dnation=ctry; + anation=country; + } + } + unit[count]=armynum; + owner[count]=country; + count++; + } + + if(valid==TRUE) { + fight(); + initialized=FALSE; + } + } + } + + /*navy combat*/ + for(j=0;jnvy[j].warships!=0) + &&(!(fought[nptr->nvy[j].xloc][nptr->nvy[j].yloc]&COMBAT_N))) { + + xspot=nptr->nvy[j].xloc; + yspot=nptr->nvy[j].yloc; + fought[xspot][yspot]|=COMBAT_N; + + /*initialize matrix*/ + if( !initialized ){ + for(temp=0;tempdstatus[country]>HOSTILE)){ + valid=TRUE; + anation=ctry; + dnation=country; + } + unit[count]=nvynum; + owner[count]=country; + count++; + } + if(valid==TRUE) { + navalcbt(); + initialized=FALSE; + } + } + } + free(fought); + printf("\nall army and navy attacks completed\n"); +} + +/* macro for owner, accounts for runaway indicator */ +#define UOWNER(x) ((owner[(x)]<(-1))?(-owner[(x)]-1):(owner[(x)])) +/************************************************************************/ +/* FIGHT() - fight an individual battle given the three */ +/* matricies global to this module */ +/************************************************************************/ +void +fight() +{ + int roll,strength,fortdam=FALSE; + int odds; /* odds (asold/dsold) times 100 */ + int done; + int i,j,k; + long asold=0,dsold=0; /*a's and d's total soldiers*/ + float astr=0,dstr=0; /*a's and d's relative strength*/ + long Aloss,Dloss; /*a's and d's total losses*/ + int PAloss,PDloss; /*percent a and d loss*/ + long loss; + int abonus=0,dbonus=0; /* bonus aggregate */ + long vampire=0; /* # non vamps deaded */ + short nvamps=0; /* number of vampire armies */ + + /* determine who is attacker & who is on defenders side?*/ + for(j=0;jHOSTILE)) side[j]=ATKR; + else if((ntn[owner[j]].dstatus[anation]==ALLIED)&&(ntn[owner[j]].dstatus[dnation]>HOSTILE)) side[j]=ATKR; + } + + /*calculate number of troops and assign statuses */ + asold=0; + dsold=0; + for(i=0;i(-1)) { + /* record troops for all units in sector */ + troops[i]=ntn[owner[i]].arm[unit[i]].sold; + + if(((ntn[owner[i]].arm[unit[i]].unittyp == A_MERCENARY) + ||(ntn[owner[i]].arm[unit[i]].unittyp == A_ORC) + ||(ntn[owner[i]].arm[unit[i]].unittyp == A_GOBLIN)) + &&( ntn[owner[i]].arm[unit[i]].stat < NUMSTATUS ) + &&( rand()%100<15 )) { + if( ispc(ntn[owner[i]].active)) { + if (mailopen( owner[i] )!=(-1)) { + fprintf(fm,"Message to %s from Conquer\n\n",ntn[owner[i]].name); + fprintf(fm," Your %s Army %d Refuses to Fight\n", + unittype[ntn[owner[i]].arm[unit[i]].unittyp], + unit[i]); + mailclose(owner[i]); + } + } + retreatside = side[i]; + fdxyretreat(); + if((retreatx==xspot)&&(retreaty==yspot)){ + /* move to capitol & kill 30% */ + ntn[owner[i]].arm[unit[i]].xloc=ntn[owner[i]].capx; + ntn[owner[i]].arm[unit[i]].yloc=ntn[owner[i]].capy; + ntn[owner[i]].arm[unit[i]].sold*=7; + ntn[owner[i]].arm[unit[i]].sold/=10; + } else { + /* retreat normally and kill 20% */ + ntn[owner[i]].arm[unit[i]].sold*=8; + ntn[owner[i]].arm[unit[i]].sold/=10; + retreat( i ); + } + owner[i]=(-1-owner[i]); + continue; + } + else if(side[i]==ATKR){ + if ((ntn[owner[i]].arm[unit[i]].stat >= ATTACK) + &&(ntn[owner[i]].arm[unit[i]].stat <= SORTIE + ||ntn[owner[i]].arm[unit[i]].stat >= NUMSTATUS)) { + asold += ntn[owner[i]].arm[unit[i]].sold; + } else { + side[i]=NTRL; + } + /* sortie 20% bonus in odds */ + if(ntn[owner[i]].arm[unit[i]].stat==SORTIE) + asold += ntn[owner[i]].arm[unit[i]].sold/5; + } else if(side[i]==DFND){ + if(ntn[owner[i]].arm[unit[i]].stat!=RULE) { + dsold += ntn[owner[i]].arm[unit[i]].sold; + } + } + if((magic(owner[i],VAMPIRE)==TRUE) && + (ntn[owner[i]].arm[unit[i]].unittyp==A_ZOMBIE)) nvamps++; + } + + if(asold<=0) { + printf("\nCombat aborted due to lack of attackers.\n"); + return; + } + if( asold > dsold*100) odds=10000; + else if( dsold > asold*100 ) odds=1; + else odds = (asold*100)/dsold; + + /* mercenaries/orcs/goblins might run away */ + for(i=0;i(-1)) { + if(((( odds > 200 )&&(side[i]==DFND)) + ||(( odds < 100 )&&(side[i]==ATKR))) + &&((ntn[owner[i]].arm[unit[i]].unittyp == A_MERCENARY) + ||(ntn[owner[i]].arm[unit[i]].unittyp == A_ORC) + ||(ntn[owner[i]].arm[unit[i]].unittyp == A_GOBLIN)) + &&(ntn[owner[i]].arm[unit[i]].stat < NUMSTATUS) + &&( rand()%100<30 )) { + if( ispc(ntn[owner[i]].active)) { + if(mailopen( owner[i] )!=(-1)) { + fprintf(fm,"Message to %s from Conquer\n\n",ntn[owner[i]].name); + fprintf(fm," Your %s Army %d Runs Away\n", + unittype[ntn[owner[i]].arm[unit[i]].unittyp], + unit[i]); + mailclose(owner[i]); + } + } + retreatside = side[i]; + if( side[i] == ATKR ) asold-= troops[i]; + if( side[i] == DFND ) dsold-= troops[i]; + fdxyretreat(); + if((retreatx==xspot)&&(retreaty==yspot)){ + /* move to capitol & kill 75% */ + ntn[owner[i]].arm[unit[i]].xloc=ntn[owner[i]].capx; + ntn[owner[i]].arm[unit[i]].yloc=ntn[owner[i]].capy; + ntn[owner[i]].arm[unit[i]].sold/=4; + } else { + /* retreat normally and kill 50% */ + ntn[owner[i]].arm[unit[i]].sold/=2; + retreat( i ); + } + owner[i]=(-1-owner[i]); + continue; + } + } + retreatside=0; + if( asold<=0 ) { + printf("Exit from battle due to lack of attackers\n"); + return; + } + + /* CALCULATE AVERAGE COMBAT BONUS */ + abonus=0; + dbonus=0; + for(i=0;i(-1)) { + if(side[i]==ATKR) + abonus += cbonus(i)*troops[i]; + else if(side[i]==DFND && ntn[owner[i]].arm[unit[i]].stat!=RULE) + dbonus += cbonus(i)*troops[i]; + } + + /*archer bonus if not in fort vs knights/cavalry*/ + j=0; + k=0; + for(i=0;i(-1)) + if(ISCITY(sct[xspot][yspot].designation)){ + if((ntn[owner[i]].arm[unit[i]].unittyp == A_CAVALRY) + ||(ntn[owner[i]].arm[unit[i]].unittyp == A_KNIGHT)) + if(side[i]==ATKR) j+=troops[i]; + else if(side[i]==DFND) k+=troops[i]; + } + + for(i=0;i(-1)) { + if(j>0) abonus += (15 * j * troops[i]) / asold; + if(k>0 && dsold>0) dbonus += (15 * k * troops[i]) / dsold; + } + + abonus/=asold; + if (dsold>0) dbonus/=dsold; + + /*CALCULATED BONUSES TO WHOLE COMBAT*/ + for(i=0;i(-1)) { + if(fort_val(&sct[xspot][yspot]) != 0){ + /*Catapults add +1%/20 men defending castle (max +10%)*/ + if((ntn[owner[i]].arm[unit[i]].unittyp == A_CATAPULT) + &&(side[i]==DFND)) + dbonus += max((troops[i]/20),10); + /*Catapults add +1%/40 men attacking castle (max +10%)*/ + else if((ntn[owner[i]].arm[unit[i]].unittyp == A_CATAPULT) + &&(side[i]==ATKR)) { + strength = max((troops[i]/40),10); + abonus += strength; + /* possible damage 20% chance */ + if(rand()%100<2*strength) { + fortdam=TRUE; + sct[xspot][yspot].fortress--; + if(sct[xspot][yspot].fortress == 0) + sct[xspot][yspot].designation = DRUIN; + } + } + /*Siege_engines add +1%/20 men when attacking fortress*/ + else if((ntn[owner[i]].arm[unit[i]].unittyp == A_SIEGE) + &&(side[i]==ATKR)) { + strength = max((troops[i]/20),30); + abonus += strength; + /* possible damage 15% chance */ + if(rand()%100 dstr*100) odds=10000; + else if( dstr > astr*100 ) odds=1; + else odds = (astr*100)/dstr; + + /* calculate loss for an even battle */ + PDloss = MAXLOSS * roll / 100; + PAloss = MAXLOSS * (100 - roll) / 100; + + /* adjust for odds */ + if( odds == 1 ) { + PDloss=0; + PAloss=200; + } else if( odds == 10000 ) { + PAloss=0; + PDloss=200; + } else if(odds > 100) { + PDloss += (odds / 12 - 8); /* 8.33% for higher odds */ + PAloss -= (odds / 16 - 6); /* 6.25% for lower odds */ + if(PAloss<(100-roll)/20) + PAloss=(100-roll)/20; /* can't get too small */ + } else { + PAloss += ( 800 / odds - 8); /* 8% for higher odds */ + PDloss -= ( 600 / odds - 6); /* 6% for lower odds */ + if(PDloss 0 ){ + PDloss *= 120; + PAloss *= 120; + PDloss /= 100; + PAloss /= 100; + } + + retreatside = 0; + + if((PDloss > 2* PAloss) + &&(odds>150) + &&(((PDloss>=50)&&(rand()%4==0)) + ||(rand()%8))) retreatside=DFND; + + if((PAloss > 2* PDloss) + &&(odds<150) + &&(((PAloss>=50)&&(rand()%2==0)) + ||(rand()%6))) retreatside=ATKR; + + if(retreatside!=0) { + fdxyretreat(); + /* no legal retreat route */ + if((retreatside!=0) && (retreatx== xspot) + && (retreaty== yspot)){ + if(retreatside==ATKR) PAloss+=15; + else if(retreatside==DFND) PDloss+=15; +#ifdef DEBUG + printf("side %d (%d %d) can't retreat...+15%% loss\n",retreatside,retreatx,retreaty); +#endif /* DEBUG */ + retreatside = 0; + } +#ifdef DEBUG + else printf("retreat side %d to %d %d\n",retreatside,retreatx,retreaty); +#endif /* DEBUG */ + } + + if(PAloss>100) PAloss = 100; + if(PDloss>100) PDloss = 100; + + Aloss = Dloss = 0; + for(i=0;i(-1)){ + if(side[i]==ATKR){ + if( ntn[owner[i]].arm[unit[i]].unittyp >= MINLEADER) { + if((rand()%100) < PAloss){ /* kill it */ + for(j=0;j 0) + &&(sct[xspot][yspot].owner==country) + &&((ntn[owner[i]].arm[unit[i]].unittyp==A_ARCHER) + ||(ntn[owner[i]].arm[unit[i]].unittyp==A_CATAPULT))) + loss /= 4; + /*army can't have less than 25 men in it*/ + if(troops[i]-loss<25) + loss=troops[i]; +if( loss>troops[i] ) { +printf("I AM VERY CONFUSED - PLEASE HELP... combat.c\n"); +} + Aloss+=loss; + ntn[owner[i]].arm[unit[i]].sold-=loss; + if((ntn[owner[i]].arm[unit[i]].unittyp==A_MILITIA)&&(retreatside==ATKR)) { + sct[ntn[owner[i]].arm[unit[i]].xloc][ntn[owner[i]].arm[unit[i]].yloc].people += ntn[owner[i]].arm[unit[i]].sold; + ntn[owner[i]].arm[unit[i]].sold=0; + } + } + } else if(side[i]==DFND){ + if( ntn[owner[i]].arm[unit[i]].unittyp >= MINLEADER) { + if((ntn[owner[i]].arm[unit[i]].stat!=RULE + ||PDloss>=80)&&((rand()%100) < PDloss)){ /* kill it */ + for(j=0;j0)&&(magic(owner[i],VAMPIRE)==FALSE) + &&(ntn[owner[i]].arm[unit[i]].unittyp!=A_ZOMBIE) + &&(ntn[owner[i]].arm[unit[i]].unittyp(-1)){ + done=FALSE; + for(i=0;i79) { + k = 30; + fprintf(fnews,",\n4.\t "); + } else fprintf(fnews,", "); + if(loss==ATKR) + fprintf(fnews,"attacker %s",ntn[UOWNER(j)].name); + else if(loss==DFND) + fprintf(fnews,"defender %s",ntn[UOWNER(j)].name); + else if(loss==WIMP) + fprintf(fnews,"retreater %s",ntn[UOWNER(j)].name); + } + } + } + fprintf(fnews,"\n"); + if(nvamps>0){ + for(i=0;i(-1)){ + if((magic(owner[i],VAMPIRE)==TRUE) + &&(ntn[owner[i]].arm[unit[i]].unittyp==A_ZOMBIE) + &&(ntn[owner[i]].arm[unit[i]].sold > 0)) + ntn[owner[i]].arm[unit[i]].sold+=vampire/nvamps; + } + } + + /*who is in the battle; but don't send to scared armies */ + for(j=0;j(-1)){ + done=FALSE; + + /*first time your nation appears done=FALSE*/ + for(i=0;i= MINLEADER) + &&( ntn[UOWNER(k)].arm[unit[k]].sold == 0)) + fprintf(fm," (killed)\n"); + else if((ntn[UOWNER(k)].arm[unit[k]].unittyp == A_MILITIA) + &&( ntn[UOWNER(k)].arm[unit[k]].sold == 0)) + fprintf(fm," (disbanded)\n"); + else fputc('\n',fm); + } + + fprintf(fm,"attacking soldiers=%ld -> percent loss %d%%\n",asold,PAloss); + fprintf(fm,"defending soldiers=%ld -> percent loss %d%%\n",dsold,PDloss); + fprintf(fm,"ODDS=%d => adjusted to %d to 100; Die Roll is %d\n",odds*(100+dbonus)/(100+abonus),odds,roll); + fprintf(fm,"RESULT: Attackers lose %ld men, Defenders lose %ld men\n",Aloss, Dloss); + if(fortdam==TRUE) fprintf(fm,"Fortifications damaged during the attack\n"); + if(retreatside==ATKR){ + if(Aloss=NUMSTATUS) armbonus+=20; /* army group */ + if(side[num]==DFND){ + + if(sct[xspot][yspot].altitude==MOUNTAIN) armbonus+=20; + else if(sct[xspot][yspot].altitude==HILL) armbonus+=10; + + if(sct[xspot][yspot].vegetation==JUNGLE) armbonus+=20; + else if(sct[xspot][yspot].vegetation==FOREST) armbonus+=15; + else if(sct[xspot][yspot].vegetation==WOOD) armbonus+=10; + + if(ATYPE==A_MERCENARY) armbonus += MERCDEF; + else armbonus += ntn[UOWNER(num)].dplus; + + if(ASTAT==MAGDEF) armbonus+=30; + else if(ASTAT==SORTIE) armbonus-=30; + else if(ASTAT==SIEGED) armbonus-=20; + + if((sct[xspot][yspot].owner==country) + &&(ASTAT==GARRISON||ASTAT==MILITIA||ASTAT==SIEGED)){ + if(ATYPE == A_ZOMBIE) /* don't utilize walls well */ + armbonus += fort_val(&sct[xspot][yspot])/2; + else armbonus += fort_val(&sct[xspot][yspot]); + } + } + else if(side[num]==ATKR) { + if( (fort_val(&sct[xspot][yspot]) > 0) + &&( magic(country,SAPPER)==TRUE)) armbonus += 10; + + if(ATYPE == A_MERCENARY) armbonus += MERCATT; + else armbonus += ntn[UOWNER(num)].aplus; + if(ASTAT==MAGATT) armbonus += 30; + if(ASTAT==SORTIE && (fort_val(&sct[xspot][yspot]) > 0) + && sct[xspot][yspot].owner==country) { + armbonus += 10; + if((ATYPE==A_DRAGOON)||(ATYPE==A_LEGION) + ||(ATYPE==A_PHALANX)) { + /* bonus for organization or riding cavalry */ + armbonus += 5; + } else if ((ATYPE==A_LT_CAV)||(ATYPE==A_CAVALRY)) { + /* bonus for mounted sortie */ + armbonus += 10; + } else if (avian(ATYPE)||ATYPE==A_ELEPHANT||ATYPE==A_KNIGHT) { + /* bonus for mounted or flying sortie */ + armbonus += 15; + } + if ((ATYPE>=MINMONSTER)||(ATYPE<=MAXMONSTER)) { + /* bonus for monsters (scare factor) */ + armbonus += 5; + } + } + } + + /*army status is important*/ + if(ASTAT==MARCH) armbonus-=40; + + /*if a fortress*/ + if(fort_val(&sct[xspot][yspot]) > 0){ + /*Cavalry and Knights get -20%*/ + if((ATYPE == A_CAVALRY) ||(ATYPE == A_KNIGHT)) armbonus -= 20; + /*Archers gain pluses*/ + else if((ATYPE == A_ARCHER)&&(sct[xspot][yspot].owner==country)) + armbonus += 15; + else if(ATYPE == A_ARCHER) armbonus += 5; + } + + if(side[num]==ATKR) armbonus+= *(unitattack+(ATYPE%UTYPE)); + else armbonus+= *(unitdefend+(ATYPE%UTYPE)); + + /*Phalanx and Legionaires need certain numbers of troops*/ + if((ATYPE==A_PHALANX)||(ATYPE==A_LEGION)) { + if(ASOLD>1000){ armbonus+=20; + } else if(ASOLD>500) armbonus+=10; + } + + return(armbonus); +} + +void +fdxyretreat() /* finds retreat location */ +{ + int x,y,nation=(-1); + int xsctr= xspot; + int ysctr= yspot; + + retreatx=xsctr; + retreaty=ysctr; + + if((sct[xsctr][ysctr].designation==DTOWN) + ||(sct[xsctr][ysctr].designation==DCAPITOL) + ||(sct[xsctr][ysctr].designation==DCITY)){ + retreatside=0; + return; + } + + if(retreatside == ATKR) nation=anation; + else nation=dnation; + + for(x= xsctr-1; x<=xsctr+1; x++) + for(y= ysctr-1; y<=ysctr+1; y++) if(ONMAP(x,y)){ + if(tofood( &sct[x][y], + sct[x][y].owner == country ? country : 0)==0) continue; + if(((sct[x][y].owner == nation) + ||(ntn[sct[x][y].owner].dstatus[nation] < NEUTRAL)) + ||(solds_in_sector( x, y, sct[x][y].owner) == 0)){ + retreatx=x; + retreaty=y; +#ifdef DEBUG + printf("armies in %d %d retreat to %d %d\n",xsctr,ysctr,x,y); +#endif /* DEBUG */ + return; + } + } +} + +void +retreat(unitnum) +int unitnum; /* if -1 then normal, else retreat only unit ismerc */ +{ + int cnum; + + if(retreatside == 0) return; + + for(cnum=0;cnum(-1)){ + if( unitnum != (-1) ) cnum=unitnum; + if(side[cnum] == retreatside){ + if ((ntn[owner[cnum]].arm[unit[cnum]].unittyp==A_MARINES)|| + (ntn[owner[cnum]].arm[unit[cnum]].unittyp==A_SAILOR)){ + ntn[owner[cnum]].arm[unit[cnum]].sold *= 85; + ntn[owner[cnum]].arm[unit[cnum]].sold /= 100; + } else { + ntn[owner[cnum]].arm[unit[cnum]].xloc = retreatx; + ntn[owner[cnum]].arm[unit[cnum]].yloc = retreaty; + } + } + if( unitnum != (-1) ) return; + } +} + + +/*SUBROUTINE TO RUN NAVAL COMBAT ON ALL SHIPS */ +/* quick define for easier reading */ +#define QWAR 1 +#define QGAL 2 +#define QMER 3 +/* just like fight, this takes array of owner,side,unit and calculates */ +/* a random battle based on the strengths of the combatants. */ +void +navalcbt() +{ + int acrew=0,dcrew=0; /*a's and d's crew and soldier strength*/ + int ahold=0,dhold=0; /*a's and d's warship strength*/ + int awsunk=0,dwsunk=0; /*a's and d's warship losses for the round*/ + int agsunk=0,dgsunk=0; /*a's and d's galley losses for the round*/ + int amsunk=0,dmsunk=0; /*a's and d's merchent losses for the round*/ + int awcapt=0,dwcapt=0; /*a's and d's warship captures for the round*/ + int agcapt=0,dgcapt=0; /*a's and d's galley captures for the round*/ + int amcapt=0,dmcapt=0; /*a's and d's merchant captures for the round*/ + int akcrew=0,dkcrew=0; /*a's and d's crew losses for the round*/ + char wnum[MGKNUM],gnum[MGKNUM],mnum[MGKNUM]; + register int done,i,j,k; + int roll,odds,savecntry=country; + int PAloss, PDloss, Ploss, which, shipsize; + int thold, ghold, nvynum, armynum; + int dcptpct, acptpct, cptpct; + struct s_nation *saventn=curntn; + void show_ships(),capture(); + + printf("In Naval Combat....\n"); + + /* determine who is attacker & who is on defenders side?*/ + for(j=0;jHOSTILE)) side[j]=ATKR; + else if((ntn[owner[j]].dstatus[anation]==ALLIED) + &&(ntn[owner[j]].dstatus[dnation]>HOSTILE)) side[j]=ATKR; + } + + /* Loop through all competitors to determine + * relative combat strengths: + * men/unit strength + * crew on ship: + * warship crew 1 + * galley crew 2 + * merchant crew 4 + * soldiers onboard: + * SAILOR/ARCHER 3/4 + * MARINE 1/3 + * others 4/3 + */ + for(j=0;j0) { + dhold += k; + if (magic(country,SAILOR)==TRUE) { + dcrew += 5*k*curntn->nvy[unit[j]].crew/4; + } else dcrew += k*curntn->nvy[unit[j]].crew; + } + if((k=fltmhold(unit[j]))>0) { + if (magic(country,SAILOR)==TRUE) { + dcrew += 5*k*curntn->nvy[unit[j]].crew/16; + } else dcrew += k*curntn->nvy[unit[j]].crew/4; + } + if((k=fltghold(unit[j]))>0) { + if (magic(country,SAILOR)==TRUE) { + dcrew += 5*k*curntn->nvy[unit[j]].crew/8; + } else dcrew += k*curntn->nvy[unit[j]].crew/2; + if(curntn->nvy[unit[j]].armynum!=MAXARM) { + k = curntn->nvy[unit[j]].armynum; + switch (curntn->arm[k].unittyp) { + case A_ARCHER: + case A_SAILOR: + dcrew += 3*curntn->arm[k].sold/2; + break; + case A_MARINES: + dcrew += 3*curntn->arm[k].sold; + break; + default: + dcrew += 3*curntn->arm[k].sold/4; + break; + } + } + } + } else if(side[j]==ATKR) { + if((k=fltwhold(unit[j]))>0) { + ahold += k; + if (magic(country,SAILOR)==TRUE) { + acrew += 5*k*curntn->nvy[unit[j]].crew/4; + } else acrew += k*curntn->nvy[unit[j]].crew; + } + if((k=fltmhold(unit[j]))>0) { + if (magic(country,SAILOR)==TRUE) { + acrew += 5*k*curntn->nvy[unit[j]].crew/16; + } else acrew += k*curntn->nvy[unit[j]].crew/4; + } + if((k=fltghold(unit[j]))>0) { + if (magic(country,SAILOR)==TRUE) { + acrew += 5*k*curntn->nvy[unit[j]].crew/8; + } else acrew += k*curntn->nvy[unit[j]].crew/2; + if(curntn->nvy[unit[j]].armynum!=MAXARM) { + k = curntn->nvy[unit[j]].armynum; + switch (curntn->arm[k].unittyp) { + case A_ARCHER: + case A_SAILOR: + acrew += 3*curntn->arm[k].sold/2; + break; + case A_MARINES: + acrew += 3*curntn->arm[k].sold; + break; + default: + acrew += 3*curntn->arm[k].sold/4; + break; + } + } + } + } + } + + /*find battle odds*/ + if( acrew > dcrew*100 ) odds=10000; + else if ( dcrew > acrew*100 ) odds=1; + else odds = (acrew*100)/dcrew; + + /* calculate capture percentages */ + /* + * This formula produces: + * 0% capture for 1:100 odds + * 2% capture for 1:10 odds + * 15% capture for 1:1 odds + * 60% capture for 10:1 odds + * 100% capture for >60:1 odds + * with linear progression between each. + */ + if (odds>6000) { + dcptpct=0; + acptpct=100; + } else if (odds>1000) { + dcptpct= (6000-odds)/2500; + acptpct= (odds-1000)/125+60; + } else if (odds>100) { + dcptpct= (1000-odds)/69+2; + acptpct= (odds-100)/20+15; + } else if (odds>10) { + dcptpct= (100-odds)/2+15; + acptpct= (odds-10)/6.9+2; + } else if (odds>6) { + dcptpct= (10-odds)*14+60; + acptpct= (odds-6)/2; + } else { + dcptpct= 100; + acptpct= 0; + } +#ifdef DEBUG + printf("capture percentage: attack = %d defend = %d\n",acptpct,dcptpct); +#endif /* DEBUG */ + + /*figure combat on a one-to-one basis */ + /* use a bell curve roll */ + roll = 0; + for(i=0;i<5;i++) { + roll += rand()%21+1; + } + roll -= 5; + PDloss = MAXLOSS * roll / 100; + PAloss = MAXLOSS * (100 - roll) / 100; +#ifdef DEBUG + printf("Pdloss = %d PAloss = %d\n",PDloss,PAloss); +#endif /* DEBUG */ + + /* adjust based on the odds */ + if( odds == 1 ) { + PDloss = 0; + PAloss = 100; + } else if ( odds == 10000 ) { + PAloss = 0; + PDloss = 100; + } else if ( odds > 100 ) { + PDloss += (odds / 10 - 10); /* 10% increase */ + PAloss -= (odds / 25 - 4); /* 4% decrease */ + if(PAloss<(100-roll)/5) + PAloss=(100-roll)/5; + } else { + PAloss += ( 1000 / odds - 10); /* 10% increase */ + PDloss -= ( 400 / odds - 4); /* 4% decrease */ + if(PDloss100) PAloss=100; + if (PDloss>100) PDloss=100; + + /* calculate actual losses */ + for(j=0;j90) { + /* destroy a ship */ + NSUB_WAR(1); + k = P_NCREW*(shipsize+1); + thold -= (shipsize+1); + if(which==ATKR) { + awsunk++; + ahold-=(shipsize+1); + akcrew+=k; + } else { + dwsunk++; + dhold-=(shipsize+1); + dkcrew+=k; + } + } else { + /* damage a ship */ + k = (shipsize+1)*Ploss*P_NCREW/100; + if(which==ATKR) akcrew += k; + else dkcrew += k; + P_NCREW -= k/thold; + } + } + /* check galleys */ + for(i=0;i90) { + /* ship destroyed */ + k = (shipsize+1)*SHIPCREW; + if(which==ATKR) akcrew += k; + else dkcrew += k; + NSUB_GAL(1); + ghold-=(shipsize+1); + thold-=(shipsize+1); + /* kill all soldiers onboard */ + if (P_NARMY!=MAXARM) { + armynum = P_NARMY; + k = P_ASOLD*(shipsize+1)/(ghold+shipsize+1); + if(P_ATYPE90) { + /* ship destroyed */ + k = (shipsize+1)*P_NCREW; + if(which==ATKR) akcrew += k; + else dkcrew += k; + P_NCREW -= k/thold; + k = P_NCREW*thold; + NSUB_MER(1); + if((thold-=(shipsize+1))!=0) P_NCREW = k / thold; + else P_NCREW = 0; + /* kill all people onboard */ + k = (shipsize+1)*P_NPEOP; + if(which==ATKR) akcrew += k; + else dkcrew += k; + P_NPEOP -= k/(thold+shipsize+1); + k = P_NPEOP*(thold+shipsize+1); + if (thold>0) P_NPEOP = k / thold; + else P_NPEOP=0; + if(which==ATKR) amsunk++; + else dmsunk++; + } else { + /* damage a ship */ + k = (shipsize+1)*Ploss*P_NCREW/100; + if(which==ATKR) akcrew += k; + else dkcrew += k; + P_NCREW -= k/thold; + /* damage any people onboard */ + k = (shipsize+1)*Ploss*P_NPEOP/100; + if(which==ATKR) akcrew += k; + else dkcrew += k; + P_NPEOP -= k/thold; + } + } + } + } +#ifdef HIDELOC + fprintf(fnews,"4.\tNaval Battle occurs"); +#else + fprintf(fnews,"4.\t%d,%d: Naval Battle",xspot,yspot); +#endif + for(j=0;j percent loss %d%%\n",acrew,PAloss); + fprintf(fm,"defender strength (%d men) -> percent loss %d%%\n",dcrew,PDloss); + fprintf(fm,"Odds are %d to 100; RANDOM ROLL is %d\n",odds,roll); + fprintf(fm,"RESULT: Attackers lose %d men Defenders lose %d men\n",akcrew,dkcrew); + /* display any other results */ + show_ships("Attacking","sunk",awsunk,agsunk,amsunk); + show_ships("Defending","sunk",dwsunk,dgsunk,dmsunk); + show_ships("Attacking","captured",awcapt,agcapt,amcapt); + show_ships("Defending","captured",dwcapt,dgcapt,dmcapt); + mailclose(owner[j]); + } + } + curntn= saventn; + country= savecntry; + printf("Out Naval Combat....\n"); +} + +/* routine to distribute a captured ship */ +void +capture(type,to,shipsize,holdcount) + int type,to,shipsize,holdcount; +{ + int i,nvynum; + struct s_nation *saventn=curntn; +#ifdef DEBUG + printf("capture: hdcnt==%d typ==%d spsz==%d to==%d\n",holdcount, + type,shipsize,to); +#endif /* DEBUG */ + for (i=0;holdcount && i0) { + fprintf(fm,"%s ships %s: ",who,what); + if (war) fprintf(fm,"%d Warships ",war); + if (gal) fprintf(fm,"%d Galleys ",gal); + if (mer) fprintf(fm,"%d Merchants",mer); + putc('\n',fm); + } +} diff --git a/original/commands.c b/original/commands.c new file mode 100644 index 0000000..f966bb6 --- /dev/null +++ b/original/commands.c @@ -0,0 +1,1465 @@ +/*conquer : Copyright (c) 1988 by Ed Barlow. + * I spent a long time writing this code & I hope that you respect this. + * I give permission to alter the code, but not to copy or redistribute + * it without my explicit permission. If you alter the code, + * please document changes and send me a copy, so all can have it. + * This code, to the best of my knowledge works well, but it is my first + * 'C' program and should be treated as such. I disclaim any + * responsibility for the codes actions (use at your own risk). I guess + * I am saying "Happy gaming", and am trying not to get sued in the process. + * Ed + */ + +#include +#include +#include +#include +#include +#ifdef CONQUER +#include +#include +#endif /*CONQUER*/ +#include "header.h" +#include "data.h" + +extern long conq_mail_size; + +extern FILE *fexe; /*execute file pointer*/ +extern short country; +extern short selector; +extern short pager; +extern short xcurs,ycurs,xoffset,yoffset; +extern short redraw; + +int roads_this_turn = 0; + +/* routine to determine if the given designation is ok; TRUE for ok */ +int +desg_ok(prtflag, desg, sptr) + int prtflag; + char desg; + struct s_sector *sptr; +{ + /* check vegetation */ + if((desg!=DNODESIG)&&(desg!=DROAD)&&(desg!=DFORT) + &&(desg!=DSTOCKADE)&&(tofood(sptr,country)designation) { + if(prtflag) errormsg("Hey, get your act together! There is already one there."); + return(FALSE); + } + + /* check for city/capitol being made into something else */ + if((desg!=DRUIN) + &&((desg!=DCAPITOL && sptr->designation==DCITY) + ||sptr->designation==DCAPITOL)) { + if(prtflag) { + char buf[LINELTH+1]; + sprintf(buf,"Must first burn down city/capitol (designate as '%c')",DRUIN); + errormsg(buf); + } + return(FALSE); + } + + /* check for proper population */ + if((sptr->people<500) + &&(desg==DCAPITOL || desg==DCITY || desg==DTOWN)) { + if(prtflag) errormsg("Need 500 people to build a city or town"); + return(FALSE); + } + + /* only god may create pirate */ + if(desg==DBASECAMP) { + if(prtflag) errormsg("A Pirate Cove?? Are you serious?!"); + return(FALSE); + } + + /* should not appear in display list */ + if (prtflag==FALSE && + ((desg==DSPECIAL && sptr->tradegood!=TG_stones) || desg==DNODESIG)) + return(FALSE); + + if (desg==DRUIN) { + if(sptr->designation!=DCITY&&sptr->designation!=DCAPITOL) { + if(prtflag) errormsg("Ruins may only come from cities or capitols"); + return(FALSE); + } + } + + if (desg==DCAPITOL || desg==DCITY) { + if((desg==DCAPITOL && sptr->designation!=DCITY) + && sptr->designation!=DTOWN && sptr->designation!=DRUIN) { + if(prtflag) errormsg("You can't build a city from that!"); + return(FALSE); + } + } + + if (desg==DUNIVERSITY || desg==DLUMBERYD) { + if((sptr->tradegood != TG_none) + &&(*(tg_stype + sptr->tradegood) != desg) + &&(*(tg_stype + sptr->tradegood) != 'x')) { + if(prtflag) errormsg("You can't have one of those here!"); + return(FALSE); + } + } + + if(desg==DMINE || desg==DGOLDMINE) { + if( !tg_ok( country, sptr )) { + if(prtflag) errormsg("Your people refuse to be unemployed"); + return(FALSE); + } + if((desg==DMINE && sptr->metal==0 ) + ||( desg==DGOLDMINE && sptr->jewels==0)) { + if(prtflag) errormsg("Your people refuse to be unemployed"); + return(FALSE); + } + } + + if((desg==DSPECIAL)&&(magic(country,SUMMON)!=TRUE)) { + if(prtflag) errormsg("You are gonna need SUMMON power to use those stones!"); + return(FALSE); + } + + return(TRUE); +} + +/*change current hex designation*/ +void +redesignate() +{ + char newdes; + char tgtype[NAMELTH+1]; + struct s_sector *sptr= &sct[XREAL][YREAL]; + short x,y; + long metal=0; + int isgod=FALSE; + + if(country==0){ + isgod=TRUE; + country=sptr->owner; + curntn= &ntn[country]; + + clear_bottom(0); + mvaddstr(LINES-4,0,"SUPER USER: CHANGE (v)eg, (e)lev, (d)esig, (o)wner, (p)op, (t)radegood"); + refresh(); + switch(getch()){ + case 'd': + /* fall into normal redesignation command */ + break; + case 'e': + /*simple contour map definitions*/ + mvprintw(LINES-3,7,"ELEVATIONS: change to %c, %c, %c, %c or %c?",WATER,PEAK,MOUNTAIN,HILL,CLEAR); + refresh(); + newdes=getch(); + if(newdes!=WATER&&newdes!=PEAK&&newdes!=MOUNTAIN + &&newdes!=HILL&&newdes!=CLEAR) { + reset_god(); + return; + } + sptr->altitude=newdes; + if((newdes==PEAK)||(newdes==WATER)) { + sptr->owner=0; + sptr->people=0; + sptr->fortress=0; + } + /*will fall through as must change vegetation*/ + case 'v': + /*vegetation types*/ + mvprintw(LINES-3,7,"VEGETATIONS: change to %c, %c, %c, %c, %c, %c, %c, %c, %c, %c, %c or %c?", + VOLCANO,DESERT,TUNDRA,BARREN,LT_VEG, + GOOD,WOOD,FOREST,JUNGLE,SWAMP,ICE,NONE); + refresh(); + newdes=getch(); + if(newdes!=VOLCANO + &&newdes!=DESERT&&newdes!=TUNDRA + &&newdes!=BARREN&&newdes!=LT_VEG + &&newdes!=NONE&&newdes!=GOOD + &&newdes!=WOOD&&newdes!=FOREST&&newdes!=JUNGLE + &&newdes!=SWAMP&&newdes!=ICE) { + reset_god(); + return; + } + sptr->vegetation=newdes; + if( tofood(sptr,0) < DESFOOD ) + sptr->designation=newdes; + else sptr->designation=DNODESIG; + reset_god(); + return; + case 'o': + mvaddstr(LINES-3,7,"What nation owner:"); + refresh(); + x = get_country(); + if (x>0 && xowner=x; + reset_god(); + return; + case 'p': + if (sptr->altitude == WATER) { + errormsg("Trying to build a colony of mermen?"); + reset_god(); + return; + } + mvaddstr(LINES-3,7,"new population for sector: "); + refresh(); + metal = get_number(); + if (metal <= (-1)) return; + sptr->people = metal; + reset_god(); + return; + case 't': + x=TRUE; + while(x==TRUE) { + mvaddstr(LINES-2,7,"new sector tradegood type:"); + clrtoeol(); + refresh(); + get_nname(tgtype); + if(strlen(tgtype)==0) { + reset_god(); + return; + } + for(y=0;x==TRUE && y<=TG_none;y++) + if(strcmp(tg_name[y],tgtype)==0) x=FALSE; + } + y--; + if((y!=TG_none)&&(y>END_NORMAL)) { + mvaddstr(LINES-1,7,"new sector value: "); + refresh(); + x = get_number(); + if(x<100 && x>0) { + if(y>END_MINE) { + sptr->jewels = (char)x; + sptr->metal = 0; + } else { + sptr->metal = (char)x; + sptr->jewels = 0; + } + } else { + sptr->jewels = 0; + sptr->metal = 0; + } + } else { + sptr->jewels=0; + sptr->metal=0; + } + sptr->tradegood= (char)y; + reset_god(); + return; + default: + reset_god(); + return; + } + } + + clear_bottom(0); + if((SOWN!=country)&&(isgod==FALSE)) { + errormsg("Hey! You don't own that sector!"); + return; + } + + mvaddstr(LINES-4,0,"Possible sector designations: "); + x = 30; + y = LINES-4; + for(newdes=0; *(des+newdes) != '0'; newdes++ ) { + if((isgod==TRUE)||desg_ok(FALSE,*(des+newdes),sptr)) { + mvprintw(y,x,"(%c)",*(des+newdes)); + x+=4; + if(x>COLS-15) { + x=5; + y++; + } + } + } + + if((sptr->tradegood != TG_none) + &&( *(tg_stype+sptr->tradegood) != 'x') + &&( isgod==TRUE || desg_ok(FALSE,*(tg_stype+sptr->tradegood),sptr)) ) + mvprintw(y,x,"(%c special=>%c)",DSPECIAL,*(tg_stype+sptr->tradegood)); + + mvaddstr(++y,0," What new designation:"); + refresh(); + + /*read answer*/ + if((newdes=getch())==DSPECIAL) { + if((sptr->tradegood == TG_none) + ||( *(tg_stype+sptr->tradegood) == 'x')||(isgod==FALSE + && !desg_ok(FALSE,*(tg_stype+sptr->tradegood),sptr)) ) { + errormsg("no special designation possible" ); + if(isgod==TRUE) reset_god(); + return; + } else + newdes = *(tg_stype + sptr->tradegood); + } + + for(x=0; *(des+x) != '0'; x++ ) + if(newdes == *(des+x)) break; + + if(*(des+x) == '0') { + if(isgod==TRUE) reset_god(); + return; + } + + /* validate designation */ + if((isgod==FALSE)&&!desg_ok(TRUE,newdes,sptr)) { + return; + } + + if (newdes == DROAD && isgod==FALSE) { + if( sptr->people < 100 ) { + errormsg("Need 100+ people to build a road!"); + return; + } + roads_this_turn++; + if (roads_this_turn>2) { + roads_this_turn=2; + errormsg("Only two roads a turn! Let the road crews sleep!!"); + return; + } + } + + /* do not need metal to build a capitol from a city */ + if((newdes==DFORT)||(newdes == DTOWN)) metal=DESCOST; + else if((newdes == DCITY) + ||(newdes == DCAPITOL && sptr->designation!=DCITY)) metal=5*DESCOST; + + if((newdes!=DTOWN)&&(newdes!=DFORT)&&(newdes!=DCITY)&&(newdes!=DCAPITOL)){ + /*decrement treasury*/ + if(newdes==DRUIN) { + if (sptr->fortress>4) { + sptr->fortress-=4; + } else { + sptr->fortress=0; + } + } else if (sptr->designation==DRUIN) { + curntn->tgold-=REBUILDCOST; + } + sptr->designation=newdes; + + SADJDES; + if(newdes == DSTOCKADE) + curntn->tgold-=STOCKCOST*(1-isgod); + else + curntn->tgold-=DESCOST*(1-isgod); + + } else if((isgod==FALSE)&&(curntn->metalsdesignation==DRUIN){ + curntn->tgold-=10*DESCOST*(1-isgod); + curntn->metals-=metal/2*(1-isgod); + } else { + curntn->tgold-=20*DESCOST*(1-isgod); + if(newdes==DCITY || sptr->designation!=DCITY) + curntn->metals-=metal*(1-isgod); + } + x=curntn->capx; /* need this for SADJDES2 */ + y=curntn->capy; + /* can only have one capitol */ + if(newdes==DCAPITOL){ + if (sct[x][y].owner==country) { + sct[x][y].designation=DCITY; + SADJDES2; + } + curntn->capx=XREAL; + curntn->capy=YREAL; + } + sptr->designation=newdes; + SADJDES; + } else if((newdes==DFORT)||(newdes==DTOWN)){ + curntn->tgold-=10*DESCOST*(1-isgod); + curntn->metals-=metal*(1-isgod); + sptr->designation=newdes; + SADJDES; + } else errormsg("Serious error: What designation are you?"); + if(isgod==TRUE) reset_god(); +} + +/*build fort or ship-type */ +void +construct() +{ + int tmpvar,tmpvar2,onboard; + long cost; + int armbonus; + int x,y; + short nvynum=0; + short shipsize,amount; + short isgod=FALSE; + char type; + + clear_bottom(0); + if(country==0){ + isgod=TRUE; + country=sct[XREAL][YREAL].owner; + curntn= &ntn[country]; + } + + if(sct[XREAL][YREAL].owner!=country) { + errormsg("You do not own"); + if(isgod==TRUE) reset_god(); + return; + } + if((isgod==FALSE)&&(sct[XREAL][YREAL].people<=500)) { + errormsg("You need over 500 people to construct"); + return; + } + + if((isgod==FALSE) && (curntn->tgold < 0 )) { + errormsg("You are broke"); + return; + } + tmpvar=FALSE; + for(x=XREAL-1;x<=XREAL+1;x++) + for(y=YREAL-1;y<=YREAL+1;y++) + if(ONMAP(x,y) && sct[x][y].altitude==WATER) + tmpvar=TRUE; + + if((sct[XREAL][YREAL].designation==DTOWN) + ||(sct[XREAL][YREAL].designation==DFORT) + ||(sct[XREAL][YREAL].designation==DCAPITOL) + ||(sct[XREAL][YREAL].designation==DCITY)) { + /*calculate cost for fort*/ + cost=FORTCOST; + if(isgod==TRUE) cost=0; + else for(x=1;x<=sct[XREAL][YREAL].fortress;x++) + cost*=2; + + if(sct[XREAL][YREAL].designation==DTOWN) armbonus=TOWNSTR; + else if(sct[XREAL][YREAL].designation==DFORT) armbonus=FORTSTR; + else if(sct[XREAL][YREAL].designation==DCAPITOL) armbonus=CITYSTR; + else if(sct[XREAL][YREAL].designation==DCITY) armbonus=CITYSTR; + if(magic(country,ARCHITECT)==TRUE) armbonus*=2; + + if(tmpvar) + mvprintw(LINES-4,0,"ortify sector (+%d%%/%ld talons); uild or epair ships?: ",armbonus,cost); + else + mvprintw(LINES-4,0,"ortify sector (+%d%% - %ld talons):",armbonus,cost); + refresh(); + type=getch(); + } else { + errormsg("Must construct in town, city, or fortress"); + if (isgod==TRUE) reset_god(); + return; + } + + /* construct ships*/ + if((type=='b')||(type=='r')) { + /*check if next to sea*/ + if((tmpvar==FALSE)||(sct[XREAL][YREAL].designation==DFORT)){ + errormsg("not in a harbor"); + if(isgod==TRUE) reset_god(); + return; + } + + nvynum=getselunit()-MAXARM; + if(type=='r') { + if((nvynum>=MAXNAVY)||(nvynum<0)){ + errormsg("INVALID NAVY"); + if(isgod==TRUE) reset_god(); + return; + } + + if (P_NCREW==SHIPCREW) { + errormsg("You may only &^#$! repair damaged fleets!!!"); + return; + } + clear_bottom(0); + shipsize = flthold(nvynum); + mvprintw(LINES-4,0,"Repairing Fleet (%d)",nvynum); + mvprintw(LINES-4,30,"Storage Units [%d]",shipsize); + mvprintw(LINES-3,0,"crew per unit = %d",(int)P_NCREW); + mvprintw(LINES-3,30,"max crew per unit = %d",SHIPCREW); + mvaddstr(LINES-2,0,"How many crew per unit do you wish to add:"); + clrtoeol(); + refresh(); + amount = (short) get_number(); + if (amount<0) { + if(isgod==TRUE) reset_god(); + return; + } + + + /* find cost of repairs on all ships */ + cost = 0; + for(tmpvar=N_LIGHT;tmpvar<=N_HEAVY;tmpvar++) { + cost += (tmpvar+1)*WARSHPCOST*P_NWAR(tmpvar); + cost += (tmpvar+1)*MERSHPCOST*P_NMER(tmpvar); + cost += (tmpvar+1)*GALSHPCOST*P_NGAL(tmpvar); + } + cost *= amount / SHIPCREW; + + if(isgod==TRUE) cost=0; + else if(magic(country,SAILOR)==TRUE) cost/=2L; + + if( curntn->tgold < cost ) { + errormsg("NOT ENOUGH GOLD"); + if(isgod==TRUE) reset_god(); + return; + } + if( sct[XREAL][YREAL].people < amount * shipsize) { + errormsg("NOT ENOUGH CIVILIANS IN SECTOR"); + if(isgod==TRUE) reset_god(); + return; + } + if( SHIPCREW < P_NCREW + amount ){ + errormsg("THAT WOULD EXCEED MAXIMUM SHIP CREW"); + if(isgod==TRUE) reset_god(); + return; + } + + curntn->tgold -= cost; + sct[XREAL][YREAL].people -= amount*shipsize; + P_NCREW += (unsigned char) amount; + NADJCRW; + SADJCIV; + + if(isgod==TRUE) reset_god(); + return; + } + + mvaddstr(LINES-3,0,"Do you wish to raise a new fleet? (y or n)"); + clrtoeol(); + refresh(); + if(getch()=='y') nvynum=(-1); + + clear_bottom(0); + if(nvynum<0) { + nvynum=0; + x=(-1); + while((x==(-1))&&(nvynumN_MASK)) amount=0; + if (amount<=0) + { + if(isgod==TRUE) reset_god(); + return; + } + + /* 6 and 3 hard coded ... see above comment */ + cost = (long) amount * ( shipsize%3 + 1 ); + if (shipsize>=6) { + cost *= MERSHPCOST; + } else if (shipsize>=3) { + cost *= GALSHPCOST; + } else { + cost *= WARSHPCOST; + } + + if(isgod==TRUE) cost=0; + else if(magic(country,SAILOR)==TRUE) cost/=2L; + + if((cost > curntn->tgold) && (cost > 0)) { + errormsg("sorry - not enough talons"); + return; + } + + if( sct[XREAL][YREAL].people < amount * (shipsize+1) * SHIPCREW ){ + errormsg("NOT ENOUGH CIVILIANS IN SECTOR"); + if(isgod==TRUE) reset_god(); + return; + } + + if((nvynum>=0)&&(nvynum=6) { + shipsize %= 3; + tmpvar2 = NADD_MER(amount); + } else if (shipsize>=3) { + shipsize %= 3; + tmpvar2 = NADD_GAL(amount); + } else { + shipsize %= 3; + tmpvar2 = NADD_WAR(amount); + } + + /* check for bad build */ + if (tmpvar2==FALSE) { + errormsg("Too many such ships in fleet."); + if(isgod==TRUE) reset_god(); + return; + } + + /* crew average based on number of holding units */ + P_NCREW = (unsigned char)( tmpvar / flthold(nvynum) ); + + sct[XREAL][YREAL].people-=amount*(shipsize+1)*SHIPCREW; + curntn->tgold -= cost; + + P_NXLOC =XREAL; + P_NYLOC =YREAL; + P_NMOVE=0; + + mvprintw(LINES-4,0,"Fleet (%2d): Warships = [Light %2hd/Medium %2hd/Heavy %2hd]",nvynum,P_NWAR(N_LIGHT),P_NWAR(N_MEDIUM),P_NWAR(N_HEAVY)); + mvprintw(LINES-3,0," Merchants = [Light %2hd/Medium %2hd/Heavy %2hd]",P_NMER(N_LIGHT),P_NMER(N_MEDIUM),P_NMER(N_HEAVY)); + mvprintw(LINES-2,0,"Avg Crew[%3d] Galleys = [Light %2hd/Medium %2hd/Heavy %2hd]",(int)P_NCREW,P_NGAL(N_LIGHT),P_NGAL(N_MEDIUM),P_NGAL(N_HEAVY)); + + if(fltmhold(nvynum)>0) + P_NPEOP = (unsigned char) (onboard/fltmhold(nvynum)); + else P_NPEOP = 0; + SADJCIV; + NADJCRW; + NADJWAR; + NADJMER; + NADJGAL; + NADJHLD; + NADJLOC; + NADJMOV; + mvaddstr(LINES-2,65,"HIT ANY KEY"); + refresh(); + getch(); + + } else errormsg("ERROR!!!!!!!!!!!!!"); + } + /* construct fortification points*/ + else if(type=='f'){ + /* can only go into debt as much as the nation has jewels */ + if (sct[XREAL][YREAL].fortress>11) { + errormsg("That sector is as impregnable as you can make it"); + } else if ((curntn->tgold - cost) >= ((-1)*10*curntn->jewels)) { + mvprintw(LINES-2,5,"you build +%d%% fort points for %ld gold",armbonus,cost); + curntn->tgold-=cost; + sct[XREAL][YREAL].fortress++; + INCFORT; + errormsg(""); + } else errormsg("you may not spend that much"); + } + else errormsg("invalid input error"); + + if(isgod==TRUE) reset_god(); + refresh(); +} + +/*DRAFT IF IN A CITY*/ +void +draft() +{ + short armynum,x,y,i; + long men=0,mercs; + short army=(-1), isgod=FALSE, newtype=0; + long i_cost, e_cost; + char ch; + + clear_bottom(0); + if(country==0) { + isgod=TRUE; + country=sct[XREAL][YREAL].owner; + curntn= &ntn[country]; + } else if(sct[XREAL][YREAL].owner!=country) { + errormsg("You do not own"); + return; + } + + if((sct[XREAL][YREAL].designation!=DTOWN) + &&(sct[XREAL][YREAL].designation!=DCAPITOL) + &&(sct[XREAL][YREAL].designation!=DCITY)) { + errormsg("must raise in towns/cities/capitols"); + if(isgod==TRUE) reset_god(); + return; + } + if(curntn->tgold <= 0){ + errormsg("You are broke"); + if(isgod==TRUE) reset_god(); + return; + } + + if(ISCITY(sct[XREAL][YREAL].designation) + &&(sct[XREAL][YREAL].people*(3*CITYLIMIT+(curntn->tsctrs/2))tciv)){ + mvprintw(LINES-1,0,"Need %d people in sector: hit any key",curntn->tciv/(3*CITYLIMIT+(curntn->tsctrs/2))); + refresh(); + getch(); + if(isgod==TRUE) reset_god(); + return; + } + + /*ask what type of unit*/ + y=LINES-2; + mvaddstr(y,0,"options: 1) spy 2) scout"); + clrtoeol(); + x=25; + for(i=0;i<=NOUNITTYPES;i++){ + if(unitvalid(i)==TRUE) { + mvprintw(y,x+2,"%s",*(shunittype+i)); + mvprintw(y,x,"(%c)",*(shunittype+i)[0]); + x+= strlen( *(shunittype+i) ) +3; + if(x>COLS-10){ + x=0; + y++; + } + } + } + move(y,x); + clrtoeol(); + if((magic(country,WARRIOR)==TRUE) + ||(magic(country,WARLORD)==TRUE) + ||(magic(country,CAPTAIN)==TRUE)) + mvaddstr(LINES-3,0,"(Warrior = 1/2 enlist cost) what type of unit do you want:"); + else + mvaddstr(LINES-3,0,"what type of unit do you want to raise:"); + + clrtoeol(); + refresh(); + ch = getch(); + for(newtype=0;newtype<=NOUNITTYPES;newtype++) + if(ch == *(shunittype+newtype)[0]) break; + + if((newtype == NOUNITTYPES+1 )||(unitvalid(newtype)==FALSE)) { + if( ch == '1' ) newtype=A_SPY; + else if( ch == '2' ) newtype=A_SCOUT; + else { + errormsg("Invalid type"); + if (isgod==TRUE) reset_god(); + return; + } + } + clear_bottom(0); + + /* marines and sailors may only be drafted in harbors */ + if(newtype==A_MARINES || newtype==A_SAILOR) { + i=FALSE; + for (x=XREAL-1;x<=XREAL+1;x++) + for (y=YREAL-1;y<=YREAL+1;y++) + if (sct[x][y].altitude==WATER) i=TRUE; + + /* not a harbor */ + if (i==FALSE) { + if (newtype==A_MARINES) + errormsg("Huh? What would marines do without the water?"); + else errormsg("You gotta be kinding!? Sailors on land?"); + if (isgod==TRUE) reset_god(); + return; + } + } + + /*raise an untrained army */ + i = FALSE; + if( newtype==A_SPY || newtype==A_SCOUT ) { + men=1; + } else { + mvprintw(LINES-3,0,"how many %s do you wish to raise:",unittype[newtype]); + clrtoeol(); + refresh(); + men = get_number(); + if(men<=0) { + if (isgod==TRUE) reset_god(); + return; + } + } + + /* i_people*256 is initial people -> can draft up to following */ + /* draftable = max_draft - already drafted */ + /* = imen/4 - ( imen - people) */ + /* = -3/4 * imen + people) */ + /* 192 comes from 3*256/4 */ + if( (newtype != A_MERCENARY && (men > sct[XREAL][YREAL].people - (sct[XREAL][YREAL].i_people*192) ) ) + ||(sct[XREAL][YREAL].i_people < 0)) { + if(sct[XREAL][YREAL].i_people < 0) + errormsg("error: sector wasn't city at beginning of turn"); + else errormsg("error: raising too many soldiers"); + if(isgod==TRUE) reset_god(); + return; + } + + /* check that you dont have too many mercenaries */ + mercs=0; + if(newtype == A_MERCENARY){ + int totalsolds=0; + for(armynum=0;armynum (totalsolds+men)/2) { + errormsg("you would then have more than 50%% mercenaries"); + if(isgod==TRUE) reset_god(); + return; + } + if(mercgot+men > MERCMEN/NTOTAL) { + errormsg("there are not that many mercanaries available"); + if(isgod==TRUE) reset_god(); + return; + } + } + + e_cost= (long) *(u_encost+newtype) * men; + i_cost= (long) *(u_enmetal+newtype) * men; + + /*magiced get 1/2 enlistment costs*/ + if((magic(country,WARRIOR)==TRUE) + ||(magic(country,WARLORD)==TRUE) + ||(magic(country,CAPTAIN)==TRUE)) + e_cost/=2; + + if((magic(country,SAPPER)==TRUE) + &&((newtype==A_SIEGE)||(newtype==A_CATAPULT))){ + e_cost/=2; + i_cost/=2; + } + + /*check to see if enough gold*/ + if(e_cost > curntn->tgold) { + errormsg("You don't have enough talons"); + if(isgod==TRUE) reset_god(); + return; + } else if(i_cost > curntn->metals) { + mvprintw(LINES-1,0,"You don't have %ld metal",i_cost); + mvaddstr(LINES-1,COLS-20,"PRESS ANY KEY"); + clrtoeol(); + refresh(); + getch(); + if(isgod==TRUE) reset_god(); + return; + } else { + move(LINES-2,0); + clrtoeol(); + } + + /*count is order of that army in sector*/ + /*armynum is number of that army*/ + if((armynum=getselunit())>=0){ + if(armynum>=MAXARM || newtype==A_SPY || newtype==A_SCOUT) { + army = -1; + } else { + /*if different types, must raise new army*/ + if((newtype == P_ATYPE)&&(P_ASTAT!=ONBOARD)) { + mvaddstr(LINES-1,0,"Do you wish to raise a new army:"); + clrtoeol(); + refresh(); + if(getch()!='y') army=armynum; + else army= -1; + } + else army=(-1); + } + } + if(army==(-1)) { + mvprintw(LINES-2,0,"(%s, gold talons=%ld, metal=%ld) raising a new army",*(unittype+newtype),e_cost,i_cost); + clrtoeol(); + refresh(); + sleep(1); + + armynum=0; + while((army==(-1))&&(armynumdstatus[i]!=UNMET) { + P_AYLOC = ntn[i].capy; + P_AXLOC = ntn[i].capx; + mvprintw(LINES-2,0,"The Spy Starts in %s's Capitol (%d,%d)", + ntn[i].name,(int)P_AXLOC,(int)P_AYLOC); + clrtoeol(); + } else { + clear_bottom(0); + mvprintw(LINES-4,0,"You do not yet know where %s is",ntn[i].name); + mvaddstr(LINES-3,0,"Have the Spy start from this sector? [y or n]"); + refresh(); + if(getch()!='y') { + if(isgod==TRUE) reset_god(); + return; + } + P_AYLOC = YREAL; + P_AXLOC = XREAL; + mvprintw(LINES-2,0,"Intelligence indicates that %s lies to the %s",ntn[i].name, + *(directions+compass((int)P_AXLOC,(int)P_AYLOC, + (int)ntn[i].capx,(int)ntn[i].capy))); + clrtoeol(); + } + errormsg(""); + redraw=PART; + } else { + P_AYLOC=YREAL; + P_AXLOC=XREAL; + } + if( newtype == A_SPY || newtype == A_SCOUT ) { + P_ASTAT = SCOUT; + AADJSTAT; + } + P_ATYPE=newtype; + if(P_ATYPE != A_MERCENARY){ + sct[XREAL][YREAL].people -= men; + SADJCIV; + } else { + mercgot += men; + AADJMERC; + } + AADJLOC; + P_AMOVE=0; + AADJMOV; + P_ASOLD+=men; + AADJMEN; + if(P_ASTAT>=NUMSTATUS) { + P_ASTAT=ATTACK; + AADJSTAT; + } + curntn->metals -= i_cost; + curntn->tgold -= e_cost; + makemap(); /* if display 'y' is set, this will show new army */ + if(isgod==TRUE) reset_god(); +} + +/*go through msgfile not rewriting to temp messages you discard*/ +/* then move temp to msgfile*/ +void +rmessage() +{ + int unlink(); + FILE *mesgfp; + FILE *fptemp; + int i; + int count,msglen; + int contd; + int done=FALSE; + char tempfile[FILELTH]; + char mesgfile[FILELTH]; + char line[LINELTH+1], inpch; + char save[LINELTH][LINELTH+1]; + struct stat fst; + + /*open file; used in mailopen() as well */ + sprintf(tempfile,"%s%hd.tmp",msgfile,country); + if( (fptemp = fopen(tempfile,"w")) == NULL ) { + clear_bottom(0); + sprintf(mesgfile,"error: %s open",tempfile); + errormsg(mesgfile); + redraw=DONE; + makebottom(); + return; + } + + sprintf(mesgfile,"%s%d",msgfile,country); + if ((mesgfp=fopen(mesgfile,"r"))==NULL) { + (void) unlink (tempfile) ; + clear_bottom(0); + errormsg("No Messages"); + makebottom(); + redraw=DONE; + return; + } + + /* check for people sending mail */ + sprintf(line,"send.%s%hd",msgfile,country); + if (stat(line,&fst)==0) { + long now; + now = time(0); + if (now - fst.st_mtime < TIME_DEAD) { + /* someone is sending mail to the country */ + (void) unlink (tempfile) ; + clear_bottom(0); + errormsg("Someone is sending you mail... please wait."); + makebottom(); + redraw=DONE; + return; + } else { + /* remove useless file */ + (void) unlink(line); + } + } + + /*read in file a line at at time*/ + if(fgets(line,LINELTH,mesgfp)==NULL) { + done=TRUE; + redraw=DONE; + clear_bottom(0); + errormsg("No messages"); + makebottom(); + } + if (done==FALSE) clear(); + while(done==FALSE) { + contd=FALSE; + msglen=0; + count=3; + clear(); + standout(); + /*print to end of message*/ + while(contd==FALSE) { + if(msglen=NTOTAL + || (!isntn(ntn[temp].active) && temp!=0)) { + makebottom(); + return; + } + strcpy(name,ntn[temp].name); /* find nation name */ + } + + if(mailopen( temp )==(-1)) { + makebottom(); + return; + } + redraw=FULL; + + if(temp != -2) { + if (country==0) + fprintf(fm,"Message to %s from GOD (%s of year %d)\n\n",name,PSEASON(TURN),YEAR(TURN)); + else fprintf(fm,"Message to %s from %s (%s of year %d)\n\n",name,curntn->name,PSEASON(TURN),YEAR(TURN)); + } else fprintf(fm,"5.----------\n"); + strcpy(line,""); + + while(done==FALSE) { + if (dotitles==TRUE) { + move(0,0); + clrtobot(); + standout(); + if(temp != -2) + mvprintw(3,(COLS-25)/2,"Message to Nation %s",name); + else + mvaddstr(3,(COLS-25)/2,"Message to All Players"); + mvaddstr(LINES-2,(COLS-37)/2,"End with a on a New Line"); + mvaddstr(LINES-1,(COLS-28)/2,"Hit ESC to Abort the Message"); + standend(); + mvaddstr(5,0,line); + y=6; + x=0; + refresh(); + dotitles=FALSE; + } + linedone=FALSE; + ch=' '; + /*read line*/ + while(linedone==FALSE){ + /* check for delete or backspace */ + switch(ch) { + case '\b': + case '\177': + /* backspace or delete */ + if(x>1) x--; + mvaddch(y,x,' '); + move(y,x); + line[x]=' '; + refresh(); + ch=getch(); + break; + case '\n': + case '\r': + /* newline or carriage return */ + linedone=TRUE; + break; + case '\004': + /* a control-d was hit */ + if (x==1) { + linedone=TRUE; + done=TRUE; + } else { + standout(); + mvaddstr(LINES-3,(COLS-37)/2,"Hit [RETURN] Control-D to End Message"); + standend(); + move(y,x); + refresh(); + ch = getch(); + move(LINES-3,0); + clrtoeol(); + refresh(); + } + break; + case '\033': + /* escape key was hit */ + mvaddstr(LINES-3,0,"Abort Message? "); + refresh(); + if(getch()=='y') { + linedone=TRUE; + done=TRUE; + temp=ABORTMAIL; + } else { + move(LINES-3,0); + clrtoeol(); + move(y,x); + refresh(); + ch = getch(); + } + break; + case ' ': + /* new page -- end of form */ + wrefresh(stdscr); + ch=getch(); + break; + default: + /* any remaining possibilities */ + if(isprint(ch)&&(x<65)){ + /*concatonate to end*/ + line[x]=ch; + mvaddch(y,x,ch); + x++; + refresh(); + } + ch=getch(); + break; + } + } + if((ch!='\n')&&(ch!='\r')&&(ch!='\033')) { + mvaddch(y,x,ch); + line[x]=ch; + x++; + } + line[x]='\0'; + + /*check for single period */ + if (strcmp(line," .")==0) done=TRUE; + + /*write to file*/ + if (done==FALSE) { + if (temp != -2) fprintf(fm,"%s\n",line); + else { + if (country!=0) fprintf(fm,"5.%-9s:%s\n",curntn->name,line); + else fprintf(fm,"5.God :%s\n",line); + } + x=0; + y++; + if (y==LINES-3) { + standout(); + mvaddstr(LINES-3,0,"Continuing..."); + standend(); + refresh(); + sleep(2); + dotitles=TRUE; + } + } + } + mailclose(temp); +} + +/*strategic move of civilians...once only*/ +void +moveciv() +{ + long people; + short i,j; + + clear_bottom(0); +#ifdef OGOD + if(sct[XREAL][YREAL].owner!=country && country!=0) +#else + if(sct[XREAL][YREAL].owner!=country) +#endif + { + errormsg("Sorry, you don't own that sector."); + return; + } + else if(sct[XREAL][YREAL].people==0){ + errormsg("Nobody lives there!!!"); + return; + } + + mvprintw(LINES-4,0,"Sector contains %d people [cost 50 per civilian]",sct[XREAL][YREAL].people); + mvaddstr(LINES-3,0,"How many people to move?"); + clrtoeol(); + refresh(); + people = get_number(); + if (people <= 0) { + return; + } + if (people>sct[XREAL][YREAL].people) { + errormsg("Sorry, not that many people live there."); + return; + } + if (people*50>curntn->tgold) { + errormsg("Sorry, you do not have enough gold talons."); + return; + } + + mvprintw(LINES-4,0,"Sector location is x=%d, y=%d",XREAL,YREAL); + clrtoeol(); + mvaddstr(LINES-3,0,"What X location to move to?"); + clrtoeol(); + refresh(); + i = get_number(); + if (i < 0) { + return; + } + + if((i-(XREAL))>2||(i-(XREAL))<-2) { + errormsg("Sorry, your people refuse to move more than two sectors."); + return; + } + + mvaddstr(LINES-2,0,"What Y location to move to?"); + clrtoeol(); + refresh(); + j = get_number(); + if (j < 0) { + return; + } + if((j-(YREAL)>2)||((YREAL)-j>2)) { + errormsg("Sorry, your people refuse to move more than two sectors."); + } +#ifdef OGOD + else if(sct[i][j].owner!=country && country!=0) +#else + else if(sct[i][j].owner!=country) +#endif /*OGOD*/ + { + errormsg("Sorry, you don't own that sector."); + } else if(movecost[i][j]<0){ + /*need to check move cost > 0 for sector*/ + errormsg("Sorry, your people refuse to enter that sector."); + } else if ((i!=XREAL)||(j!=YREAL)){ + curntn->tgold-=50*people; + sct[XREAL][YREAL].people-=people; + SADJCIV; + sct[i][j].people+=people; + SADJCIV2; + } +} + +int +armygoto() +{ + short armynum=0,loop=0; + armynum=getselunit(); + if((armynum<0)||(armynum>MAXARM)) armynum=0; + else armynum++; + /* move to next army with > 0 soldiers or army not in group */ + while((armynum < MAXARM) && ((P_ASOLD <= 0) || (P_ASTAT>=NUMSTATUS))) + armynum++; + if(armynum >= MAXARM) { + armynum=0; + if(P_ASOLD <= 0) return(0); + } + /*move to correct location*/ + xcurs = (int)P_AXLOC - xoffset; + ycurs = (int)P_AYLOC - yoffset; + coffmap(); + + /*select correct unit*/ + selector=0; + pager=0; + while((getselunit() != armynum) && (loop++ < 500)) { + selector+=2; + if(selector>=10) { + selector=0; + pager+=1; + } + } + return(1); +} + +int +navygoto() +{ + short nvynum=0,loop=0; + nvynum=getselunit()-MAXARM; + if((nvynum<0)||(nvynum>MAXNAVY)) nvynum=0; + else nvynum++; + /* move to next nvy with > 0 soldiers*/ + while ((nvynum < MAXNAVY) && (P_NMSHP==0) && (P_NWSHP==0) + && (P_NGSHP == 0)) nvynum++; + if(nvynum >= MAXNAVY) { + nvynum=0; + if((P_NMSHP==0)&&(P_NWSHP==0)&&(P_NGSHP == 0)) return(0); + } + /*move to correct location*/ + xcurs = P_NXLOC - xoffset; + ycurs = P_NYLOC - yoffset; + coffmap(); + + /*select correct unit*/ + selector=0; + pager=0; + while(((getselunit()-MAXARM) != nvynum) && (loop++ < 500)) { + selector+=2; + if(selector>=10) { + selector=0; + pager+=1; + } + } + return(1); +} diff --git a/original/data.c b/original/data.c new file mode 100644 index 0000000..e627a36 --- /dev/null +++ b/original/data.c @@ -0,0 +1,286 @@ +/*conquer : Copyright (c) 1988 by Ed Barlow. + * I spent a long time writing this code & I hope that you respect this. + * I give permission to alter the code, but not to copy or redistribute + * it without my explicit permission. If you alter the code, + * please document changes and send me a copy, so all can have it. + * This code, to the best of my knowledge works well, but it is my first + * 'C' program and should be treated as such. I disclaim any + * responsibility for the codes actions (use at your own risk). I guess + * I am saying "Happy gaming", and am trying not to get sued in the process. + * Ed + */ + +#include +#include +#include +#include +#include "header.h" +#include "data.h" + +/* ele is display characters */ +char *ele= "~#^%-0"; + +/* Movement costs for varying types of terain by race - '/'=error */ +char *HElecost= "//521/"; +char *OElecost= "//222/"; +char *EElecost= "//631/"; +char *DElecost= "//311/"; +char *FElecost= "16211/"; /* flight costs */ + +/* BELOW ARE MOVEMENT COSTS FOR VEG */ +char *veg= "vdtblgwfjsi~0"; +char *HVegcost= "63210001332//"; /* Human */ +char *OVegcost= "43100022527//"; /* Orcs */ +char *EVegcost= "86221000027//"; /* Elves */ +char *DVegcost= "47100013577//"; /* Dwarves */ +char *FVegcost= "410000001000/"; /* Flight */ +char *vegfood= "0004697400000"; /* food value given veg */ + +char *des= "tcmfx$!&sC?lb+*g=u-P0"; +#ifdef CONQUER +char *elename[]= { "WATER","PEAK", "MOUNTAIN", "HILL", "FLAT","ERROR"}; +char *vegname[]= { "VOLCANO", "DESERT", "TUNDRA", "BARREN", "LT VEG", +"GOOD", "WOOD", "FOREST", "JUNGLE", "SWAMP", "ICE", "NONE"}; +char *desname[]= {"TOWN", "CITY", "MINE", "FARM", "DEVASTATED", "GOLDMINE", +"FORT","RUIN","STOCKADE","CAPITOL","SPECIAL","LUMBERYD","BLKSMITH","ROAD", +"MILL","GRANARY","CHURCH","UNIVERSITY","NODESIG","BASE CAMP","ERROR"}; +char *races[]= { "GOD","ORC","ELF","DWARF","LIZARD", +"HUMAN","PIRATE","SAVAGE","NOMAD","UNKNOWN"}; +char *diploname[]= { "UNMET", "TREATY", "ALLIED", "FRIENDLY", +"NEUTRAL", "HOSTILE", "WAR", "JIHAD"}; +char *soldname[]= { "?","MARCH","SCOUT","GARRISON","TRADED","MILITIA", + "FLYING","DEFEND","MAG_DEF","ATTACK","MAG_ATT","GENERAL","SORTIE", + "SIEGE","BESIEGED","ON_BOARD","RULE"}; +#endif /* CONQUER */ + +char *directions[]= { "here", "north", "northeast", "east", "southeast", + "south", "southwest", "west", "northwest"}; +char *Class[]= { "monster", "king", "emperor", "wizard", "priest", "pirate", +"trader", "warlord", "demon", "dragon", "shadow"}; +char *alignment[]= { "Other","Good","Neutral","Evil","Other" }; + +char *unittype[]= { +"Militia", "Goblins", "Orcs", "Infantry", "Sailors", "Marines", "Archers", +"Uruk-Hai", "Ninjas", "Phalanx", "Olog-Hai", "Legionaries", "Dragoons", "Mercenaries", +"Trolls", "Elite", "Lt_Cavalry", "Hv_Cavalry", "Catapults", "Siege", "Rocs", +"Knights", "Gryfins","Elephants","Zombies","Spy","Scout", +"King","Baron","Emperor","Prince","Wizard","Mage", +"Pope","Bishop","Admiral","Captain","Warlord","Lord", +"Demon","Devil","Dragyn","Wyrm","Shadow","Nazgul", +"Spirit", "Assasin", "Efreet", "Gargoyl", "Wraith", +"Hero", "Centaur", "Giant", "Suphero", "Mummy", +"Elmentl", "Mintaur", "Daemon", "Balrog", "Dragon" +}; + +#ifdef CONQUER +/*short unit types...for printing in upper right corner*/ +char *shunittype[]= { +"mlta", "Gob", "Orc", "Inf", "Sail", "XMar", "Arch", +"Uruk", "Ninj", "Phax", "olog", "Legn", "Drag", "Merc", +"Trol", "Elt", "lCav", "hCav", "cat", "sge", "Roc", +"Kni", "grif","ele","zom","Spy","Scout", +"King","Bar","Emp","Prin","Wizd","Magi", +"Apos","Bish","Admi","Capt","Warl","Lord", +"Demn","Devl","Drag","Wyrm","Shad","Nazg", +"spir", "Assn", "efr", "Garg", "Wra", +"Hero", "Cent", "gt", "Shro", "Mumm", +"Elem", "mino", "daem", "Bal", "Drgn" +}; +#endif /* CONQUER */ +int unitminsth[]= /* min strength of a unit */ +{ +1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, +100,50,100,50,250,50, +100,50,100,50,250,125, +250,50,500,100,250,125, +50, 50, 50, 75, 75, +75, 50, 150, 150, 150, +175, 150, 500, 500, 1000 +}; + +int unitattack[]= +{ -40, -15, 0, 0, 0, 5, 0, +5, 20, 10, 15, 20, 10, 0, +25, 20, 20, 30, -20, -20, 20, +40, 40, 50, -15, -30, -30, +30,20,30,20,30,20, +30,20,30,20,30,30, +50,20,50,40,50,40, +0, 20, 10, 10, 10, +0, 10, 0, 15, 15, +5, 20, 50, 40, 50 +}; +int unitdefend[]= +{ +-25, -15, 0, 0, 0, 0, 10, +5, 0, 10, 15, 20, 10, 0, +15, 20, 20, 30, 20, 20, 30, +40, 50, 50, -15, -30, -30, +30,20,30,20,30,20, +30,20,30,20,30,30, +50,20,50,40,50,40, +0, 20, 10, 10, 10, +0, 10, 0, 15, 15, +5, 20, 50, 40, 50 +}; +/*ten times the move rate of a unit*/ +int unitmove[]= +{ + 0, 10, 10, 10, 0, 0, 10, +10, 10, 10, 10, 10, 20, 10, +10, 13, 20, 20, 5, 5, 10, +20, 15, 5, 10, 10, 20, +20,20,20,20,20,20, +20,20,20,20,20,20, +20,20,20,20,20,20, +10, 10, 15, 10, 10, +10, 15, 10, 10, 10, +15, 10, 10, 15, 20 +}; +/*metal cost of a unit*/ +int u_enmetal[]= +{ + 0, 80, 80, 100, 100, 100, 100, +150, 150, 150, 150, 150, 100, 0, +200, 200, 100, 300,1000,1000, 300, +600, 400, 600, 100, 0, 0, +0,0,0,0,0,0, +0,0,0,0,0,0, +0,0,0,0,0,0, +0, 0, 0, 0, 0, +0, 0, 0, 0, 0, +0, 0, 0, 0, 0 +}; +/*enlist cost for a unit*/ +int u_encost[]= +{ + 50, 70, 85, 100, 100, 100, 100, /* gold cost for enlistment */ + 125, 125, 150, 180, 180, 300, 225, + 225, 225, 300, 450, 600, 600, 600, + 600, 800, 600, 100, 10000, 100, +0,0,0,0,0,0, +0,0,0,0,0,0, +0,0,0,0,0,0, +2, 2, 2, 2, 2, /* spell points for enlistment */ +2, 2, 5, 5, 5, +5, 5,10,10,15 +}; +/*maintenance cost for a unit*/ +int unitmaint[]= { + 20, 20, 50, 50, 50, 50, 50, + 50, 50, 50, 75, 75, 200, 100, +100, 100, 175, 225, 250, 250, 250, +250, 250, 250, 0, 2000, 100, +0,0,0,0,0,0, /* GOLD COST PER EQUIVALENT MAN FOR MONSTERS */ +0,0,0,0,0,0, +0,0,0,0,0,0, +1000, 400, 400, 450, 450, /* JEWELS / TURN COST FOR ENTIRE UNIT */ +200, 200, 2100, 450, 1000, /* MULTIPLY BY 5 FOR GOLD COST FOR UNIT */ +1900, 2100, 6000, 6000, 10000 +}; + +char *exefile = "exec"; +char *datafile = "data"; +char *msgfile = "mesg"; +char *timefile = "timelog"; +char *sortname = "conqsort"; + +#ifdef ADMIN +char scenario[NAMELTH+1]; +char *npcsfile = "nations"; +#endif /* ADMIN */ +char *helpfile = "help"; +char *newsfile = "news"; +char *isonfile = "lock"; +#ifdef TRADE +char *tradefile = "commerce"; +#endif /* TRADE */ + +char *seasonstr[] = { "Winter", "Spring", "Summer", "Fall" }; + +char *pwrname[] = { +"WARRIOR", "CAPTAIN", "WARLORD", "ARCHER", "CAVALRY", "SAPPER", +"ARMOR", "AVIAN", "MI_MONST", "AV_MONST", "MA_MONST", + +"SLAVER", "DERVISH", "HIDDEN", "ARCHITECT", "RELIGION", "MINER", +"BREEDER", "URBAN", "STEEL", "NINJA", "SAILOR", "DEMOCRACY", "ROADS", + +"THE_VOID", "KNOWALL", "DESTROYER", "VAMPIRE", +"SUMMON", "WYZARD", "SORCERER", "ERROR" +}; + +long powers[] = { + WARRIOR, /*MILITARY POWERS => START=0*/ + CAPTAIN, /*1*/ + WARLORD, /*2*/ + ARCHER, /*3*/ + CAVALRY, /*4*/ + SAPPER, /*5*/ + ARMOR, /*6*/ + AVIAN, /*7*/ + MI_MONST, /*8*/ + AV_MONST, /*9*/ + MA_MONST, /*10th power; Mil power #11*/ + SLAVER, /*CIVILIAN POWERS => START=11*/ + DERVISH, /*12*/ + HIDDEN, /*13*/ + ARCHITECT, /*14*/ + RELIGION, /*15*/ + MINER, /*16*/ + BREEDER, /*17*/ + URBAN, /*18*/ + STEEL, /*19*/ + NINJA, /*20*/ + SAILOR, /*21*/ + DEMOCRACY, /*22*/ + ROADS, /* 13th CIVILIAN POWER (23rd total) */ + THE_VOID, /* MAGICAL SKILLS => START=24 */ + KNOWALL, /*25*/ + DESTROYER, /*26*/ + VAMPIRE, /*27*/ + SUMMON, /*28*/ + WYZARD, /*29*/ + SORCERER, /*30th Entry => 31 total powers => End=7*/ + 0 +}; + +FILE *fnews, *fopen(); +struct sprd_sht spread; + +FILE *fm; +int mailok=DONEMAIL; + +#ifdef CONQUER +#ifdef SYSMAIL +char sysmail[FILELTH]; +int sys_mail_status; +#endif /* SYSMAIL */ +char conqmail[FILELTH]; +int conq_mail_status; +#endif /* CONQUER */ + +/* trade good value - zeroes in this comment line mark increments of ten*/ +/* 0 0 0 0 0 0 */ +/* a value of x means any designation is possible */ +/* fwbcwmhpgcfshfrwdpbcpstgponpmldpllpiopshmtpbcltismasspdsgridp*/ +char *tg_stype="xffffttttffffffffffftxlxllttuuctcccfff?xtccmmmmmmmm$$$$$$$$$$0"; +char *tg_value="13335157911433442331131135734567789123937571111111111111111110"; + +char *tg_name[] = { +"furs", "wool", "beer", "cloth", "wine", +"mules", "horses", "pigeons", "griffons", +"corn", "fish", "sugar", "honey", "fruit", +"rice", "wheat", "dairy", "peas", "bread", "cereal", +"pottery", "salt", "timber", "granite", "pine", "oak", "nails", +"papyrus","math","library","drama","paper","literature","law","philosophy", +"irrigation", "oxen", "plows", +"stones", +"herbs", "medicine", +"torture", "prison", +"bronze", "copper", "lead", "tin", "iron","steel", "mithral", "adamantine", +"spice","silver","pearls","dye","silk","gold","rubys","ivory","diamonds","platinum", +"none" +}; diff --git a/original/data.h b/original/data.h new file mode 100644 index 0000000..88fecba --- /dev/null +++ b/original/data.h @@ -0,0 +1,1013 @@ +/* conquer : Copyright (c) 1988 by Ed Barlow. */ + +/*--------I DO NOT BELIEVE IT IS NECESSARY TO ALTER THIS FILE----------------*/ +#define FAIL 1 /* fail return to shell */ +#define SUCCESS 0 /* successful return to shell */ +#define TIME_DEAD 3600 /* number of seconds for file aging */ +#define BIG 500000000L /* BIGGER THAN ANYTHING SHOULD BE */ + /* this is used to protect against overflow */ +#define SCRARM ((LINES-14)/2) /* number of armies to fit on screen */ + +/* sometimes curses.h defines TRUE */ +#ifndef TRUE +#define TRUE 1 +#define FALSE 0 +#endif + +/* definitions for mail sending */ +#define DONEMAIL (-3) +#define NEWSMAIL (-2) +#define ABORTMAIL (-1) + +/* definitions for screen redrawing */ +#define DONE 0 +#define PART 1 +#define FULL 2 + +#define SCREEN_X_SIZE (( COLS - 21) / 2) /* divide by two as only 1/2 + sectors will be shown */ +#define SCREEN_Y_SIZE ( LINES - 5 ) +#define HAS_SEEN(x,y) hasseen[(x)+((y)*((COLS-10)/2))] +#define PASSLTH 7 /* the number of characters in the passwd*/ +#define NAMELTH 9 /* the number of characters in the name*/ +#define LEADERLTH 9 /* the number of characters in the leader*/ +#define FILELTH 80 /*length for filename holders*/ +#define LINELTH 80 /*length for input string lines*/ +#define BIGLTH 256 /*length for large storage strings*/ +#define NUMCLASS 11 /*number of nation classes */ + +/* environment variable strings to check */ +#define ENVIRON_OPTS "CONQ_OPTS" + +/*simple contour map definitions*/ +#define WATER (*(ele+0)) +#define PEAK (*(ele+1)) +#define MOUNTAIN (*(ele+2)) +#define HILL (*(ele+3)) +#define CLEAR (*(ele+4)) + +/*racial types*/ +#define GOD '-' +#define ORC 'O' +#define ELF 'E' +#define DWARF 'D' +#define LIZARD 'L' +#define HUMAN 'H' +#define PIRATE 'P' +#define SAVAGE 'S' +#define NOMAD 'N' +#define TUNKNOWN '?' + +/*designations*/ +#define DTOWN (*(des+0)) +#define DCITY (*(des+1)) +#define DMINE (*(des+2)) +#define DFARM (*(des+3)) +#define DDEVASTATED (*(des+4)) +#define DGOLDMINE (*(des+5)) +#define DFORT (*(des+6)) +#define DRUIN (*(des+7)) +#define DSTOCKADE (*(des+8)) +#define DCAPITOL (*(des+9)) +#define DSPECIAL (*(des+10)) +#define DLUMBERYD (*(des+11)) +#define DBLKSMITH (*(des+12)) +#define DROAD (*(des+13)) +#define DMILL (*(des+14)) +#define DGRANARY (*(des+15)) +#define DCHURCH (*(des+16)) +#define DUNIVERSITY (*(des+17)) +#define DNODESIG (*(des+18)) +#define DBASECAMP (*(des+19)) + +/* nation placement variables */ +#define GREAT 'G' +#define FAIR 'F' +#define RANDOM 'R' +#define OOPS 'X' + +/*vegetation types -- these are legal in designations too*/ +#define VOLCANO (*(veg+0)) +#define DESERT (*(veg+1)) +#define TUNDRA (*(veg+2)) +#define BARREN (*(veg+3)) +#define LT_VEG (*(veg+4)) +#define GOOD (*(veg+5)) +#define WOOD (*(veg+6)) +#define FOREST (*(veg+7)) +#define JUNGLE (*(veg+8)) +#define SWAMP (*(veg+9)) +#define ICE (*(veg+10)) +#define NONE (*(veg+11)) + +/*Diplomacy Variables*/ +#define JIHAD 7 +#define WAR 6 +#define HOSTILE 5 +#define NEUTRAL 4 +#define FRIENDLY 3 +#define ALLIED 2 +#define TREATY 1 +#define UNMET 0 + +#define BREAKJIHAD 200000L /* $ cost to break confederacy or jihad */ + +/*army status*/ +#define MARCH 1 /*March */ +#define SCOUT 2 /*Scouting--will not engage enemy if possible*/ +#define GARRISON 3 /*Garrison--for a town or Capitol */ +#define TRADED 4 /*Indicates an army that has been traded*/ +#define MILITIA 5 /*Unit is a militia unit */ +#define FLIGHT 6 /*Indicates army is flying*/ +#define DEFEND 7 /*Defend */ +#define MAGDEF 8 /*Magically enhanced defend mode*/ +#define ATTACK 9 /*Attack anybody (Hostile+) within 2 sectors*/ +#define MAGATT 10 /*Magically enhanced attack mode*/ +#define GENERAL 11 /* group leader !!! */ +#define SORTIE 12 /*Quick attack from a city */ +#define SIEGE 13 /*Set siege on a city */ +#define SIEGED 14 /*Unit under siege */ +#define ONBOARD 15 /*On board a fleet */ +#define RULE 16 /*Nation leader status for capitol */ +#define NUMSTATUS 17 /* number of possible stats */ + /* Army groups are implemented in the army + status vbl. if >= NUMSTATUS, you belong to + army group x-NUMSTATUS - army groups always + of status attack and may not be magicked */ + +/*seasonal definitions */ +#define TURN world.turn /* game turn */ +#define SEASON(x) ((x)%4) +#define PSEASON(x) seasonstr[((x)%4)] +#define YEAR(x) ((int)((x+3)/4)) +#define WINTER 0 +#define SPRING 1 +#define SUMMER 2 +#define FALL 3 + +/* definitions for compass directions */ +#define CENTERED 0 +#define NORTH 1 +#define NORTHEAST 2 +#define EAST 3 +#define SOUTHEAST 4 +#define SOUTH 5 +#define SOUTHWEST 6 +#define WEST 7 +#define NORTHWEST 8 + +struct s_world +{ + short mapx,mapy; /* size of world */ + short nations; /* number of actual nations */ + short othrntns; /* god, lizard... */ + short turn; /* game turn */ + long m_mil; /* number of mercs available */ + short m_aplus; /* mercenary attack bonus */ + short m_dplus; /* mercenary defense bonus */ + long w_jewels; /* jewels in world */ + long w_gold; /* gold talons in world */ + long w_food; /* food in world */ + long w_metal; /* metal in world */ + long w_civ; /* world population */ + long w_mil; /* world military */ + long w_sctrs; /* owned sectors in world */ + long score; /* world score total */ +}; + +#define MAPX world.mapx +#define MAPY world.mapy +#define MERCMEN world.m_mil +#define MERCATT world.m_aplus +#define MERCDEF world.m_dplus +#define WORLDJEWELS world.w_jewels +#define WORLDGOLD world.w_gold +#define WORLDMETAL world.w_metal +#define WORLDFOOD world.w_food +#define WORLDSCORE world.score +#define WORLDCIV world.w_civ +#define WORLDSCT world.w_sctrs +#define WORLDMIL world.w_mil +#define WORLDNTN world.nations + +struct s_sector +{ + unsigned char designation; /* designation of sector */ + unsigned char altitude; /* sector altitude */ + unsigned char vegetation; /* sector vegetation */ + unsigned char owner; /* nation id of owner */ + long people; /* civilians in sector */ + short i_people; /* initial civilians in sector */ + unsigned char jewels; /* jewel production ability */ + unsigned char fortress; /* fortification level; 0 to 12 */ + unsigned char metal; /* metal produced by sector */ + unsigned char tradegood; /* exotic trade goods in sector */ + /* unsigned char region; /* index of region */ +}; +#define SOWN sct[xcurs+xoffset][ycurs+yoffset].owner +#define XREAL (xcurs+xoffset) +#define YREAL (ycurs+yoffset) + +struct navy +{ + unsigned short warships; + unsigned short merchant; + unsigned short galleys; + unsigned char xloc; + unsigned char yloc; + unsigned char smove; /* movement ability of ship */ + unsigned char crew; /* crew on ship */ + unsigned char people; /* people carried */ + unsigned char commodity; /* future commodities */ + unsigned char armynum; /* army carried */ +}; + + +/* NATION STRATEGY: a nation's strategy is a part of the ntn[].active + * variable which tells if it is a PC or NPC, its alignment, and its + * constraints alignments can be good, neutral, or evil. + * NPC Nations can be Expansionsist (with 0,2,4,6 sectors to expand into) + * or Isolationist. */ +#define INACTIVE 0 +#define PC_GOOD 1 /* PC NATIONS */ +#define PC_NEUTRAL 2 +#define PC_EVIL 3 +#define GOOD_0FREE 4 /* NPC NATIONS */ +#define GOOD_2FREE 5 +#define GOOD_4FREE 6 +#define GOOD_6FREE 7 +#define NEUTRAL_0FREE 8 +#define NEUTRAL_2FREE 9 +#define NEUTRAL_4FREE 10 +#define NEUTRAL_6FREE 11 +#define EVIL_0FREE 12 +#define EVIL_2FREE 13 +#define EVIL_4FREE 14 +#define EVIL_6FREE 15 +#define ISOLATIONIST 16 /* ISOLATIONIST NATIONS */ +#define NPC_PEASANT 17 /* PEASANT REVOLT TYPE NATIONS */ +#define NPC_PIRATE 18 +#define NPC_LIZARD 19 +#define NPC_NOMAD 20 +#define NPC_SAVAGE 21 + +#define ispc(x) (((x)==PC_GOOD)||((x)==PC_EVIL)||((x)==PC_NEUTRAL)) +#define npctype(x) (ispc(x) ? (x) : (ismonst(x)?0:(x)/4)) +#define isgood(x) (npctype(x) == 1) +#define isneutral(x) (npctype(x) == 2) +#define isevil(x) (npctype(x) == 3) +#define isnpc(x) (((x)>=GOOD_0FREE)&&((x)<=ISOLATIONIST)) +#define isnotpc(x) (((x)>=GOOD_0FREE)&&((x)!=INACTIVE)) +#define ismonst(x) ((x)>=NPC_PEASANT) +#define ispeasant(x) ((x)==NPC_PEASANT) +#define isntn(x) (((x)!=INACTIVE)&&((x)<=ISOLATIONIST)) +#define isntnorp(x) (((x)!=INACTIVE)&&((x)<=NPC_PEASANT)) +#define isactive(x) ((x)!=INACTIVE) + +/* definitions for mail checker */ +#define NO_MAIL 0 +#define NEW_MAIL 1 + +/* definitions for naval types */ +#define N_LIGHT 0 +#define N_MEDIUM 1 +#define N_HEAVY 2 +#define N_BITSIZE 5 +#define N_MASK ((unsigned short) 0x001f) + +/* definitions for naval calculations */ +#define N_WSPD 20 /* speed of warships */ +#define N_GSPD 18 /* speed of galleys */ +#define N_MSPD 15 /* speed of merchants */ +#define N_NOSPD 0 /* no ships no speed */ +#define N_SIZESPD 3 /* bonus speed for lighter ships */ + +#define UTYPE 75 +#define TWOUTYPE 150 /* two times value of UTYPE above */ + +#define A_MILITIA 0 +#define A_GOBLIN 1 +#define A_ORC 2 +#define A_INFANTRY 3 +#define A_SAILOR 4 +#define A_MARINES 5 +#define A_ARCHER 6 +#define A_URUK 7 +#define A_NINJA 8 +#define A_PHALANX 9 +#define A_OLOG 10 +#define A_LEGION 11 +#define A_DRAGOON 12 +#define A_MERCENARY 13 +#define A_TROLL 14 +#define A_ELITE 15 +#define A_LT_CAV 16 +#define A_CAVALRY 17 +#define A_CATAPULT 18 +#define A_SIEGE 19 +#define A_ROC 20 +#define A_KNIGHT 21 +#define A_GRIFFON 22 +#define A_ELEPHANT 23 +#define A_ZOMBIE 24 +#define A_SPY 25 +#define A_SCOUT 26 +#define NOUNITTYPES 26 /*number of unit types*/ + +#define MINLEADER (27+UTYPE) /* min value of a leader -1*/ +#define L_KING (27+UTYPE) +#define L_BARON (28+UTYPE) +#define L_EMPEROR (29+UTYPE) +#define L_PRINCE (30+UTYPE) +#define L_WIZARD (31+UTYPE) +#define L_MAGI (32+UTYPE) +#define L_APOSTLE (33+UTYPE) +#define L_BISHOP (34+UTYPE) +#define L_ADMIRAL (35+UTYPE) +#define L_CAPTAIN (36+UTYPE) +#define L_WARLORD (37+UTYPE) +#define L_LORD (38+UTYPE) +#define L_DEMON (39+UTYPE) +#define L_DEVIL (40+UTYPE) +#define L_DRAGON (41+UTYPE) +#define L_WYRM (42+UTYPE) +#define L_SHADOW (43+UTYPE) +#define L_NAZGUL (44+UTYPE) + +#define MINMONSTER (45+TWOUTYPE) /* min value of a monster */ +#define SPIRIT (45+TWOUTYPE) +#define ASSASSIN (46+TWOUTYPE) +#define DJINNI (47+TWOUTYPE) +#define GARGOYLE (48+TWOUTYPE) +#define WRAITH (49+TWOUTYPE) +#define HERO (50+TWOUTYPE) +#define CENTAUR (51+TWOUTYPE) +#define GIANT (52+TWOUTYPE) +#define SUPERHERO (53+TWOUTYPE) +#define MUMMY (54+TWOUTYPE) +#define ELEMENTAL (55+TWOUTYPE) +#define MINOTAUR (56+TWOUTYPE) +#define DEMON (57+TWOUTYPE) +#define BALROG (58+TWOUTYPE) +#define DRAGON (59+TWOUTYPE) +#define MAXMONSTER (59+TWOUTYPE) + +struct army +{ + unsigned char unittyp; + unsigned char xloc; + unsigned char yloc; + unsigned char smove; + long sold; + unsigned char stat; +}; + +struct s_nation /* player nation stats */ +{ + char name[NAMELTH+1]; /* name */ + char passwd[PASSLTH+1]; /* password */ + char leader[LEADERLTH+1]; /* leader title */ + char race; /* national race (integer--see header.h)*/ + char location; /* location variable (gfr) */ + char mark; /* unique mark for nation */ +#ifdef CHECKUSER + short int uid; /* for uid checking (CHECKUSER) */ +#endif /* CHECKUSER */ + unsigned char capx; /* Capitol x coordinate */ + unsigned char capy; /* Capitol y coordinate */ + unsigned char active; /* nation type and strategy */ + unsigned char maxmove;/* maximum movement of soldiers */ + char repro; /* reproduction rate of nation */ + long score; /* score */ + long tgold; /* gold in treasury */ + long jewels; /* raw amount of jewels in treasury */ + long tmil; /* total military */ + long tciv; /* total civilians */ + long metals; /* total real metal in nation */ + long tfood; /* total food in nation */ + long powers; + short class; /* national class */ + short aplus; /* attack plus of all soldiers */ + short dplus; /* attack plus of all soldiers */ + short spellpts; /* spell points */ + short tsctrs; /* total number sectors */ + short tships; /* number warships */ + short inflation; /* inflation rate */ + unsigned char charity; /* charity budget (% of Taxes) */ + struct army arm[MAXARM]; + struct navy nvy[MAXNAVY]; + char dstatus[NTOTAL]; /* diplomatic status */ + unsigned char tax_rate; /* taxrate populace */ + unsigned char prestige; /* nations prestige */ + unsigned char popularity; /* governments popularity */ + unsigned char power; /* nation power */ + unsigned char communications; /* leader communication */ + unsigned char wealth; /* per capita income */ + unsigned char eatrate; /* food eaten / 10 people*/ + unsigned char spoilrate; /* food spoilage rate */ + unsigned char knowledge; /* general knowledge */ + unsigned char farm_ability; /* farming ability */ + unsigned char mine_ability; /* mine ability */ + unsigned char poverty; /* % poor people */ + unsigned char terror; /* peoples terror of you*/ + unsigned char reputation; /* reputation of nation */ +}; +#define P_NTNCOM ((((float) curntn->communications)/ 50.0 )) +#define P_EATRATE ((((float) curntn->eatrate) / 25.0 )) +#define P_REPRORATE ( ((float) (100.0 + 25.0*curntn->repro )/100.0)) + +#define P_ATYPE curntn->arm[armynum].unittyp +#define P_AXLOC curntn->arm[armynum].xloc +#define P_AYLOC curntn->arm[armynum].yloc +#define P_AMOVE curntn->arm[armynum].smove +#define P_ASOLD curntn->arm[armynum].sold +#define P_ASTAT curntn->arm[armynum].stat +#define P_NWSHP curntn->nvy[nvynum].warships +#define P_NMSHP curntn->nvy[nvynum].merchant +#define P_NGSHP curntn->nvy[nvynum].galleys +#define P_NCREW curntn->nvy[nvynum].crew +#define P_NARMY curntn->nvy[nvynum].armynum +#define P_NPEOP curntn->nvy[nvynum].people +#define P_NXLOC curntn->nvy[nvynum].xloc +#define P_NYLOC curntn->nvy[nvynum].yloc +#define P_NMOVE curntn->nvy[nvynum].smove + +/* naval routine macros */ +#define SHIPS(x,y) (short)( ((x)&(N_MASK<<((y)*N_BITSIZE))) >> ((y)*N_BITSIZE) ) +#define P_NWAR(x) SHIPS(P_NWSHP,x) +#define P_NMER(x) SHIPS(P_NMSHP,x) +#define P_NGAL(x) SHIPS(P_NGSHP,x) +#define NADD_WAR(x) addwships(nvynum,shipsize,(x)); +#define NADD_MER(x) addmships(nvynum,shipsize,(x)); +#define NADD_GAL(x) addgships(nvynum,shipsize,(x)); +#define NSUB_WAR(x) subwships(nvynum,shipsize,(x)); +#define NSUB_MER(x) submships(nvynum,shipsize,(x)); +#define NSUB_GAL(x) subgships(nvynum,shipsize,(x)); + +#define ATYPE ntn[country].arm[armynum].unittyp +#define AXLOC ntn[country].arm[armynum].xloc +#define AYLOC ntn[country].arm[armynum].yloc +#define AMOVE ntn[country].arm[armynum].smove +#define ASOLD ntn[country].arm[armynum].sold +#define ASTAT ntn[country].arm[armynum].stat +#define NWSHP ntn[country].nvy[nvynum].warships +#define NMSHP ntn[country].nvy[nvynum].merchant +#define NGSHP ntn[country].nvy[nvynum].galleys +#define NCREW ntn[country].nvy[nvynum].crew +#define NARMY ntn[country].nvy[nvynum].armynum +#define NPEOP ntn[country].nvy[nvynum].people +#define NXLOC ntn[country].nvy[nvynum].xloc +#define NYLOC ntn[country].nvy[nvynum].yloc +#define NMOVE ntn[country].nvy[nvynum].smove + +/* these defines are for types of magic powers */ +#define M_MIL 1 /* military */ +#define M_CIV 2 /* civilian */ +#define M_MGK 3 /* magical */ +#define M_TECH 4 /* technological */ +#define M_ALL 5 + +#define AORN 0 +#define ARMY 1 +#define NAVY 2 + +#define XASTAT 1 +#define XAMEN 2 +#define XBRIBE 3 +#define XALOC 4 +#define XNLOC 5 +#define XNAMER 6 +#define XNACREW 7 +#define XECNAME 8 +#define XECPAS 9 +#define EDSPL 10 +#define XSADES 11 +#define XSACIV 12 +#define XSIFORT 13 +#define XNAGOLD 14 +#define XAMOV 15 +#define XNMOV 16 +#define XSAOWN 17 +#define EDADJ 18 +#define XNARGOLD 19 +#define XNAMETAL 20 +#define INCAPLUS 22 +#define INCDPLUS 23 +#define CHG_MGK 24 +#define DESTRY 25 +#define MSETA 26 +#define MSETB 27 +#define NTAX 28 +#define XNAWAR 29 +#define XNAGAL 30 +#define XNAHOLD 31 +#define NPOP 32 +#define XSACIV3 33 + +#define BRIBENATION fprintf(fm,"L_NGOLD\t%d\t%d\t%ld\t0\t%d\t%s\n",XBRIBE,country,bribecost,nation,"null"); +#define DESTROY fprintf(fexe,"DESTROY\t%d\t%d\t%hd\t0\t0\t%s\n",DESTRY,save,country,"null") +#define CHGMGK fprintf(fexe,"L_MAGIC\t%d\t%hd\t%ld\t%ld\t0\t%s\n",CHG_MGK,country,ntn[country].powers,x,"null") +#define I_APLUS fprintf(fexe,"INC_APLUS\t%d\t%hd\t0\t0\t0\t%s\n",INCAPLUS,country,"null") +#define I_DPLUS fprintf(fexe,"INC_DPLUS\t%d\t%hd\t0\t0\t0\t%s\n",INCDPLUS,country,"null") +#define AADJMERC fprintf(fexe,"A_MERC\t%d\t%d\t%ld\t0\t0\t%s\n",MSETA,country,men,"null") +#define AADJDISB fprintf(fexe,"A_MERC\t%d\t%d\t%ld\t%d\t%d\t%s\n",MSETB,country,bemerc,attset,defset,"null") +#define AADJSTAT fprintf(fexe,"A_STAT\t%d\t%hd\t%d\t%d\t0\t%s\n",XASTAT,country,armynum,ntn[country].arm[armynum].stat,"null") +#define AADJMEN fprintf(fexe,"L_ADJMEN\t%d\t%hd\t%hd\t%ld\t%d\t%s\n",XAMEN,country,armynum,P_ASOLD,P_ATYPE,"null") +#define NADJCRW fprintf(fexe,"N_ASHP\t%d\t%hd\t%hd\t%d\t%d\t%s\n",XNACREW,country,nvynum,NCREW,ntn[country].nvy[nvynum].armynum,"null") +#define NADJMER fprintf(fexe,"N_ASHP\t%d\t%hd\t%d\t%hd\t%d\t%s\n",XNAMER,country,nvynum,ntn[country].nvy[nvynum].merchant,0,"null") +#define NADJWAR fprintf(fexe,"N_ASHP\t%d\t%hd\t%d\t%hd\t%d\t%s\n",XNAWAR,country,nvynum,ntn[country].nvy[nvynum].warships,0,"null") +#define NADJGAL fprintf(fexe,"N_ASHP\t%d\t%hd\t%d\t%hd\t%d\t%s\n",XNAGAL,country,nvynum,ntn[country].nvy[nvynum].galleys,0,"null") +#define NADJHLD fprintf(fexe,"N_ASHP\t%d\t%hd\t%d\t%hd\t%d\t%s\n",XNAHOLD,country,nvynum,ntn[country].nvy[nvynum].armynum,ntn[country].nvy[nvynum].people,"null") +#define AADJLOC fprintf(fexe,"A_LOC\t%d\t%hd\t%d\t%d\t%d\t%s\n",XALOC,country,armynum,ntn[country].arm[armynum].xloc,ntn[country].arm[armynum].yloc,"null") +#define NADJLOC fprintf(fexe,"N_LOC\t%d\t%hd\t%d\t%d\t%d\t%s\n",XNLOC,country,nvynum,ntn[country].nvy[nvynum].xloc,ntn[country].nvy[nvynum].yloc,"null") +#define AADJMOV fprintf(fexe,"A_MOV\t%d\t%hd\t%d\t%d\t0\t%s\n",XAMOV,country,armynum,ntn[country].arm[armynum].smove,"null") +#define NADJMOV fprintf(fexe,"N_MOV\t%d\t%hd\t%d\t%d\t0\t%s\n",XNMOV,country,nvynum,ntn[country].nvy[nvynum].smove,"null") +#define ECHGNAME fprintf(fexe,"E_CNAME\t%d\t%hd\t0\t0\t0\t%s\n",XECNAME,country,ntn[country].name) +#define ECHGPAS fprintf(fexe,"E_CPAS\t%d\t%hd\t0\t0\t0\t%s\n",XECPAS,country,curntn->passwd) +#define SADJDES fprintf(fexe,"S_ADES\t%d\t%hd\t0\t%d\t%d\t%c\n",XSADES,country,xcurs+xoffset,ycurs+yoffset,sct[xcurs+xoffset][ycurs+yoffset].designation) +#define SADJDES2 fprintf(fexe,"S_ADES\t%d\t%hd\t0\t%d\t%d\t%c\n",XSADES,country,x,y,sct[x][y].designation) +#define SADJCIV2 fprintf(fexe,"S_ACIV\t%d\t%hd\t%ld\t%d\t%d\t%s\n",XSACIV,country,sct[i][j].people,i,j,"null") +#define SADJCIV fprintf(fexe,"S_ACIV\t%d\t%hd\t%ld\t%d\t%d\t%s\n",XSACIV,country,sct[xcurs+xoffset][ycurs+yoffset].people,xcurs+xoffset,ycurs+yoffset,"null") +#define SADJCIV3 fprintf(fexe,"S_ACIV3\t%d\t%hd\t%ld\t%d\t%d\t%s\n",XSACIV3,country,people_to_add,i,j,"null") +#define INCFORT fprintf(fexe,"SIFORT\t%d\t%hd\t0\t%d\t%d\t%s\n",XSIFORT,country,xcurs+xoffset,ycurs+yoffset,"null") +#define SADJOWN fprintf(fexe,"S_AOWN\t%d\t%hd\t0\t%d\t%d\t%s\n",XSAOWN,country,xcurs+xoffset,ycurs+yoffset,"null") +#define EADJDIP(a,b) fprintf(fexe,"E_ADJ\t%d\t%hd\t%d\t%d\t0\t%s\n",EDADJ,a,b,ntn[a].dstatus[b],"null") +#define EDECSPL fprintf(fexe,"E_SPL\t%d\t%hd\t%d\t%d\t0\t%s\n",EDSPL,country,s_cost,0,"null") +#define NADJNTN fprintf(fexe,"N_TAX \t%d \t%hd \t%d \t%d \t%d \tnull\n",NTAX,country,(int) curntn->tax_rate,(int) curntn->active, (int) curntn->charity) +#define NADJNTN2 fprintf(fexe,"N_POP \t%d \t%hd \t%d \t%d \t%d \tnull\n",NPOP,country,(int) curntn->popularity,(int) curntn->terror, (int) curntn->reputation) + +#define S_MIL 0 /* position in powers array */ +#define WARRIOR 0x00000001L +#define CAPTAIN 0x00000002L +#define WARLORD 0x00000004L +#define ARCHER 0x00000008L +#define CAVALRY 0x00000010L +#define SAPPER 0x00000020L +#define ARMOR 0x00000040L +#define AVIAN 0x00000080L +#define MI_MONST 0x00000100L +#define AV_MONST 0x00000200L +#define MA_MONST 0x00000400L +#define E_MIL 11 + /*CIVILIAN POWERS */ +#define S_CIV 11 +#define SLAVER 0x00000800L +#define DERVISH 0x00001000L +#define HIDDEN 0x00002000L +#define ARCHITECT 0x00004000L +#define RELIGION 0x00008000L +#define MINER 0x00010000L +#define BREEDER 0x00020000L +#define URBAN 0x00040000L +#define STEEL 0x00080000L +#define NINJA 0x00100000L +#define SAILOR 0x00200000L +#define DEMOCRACY 0x00400000L +#define ROADS 0x00800000L +#define E_CIV 13 + /* MAGICAL SKILLS */ +#define S_MGK 24 +#define THE_VOID 0x01000000L +#define KNOWALL 0x02000000L +#define DESTROYER 0x04000000L +#define VAMPIRE 0x08000000L +#define SUMMON 0x10000000L +#define WYZARD 0x20000000L +#define SORCERER 0x40000000L +#define E_MGK 7 +#define MAXPOWER 31 /* number of powers */ + +/* magic macro: returns TRUE if the nation has that power*/ +#define magic(NATION,POWER) ((ntn[NATION].powers&(POWER))!=0) +#define ONMAP(x,y) ((x)>=0 && (y)>=0 && (x)(y) ? (x) : (y)) +#define min(x,y) ((x)<(y) ? (x) : (y)) +#endif + +/* attractiveness of sector to general populace */ +#define GOLDATTR 9 /* per jewel value of sector */ +#define FARMATTR 7 /* per point of food producable */ +#define MINEATTR 9 /* per metal value of sector */ +#define TOWNATTR 150 +#define CITYATTR 300 +#define TGATTR 10 /* bonus per point of value for tradegoods */ +#define OTHRATTR 50 /* attractiveness of other sector types */ + + +#define DMNTNATTR 40 /* DWARF ATTRACTIVENESS */ +#define DHILLATTR 20 +#define DCLERATTR 0 +#define DCITYATTR -20 +#define DTOWNATTR -20 +#define DGOLDATTR 40 +#define DMINEATTR 40 +#define DFOREATTR -20 +#define DWOODATTR -10 + +#define EMNTNATTR -40 /* ELF */ +#define EHILLATTR -20 +#define ECLERATTR 0 +#define ECITYATTR -50 +#define ETOWNATTR -50 +#define EGOLDATTR 0 +#define EMINEATTR 0 +#define EFOREATTR 40 +#define EWOODATTR 40 + +#define OMNTNATTR 30 /* ORC */ +#define OHILLATTR 20 +#define OCLERATTR 0 +#define OCITYATTR 50 +#define OTOWNATTR 25 +#define OGOLDATTR 20 +#define OMINEATTR 20 +#define OFOREATTR -40 +#define OWOODATTR -20 + +#define HMNTNATTR -10 /* HUMAN */ +#define HHILLATTR 0 +#define HCLERATTR 30 +#define HCITYATTR 50 +#define HTOWNATTR 40 +#define HGOLDATTR 10 +#define HMINEATTR 10 +#define HFOREATTR -20 +#define HWOODATTR 0 + +/* EXOTIC TRADE GOODS */ +#define TG_furs 0 +#define TG_wool 1 +#define TG_beer 2 +#define TG_cloth 3 +#define TG_wine 4 +#define END_POPULARITY 4 + +#define TG_mules 5 +#define TG_horses 6 +#define TG_pigeons 7 +#define TG_griffons 8 +#define END_COMMUNICATION 8 + +#define TG_corn 9 +#define TG_fish 10 +#define TG_sugar 11 +#define TG_honey 12 +#define TG_fruit 13 +#define TG_rice 14 +#define TG_wheat 15 +#define TG_dairy 16 +#define TG_peas 17 +#define TG_bread 18 +#define TG_cereal 19 +#define END_EATRATE 19 + +#define TG_pottery 20 +#define TG_salt 21 +#define TG_timber 22 +#define TG_granite 23 +#define TG_pine 24 +#define TG_oak 25 +#define TG_nails 26 +#define END_SPOILRATE 26 /* also Knowledge start */ + +#define TG_papyrus 27 +#define TG_math 28 +#define TG_library 29 +#define TG_drama 30 +#define TG_paper 31 +#define TG_literature 32 +#define TG_law 33 +#define TG_philosophy 34 +#define END_KNOWLEDGE 34 + +#define TG_irregation 35 +#define TG_oxen 36 +#define TG_plows 37 +#define END_FARM 37 + +#define TG_stones 38 +#define END_SPELL 38 + +#define TG_herbs 39 +#define TG_medecine 40 +#define END_HEALTH 40 + +#define TG_torture 41 +#define TG_prison 42 +#define END_TERROR 42 +#define END_NORMAL 42 /* also end of non mine/jewel goods */ + +#define TG_bronze 43 +#define TG_copper 44 +#define TG_lead 45 +#define TG_tin 46 +#define TG_iron 47 +#define TG_steel 48 +#define TG_mithral 49 +#define TG_adamantine 50 +#define END_MINE 50 + +#define TG_spice 51 +#define TG_silver 52 +#define TG_pearls 53 +#define TG_dye 54 +#define TG_silk 55 +#define TG_gold 56 +#define TG_rubys 57 +#define TG_ivory 58 +#define TG_diamonds 59 +#define TG_platinum 60 +#define END_WEALTH 60 +#define TG_none 61 /* no trade goods in sector */ +#define MAXTGVAL 100 /* maximum value for stat */ + +/* defines for a nations class */ +#define C_NPC 0 +#define C_KING 1 +#define C_EMPEROR 2 +#define C_WIZARD 3 +#define C_PRIEST 4 +#define C_PIRATE 5 +#define C_TRADER 6 +#define C_WARLORD 7 +#define C_DEMON 8 +#define C_DRAGON 9 +#define C_SHADOW 10 +#define C_END 10 + +#define ISCITY(desig) ((desig==DCITY)||(desig==DCAPITOL)||(desig==DFORT)||(desig==DTOWN)) + +#define PWR_NA 10 /* national attributes gained from power */ +#define CLA_NA 30 /* national attributes gained from class */ + +/* MAGIC/CIVILIAN/MILITARY POWER COSTS BY RACE */ +#define BASEMAGIC 50000L /* default for all not mentioned */ +#define DWFMAGIC 80000L +#define HUMMAGIC 100000L +#define ORCMAGIC 150000L +#define DWFCIVIL 40000L +#define ORCCIVIL 75000L +#define HUMCIVIL 25000L +#define DWFMILIT 40000L +#define ORCMILIT 45000L + +#define abrt() { \ +fprintf(stderr,"\nSerious Error (File %s, Line %d) - Aborting\n",__FILE__,__LINE__); \ +abort(); \ +} + +#define DEVASTATE(X,Y) { \ +if(is_habitable(X,Y)) { \ +if((sct[X][Y].designation == DCAPITOL) \ +||(sct[X][Y].designation == DRUIN) \ +||(sct[X][Y].designation == DCITY)) { \ + if(sct[X][Y].fortress >= 4) { \ + sct[X][Y].fortress -= 4; \ + } else sct[X][Y].fortress = 0; \ + sct[X][Y].designation = DRUIN; \ +} else sct[X][Y].designation = DDEVASTATED; \ +} \ +} + +extern FILE *fm; +extern int mailok; +extern char *seasonstr[]; +extern char *alignment[]; +extern struct s_sector **sct; +extern struct s_nation ntn[NTOTAL]; +extern struct s_nation *curntn; +extern struct s_world world; + +extern short **movecost; +extern char **occ; /* sector occupied?, NTOTAL+1 if contested */ +extern char *ele, *elename[], *veg, *vegfood, *vegname[]; +extern char *Class[],*races[],*diploname[]; +extern char *soldname[], *unittype[], *shunittype[], *directions[]; +extern int unitminsth[], u_enmetal[], u_encost[], unitmaint[]; +extern char *des, *desname[], *pwrname[]; +extern long powers[]; +extern char *tg_value, *tg_name[], *tg_stype; /* trade goods */ + +#ifdef CONQUER +extern long mercgot; +#endif /* CONQUER */ + +#ifdef ADMIN +extern char *npcsfile; +extern char scenario[]; +#endif /* ADMIN */ +extern int unitmove[], unitattack[], unitdefend[]; + +/* file name definitions */ +extern char *sortname,*exefile,*datafile,*msgfile; +extern char *helpfile,*newsfile,*isonfile,*timefile; + +#ifdef CONQUER +extern int conq_mail_status; +extern char conqmail[]; +#ifdef SYSMAIL +extern int sys_mail_status; +extern char sysmail[]; +#endif /* SYSMAIL */ +#endif /* CONQUER */ +#ifdef TRADE +extern char *tradefile; +#endif /* TRADE */ + +#define EXT_CMD '\033' /* ESC to start extended command */ + +#define MAXX (MAPX / 8) /* Number of X areas on map */ +#define MAXY (MAPY / 8) /* Number of Y areas on map */ +#define NUMAREAS (MAXX * MAXY) /* total # areas, MAXX*MAXY */ +#define NUMSECTS (MAPX * MAPY) /* total # areas, MAXX*MAXY */ +#define MAXHELP 6 + +#ifdef HPUX +#define SYSV +#endif /* HPUX */ + +/* minor market items */ +#define GETFOOD 97 /* response needed to get food */ +#define GETMETAL 98 +#define GETJEWL 99 +#define GODFOOD 8000L /* food recieved for GODPRICE */ +#define GODMETAL 2000L /* " */ +#define GODJEWL 3000L /* " */ +#define GODPRICE 25000L + +#ifdef XYZ +/* THE FOLLOWING DEFINES ARE NOT IMPLEMENTED YET */ +/* THEY DEFINE THE ATTRIBUTES OF A (TO BE IMPLEMENTED) REGION */ + +/* REGIONS REVOLT STATUS: if larger than the value */ +#define R_OPEN_REVOLT 220 +#define R_GUERILLA_WAR 170 +#define R_UNREST 150 +#define R_DISSENT 120 +#define R_CALM 80 +#define R_HAPPY 50 +#define R_PROSPEROUS 0 + +/* REGIONS GOVERNMENTAL STRENGTH */ +#define R_BARBARIAN 0 +#define R_IND_VILAGES 20 +#define R_TRIBAL 40 +#define R_CITY_STATES 80 +#define R_BALKANIZED 110 +#define R_CONFEDERACY 140 +#define R_NATION 160 +#define R_MONARCHY 180 +#define R_EMPIRE 200 + +/* REGION STRATEGY: region strategy by owning nation */ +#define R_ISOLATION 37 +#define R_BUILD_ECON 36 +#define R_EXPAND_PCE 35 +#define R_TAX 34 +#define R_BUILD_MIL 33 +#define R_EXPAND_MIL 32 +#define R_AT_WAR 31 +#define R_SUBDUE 20 /* 20-30: # of turns left in unrest */ +#define R_CIVIL_WAR 0 /* 0-19: number of turns left in war */ + +#define NUMREGIONS 250 /* number of regions in the world */ +#define STARTYEAR -10000 /* year that game treats as 0. In this + case - ten thousand years B.C */ + +struct s_region +{ + char *name; /* name of region */ + long people; /* civilians in sector*/ + long tax; /* tax production ability*/ + unsigned char owner; /* nation id of owner */ + unsigned char color; /* color to display region*/ + unsigned char tech_level; /* technology level */ + unsigned char law_level; /* law level of region */ + unsigned char social_level; /* social level of region*/ + unsigned char govt_sth; /* owners sth. in region */ + unsigned char strategy; /* owners strategy in region */ + unsigned char revolt; /* status of region */ + unsigned char prestige; /* prestige for owning */ +}; +#endif /* 0 */ diff --git a/original/display.c b/original/display.c new file mode 100644 index 0000000..b711531 --- /dev/null +++ b/original/display.c @@ -0,0 +1,491 @@ +/*Print and io subroutines for interactive game*/ + +/*conquer : Copyright (c) 1988 by Ed Barlow. + * I spent a long time writing this code & I hope that you respect this. + * I give permission to alter the code, but not to copy or redistribute + * it without my explicit permission. If you alter the code, + * please document changes and send me a copy, so all can have it. + * This code, to the best of my knowledge works well, but it is my first + * 'C' program and should be treated as such. I disclaim any + * responsibility for the codes actions (use at your own risk). I guess + * I am saying "Happy gaming", and am trying not to get sued in the process. + * Ed + */ + +/*include files*/ +#include +#include +#include +#include +#include +#include "header.h" +#include "data.h" + +/*offset of upper left hand corner*/ +extern short xoffset; +extern short yoffset; +/*current cursor postion (relative to 00 in upper corner)*/ +/* position is 2*x,y*/ +extern short xcurs; +extern short ycurs; +/*redraw map in this turn if redraw is a 1*/ +extern short redraw; +/*display state SEE data.h FOR CURRENT VALUES OF THESE */ +extern short hilmode; +extern short dismode; +extern short otherdismode; +extern short otherhilmode; + +/* nation id of owner*/ +extern short country; + +static char *hasseen; + +/* allocate space for the hasseen array based on the actual screen size */ +void +init_hasseen() +{ + hasseen = (char *)malloc(((COLS-10)/2) * (LINES-5)); +#ifdef BSD + bzero(hasseen,((COLS-10)/2) * (LINES-5)); +#else + memset( hasseen, 0, ((COLS-10)/2) * (LINES-5)); +#endif + if (hasseen == (char *)NULL) { + errormsg("Cannot allocate memory."); + bye(FALSE); + } +} + +/*make a map*/ +void +makemap() +{ + register int x,y; + + for(x=0;x 0) /* just 'd' not 'd1 or 'd2' */ + *odmode= - *odmode; + break; + case 'a': /* armies hilighted map*/ + prep(country,FALSE); + *hmode=HI_ARMY; + goto changed_highlight; + case 'o': /* owners hilighted map*/ + *hmode=HI_OWN; + goto changed_highlight; + case 's': /* hilight tradegoods */ + *hmode=HI_GOOD; + goto changed_highlight; + case 'x': /*no highlighting*/ + *hmode=HI_NONE; + goto changed_highlight; + case 'y': /* your armies hilighted map*/ + prep(country,FALSE); + *hmode=HI_YARM; + goto changed_highlight; + case 'l': /* your armies with moves left hilighted map*/ + prep(country,FALSE); + *hmode=HI_MOVE; + changed_highlight: + if ( odmode !=NULL ) /* just 'd' not 'd1 or 'd2' */ + *ohmode= *hmode; + break; + default: + error: + beep(); + redraw=DONE; + } +} + +void +newdisplay() +{ + get_display_mode(&dismode,&hilmode,&otherdismode,&otherhilmode); + makebottom(); +} + +/*see what is in xy as per display modes*/ +char +get_display_for(x,y,dmode) + int x,y; + short dmode; +{ + int armbonus; + + char ch= '{'; + if((magic(sct[x+xoffset][y+yoffset].owner,THE_VOID)==TRUE) + &&((dmode==DI_DEFE)||(dmode==DI_GOLD)||(dmode==DI_METAL) + ||(dmode==DI_PEOP)||(dmode==DI_FOOD)||(dmode==DI_ITEMS)) + &&(country!=sct[x+xoffset][y+yoffset].owner) + &&(magic(country,NINJA)!=TRUE) + &&(country!=0)) { + ch='?'; + } else { + switch(dmode){ + case DI_FOOD: /*food */ + if(tofood( &sct[x+xoffset][y+yoffset],country)==0) + ch=sct[x+xoffset][y+yoffset].vegetation; + else if (tofood( &sct[x+xoffset][y+yoffset],country)<10) + ch=tofood( &sct[x+xoffset][y+yoffset],country)+'0'; + else ch='+'; + break; + case DI_VEGE: /*vegetation*/ + ch=sct[x+xoffset][y+yoffset].vegetation; + break; + case DI_DESI: /*designation*/ + if(sct[x+xoffset][y+yoffset].owner==0){ + if(tofood( &sct[x+xoffset][y+yoffset],country)!=0) + ch=sct[x+xoffset][y+yoffset].altitude; + else ch=sct[x+xoffset][y+yoffset].vegetation; + } + else if((country==0) + ||(sct[x+xoffset][y+yoffset].owner==country)) + ch=sct[x+xoffset][y+yoffset].designation; + else ch=ntn[sct[x+xoffset][y+yoffset].owner].mark; + break; + case DI_CONT: /*contour*/ + ch=sct[x+xoffset][y+yoffset].altitude; + break; + case DI_NATI: /*ownership*/ + if(sct[x+xoffset][y+yoffset].owner==0) + ch=sct[x+xoffset][y+yoffset].altitude; + else ch=ntn[sct[x+xoffset][y+yoffset].owner].mark; + break; + case DI_RACE: /*race*/ + if(sct[x+xoffset][y+yoffset].owner==0) + ch=sct[x+xoffset][y+yoffset].altitude; + else ch=ntn[sct[x+xoffset][y+yoffset].owner].race; + break; + case DI_MOVE: /*movement cost map*/ + if(movecost[x+xoffset][y+yoffset]>=0) { + if(movecost[x+xoffset][y+yoffset]>=10) + ch='+'; + else ch=movecost[x+xoffset][y+yoffset]+'0'; + } else if(sct[x+xoffset][y+yoffset].altitude==WATER) + ch=WATER; + else + ch='X'; + break; + case DI_DEFE: /*Defence*/ + if (sct[x+xoffset][y+yoffset].altitude==WATER) + ch=WATER; + else if(movecost[x+xoffset][y+yoffset]<0) + ch='X'; + else { + /*Racial combat bonus due to terrain (the faster you move the better)*/ + armbonus=0; + armbonus+=5*(9-movecost[x+xoffset][y+yoffset]); + + if(sct[x+xoffset][y+yoffset].altitude==MOUNTAIN) + armbonus+=40; + else if(sct[x+xoffset][y+yoffset].altitude==HILL) + armbonus+=20; + + if(sct[x+xoffset][y+yoffset].vegetation==JUNGLE) + armbonus+=30; + else if(sct[x+xoffset][y+yoffset].vegetation==FOREST) + armbonus+=20; + else if(sct[x+xoffset][y+yoffset].vegetation==WOOD) + armbonus+=10; + + armbonus+=fort_val(&sct[x+xoffset][y+yoffset]); + + if(armbonus<200) ch=armbonus/20+'0'; + else ch='+'; + } + break; + case DI_PEOP: /*People*/ + if (sct[x+xoffset][y+yoffset].altitude==WATER) + ch=WATER; + else if (sct[x+xoffset][y+yoffset].people>=9950) + ch='X'; + else if (sct[x+xoffset][y+yoffset].people>=4950) + ch='V'; + else if (sct[x+xoffset][y+yoffset].people>=950) + ch='I'; + else + ch=(50+sct[x+xoffset][y+yoffset].people)/100+'0'; + break; + case DI_GOLD: /*Gold*/ + if (sct[x+xoffset][y+yoffset].altitude==WATER) + ch=WATER; + else if(tofood( &sct[x+xoffset][y+yoffset],country)==0) + ch='X'; + else if (tg_ok(country,&sct[x+xoffset][y+yoffset])){ + if (sct[x+xoffset][y+yoffset].jewels>=10) + ch='+'; + else + ch=sct[x+xoffset][y+yoffset].jewels+'0'; + } else ch='0'; + break; + case DI_METAL: /*Metal*/ + if (sct[x+xoffset][y+yoffset].altitude==WATER) + ch=WATER; + else if(tofood( &sct[x+xoffset][y+yoffset],country)==0) + ch='X'; + else if (tg_ok(country,&sct[x+xoffset][y+yoffset])){ + if (sct[x+xoffset][y+yoffset].metal>=10) + ch='+'; + else + ch=sct[x+xoffset][y+yoffset].metal+'0'; + } else ch='0'; + break; + case DI_ITEMS: /* designations needed for tradegoods */ + if (sct[x+xoffset][y+yoffset].altitude==WATER) + ch=WATER; + else if(tofood( &sct[x+xoffset][y+yoffset],country)==0) + ch='X'; + else if (sct[x+xoffset][y+yoffset].tradegood!=TG_none + && (*(tg_stype+sct[x+xoffset][y+yoffset].tradegood)!='x') + && tg_ok(country,&sct[x+xoffset][y+yoffset])) + ch= *(tg_stype+sct[x+xoffset][y+yoffset].tradegood); + else ch='-'; + break; + default: + break; + } + } + return ch; +} + +void +see(x,y) +{ + char ch; + if((x<0)||(y<0)||(x>=SCREEN_X_SIZE)||(y>=SCREEN_Y_SIZE) + ||((y+yoffset)>=MAPY)||((x+xoffset)>=MAPX)) return; + if(((y+yoffset) 0 ) { + highlight(x,y,otherhilmode); + ch=get_display_for(x,y,otherdismode); + mvaddch(y,2*x+1,ch); + } + } + else { + mvaddch(y,2*x,' '); + mvaddch(y,2*x+1,' '); + } +} + +/*highlight what is in xy as per highlight mode*/ +void +highlight(x,y,hmode) + short hmode; +{ + int armynum; + if((x<0)||(y<0)||(x>=SCREEN_X_SIZE)||(y>=SCREEN_Y_SIZE) + ||((y+yoffset)>=MAPY)||((x+xoffset)>=MAPX)) return; + standend(); + switch(hmode){ + case HI_MOVE: /* your armies w/ move left */ + for(armynum=0;armynum=SCREEN_X_SIZE-1 || + ycurs>=SCREEN_Y_SIZE-1 || XREAL>=MAPX || YREAL>=MAPY) { + centermap(); + redraw=PART; + } + + if(redraw!=DONE) { + if (redraw==FULL) { + clear(); /* clear real screen */ + } else { + move(0,0); /* clear curses screen but not real screen */ + clrtobot(); + } + makemap(); /* update map */ + makebottom(); + redraw=DONE; + } + move(ycurs,2*xcurs); + makeside(FALSE); /*update side*/ + move(ycurs,2*xcurs); + refresh(); +} + +int +canbeseen(x,y) +int x,y; +{ + if(!ONMAP(x,y)) return(FALSE); + return( (int) HAS_SEEN(x-xoffset,y-yoffset) ); +} + +/** CANSEE() fills seen[SCREEN_X_SIZE][SCREEN_Y_SIZE] */ +void +whatcansee() +{ + register int x,y; + int i,j; + short armynum,nvynum; + + if((magic(country,KNOWALL)==TRUE)||(country==0)) { + for(x=0;x=0 && j>=0 && i=0 && j>=0 + && i0) + for(i=(int)P_AXLOC-xoffset-ARMYSEE;i!=1+(int)P_AXLOC-xoffset+ARMYSEE;i++) + for(j=(int)P_AYLOC-yoffset-ARMYSEE;j!=1+(int)P_AYLOC-yoffset+ARMYSEE;j++) + if(ONMAP(i+xoffset,j+yoffset) && i>=0 && j>=0 + && i +#include +#include +#include +#include +#include "header.h" +#include "data.h" + +extern FILE *fexe; +extern short selector; +extern short country; +extern short xcurs, ycurs, xoffset, yoffset; + +void +ext_cmd(armie) +int armie; +{ + int stat=0,armynum,army2,men; + + clear_bottom(0); + + if( armie == -1 ) armynum = getselunit(); + else armynum=armie; + + mvaddstr(LINES-2, 0, + " (+) combine, (-) split n men, (/) divide by 2, (G)roup"); + mvaddstr(LINES-3, 0, + " (a)ttack, (d)efend, (s)cout, (m)arch, (g)arrison"); + if(fort_val(&sct[P_AXLOC][P_AYLOC]) > 0) { + if (sct[P_AXLOC][P_AYLOC].owner==country) addstr(", (S)ortie"); + else addstr(", (S)iege"); + if (P_ATYPE>=MINLEADER && P_ATYPE= MAXARM + || army2 < 0 || army2 >= MAXARM || P_ASOLD == 0 + || curntn->arm[army2].sold == 0) { + errormsg("Selected unit doesn't exist"); + return; + } + if (P_ASTAT != curntn->arm[army2].stat + || P_ATYPE != curntn->arm[army2].unittyp + || P_ATYPE >= MINLEADER + || P_ASTAT == ONBOARD || P_ASTAT == TRADED) { + if ((nocomb_stat(P_ASTAT) == TRUE) || + (nocomb_stat(curntn->arm[army2].stat) == TRUE) || + curntn->arm[army2].stat == MARCH || + curntn->arm[army2].stat == SIEGE || /* may not jump out */ + curntn->arm[army2].stat == SORTIE || /* of these statuses */ + P_ATYPE >= MINLEADER || + P_ATYPE!=curntn->arm[army2].unittyp) { + errormsg("Selected armies not legal"); + return; + } + } + if((curntn->arm[army2].xloc!=P_AXLOC) + ||(curntn->arm[army2].yloc!=P_AYLOC)) { + errormsg("Selected armies not together"); + return; + } + P_ASOLD += curntn->arm[army2].sold; + curntn->arm[army2].sold = 0; + P_AMOVE=min(P_AMOVE,curntn->arm[army2].smove); + AADJMEN; + AADJMOV; + if (P_ASTAT>NUMSTATUS) { + curntn->arm[P_ASTAT-NUMSTATUS].smove=P_AMOVE; + armynum = P_ASTAT-NUMSTATUS; + AADJMOV; + } + armynum = army2; + AADJMEN; +} + +void +change_status(armynum,new_stat) +int armynum,new_stat; +{ + int i; + if(armynum<0 || armynum >= MAXARM || P_ASTAT==SCOUT || + P_ASTAT==TRADED || P_ASTAT==ONBOARD || P_ASTAT==SORTIE){ + errormsg("Can't change status on that army"); + return; + } + if( P_ATYPE == A_MILITIA && new_stat!=MILITIA ) { + errormsg("Militia is all you get"); + return; + } + if( P_ATYPE == A_ZOMBIE && new_stat==MARCH ) { + errormsg("Duh? Your Zombies just lumber about."); + return; + } + if(P_ASTAT == SIEGED && new_stat != SORTIE && new_stat != RULE) { + errormsg("Sieged troops may only switch to sortie"); + return; + } + if(P_ASTAT == new_stat) { + errormsg("Uh, sir. Aren't we doing that already?"); + return; + } + if(new_stat == SCOUT) { + if(( P_ATYPE != A_SCOUT )&&( P_ASOLD >= 25)) { + errormsg("Need less than 25 men to scout"); + return; + } else { + P_ATYPE=A_SCOUT; + AADJMEN; + } + } + if(P_ASTAT == GENERAL ){ + i=armynum; + for(armynum=0;armynum0) && (P_ASTAT==i+NUMSTATUS)){ + P_ASTAT = ATTACK; + AADJSTAT; + } + } + armynum=i; + } + if(new_stat == GARRISON) { + if((sct[P_AXLOC][P_AYLOC].owner!=country) + ||(fort_val(&sct[P_AXLOC][P_AYLOC])==0)) { + errormsg("Just how do you want to garrison that?"); + return; + } + } else if(new_stat == SORTIE) { + if((sct[P_AXLOC][P_AYLOC].owner!=country) + ||(fort_val(&sct[P_AXLOC][P_AYLOC])==0)) { + errormsg("Hmmm... How do you figure to sortie from there?"); + return; + } + } else if(new_stat == SIEGE) { + if((sct[P_AXLOC][P_AYLOC].owner==country) + ||(fort_val(&sct[P_AXLOC][P_AYLOC])==0)) { + errormsg("You want to lay seige to this??"); + return; + } + } else if(new_stat == RULE) { + if((sct[P_AXLOC][P_AYLOC].owner!=country) + ||(!ISCITY(sct[P_AXLOC][P_AYLOC].designation)) + ||(P_ATYPE=MINMONSTER)) { + errormsg("Sorry, but you can't rule in that sector"); + return; + } + } + + /* eliminate half starting movement if start out on march */ + if( P_ASTAT==MARCH && new_stat!=MARCH ) { + if(P_AMOVE<(curntn->maxmove * *(unitmove+(P_ATYPE%UTYPE)))/50){ + errormsg("That troop has gone too far to stop marching"); + return; + } + P_AMOVE-=(curntn->maxmove * *(unitmove+(P_ATYPE%UTYPE)))/50; + AADJMOV; + } + + /* location dependent statuses make armies stay in place */ + if((new_stat==RULE)||(new_stat==SORTIE) + ||(new_stat==SIEGE)||(new_stat==GARRISON)) { + P_AMOVE=0; + AADJMOV; + } + P_ASTAT = new_stat; + AADJSTAT; + if( P_AMOVE != 0 ) P_AMOVE--; + AADJMOV; +} + +void +reducearmy(armynum,men) +int armynum,men; +{ + int army2; + int oldx, oldy, army; + + if(P_ATYPE>=MINMONSTER){ + errormsg("sorry -- army is monster"); + return; + } + if(P_ATYPE>=MINLEADER){ + errormsg("sorry -- army is leader"); + return; + } +#ifdef TRADE + if(men<25 || armynum < 0 || armynum >= MAXARM || P_ASOLD < men+25 || P_ASTAT==ONBOARD || P_ASTAT==TRADED) { +#else + if(men<25 || armynum < 0 || armynum >= MAXARM || P_ASOLD < men+25 || P_ASTAT==ONBOARD) { +#endif /* TRADE */ + errormsg("Selected army too small or illegal"); + return; + } + + if(P_ASOLD < men) { + errormsg("Too many men to split from army"); + return; + } + + oldx=(int)P_AXLOC; + oldy=(int)P_AYLOC; + army2=armynum; + + armynum=(-1); + for(army=0;armyarm[army].sold==0){ + if(armynum==(-1)) armynum=army; + } + /*overflow*/ + if(armynum==(-1)) { + errormsg("TOO MANY ARMIES"); + return; + } else { + P_AMOVE=curntn->arm[army2].smove; + P_ATYPE=curntn->arm[army2].unittyp; + P_ASTAT=curntn->arm[army2].stat; + P_AXLOC=oldx; + P_AYLOC=oldy; + P_ASOLD=men; + curntn->arm[army2].sold-=P_ASOLD; + AADJSTAT; + AADJMEN; + AADJLOC; + AADJMOV; + armynum=army2; + AADJMEN; + } +} + +void +splitarmy(armynum) +int armynum; +{ + int men; + clear_bottom(2); + mvaddstr(LINES-2, 0, "How many men to split? "); + refresh(); + men = get_number(); + if(men <= 0) { + return; + } + reducearmy(armynum,men); +} + +void +errormsg(str) +char *str; +{ + mvaddstr(LINES-1, 0, str); + clrtoeol(); + mvaddstr(LINES-1, COLS-16, "PRESS ANY KEY"); + beep(); + refresh(); + getch(); +} + +void +clear_bottom(i) +int i; +{ + if(i==0) i=4; + for (; i>0 ; i--) { + move( LINES-i, 0); + clrtoeol(); + } +} + +/* add army to a group */ +void +addgroup(armynum) +int armynum; +{ + int moverate,group; + + if((P_ATYPE>=MINLEADER)&&(P_ATYPE= MAXARM || P_ASTAT==SCOUT || + P_ASTAT==TRADED || P_ASTAT==ONBOARD || P_ATYPE==A_MILITIA ){ + errormsg("Selected army not groupable"); + return; + } + mvaddstr(LINES-4,0,"enter a valid leader unit/army group id: "); + refresh(); + group = get_number(); + if(group < 0) { + return; + } + if(group > MAXARM || curntn->arm[group].sold <=0){ + errormsg("invalid unit number"); + return; + } + if((P_AXLOC != curntn->arm[group].xloc) + ||(P_AYLOC != curntn->arm[group].yloc)){ + errormsg("units are not in same sector"); + return; + } + if((curntn->arm[group].unittyp arm[group].unittyp >=MINMONSTER)){ + errormsg("Group leader not a leader unit"); + return; + } else if(curntn->arm[group].stat==ONBOARD){ + errormsg("Cannot group onto a transport"); + return; + } + + P_ASTAT=group+NUMSTATUS; + moverate = P_AMOVE; + AADJSTAT; + armynum = group; + P_ASTAT=GENERAL; + AADJSTAT; + if( P_AMOVE > moverate ){ + P_AMOVE = moverate; + AADJMOV; + } +} diff --git a/original/forms.c b/original/forms.c new file mode 100644 index 0000000..4814be1 --- /dev/null +++ b/original/forms.c @@ -0,0 +1,1094 @@ +/*conquer : Copyright (c) 1988 by Ed Barlow. + * I spent a long time writing this code & I hope that you respect this. + * I give permission to alter the code, but not to copy or redistribute + * it without my explicit permission. If you alter the code, + * please document changes and send me a copy, so all can have it. + * This code, to the best of my knowledge works well, but it is my first + * 'C' program and should be treated as such. I disclaim any + * responsibility for the codes actions (use at your own risk). I guess + * I am saying "Happy gaming", and am trying not to get sued in the process. + * Ed + */ + +/* screen subroutines */ + +#include +#include +#include +#include +#include +#include +#include "header.h" +#include "data.h" + +extern FILE *fexe, *fnews; +extern short country,redraw; +extern long startgold; +extern short Gaudy; + +static char helplist[MAXHELP][20]={"Commands", "General Info", + "Military","Magic","Designations","Other"}; + +#define RPT_LINES 14 +#define RPT_COLS 13 +#define BUF_LINES 10 +#define BUF_COLS 15 +#define MAXINROW ((COLS-BUF_COLS)/RPT_COLS) +#define MAXINSCR (((LINES-BUF_LINES)/RPT_LINES)*MAXINROW) +void +showscore() +{ + int i; + int done=FALSE; + int xpos,ypos; + int count,count2; /*number of time through the loop on this screen*/ + int nationid; /*current nation id */ + + count2=1; + clear(); + while(done==FALSE) { + move(0,0); + clrtobot(); + standout(); + mvaddstr(0,(COLS/2)-10,"NATION SCORE SCREEN"); + standend(); + + nationid=count2; + xpos=BUF_COLS; + ypos=3; + count=0; + while((nationiddstatus[i]==WAR) + ||(curntn->dstatus[i]==JIHAD)) standout(); + mvprintw(count%MAXINCOL+2,offset+14, "=> %s",*(diploname+curntn->dstatus[i])); + standend(); + if((ntn[i].dstatus[country]==WAR) + ||(ntn[i].dstatus[country]==JIHAD)) standout(); + mvprintw(count%MAXINCOL+2,offset+28, "=> %s",*(diploname+ntn[i].dstatus[country])); + standend(); + count++; + } + + /* display options */ + standout(); + mvaddstr(LINES-7,COLS/2-26,"HIT RETURN KEY TO CHANGE STATUS; HIT SPACE IF DONE"); + mvprintw(LINES-6,COLS/2-31,"HIT 'B' KEY TO BRIBE NPC NATION (cost=$%ld per 1000 Mil.)",BRIBE); + mvaddstr(LINES-5,COLS/2-21,"HIT ANY OTHER KEY TO SCROLL NATIONS LIST"); + standend(); + refresh(); + k=getch(); + if(k==' ') { + if(isgod==TRUE) reset_god(); + return; + } + if((k!='B')&&(k!='\r')&&(k!='\n')) { + /* find start for next listing */ + for(; itgold<=BRIBE){ + mvaddstr(LINES-3,0,"NOT ENOUGH GOLD"); + refresh(); + getch(); + if(isgod==TRUE) reset_god(); + return; + } + mvaddstr(LINES-4,0,"BRIBES DONT ALWAYS WORK (only the update will show)"); + mvaddstr(LINES-3,0,"WHAT NATION:"); + refresh(); + nation = get_country(); + + /* may only change with NPCs */ + if((nation<=0) + ||(nation>=NTOTAL) + ||(!isnpc(ntn[nation].active))){ + errormsg("That nation is not a Non-Player Country"); + if(isgod==TRUE) reset_god(); + return; + } + if(ntn[nation].dstatus[country]==UNMET){ + errormsg("They have no knowledge that you exist"); + if(isgod==TRUE) reset_god(); + return; + } + if((isgod!=TRUE) + &&((ntn[nation].dstatus[country]==ALLIED) + ||(ntn[nation].dstatus[country]==JIHAD) + ||(ntn[nation].dstatus[country]==UNMET) + ||(ntn[nation].dstatus[country]==TREATY))){ + errormsg("Sorry, you cannot bribe them"); + return; + } + + if( isgod==TRUE ) { + bribecost = 0; + } else if( ntn[nation].tmil > 1000 ) { + bribecost = BRIBE * ntn[nation].tmil / 1000; + } else bribecost = BRIBE; + mvprintw(LINES-3,0,"This will cost %ld gold talons. continue (y or n)",bribecost); + refresh(); + + if( getch() != 'y' ) return; + if(curntn->tgold<=bribecost){ + errormsg("Sorry Not Enough Gold"); + if(isgod==TRUE) reset_god(); + return; + } + curntn->tgold-=bribecost; + + sprintf(name,"%s%d",exefile,nation); + if ((fm=fopen(name,"a+"))==NULL) { + printf("error opening news file\n"); + exit(FAIL); + } + BRIBENATION; + + ntn[nation].dstatus[country]--; + + if(isgod==TRUE) reset_god(); + return; + } + mvaddstr(LINES-3,0,"WHAT NATION:"); + refresh(); + nation = get_country(); + /* can't change with nomads...*/ + if((nation<=0)||(nation>NTOTAL)||(!isntnorp(ntn[nation].active))){ + if(isgod==TRUE) reset_god(); + return; + } + if((isgod==FALSE) + &&(curntn->tgold < BREAKJIHAD ) + &&(((curntn->dstatus[nation]==TREATY) + &&(ntn[nation].dstatus[country]dstatus[nation]==JIHAD))) { + + mvprintw(LINES-1,0,"Sorry, need %d talons to change status with ntn %s",BREAKJIHAD,ntn[nation].name); + clrtoeol(); + mvaddstr(LINES-1, 60, "PRESS ANY KEY"); + refresh(); + getch(); + if(isgod==TRUE) reset_god(); + return; + } else if (isgod==FALSE && curntn->dstatus[nation]==UNMET + && ntn[nation].dstatus[country]==UNMET) { + errormsg("Sorry, you have not met that nation yet."); + if(isgod==TRUE) reset_god(); + return; + } else { + clear(); + mvaddstr(0,0,"WHAT NEW STATUS"); + j=2; + mvprintw(j++,0,"1) TREATY (%d talons to break)",BREAKJIHAD); + mvaddstr(j++,0,"2) ALLIED"); + mvaddstr(j++,0,"3) FRIENDLY"); + mvaddstr(j++,0,"4) NEUTRAL"); + mvaddstr(j++,0,"5) HOSTILE"); + mvaddstr(j++,0,"6) WAR"); + mvprintw(j++,0,"7) JIHAD (%d talons to break):",BREAKJIHAD); + j++; + for( i=1; iJIHAD) + ||((isgod==FALSE)&&(temp==UNMET))){ + errormsg("SORRY, Invalid inputs -- hit return"); + if(isgod==TRUE) reset_god(); + return; + } + + if((curntn->dstatus[nation]==JIHAD)&&(temp!=JIHAD)) + curntn->tgold -= BREAKJIHAD; + else if ((curntn->dstatus[nation]==TREATY)&&(temp!=TREATY)) { + if (ntn[nation].dstatus[country]!=TREATY) { + errormsg("Non-binding Treaty broken... fee waived."); + } else { + curntn->tgold -= BREAKJIHAD; + } + } + + curntn->dstatus[nation]=temp; + EADJDIP(country,nation); + + if((temp>HOSTILE) + &&(ispc(ntn[nation].active)) + &&(ntn[nation].dstatus[country]name); + mailclose(nation); + } + } + + /*prevent ron from being sneaky*/ + if((temp>HOSTILE) + &&(isactive(ntn[nation].active)) + &&(ntn[nation].dstatus[country]name); + mvprintw(4,0,"alignment is %s",alignment[npctype(curntn->active)]); + + if (isgod==TRUE) + mvprintw(5,0,"active is %d",curntn->active); + mvprintw(6,0,"tax_rate...... %2d%%",curntn->tax_rate); + mvprintw(7,0,"inflation..... %2d%%",curntn->inflation); + i=(int)10*curntn->tax_rate-curntn->popularity-curntn->terror-3*curntn->charity; + if( i<0 ) i=0; + mvprintw(8,0,"peasant revolt %2d%%",(i*PREVOLT)/100); + i=(int)5*curntn->tax_rate - curntn->prestige; + if( i<0 ) i=0; + mvprintw(9,0,"other revolt.. %2d%%",(i*PREVOLT)/100); + standend(); + mvprintw(10,0,"capitol loc: x is %d",curntn->capx); + mvprintw(11,0," y is %d",curntn->capy); + mvprintw(13,0,"class is %s",*(Class+curntn->class)); + if(ispc( curntn->active ) ) + addstr(" (PC)"); + else if(isnpc( curntn->active ) ) + addstr(" (NPC)"); + else addstr(" (MON)"); + mvprintw(14,0,"nations mark is...%c ",curntn->mark); + for(i=1;i<8;i++) if(curntn->race==*(races+i)[0]){ + mvprintw(15,0, "nation race is....%s ",*(races+i)); + break; + } + + mvprintw(3,COLS/2-12, "terror........ %3d",curntn->terror); + mvprintw(4,COLS/2-12, "popularity.... %3d",curntn->popularity); + mvprintw(5,COLS/2-12, "prestige...... %3d",curntn->prestige); + mvprintw(6,COLS/2-12, "knowledge..... %3d",curntn->knowledge); + temp = P_EATRATE; + mvprintw(7,COLS/2-12, "eatrate.......%3.2f",temp); + mvprintw(8,COLS/2-12, "wealth........ %3d",curntn->wealth); + mvprintw(9,COLS/2-12, "charity....... %2d%%",curntn->charity); + mvprintw(10,COLS/2-12,"communication.%3.2f",(float) P_NTNCOM); + mvprintw(11,COLS/2-12,"reputation.... %3d",curntn->reputation); + mvprintw(12,COLS/2-12,"spoilrate.....%3d%%",curntn->spoilrate); + mvprintw(13,COLS/2-12,"farm ability.. %3d",curntn->farm_ability); + mvprintw(14,COLS/2-12,"mine ability.. %3d",curntn->mine_ability); + mvprintw(15,COLS/2-12,"poverty rate.. %2d%%",curntn->poverty); + mvprintw(16,COLS/2-12,"power......... %3d",curntn->power); + + if (country!=0) { + mvprintw(12,0,"leader is %s",curntn->leader); + mvprintw(16,0,"score currently...%ld",curntn->score); + mvprintw(3,COLS-30, "attack bonus.........%+4d%%",curntn->aplus); + mvprintw(4,COLS-30, "defense bonus........%+4d%%",curntn->dplus); + mvprintw(12,COLS-30,"total soldiers....%8ld",curntn->tmil); + } else { + mvprintw(12,0,"demigod is %s",curntn->leader); + mvprintw(16,0,"turn currently....%ld",TURN); + mvprintw(3,COLS-30, "mercs attack bonus....+%2d%%",MERCATT); + mvprintw(4,COLS-30, "mercs defense bonus...+%2d%%",MERCDEF); + mvprintw(12,COLS-30,"total mercs.......%8ld",MERCMEN); + } + + mvprintw(5,COLS-30, "maximum move rate.......%2d",curntn->maxmove); + mvprintw(6,COLS-30, "reproduction rate......%2d%%",curntn->repro); + mvprintw(8,COLS-30, "gold talons......$%8ld",curntn->tgold); + + mvprintw(9,COLS-30,"jewels ..........$%8ld",curntn->jewels); + mvprintw(10,COLS-30,"metal & minerals..%8ld",curntn->metals); + if(curntn->tfood<2*curntn->tciv) standout(); + mvprintw(11,COLS-30,"food in granary...%8ld",curntn->tfood); + standend(); + + mvprintw(13,COLS-30,"total civilians...%8ld",curntn->tciv); + mvprintw(14,COLS-30,"total ships..........%5d",curntn->tships); + mvprintw(15,COLS-30,"total sectors........%5d",curntn->tsctrs); + mvprintw(16,COLS-30,"spell points.........%5d",curntn->spellpts); + + standout(); + mvaddstr(LINES-6,COLS/2-26,"HIT 'B' FOR BUDGET SCREEN, 'P' FOR PRODUCTION SCREEN"); + mvaddstr(LINES-5,COLS/2-25,"1) NAME 2) PASSWD 3) TAX RATE 4) CHARITY 5) TERROR"); + if(magic(country,VAMPIRE)!=1 || isgod==TRUE) + mvaddstr(LINES-4,COLS/2-21,"6) ADJUST TO COMBAT BONUS"); + else mvaddstr(LINES-4,COLS/2-22,"CANT ADD TO COMBAT BONUS"); + addstr(" 7) TOGGLE PC <-> NPC"); + +#ifdef OGOD + if(isgod==TRUE) mvaddstr(LINES-3,COLS/2-33,"HIT 8 TO DESTROY, 9 TO CHANGE COMMODITY OR '0' TO CHANGE DEMI-GOD"); +#else OGOD + if(isgod==TRUE) mvaddstr(LINES-3,COLS/2-24,"HIT 8 TO DESTROY NATION, OR '0' TO CHANGE DEMI-GOD"); +#endif /* OGOD */ + else mvaddstr(LINES-3,COLS/2-14,"HIT ANY OTHER KEY TO CONTINUE"); + standend(); + refresh(); + switch(getch()){ + case '1': /*get name*/ + clear(); + mvaddstr(0,0,"What name would you like:"); + clrtoeol(); + refresh(); + get_nname(string); + if((strlen(string)<=1)||(strlen(string)>NAMELTH)){ + errormsg("Invalid name length"); + break; + } + /*check if already used*/ + else for(i=1;iname,string); + ECHGNAME; + break; + case '2': /*change password */ + clear(); + /* minimum password length setting */ + if (country != 0) intval=2; + else intval=4; + if(isgod!=TRUE){ + mvaddstr(0,0,"What is your current password:"); + refresh(); + (void) get_pass(command); + strncpy(passwd,crypt(command,SALT),PASSLTH+1); + if((strncmp(passwd,ntn[0].passwd,PASSLTH)!=0) + &&(strncmp(passwd,curntn->passwd,PASSLTH)!=0)){ + break; + } + } + mvaddstr(2,0,"What is your new password:"); + refresh(); + i = get_pass(command); + if (iPASSLTH) { + errormsg("Password too long"); + break; + } + strncpy(passwd,command,PASSLTH); + mvaddstr(4,0,"Reenter your new password:"); + refresh(); + (void) get_pass(command); + if(strncmp(passwd,command,PASSLTH)!=0) { + errormsg("Invalid password match; Password unchanged"); + break; + } + errormsg("New password can be used following next update"); + strncpy(curntn->passwd,crypt(command,SALT),PASSLTH); + ECHGPAS; + break; + case '3': /* change tax rate */ + standout(); + mvaddstr(LINES-1,0,"WHAT TAX RATE DO YOU WISH:"); + standend(); + refresh(); + intval = get_number(); + if( intval < 0 ) + break; + else if( intval > 20 ) + errormsg("NO WAY! the peasants will revolt!!!"); + else if( intval > 10 && (curntn->tsctrs<20 || curntn->score<20) ) + errormsg("Sorry, you may not go above 10% yet"); + else { + curntn->tax_rate = (unsigned char) intval; + NADJNTN; + } + break; + case '4': /* charity */ + standout(); + mvaddstr(LINES-1,0,"GIVE WHAT PERCENT OF YOUR INCOME TO THE POOR:"); + standend(); + refresh(); + intval = get_number(); + if (intval < 0) { + break; + } else if( intval > 100 ) { + errormsg("ERROR - invalid charity rate"); + } else if (intval > 25) { + errormsg("You are kidding, right?"); + /* this will protect from both underflow and overflow */ + } else if(intval > curntn->charity) { + if (2 * (intval - (int)curntn->charity) + (int) curntn->popularity > 100) { + errormsg("ERROR - you may not increase charity that much"); + } else { + curntn->popularity += (unsigned char) 2*(intval - (int) curntn->charity); + curntn->charity = intval; + NADJNTN; + NADJNTN2; + } + } else { + if (2 * (intval - (int)curntn->charity) < - (int) curntn->popularity) { + errormsg("ERROR - you may not decrease charity that much"); + } else { + curntn->popularity += (unsigned char) 2*(intval - (int) curntn->charity); + curntn->charity = intval; + NADJNTN; + NADJNTN2; + } + } + break; + case '5': /* terror */ + mvaddstr(LINES-2,0,"YOU CAN TERRORIZE YOUR PEOPLE AN ADDITONAL 1-5%:"); + standout(); + mvaddstr(LINES-1,0,"HOW MUCH MORE TO TERRORIZE THEM: "); + standend(); + refresh(); + intval = get_number(); + if( intval < 0 ) + break; + else if( intval+curntn->terror > 100 ) + errormsg("Cant go over 100 terror!!!"); + else if((intval > curntn->popularity ) + || (intval > curntn->reputation )) + errormsg("Sorry - this would cause underflow"); + else if(intval>5) { + errormsg("That is over the allowed 5%"); + } else if(terror_adj>0) { + errormsg("Terror may only be adjusted once per turn"); + } else if(intval>0) { + terror_adj++; + curntn->terror += (unsigned char) intval; + curntn->popularity -= (unsigned char) intval; + curntn->reputation -= (unsigned char) (intval+1)/2; + NADJNTN2; + } + break; + case '6': /* combat bonus */ +#ifdef OGOD + if(isgod==TRUE) { + mvaddstr(LINES-2,0,"SUPER-USER: Change (A)ttack or (D)efense Bonus? "); + refresh(); + if ((intval=getch())=='A' || intval=='a') { + mvaddstr(LINES-1,0,"Enter new value for Attack Bonus: "); + refresh(); + curntn->aplus = get_number(); + if (curntn->aplus < 0) curntn->aplus = 0; + } else if (intval=='d' || intval == 'D') { + mvaddstr(LINES-1,0,"Enter new value for Defense Bonus: "); + refresh(); + curntn->dplus = get_number(); + if (curntn->dplus < 0) curntn->dplus = 0; + } + break; + } +#endif /*OGOD*/ + if(magic(country,VAMPIRE)==1) { + errormsg("VAMPIRES CAN'T ADD TO COMBAT BONUS"); + break; + } + if(magic(country,WARLORD)==1) intval=30; + else if(magic(country,CAPTAIN)==1) intval=20; + else if(magic(country,WARRIOR)==1) intval=10; + else intval=0; + men=0; + for(armynum=0;armynum0)&&(P_ATYPEaplus-intval, 10 ) / 10; + cost = METALORE*men*armynum*armynum; + if( curntn->race == ORC) cost*=3; + mvprintw(LINES-1,0,"Do You Wish Spend %ld Metal On Attack (enter y or n):",cost); + refresh(); + if(getch()=='y'){ + if(curntn->metals> cost){ + curntn->aplus+=1; + I_APLUS; + curntn->metals-=cost; + } else { + errormsg("SORRY"); + } + } + armynum = max( curntn->dplus-intval, 10 ) / 10; + cost=METALORE*men*armynum*armynum; + if( curntn->race == ORC) cost*=3; + mvprintw(LINES-1,0,"Do You Wish Spend %ld Metal On Defense (enter y or n):",cost); + refresh(); + if(getch()=='y'){ + if(curntn->metals>cost){ + curntn->dplus+=1; + I_DPLUS; + curntn->metals-=cost; + } else { + errormsg("SORRY"); + } + } + break; + case '7': + if(ispc(curntn->active)) { + errormsg("Note: you get no mail while playing as an NPC!"); + curntn->active *= 4; + } else if(isnpc(curntn->active)) { + errormsg("Okay.... you have now come back to reality."); + curntn->active /= 4; + } + NADJNTN; + break; + case '8': + if(isgod==TRUE){ + standout(); + mvaddstr(LINES-1,0,"DO YOU WANT TO DESTROY THIS NATION (y or n)"); + standend(); + refresh(); + + if(getch()=='y') { + /* save to last turns news file */ + sprintf(filename,"%s%d",newsfile,TURN-1); + if ((fnews=fopen(filename,"a+"))==NULL) { + printf("error opening news file\n"); + exit(FAIL); + } + destroy(country); + fclose(fnews); + sprintf(command,"%s/%s", EXEDIR, sortname); + sprintf(command,"%s %s %s", command, filename, filename); + system(command); + } + } + break; +#ifdef OGOD + case '9': + if (isgod==TRUE) { + /* open the target country's files */ + sprintf(filename,"%s%d",exefile,country); + if ((ftmp=fopen(filename,"a"))==NULL) { + beep(); + errormsg("error opening country's file"); + reset_god(); + return; + } + /* adjust commodities */ + mvaddstr(LINES-2,0,"CHANGE: 1) Gold 2) Jewels 3) Iron 4) Food ?"); + clrtoeol(); + refresh(); + switch(getch()) { + case '1': + mvaddstr(LINES-1,0,"WHAT IS NEW VALUE FOR TREASURY? "); + refresh(); + curntn->tgold = (long) get_number(); + if (curntn->tgold < 0L) curntn->tgold=0L; + fprintf(ftmp,"L_NGOLD\t%d \t%d \t%ld \t0 \t0 \t%s\n", XNAGOLD ,country,curntn->tgold,"null"); + break; + case '2': + mvaddstr(LINES-1,0,"WHAT IS NEW AMOUNT OF JEWELS? "); + refresh(); + curntn->jewels = (long) get_number(); + if (curntn->jewels < 0L) curntn->jewels=0L; + fprintf(ftmp,"L_NJWLS\t%d \t%d \t%ld \t0 \t0 \t%s\n", XNARGOLD ,country,curntn->jewels,"null"); + break; + case '3': + mvaddstr(LINES-1,0,"WHAT IS NEW AMOUNT OF METAL? "); + refresh(); + curntn->metals = (long) get_number(); + if (curntn->metals < 0L) curntn->metals=0L; + fprintf(ftmp,"L_NMETAL\t%d \t%d \t%ld \t0 \t0 \t%s\n", XNAMETAL ,country,curntn->metals,"null"); + break; + case '4': + mvaddstr(LINES-1,0,"WHAT IS NEW AMOUNT OF FOOD? "); + refresh(); + curntn->tfood = (long) get_number(); + if (curntn->tfood < 0L) curntn->tfood = 0L; + break; + default: + break; + } + fclose(ftmp); + } + break; +#endif /* OGOD */ + case '0': + if(isgod==TRUE) { + mvaddstr(LINES-2,0,"ENTER CONQUER SUPER-USER PASSWORD:"); + refresh(); + (void) get_pass(string); + strcpy(passwd,crypt(string,SALT)); + if(strncmp(passwd,ntn[0].passwd,PASSLTH)!=0) break; + mvaddstr(LINES-1,0,"PROMOTE WHAT USER TO DEMI-GOD? "); + refresh(); + get_nname(string); + if (strlen(string)!=0 && getpwnam(string)!=NULL) { + strncpy(ntn[0].leader,string,LEADERLTH); + } + } + break; + case 'p': + case 'P': + produce(); + if (isgod==TRUE) reset_god(); + return; + case 'b': + case 'B': + budget(); + if(isgod==TRUE) reset_god(); + return; + default: + if(isgod==TRUE) reset_god(); + return; + } + } /* end of continuous loop */ +} + +void +help() +{ + int lineno; + FILE *fp, *fopen(); + int i,xcnt,ycnt,done=FALSE; + char line[LINELTH],fname[FILELTH]; + + /*find out which helpfile to read in */ + clear_bottom(0); + ycnt = LINES - 3; + xcnt = 0; + mvaddstr(LINES-4,0,"Help on which topic:"); + for (i=0;iMAXHELP) { + redraw=DONE; + makebottom(); + return; + } + + /*open help file*/ + sprintf(fname,"%s/%s%d",DEFAULTDIR,helpfile,i); + if ((fp=fopen(fname,"r"))==NULL) { + mvprintw(0,0,"\nerror on read of %s\n",fname); + refresh(); + getch(); + return; + } + + while(done==FALSE){ + /*read in screen (until DONE statement)*/ + fgets(line,80,fp); + if(strncmp(line,"DONE",4)==0) done=TRUE; + else { + clear(); + lineno=0; + while(strncmp(line,"END",3)!=0) { + if(lineno==0) { + /* highlight topic line */ + for(i=0;line[i]==' ';i++) ; + i--; /* back up 1 */ + standout(); + mvaddstr(lineno,i,line+i); + /* add a blank space on the end */ + mvaddch(lineno,strlen(line)-1,' '); + standend(); + } else mvaddstr(lineno,0,line); + lineno++; + if(lineno>LINES-3) strcpy(line,"END"); + else fgets(line,80,fp); + } + standout(); + /* help screen 80 col format; constants needed */ + mvaddstr(LINES-2,16,"HIT ANY KEY TO CONTINUE HELP SCREENS"); + mvaddstr(LINES-1,21,"TO END HELP HIT SPACE KEY"); + standend(); + refresh(); + if(getch()==' ') done=TRUE; + } + } + fclose(fp); +} + +/* routine to highlight a line for news display */ +/* if country name is mentioned. By T. Kivinen */ +mvaddstrnahil(li,col,p) + int li; + int col; + char *p; +{ + int i,j; + move(li,col); + for (i=0;p[i];i++) { + for (j=0;p[i+j]==ntn[country].name[j];j++); + if (ntn[country].name[j]==0 && p[i+j]!='-') { + standout(); + addstr(ntn[country].name); + standend(); + i+=j-1; + } + else + addch(p[i]); + } +} + +void +newspaper() +{ + int lineno; + FILE *fp, *fopen(); + int newpage,choice,done; + short pagenum,subpage; + int i,ydist,xdist; + char line[LINELTH],name[FILELTH]; + int readold; + int c; + + /* check to make sure that there are newspapers */ + if (TURN==0) { + clear_bottom(0); + errormsg("no news to read"); + redraw=DONE; + makebottom(); + return; + } + + /* set to 1 if news already read and redraw is needed */ + readold=0; + readoldp: /* label to jump if reading old pages */ + clear_bottom(0); + ydist=LINES-3; + xdist=0; + + /* check for all newspapers up until the current turn */ + for (i=TURN-1;i>=0 && i>=TURN-MAXNEWS;i--) { + sprintf(line," %d) %s of Year %d",TURN-i, + PSEASON(i), YEAR(i)); + /* align all strings */ + mvprintw(ydist,xdist,"%s",line); + xdist += strlen(line); + if (xdist>60) { + xdist=0; + ydist++; + } + } + mvaddstr(LINES-4,0,"Read Which Newspaper:"); + standend(); + refresh(); + + /* get the choice */ + choice = getch() - '0'; + /* make sure the choice is valid */ + if (choice<1 || choice > MAXNEWS) { + if (readold) + return; + makebottom(); + redraw=DONE; + return; + } + /* select page to read */ + pagenum=1; + backpage: /* label for reading previous pages. pagenum set to page */ + sprintf(name,"%s%d",newsfile,TURN-choice); + if ((fp=fopen(name,"r"))==NULL) { + clear_bottom(0); + sprintf(line,"unable to open news file <%s>",name); + errormsg(line); + if (readold) + return; + redraw=DONE; + makebottom(); + return; + } + + /*open and read one page */ + forpage: /* label for reading forward pages. pagenum set to page */ + subpage=1; + newpage=FALSE; + line[0]='\0'; + strcpy(name,""); + /* reading to correct page */ + i=0; + done=FALSE; + while(done==FALSE && i2) { + if (Gaudy) mvaddstrnahil(lineno++,0,line+2); + else mvaddstr(lineno++,0,line+2); + } + } else if(fgets(line,80,fp)==NULL) done=TRUE; + else { + if(line[1]!='.' && line[1]!=':') { + strcpy(name,line); + newpage=FALSE; + pagenum=todigit(line[0]); + subpage=1; + } else { + if(todigit(line[0])!=pagenum) { + newpage=FALSE; + pagenum=todigit(line[0]); + subpage=1; + } + else if(lineno>LINES-4) newpage=FALSE; + else if(strlen(line)>2) { + if (Gaudy) mvaddstrnahil(lineno++,0,line+2); + else mvaddstr(lineno++,0,line+2); + } + } + } + if(newpage==FALSE||done==TRUE){ + standout(); + /* constants since news is 80 col format */ + mvaddstr(LINES-2,4,"N=next page, P=previous page, 1-5=jump to page, O=Read other news"); + mvaddstr(LINES-1,12,"ANY OTHER KEY TO ADVANCE -- TO END NEWS HIT SPACE"); + standend(); + refresh(); + stayhere: + c=getch(); + switch (c) { + case 'N': + case 'n': + /* go forward a page */ + if (subpage!=1 && done!=TRUE) { + pagenum++; + if (pagenum>5) pagenum=5; + goto forpage; + } else if (done==TRUE) { + goto stayhere; + } + break; + case 'P': + case 'p': + /* go backward a page */ + if (subpage==1) pagenum--; + pagenum--; + if (pagenum<1) pagenum=1; + fclose(fp); + goto backpage; + break; + case '1': + case '2': + case '3': + case '4': + case '5': + /* goto a specific page */ + i=todigit(c); + if (i<=pagenum) { + pagenum=i; + fclose(fp); + goto backpage; + } else { + pagenum=i; + goto forpage; + } + break; + case ' ': + done=TRUE; + break; + case 'O': + case 'o': + readold=1; + fclose(fp); + goto readoldp; + break; + } + } + } while (done==FALSE); + fclose(fp); +} diff --git a/original/header.h b/original/header.h new file mode 100644 index 0000000..d29953a --- /dev/null +++ b/original/header.h @@ -0,0 +1,201 @@ +/* conquer : Copyright (c) 1988, 1989 by Ed Barlow. + MODIFICATION OF THIS FILE IMPLIES THAT THE MODIFIER WILL ACCEPT + A LIMITED USE COPYRIGHT AS FOLLOWS: + + + 1) This software is copyrighted and protected by law. The + sole owner of this software, which hereafter is known as + "conquer" is Edward M. Barlow, who hereby grants you a + personal, non-exclusive right to use this software. + All rights on this software are reserved. + 2) conquer may not be redistributed in any form. Any requests for + new software shall, for now, be the perogative of the author. + 3) loss or damage caused by this software shall not be + the responsibility of the author. + 4) Ed Barlow or Adam Bryant shall be notified of enhancements to this + software via electronic mail and, if there is no response, via + US mail to: + + Ed Barlow + 115 E 34ths St. + NY, NY 10016 + + My home phone is 212-679-1439. Use it sparingly and call + before 11PM if it is important. Note that I no longer have + access to the arpanet and cant really support conquer like + I used to. If somebody knows of a cheap (free) way of getting + a login somewhere where there is network access - HELP ME!!!! + Since i am "volunteering" my time for this project, I am not + about to spend millions of dollars to buy network access... + I can get a modem for my PC if somebody will help me get + something to call into. -ED- + 5) no attempt shall be made to make any money from this game or to + use any portion of this code to make any money without the + authors permission. + 6) no attempt shall be made to port this software to any form of + personal computer without the permission of Ed Barlow. + 7) you agree to use your best efforts to see that any user + of conquer complies with the terms and conditions stated above. + 8) The above copyright agreement will not be tampered with in any form. + + + Special thanks to Brian Beuning, Adam Bryant, and any others who helped + me by making enhancements and bug reports +*/ + +/* --- MODIFICATION IS REQUIRED OF THE FOLLOWING DEFINE STATEMENTS --- */ +#define OWNER "Adam Bryant" /* administrators name */ +#define LOGIN "adb" /* administrators login id. IMPORTANT! */ + /* only this UID may update. */ +/* #define SYSV /* uncomment this line on a UNIX SYSV machine */ +#define BSD /* uncomment this line on a BSD machine */ +/* #define HPUX /* uncomment for HP-UNIX */ +/*#define XENIX /* this plus SYSV for XENIX machines, untested */ +#define SYSMAIL /* if your system supports mail */ + /* conquer will notify you about system mail */ + +/* ------------------MODIFICATION IS OPTIONAL ON THE FOLLOWING----------*/ +#define SPOOLDIR "/usr/spool/mail" /* location of mail spool */ +#define FILELOCK /* if your system supports BSD flock() */ + /* other file locking is not well implemented */ +/*#define LOCKF /* in addition to FILELOCK if you have lockf */ + /* this is needed on NFS remote file systems */ +#define TIMELOG /* if your system has the date command */ + +#define NTOTAL 25 /* max # of nations ( player + npc + monster ) */ +#define MAXPTS 65 /* points for players to buy stuff with at start*/ +#define MAXARM 50 /* maximum number of armies per nation */ +#define MAXNAVY 10 /* maximum number of fleets per nation */ +#define PDEPLETE 30 /* % of armies/sectors depleted without Capitol */ +#define PFINDSCOUT 50 /* percentage chance for capturing scouts */ + +#define RUNSTOP /* defined to stop update if players are in */ + /* game -- not recommended with automatic update*/ +#define TRADE /* defined to allow commerce between nations */ +#define TRADEPCT 75 /* percent of sectors with exotic trade goods */ +#define METALPCT 33 /* percent of tradegoods that are metals */ +#define JEWELPCT 33 /* percent of tradegoods that are luxury items */ +#define HIDELOC /* defined if news is not to report sectors */ +#define OGOD /* defined if you wish to enhance god powers. */ +#define REMAKE /* may make a world even if datafile exists. */ + /* this allows demi-gods the ability to remake */ + /* their world. */ +#define NOSCORE /* only show full scores to god while in game */ +/* #define CHECKUSER */ /* only allow owner of nation to play it */ +#define REVSPACE 5 /* allow for this many revolts in nation list */ +#define LASTADD 5 /* last turn players may w/out password */ +#define USERLOG /* log users who play a nation */ +#define MASK 037 /* data file protection mask (umask) */ +#define DERVDESG /* allow DERVISH to redesignate in DESERT/ICE */ +#define MONSTER 45 /* defined if pirates/savages/nomads/lzard exist. + represents # of sectors of land that need to be + in world per pirate/savage/nomad nation */ +#define MORE_MONST /* defined if destroyed monsters are replaced */ +#define NPC 45 /* defined if NPC nations should exist. The numeric + represents # of sectors of land that need to be + in world per non-player character nation */ +#define CHEAT /* npcs will cheat to keep up - this is a very weak + form of cheating. I use good npc algorithms + (i think... comments) */ +/*#define NPC_COUNT_ARMIES /* defined if NPC nations can always count armies + This makes them to cheat by seeing even VOID and + HIDDEN armies when counting enemy units. */ +/*#define NPC_SEE_SECTORS /* defined if NPC nations can always see sectors + This allows them to cheat by being allowed to see + all sector attributes of even VOID sectors. */ +#define NPC_SEE_CITIES /* defined if NPC nations can always see cities + This allows them to cheat by being able to see + if a VOID sector is a city/town. Simulates the + players ability to tell cities via movement. */ +#define STORMS /* have storms strike fleets */ +#define VULCANIZE /* add in volcano eruptions.... */ +#define PVULCAN 20 /* % chance of eruption each round (see above) */ +#define ORCTAKE 100000L /* comment out if dont want orcs to takeover orc + NPCs. else is takeover price in jewels */ +#define MOVECOST 20l /* cost to do a move, get a screen... */ +#define TAKEPOINTS 10 /* spell points for orc takeover */ +#define PMOUNT 40 /* % of land that is mountains */ +#define PSTORM 3 /* % chance that a storm will strike a fleet */ + /* unless it is in harbor */ +#define CMOVE /* #ifdef NPC; defined for the computer to move + for Player nations if they forget to move */ +#define BEEP /* defined if you wish terminal to beep */ +#define HILIGHT /* defined if terminals support inverse video */ +#define RANEVENT 15 /* comment out if you dont want random events + weather, tax revolts, and volcanoes all are + considered random events. */ +#define PWEATHER 0 /* percent for weather disaster - unimplemented */ +#define PREVOLT 25 /* %/turn that a revolt acutally occurs */ + /* a turn is 1 season and 25% is a large value */ +#define SPEW /* spew random messages from npcs */ + +/* -BELOW THIS POINT ARE PARAMETERS YOU MIGHT OPTIONALLY WISH TO CHANGE-*/ + +/* making these numbers large takes more CPU time */ +#define LANDSEE 2 /* how far you can see from your land */ +#define NAVYSEE 1 /* how far navies can see */ +#define ARMYSEE 2 /* how far armies can see */ +#define PRTZONE 3 /* how far pirates roam from their basecamp */ +#define MEETNTN 2 /* how close nations must be to adjust status */ + +/* Below taxation rates are in gold talons per unit of product produced */ +#define TAXFOOD 5L +#define TAXMETAL 8L +#define TAXGOLD 8L +#define TAXOTHR 3L /* per food point equivalent */ +/* Town and City/Capitol tax rates based on # of people */ +#define TAXCITY 100L +#define TAXTOWN 80L + +#define SHIPMAINT 4000L /* ship mainatinance cost */ +#define TOMANYPEOPLE 4000L /* too many people in sector - 1/2 repro and + 1/2 production; not in cities/caps */ +#define ABSMAXPEOPLE 50000L /* absolute max people in any sector */ +#define MILLSIZE 500L /* min number of people to work a mill */ +#define TOMUCHMINED 50000L /* units mined for 100% chance of metal */ + /* depletion actual chance is prorated */ +#define DESFOOD 4 /* min food val to redesignate sector */ +#define MAXNEWS 5 /* number of news files stored */ +#define LONGTRIP 100 /* navy trip lth for 100% attrition */ + +/* min soldiers to take sector - either 75 or based on your civilians */ +#define TAKESECTOR min(500,max(75,(ntn[country].tciv/350))) + +#define MAXLOSS 60 /* maximum % of men lost in 1:1 battle */ +#define FINDPERCENT 1 /* percent to find gold/metal in sector */ +#define DESCOST 2000L /* cost to redesignate and the metal cost + for cities */ +#define FORTCOST 1000L /* cost to build a fort point */ +#define STOCKCOST 3000L /* cost to build a stockade */ +#define REBUILDCOST 3000L /* cost to remove a ruin */ +#define WARSHPCOST 20000L /* cost to build one light warship */ +#define MERSHPCOST 25000L /* cost to build one light merchant */ +#define GALSHPCOST 25000L /* cost to build one light galley */ +#define N_CITYCOST 4 /* move lost in (un)loading in cities */ +#define SHIPCREW 100 /* full strength crew on a ship */ +#define SHIPHOLD 100L /* storage space of a ship unit */ +#define CITYLIMIT 8L /* % of npc pop in sctr before => city */ +#define CITYPERCENT 20L /* % of npc pop able to be in cities */ +/* note that militia are not considered military below */ +#define MILRATIO 8L /* ratio civ:mil for NPCs */ +#define MILINCAP 8L /* ratio (mil in cap):mil for NPCs */ +#define MILINCITY 10L /* militia=people/MILINCITY in city/cap */ +#define NPCTOOFAR 15 /* npcs should not go this far from cap */ +#define BRIBE 50000L /* amount of gold/1000 men to bribe */ +#define METALORE 7L /* metal/soldier needed for +1% weapons */ +/* strength value for fortifications */ +#define DEF_BASE 10 /* base defense value 2 * in city/caps */ +#define FORTSTR 5 /* percent per fortress point in forts */ +#define TOWNSTR 5 /* percent per fortress point in towns */ +#define CITYSTR 8 /* percent per fortress point in city */ +#define LATESTART 2 /* new player gets 1 point/LATESTART turns, + when they start late into the game */ + +/* starting values for mercenaries */ +#define ST_MMEN (NTOTAL*500) /* a nation may draft ST_MMEN/NTOTAL */ + /* mercenaries per turn. Added to when */ + /* armies are disbanded. */ +#define ST_MATT 40 /* mercenary attack bonus */ +#define ST_MDEF 40 /* mercenary defense bonus */ + +#define VERSION "Version 4" /* version number of the game */ diff --git a/original/io.c b/original/io.c new file mode 100644 index 0000000..6670d6f --- /dev/null +++ b/original/io.c @@ -0,0 +1,736 @@ +/*io.c*/ +/*Print and io subroutines for game*/ + +/*conquer : Copyright (c) 1988 by Ed Barlow. + * I spent a long time writing this code & I hope that you respect this. + * I give permission to alter the code, but not to copy or redistribute + * it without my explicit permission. If you alter the code, + * please document changes and send me a copy, so all can have it. + * This code, to the best of my knowledge works well, but it is my first + * 'C' program and should be treated as such. I disclaim any + * responsibility for the codes actions (use at your own risk). I guess + * I am saying "Happy gaming", and am trying not to get sued in the process. + * Ed + */ + +#include +#include +#include +#include +#include +#include "header.h" +#include "data.h" +#include "patchlevel.h" + +extern FILE *fexe; +/*offset of upper left hand corner*/ +extern short xoffset, yoffset; +/*current cursor postion (relative to 00 in upper corner)*/ +/* position is 2*x,y*/ +extern short xcurs,ycurs; +extern short redraw; /*redraw map in this turn if redraw is a 1*/ +extern short hilmode,dismode; /*display state*/ +extern short country; /* nation id of owner*/ + +/************************************************************************/ +/* GETSPACE() - malloc all space needed */ +/************************************************************************/ +void +getspace() +{ + if (sct != NULL) free(sct); + sct = (struct s_sector **) m2alloc(MAPX,MAPY,sizeof(struct s_sector)); + if (occ != NULL) free(occ); + occ = (char **) m2alloc(MAPX,MAPY,sizeof(char)); + if (movecost != NULL) free(movecost); + movecost = (short **) m2alloc(MAPX,MAPY,sizeof(short)); +} + +#ifdef CONQUER +char **mapseen; + +/************************************************************************/ +/* MAPPREP() - initialize map with what can be seen by nation. */ +/************************************************************************/ +void +mapprep() +{ + int armynum, nvynum; + int x,y,i,j; + + /* get space for map */ + mapseen = (char **) m2alloc(MAPX,MAPY,sizeof(char)); + + /* initialize the array */ + if (country==0 || magic(country,KNOWALL)==TRUE) { + armynum = TRUE; + } else { + armynum = FALSE; + } + for (x=0;x0) { + for(i=(int)P_AXLOC-ARMYSEE;i<=(int)P_AXLOC+ARMYSEE;i++) + for(j=(int)P_AYLOC-ARMYSEE;j<=(int)P_AYLOC+ARMYSEE;j++) + if (ONMAP(i,j)) { + mapseen[i][j]=TRUE; + } + } + + /* now add sectors visible by navy */ + for(nvynum=0;nvynumname, TURN); + } + for(Y=0;Yname, TURN); + } + for(Y=0;Yname, TURN); + } + for(Y=0;Yname, TURN); + } + for(Y=0;Y= SCREEN_X_SIZE-1){ + if(XREAL=MAPX) xcurs=MAPX-1-xoffset; + if(xoffset<0) { + xcurs += xoffset; + xoffset=0; + } + if(xcurs<0) { + xoffset += xcurs; + xcurs=0; + } + else if(xcurs >= SCREEN_X_SIZE-1) { + redraw=PART; + xoffset+=15; + xcurs-=15; + } + + if(ycurs<1){ + if(YREAL<=0) { + yoffset=0; + ycurs=0; + } + else { + redraw=PART; + ycurs+=15; + yoffset-=15; + } + } + else if(ycurs >= SCREEN_Y_SIZE-1){ + if(YREAL=MAPY) ycurs=MAPY-1-yoffset; + if(yoffset<0) { + ycurs += yoffset; + yoffset=0; + } + if(ycurs<0) { + yoffset += ycurs; + ycurs=0; + } + else if(ycurs >= SCREEN_Y_SIZE-1) { + redraw=PART; + yoffset+=15; + ycurs-=15; + } + whatcansee(); +} +#endif /* XYZZY */ + +/************************************************************************/ +/* CENTERMAP() - redraws screen so that cursor is centered */ +/************************************************************************/ +void +centermap() +{ + int xx,yy; + xx=XREAL; + yy=YREAL; + xoffset = xx - (SCREEN_X_SIZE/2); + yoffset = yy - (SCREEN_Y_SIZE/2); + if (xoffset<0) + xoffset=0; + if (yoffset<0) + yoffset=0; + xcurs= xx-xoffset; + ycurs= yy-yoffset; + whatcansee(); +} + +/************************************************************************/ +/* JUMP_TO() - move screen position to a specific location */ +/* home indicates just go to capitol sector. */ +/************************************************************************/ +void +jump_to(home) + int home; +{ + int i,j,done; + static int next_ntn; + + /* find location to jump to */ + if (home) { + if (country==0) { + /* check if in sequence */ + if ((XREAL!=ntn[next_ntn].capx) + ||(YREAL!=ntn[next_ntn].capy)) { + next_ntn= 0; + } + /* find next capitol */ + done = FALSE; + do { + next_ntn++; + if (next_ntn==NTOTAL) { + j = 0; + for(i=0;icapx; + j = curntn->capy; + } + } else { + /* entered location */ + clear_bottom(0); + mvaddstr(LINES-3,0,"Jump to what X location? "); + refresh(); + i = get_number(); + if (i==(-1)) return; + if (i>=MAPX) { + errormsg("That location is out of this world!"); + return; + } + mvaddstr(LINES-2,0,"Jump to what Y location? "); + refresh(); + j = get_number(); + if (j==(-1)) return; + if (j>=MAPY) { + errormsg("That location is out of this world!"); + return; + } + } + /* now center location about given position */ + xcurs = i; + ycurs = j; + xoffset = yoffset = 0; + centermap(); +} + +/************************************************************************/ +/* PRINTSCORE() - like it says */ +/************************************************************************/ +void +printscore() +{ + int i; + int nationid; /*current nation id */ +#ifdef TIMELOG + FILE *timefp, *fopen(); + char timestr[LINELTH+1]; +#endif /* TIMELOG */ + + printf("Conquer %s.%s: %s of Year %d, Turn %d\n",VERSION,PATCHLEVEL, + PSEASON(TURN),YEAR(TURN), TURN); +#ifdef TIMELOG + if ((timefp=fopen(timefile,"r"))!=NULL) { + fgets(timestr, 50, timefp); + printf("Last Update: %s", timestr); + fclose(timefp); + } +#endif /* TIMELOG */ + printf("id name race class align score talons military civilians sect\n"); + for (nationid=1; nationid0) { +#ifdef CONQUER + if(isupd==0) { + if(slaver==TRUE){ + mvprintw(LINES-2,20,"CIVILIANS ABANDON SECTOR (%d slaves)",slaves); + }else{ + mvaddstr(LINES-2,20,"CIVILIANS ABANDON SECTOR"); + } + } +#endif /* CONQUER */ + for(i=x-2;i<=x+2;i++) for(j=y-2;j<=y+2;j++) + if(ONMAP(i,j) + &&(ntn[sct[i][j].owner].race==ntn[sct[x][y].owner].race)) { + people_to_add = sct[x][y].people / count; + /* don't show until next turn if player move */ + if(isupd==0) SADJCIV3; + else sct[x][y].people += people_to_add; + } + } else { + sct[x][y].people /= 2; + for(i=x-4;i<=x+4;i++) for(j=y-4;j<=y+4;j++) + if(ONMAP(i,j) + &&(ntn[sct[i][j].owner].race==ntn[sct[x][y].owner].race)) + count++; + if(count>0) { +#ifdef CONQUER + if(isupd==0) mvaddstr(LINES-2,20,"PEOPLE FLEE SECTOR AND HALF DIE"); +#endif /* CONQUER */ + for(i=x-4;i<=x+4;i++) for(j=y-4;j<=y+4;j++) + if(ONMAP(i,j) + &&(ntn[sct[i][j].owner].race==ntn[sct[x][y].owner].race)) { + sct[i][j].people += sct[x][y].people / count; + if(isupd==0) SADJCIV2; + } + } +#ifdef CONQUER + else if(isupd==0) mvaddstr(LINES-2,20,"PEOPLE IN SECTOR DIE"); +#endif /* CONQUER */ + } + + sct[x][y].people = slaves; + if(isupd==0) SADJCIV; + sct[x][y].fortress=0; + /*SINFORT;*/ + if(tofood( &sct[XREAL][YREAL],sct[XREAL][YREAL].owner)!=0) { + DEVASTATE(x,y); + if(isupd==0) SADJDES2; + } + country=svcountry; +} +#ifdef ADMIN +/************************************************************************/ +/* READMAP() - read a map in from map files */ +/* returns TRUE for success, FALSE for fail */ +/************************************************************************/ +int +readmap() +{ + FILE *mapfile; + char line[BIGLTH+1]; + register int x,y; + + /* read in ele.map */ + strcpy(line,scenario); + strcat(line,".ele"); + if ((mapfile=fopen(line,"r"))==NULL) { + fprintf(stderr,"error on read of %s file\n",line); + return(TRUE); + } else fprintf(stderr,"reading elevation map file from %s\n",line ); + + y=0; + while( TRUE ) { + if(fgets( line, 128, mapfile )==NULL) break; + for(x=0;x=MAPY) break; + } + fprintf(stderr,"done reading %d lines of %d characters\n",y,strlen(line)); + + /* read in veg.map */ + strcpy(line,scenario); + strcat(line,".veg"); + if ((mapfile=fopen(line,"r"))==NULL) { + fprintf(stderr,"error on read of %s file\n",line); + return(TRUE); + } else fprintf(stderr,"reading vegetation map file from %s\n",line ); + y=0; + while( TRUE ) { + if(fgets( line, BIGLTH, mapfile )==NULL) break; + for(x=0;x=MAPY) break; + } + fprintf(stderr,"done reading %d lines of %d characters\n",y,strlen(line)); + + return(TRUE); +} +#endif /* ADMIN */ + +/*********************************************************************/ +/* M2ALLOC() - two dimensional array allocator (because C is stupid) */ +/*********************************************************************/ +char **m2alloc(nrows, ncols, entrysize) +int nrows; /* row dimension */ +int ncols; /* column dimension */ +int entrysize; /* # bytes in items to be stored */ +{ + char **baseaddr; + int j; + entrysize *= ncols; + baseaddr = (char **) + malloc( (unsigned) (nrows*(sizeof(char *)+entrysize))); + + if( baseaddr == (char **) NULL ) { + printf("OOPS - cannot allocate %d by %d blocks of %d bytes\n",nrows,ncols,entrysize); + abrt(); + } + if(nrows>0){ + *baseaddr = (char *) (baseaddr + nrows); + for(j=1; j 0) { + count--; + } + } else if (ch=='\025') { + /* make sure that ^U works */ + count=0; + } else if (ch=='\n' || ch=='\r') { + done = TRUE; + } else if (ch != '\0') { + /* add any other character to the string */ + if (count < PASSLTH) { + /* don't try adding too many */ + str[count]= ch; + } + count++; + } + } + /* truncate too long a password and end others properly */ + if (count > PASSLTH) { + str[PASSLTH] = '\0'; + } else { + str[count] = '\0'; + } + return(count); +} diff --git a/original/magic.c b/original/magic.c new file mode 100644 index 0000000..c7949ef --- /dev/null +++ b/original/magic.c @@ -0,0 +1,1000 @@ +/*conquer : Copyright (c) 1988 by Ed Barlow. + * I spent a long time writing this code & I hope that you respect this. + * I give permission to alter the code, but not to copy or redistribute + * it without my explicit permission. If you alter the code, + * please document changes and send me a copy, so all can have it. + * This code, to the best of my knowledge works well, but it is my first + * 'C' program and should be treated as such. I disclaim any + * responsibility for the codes actions (use at your own risk). I guess + * I am saying "Happy gaming", and am trying not to get sued in the process. + * Ed + */ + +/*create a new login for a new player*/ +#include +#include +#include +#include +#include +#include "header.h" +#include "data.h" + +extern short country; +extern short redraw; +extern FILE *fexe; +extern FILE *fnews; + +/*give player one new magic power in current magic (powers)*/ +/*do nothing if that player has that power or it is not permitted*/ +/*getmagic() returns the value of the power gained, and stores it in power*/ + +long +getmagic(type) +int type; +{ + long newpower; + int start,end; + switch(type){ + case M_MGK: + start=S_MGK; + end=E_MGK; + break; + case M_CIV: + start=S_CIV; + end=E_CIV; + break; + case M_MIL: + start=S_MIL; + end=E_MIL; + break; + default: + printf("fatal error in num_powers"); + abrt(); + } + newpower=powers[start+(rand()%end)]; + if(newpower==0) { + printf("ILLEGAL POWER"); + abrt(); + } + + if((newpower==WARRIOR)||(newpower==CAPTAIN)||(newpower==WARLORD)){ + if(magic(country,WARRIOR)!=TRUE){ + curntn->powers|=WARRIOR; + return(WARRIOR); + } + else if(magic(country,CAPTAIN)!=TRUE){ + curntn->powers|=CAPTAIN; + return(CAPTAIN); + } + else if(magic(country,WARLORD)!=TRUE){ + curntn->powers|=WARLORD; + return(WARLORD); + } + else return(0L); + }else if((newpower==MI_MONST) ||(newpower==AV_MONST) ||(newpower==MA_MONST)){ + if(curntn->race!=ORC) return(0L); + if(magic(country,MI_MONST)!=TRUE){ + curntn->powers|=MI_MONST; + return(MI_MONST); + } + else if(magic(country,AV_MONST)!=TRUE){ + curntn->powers|=AV_MONST; + return(AV_MONST); + } + else if(magic(country,MA_MONST)==TRUE){ + curntn->powers|=MA_MONST; + return(MA_MONST); + } + else return(0L); + }else if(newpower==CAVALRY){ + if(curntn->race==ORC) return(0L); + if(isnotpc(curntn->active)) return(0L); /*npc nation*/ + if(magic(country,newpower)==TRUE) return(0L); + curntn->powers|=newpower; + return(newpower); + }else if(newpower==URBAN){ + if(magic(country,BREEDER)==TRUE) return(0L); + if(magic(country,newpower)==TRUE) return(0L); + curntn->powers|=newpower; + return(newpower); + }else if(newpower==RELIGION){ + if(curntn->race==ORC) return(0L); + if(magic(country,newpower)==TRUE) return(0L); + curntn->powers|=newpower; + return(newpower); + }else if(newpower==KNOWALL){ +#ifdef OGOD +#ifdef HIDELOC + /* only god should have KNOWALL if sectors hidden */ + if(country!=0) return(0L); +#endif +#endif + if(magic(country,KNOWALL)==TRUE) return(0L); + curntn->powers|=KNOWALL; + return(KNOWALL); + }else if((newpower==SLAVER) + ||(newpower==DERVISH) + ||(newpower==HIDDEN) + ||(newpower==ARCHITECT) + ||(newpower==THE_VOID) + ||(newpower==ARCHER)){ + if((magic(country,newpower)==TRUE) + ||((newpower==DERVISH)&&(magic(country,DESTROYER)==TRUE))) + return(0L); + curntn->powers|=newpower; + return(newpower); + }else if(newpower==DESTROYER){ + if((curntn->race!=ELF) + &&(magic(country,DESTROYER)!=TRUE) + &&(magic(country,DERVISH)!=TRUE)){ + curntn->powers|=DESTROYER; + return(DESTROYER); + } + return(0L); + }else if(newpower==VAMPIRE){ + if((curntn->race!=ELF)&&(magic(country,VAMPIRE)!=TRUE)){ + curntn->powers|=VAMPIRE; + return(VAMPIRE); + } + return(0L); + }else if(newpower==MINER){ + if((curntn->race!=ELF)&&(curntn->race!=DWARF)&&(magic(country,MINER)!=TRUE)){ + curntn->powers|=MINER; + return(MINER); + } + return(0L); + }else if(newpower==STEEL){ + if(magic(country,STEEL)==TRUE) return(0L); + if(magic(country,MINER)!=TRUE) return(0L); + curntn->powers|=STEEL; + return(STEEL); + }else if(newpower==BREEDER){ + if(magic(country,URBAN)==TRUE) return(0L); + if(magic(country,BREEDER)==TRUE) return(0L); + if(curntn->race!=ORC) return(0L); + curntn->powers|=BREEDER; + return(BREEDER); + } + else if(isnotpc(curntn->active)) { + return(0L); /* remaining powers only for pc's */ + } else if((newpower==NINJA) + ||(newpower==SLAVER) + ||(newpower==SAILOR) + ||(newpower==DEMOCRACY) + ||(newpower==ROADS) + ||(newpower==SAPPER) + ||(newpower==ARMOR) + ||(newpower==AVIAN)){ + if(magic(country,newpower)==TRUE) return(0L); + curntn->powers|=newpower; + return(newpower); + } + else if((newpower==SUMMON)||(newpower==WYZARD)||(newpower==SORCERER)){ + /* dwarves may not cast spells */ + if(curntn->race==DWARF) return(0L); + if(magic(country,SUMMON)!=TRUE) { + curntn->powers|=SUMMON; + return(SUMMON); + } else if(magic(country,WYZARD)!=TRUE) { + curntn->powers|=WYZARD; + return(WYZARD); + } else if(magic(country,SORCERER)!=TRUE) { + curntn->powers|=SORCERER; + return(SORCERER); + } else return(0L); + } else return(0L); +} +#ifdef CONQUER +/*form to interactively get a magic power*/ +void +domagic() +{ + int county, countx, done=FALSE, loop=0, i,type; + long price,x; +#ifdef OGOD + void god_magk(); +#endif /* OGOD */ + + short isgod=0; + if(country==0) { + isgod=TRUE; + if (get_god()) return; + } + + clear(); + while(done==FALSE){ + done=TRUE; + move(0,0); + clrtobot(); + county=3; + countx=0; + redraw=FULL; + standout(); + mvprintw(0,(COLS/2)-15,"MAGIC POWERS FOR %s",curntn->name); + mvprintw(county++,30,"1) %d military powers: %ld jewels", + num_powers(country,M_MIL) ,getmgkcost(M_MIL,country)); + mvprintw(county++,30,"2) %d civilian powers: %ld jewels", + num_powers(country,M_CIV) ,getmgkcost(M_CIV,country)); + mvprintw(county++,30,"3) %d magic powers: %ld jewels", + num_powers(country,M_MGK),getmgkcost(M_MGK,country)); + + price = getmgkcost(M_MIL,country); + if(price > getmgkcost(M_CIV,country)) + price = getmgkcost(M_CIV,country); + if(price > getmgkcost(M_MGK,country)) + price = getmgkcost(M_MGK,country); + + standend(); + county=3; + /*print the powers that you have*/ + i=0; + while( powers[i] != 0 ){ + if(magic(country,powers[i])==TRUE) + mvprintw(county++,countx,"you have power %s",*(pwrname+i)); + i++; + if (county > 18) { + county=7; + countx=40; + } + } + + if(county<=7) county=8; + else if(countx == 40) county = 20; + else county++; + standout(); + mvprintw(county++,0,"YOU HAVE %ld JEWELS IN YOUR TREASURY",curntn->jewels); +#ifdef OGOD + if (isgod==TRUE) { + mvaddstr(county++,0,"DO YOU WISH TO CHANGE THIS NATION'S POWERS? [yn]"); + standend(); + refresh(); + if (getch()=='y') god_magk(); + } else +#endif /* OGOD */ + if(price <= curntn->jewels){ + + mvaddstr(county++,0,"DO YOU WISH TO BUY A RANDOM NEW POWER? [yn]"); + standend(); + refresh(); + if(getch()=='y'){ + done=FALSE; + mvaddstr(county++,0,"ENTER SELECTION (1,2,3):"); + refresh(); + type = getch() - '0'; + if(type==M_MIL || type==M_CIV || type==M_MGK){ + price=getmgkcost(type,country); + if(curntn->jewels>=price) { + loop = 0; + while(loop++ < 500) if((x=getmagic(type))!=0){ + curntn->jewels -= price; + CHGMGK; + exenewmgk(x); + refresh(); + if (isgod==TRUE) reset_god(); + break; + } + if (loop >= 500) + errormsg("You have too many powers!"); + } else errormsg("CAN'T AFFORD A NEW POWER"); + } else errormsg("BAD SELECTION"); + } + } else { + mvaddstr(LINES-1,0,"CAN'T AFFORD A NEW POWER"); + clrtoeol(); + mvaddstr(LINES-1,60,"PRESS ANY KEY"); + refresh(); + standend(); + getch(); + } +#ifdef ORCTAKE + if((curntn->race==ORC)&&(curntn->jewels>=ORCTAKE)&&(curntn->spellpts>=TAKEPOINTS)) + done |= orctake(&county); +#endif /* ORCTAKE */ + } + if(isgod==TRUE) reset_god(); +} +#endif /* CONQUER */ +#ifdef ORCTAKE +/*do magic for both npcs and pcs in update*/ +/*if target is 0 then it is update and target will be picked randomly*/ +int +takeover(percent,target) +int percent,target; +{ + int loop=1,y,save,isupdate=0; + save=country; + if(target==country) return(0); + if(target==0) isupdate=1; + country=target; + if(rand()%100dstatus[country]dstatus[country]!=UNMET) + &&(country!=save)) + loop=TRUE; + else if(y>=500) { + country=save; + return(0); + } + } + sct[ntn[country].capx][ntn[country].capy].owner=save; + if(isupdate==1){ + printf("nation %s magically taken over by %s\n",ntn[country].name,ntn[save].name); + fprintf(fnews,"1.\tnation %s magically taken over by %s\n",ntn[country].name,ntn[save].name); + } + else { + DESTROY; + if ((fnews=fopen("/dev/null","w"))==NULL){ + printf("error opening null file\n"); + exit(FAIL); + } + } + destroy(country); + sct[ntn[country].capx][ntn[country].capy].designation=DCITY; + if(isupdate!=1) fclose(fnews); + y=country; + country=save; + return(y); + } + country=save; + return(0); +} +#endif /* ORCTAKE */ + +/*execute new magic*/ +void +exenewmgk(newpower) +long newpower; +{ + short x,armynum; +#ifdef ADMIN + short y; +#endif + if(newpower==WARRIOR) { + curntn->aplus+=10; + curntn->dplus+=10; + return; + } + if(newpower==CAPTAIN) { + curntn->aplus+=10; + curntn->dplus+=10; + return; + } + if(newpower==WARLORD) { + curntn->aplus+=10; + curntn->dplus+=10; + return; + } + if(newpower==RELIGION) { + if(curntn->race==ORC) { + printf("ORCS CANT HAVE RELIGION POWER\n"); + abrt(); + } else if(curntn->repro<=8){ + curntn->repro+=2; + } else if(curntn->repro==9){ + curntn->repro=10; + curntn->dplus+=5; + } else if(curntn->repro>=10){ + curntn->dplus+=10; + } + return; + } + if(newpower==DESTROYER) { +/* this ifdef is so that destroyer only takes place in an update */ +#ifdef ADMIN + for(x=(int)curntn->capx-3;x<=(int)curntn->capx+3;x++) { + for(y=(int)curntn->capy-3;y<=(int)curntn->capy+3;y++){ + if((ONMAP(x,y)) + &&(sct[x][y].altitude!=WATER) +#ifdef DERVDESG + &&((rand()%2)==0) +#else + &&(tofood( &sct[x][y],0)<6) +#endif /* DERVDESG */ + &&((x!=curntn->capx) + ||(y!=curntn->capy))){ + sct[x][y].vegetation=DESERT; + sct[x][y].designation=DNODESIG; + } + } + } + fprintf(fnews,"1.\tnation %s gets destroyer power: land turns to desert\n",curntn->name); +#endif /* ADMIN */ + updmove(curntn->race,country); + return; + } + if(newpower==DERVISH) { + updmove(curntn->race,country); + return; + } + if((newpower==MI_MONST) + ||(newpower==AV_MONST) + ||(newpower==MA_MONST) + ||(newpower==KNOWALL) + ||(newpower==HIDDEN) + ||(newpower==THE_VOID) + ||(newpower==ARCHITECT)) + return; + if(newpower==MINER) { + curntn->mine_ability+=25; + return; + } + if(newpower==VAMPIRE) { + curntn->aplus-=35; + curntn->dplus-=35; + for(armynum=0;armynumrace==ORC) { + x=curntn->repro; + if(curntn->repro>=14){ + curntn->maxmove+=3; + } + else if(curntn->repro>11){ + curntn->maxmove+= x-11; + curntn->repro=14; + } + else curntn->repro+=3; + } + else if(curntn->repro<=9){ + curntn->repro+=3; + } + else { + curntn->maxmove+=2*(curntn->repro-9); + curntn->repro=12; + } + return; + } + if(newpower==BREEDER) { + x=curntn->repro; + if(curntn->repro>=14){ + curntn->maxmove+=3; + } + else if(curntn->repro>11){ + curntn->maxmove+= x-11; + curntn->repro=14; + } + else curntn->repro+=3; + curntn->dplus-=10; + curntn->aplus-=10; + return; + } + if(newpower==DEMOCRACY){ + curntn->maxmove+=1; + curntn->repro+=1; + curntn->dplus+=10; + curntn->aplus+=10; + return; + } + if(newpower==ROADS){ + curntn->maxmove+=4; + return; + } + if(newpower==ARMOR){ + curntn->maxmove-=3; + if( curntn->maxmove<4) curntn->maxmove=4; + curntn->dplus+=20; + } + if((newpower==NINJA) + ||(newpower==STEEL) + ||(newpower==ARCHER) + ||(newpower==CAVALRY) + ||(newpower==SAILOR) + ||(newpower==SUMMON) + ||(newpower==WYZARD) + ||(newpower==SORCERER) + ||(newpower==SAPPER) + ||(newpower==AVIAN)){ /* these powers are only for pc's */ + return; + } +} +#ifdef CONQUER +/* returns 0 if summon occurred, 1 else */ +void +dosummon() +{ + int x,count,i,armynum; + long e_cost; + int newtype,s_cost; + char line[LINELTH+1],ch; + + x=0; + count=LINES-4; + clear_bottom(0); + mvaddstr(count,x,"options:"); + x+=9; + for(i=MINMONSTER;i<=MAXMONSTER;i++){ + if(unitvalid(i)==TRUE) { + mvprintw(count,x+2,"%s",*(shunittype+(i%UTYPE))); + mvprintw(count,x,"(%c)",*(shunittype+(i%UTYPE))[0]); + x+=7; + if(x>COLS-20){ + x=0; + count++; + } + } + } + count++; + mvaddstr(count++,0,"what type of unit do you want to raise:"); + refresh(); + ch=getch(); + for(newtype=MINMONSTER;newtype<=MAXMONSTER;newtype++){ + if( *(shunittype+(newtype%UTYPE))[0] == ch ) break; + } + + if (newtype==MAXMONSTER+1) { + /* quick exit */ + return; + } + if(unitvalid(newtype)==FALSE) { + beep(); + clear_bottom(0); + errormsg("you are unable to summon that monster"); + return; + } + + s_cost= *(u_encost+(newtype%UTYPE)); + if(s_cost > curntn->spellpts) { + sprintf(line,"you dont have %d spell points",s_cost); + clear_bottom(0); + errormsg(line); + return; + } + + e_cost= (long) *(u_encost+(newtype%UTYPE)) * *(unitminsth+(newtype%UTYPE)); + if(e_cost > curntn->tgold) { + sprintf(line,"you dont have %ld gold talons in your treasury",e_cost); + clear_bottom(0); + errormsg(line); + return; + } + + armynum=0; + while(armynumcapx; + P_AYLOC=curntn->capy; + P_AMOVE=0; + AADJLOC; + AADJSTAT; + AADJMEN; + AADJMOV; + armynum=MAXARM; + } else if(armynum==MAXARM-1) { + clear_bottom(0); + errormsg("NO FREE ARMIES"); + return; + } else armynum++; + } + curntn->tgold -= e_cost; + curntn->spellpts -= s_cost; + EDECSPL; +} +#ifdef ORCTAKE +/* orc takeover routine... returns 0 if run, 1 if not */ +int +orctake(count) +int *count; +{ + int chance=0,done=TRUE,i,s_cost; + if((*count)>20) { + (*count)=2; + clear(); + } + if(magic(country,MA_MONST)==TRUE) { + mvprintw((*count)++,0,"You have a 10 percent chance for %ld Jewels take over other orcs",ORCTAKE); + chance=10; + } else if(magic(country,AV_MONST)==TRUE) { + mvprintw((*count)++,0,"You have a 6 percent chance for %ld Jewels take over other orcs",ORCTAKE); + chance=6; + } else if(magic(country,MI_MONST)==TRUE){ + mvprintw((*count)++,0,"You have a 3 percent chance for %ld Jewels to take over other orcs",ORCTAKE); + chance=3; + } + if(chance==0) return(TRUE); + + mvaddstr((*count)++,0," Target can't be Unmet, Hostile, War, or Jihad"); + mvaddstr((*count)++,0,"DO YOU WISH TO TAKE OVER AN ORC NPC NATION: [ny]"); + refresh(); + if(getch()=='y'){ + done=FALSE; + mvaddstr((*count)++,0," What orc nation:"); + refresh(); + i=get_country(); + if(i<=0 || i>=NTOTAL || !isntn(ntn[i].active) ) + mvaddstr((*count)++,0," Invalid Nation"); + else if((curntn->dstatus[i]dstatus[i]!=UNMET) + &&(ntn[i].race==ORC)){ + curntn->jewels-=ORCTAKE; + s_cost=TAKEPOINTS; + curntn->spellpts-=s_cost; + EDECSPL; + if(( takeover(chance,i)) !=0 ) + mvprintw((*count)++,0," Successful: %d",i); + else { + mvaddstr((*count)++,0," Failed: Nation becomes more hostile"); + curntn->dstatus[i]++; + EADJDIP(country,i); + } + } else { + if (ntn[i].race==ORC) + mvaddstr((*count)++,0," That Nation is Outside Your Influence"); + else mvaddstr((*count)++,0," Wrong Race"); + } + refresh(); + sleep(2); + } + return(done); +} +#endif /* ORCTAKE */ +#endif /* CONQUER */ +#ifdef CONQUER + +/**********************************************************************/ +/* unitvalid() returns TRUE if nation has powers needed to draft unit */ +/**********************************************************************/ +int +unitvalid(type) +int type; +{ + int valid=FALSE; + switch(type){ + case A_INFANTRY: /* not everyone gets infantry now */ + if(defaultunit(country)==A_INFANTRY) valid=TRUE; + break; + case GARGOYLE: + case A_GOBLIN: + case A_ORC: if(magic(country,MI_MONST)==TRUE) valid=TRUE; + break; + case A_MARINES: if(magic(country,SAILOR)==TRUE) valid=TRUE; + break; + case A_ARCHER: if(magic(country,ARCHER)==TRUE) valid=TRUE; + break; + case A_URUK: if(magic(country,AV_MONST)==TRUE) valid=TRUE; + break; + case A_NINJA: if(magic(country,NINJA)==TRUE) valid=TRUE; + break; + case A_PHALANX: if(magic(country,CAPTAIN)==TRUE) valid=TRUE; + break; + case A_OLOG: if((magic(country,BREEDER)==TRUE) + &&(magic(country,AV_MONST)==TRUE)) valid=TRUE; + break; + case A_ELEPHANT:if(magic(country,DERVISH)==TRUE) valid=TRUE; + break; + case SUPERHERO: + case A_LEGION: if(magic(country,WARLORD)==TRUE) valid=TRUE; + break; + case A_TROLL: if(magic(country,MA_MONST)==TRUE) valid=TRUE; + break; + case A_ELITE: if(magic(country,ARMOR)==TRUE) valid=TRUE; + break; + case CENTAUR: + case A_LT_CAV: + case A_CAVALRY: if(magic(country,CAVALRY)==TRUE) valid=TRUE; + break; + case A_KNIGHT: if((magic(country,ARMOR)==TRUE) + &&(magic(country,CAVALRY)==TRUE)) valid=TRUE; + break; + case A_ROC: + case A_GRIFFON: if(magic(country,AVIAN)==TRUE) valid=TRUE; + break; + case ASSASSIN: if(magic(country,NINJA)==TRUE) valid=TRUE; + break; + case DJINNI: if(magic(country,DERVISH)==TRUE) valid=TRUE; + break; + case HERO: if(magic(country,WARRIOR)==TRUE) valid=TRUE; + break; + case ELEMENTAL: if(magic(country,SORCERER)==TRUE) valid=TRUE; + break; + case A_ZOMBIE: + case WRAITH: + case MUMMY: if(magic(country,VAMPIRE)==TRUE) valid=TRUE; + break; + case MINOTAUR: + case DEMON: if(magic(country,DESTROYER)==TRUE) valid=TRUE; + break; + case BALROG: if((magic(country,WYZARD)==TRUE) + &&(magic(country,VAMPIRE)==TRUE)) valid=TRUE; + break; + case DRAGON: if((magic(country,MA_MONST)==TRUE) + &&(magic(country,WYZARD)==TRUE)) valid=TRUE; + break; + case A_SPY: + case A_SCOUT: break; /* handled elsewhere */ + default: valid=TRUE; /* for all unrestricted types */ + } + return(valid); +} +#endif /* CONQUER */ + +/*remove properties of magic power; must first remove power */ +void +removemgk(oldpower) +long oldpower; +{ + short x,y,armynum; + if((oldpower==WARRIOR) + ||(oldpower==CAPTAIN) + ||(oldpower==WARLORD)) { + curntn->aplus-=10; + curntn->dplus-=10; + return; + } + if(oldpower==RELIGION) { + if(curntn->race==ORC) { + printf("ORCS CANT HAVE RELIGION POWER\n"); + abrt(); + } else curntn->repro -= 2; + return; + } + if(oldpower==DESTROYER) { + for(x=(int)curntn->capx-3;x<=(int)curntn->capx+3;x++) { + for(y=(int)curntn->capy-3;y<=(int)curntn->capy+3;y++){ + if((ONMAP(x,y)) + &&(sct[x][y].altitude!=WATER) + &&((x!=curntn->capx) + ||(y!=curntn->capy))){ + if (sct[x][y].vegetation==DESERT) + { + /* LT_VEG has medium value*/ + sct[x][y].vegetation=LT_VEG; + sct[x][y].designation=DNODESIG; + } + } + } + } + updmove(curntn->race,country); + return; + } + if(oldpower==DERVISH) { + updmove(curntn->race,country); + return; + } + if(oldpower==VAMPIRE) { + curntn->aplus+=35; + curntn->dplus+=35; + for(armynum=0;armynumrepro -= 3; + return; + } + if(oldpower==BREEDER) { + curntn->repro-=3; + curntn->dplus+=10; + curntn->aplus+=10; + for(armynum=0;armynummaxmove-=1; + curntn->repro-=1; + curntn->dplus-=10; + curntn->aplus-=10; + return; + } + if(oldpower==ROADS){ + curntn->maxmove-=4; + return; + } + if(oldpower==ARMOR){ + curntn->maxmove+=3; + curntn->dplus-=20; + return; + } + if(oldpower==MI_MONST) { + for(armynum=0;armynumname); + else + mvprintw(0,(COLS/2)-15,"LACKING POWERS FOR %s",curntn->name); + standend(); + i=0; + while( powers[i] != 0 ){ + if(magic(country,powers[i])==remove) { + mvprintw(county,countx,"%2d: %s Power",i+1,*(pwrname+i)); + county++; + } + i++; + if (county > LINES-6) { + county = 3; + countx = COLS/2; + } + } + if (countx == COLS/2) { + county = LINES-4; + } + else county++; + standout(); + if (remove) mvaddstr(county++,0,"Which power to remove?"); + else mvaddstr(county++,0,"Which power to add?"); + standend(); + addch(' '); + refresh(); + choice=get_number(); + if(choice > 0 && choice <= MAXPOWER) { + if (magic(country,powers[choice-1])==remove) { + if (remove) + mvprintw(county++,0,"Remove magic #%d? (y or [n])",choice); + else + mvprintw(county++,0,"Add magic #%d? (y or [n])",choice); + refresh(); + if (getch()=='y') { + curntn->powers ^= powers[choice-1]; + if (remove) removemgk(powers[choice-1]); + else exenewmgk(powers[choice-1]); + } + } else { + if (remove) mvaddstr(county++,0,"The nation doesn't have that power."); + else mvaddstr(county++,0,"The nation already has that power."); + } + } + mvaddstr(county++,0,"Do you wish to add or remove another power?"); + done=TRUE; + refresh(); + if (getch()=='y') done=FALSE; + } +} +#endif /* OGOD */ + +#define NUMSPELLS 4 +char *spellstr[NUMSPELLS]={"(S)ummon","(F)light","(A)ttack Enhancement", + "(D)efense Enhancement"}; +/* quick adjustment to allow magical status change */ +int magicstat[NUMSPELLS]={DEFEND, FLIGHT, MAGATT, MAGDEF}; +/* number of soldiers per point of spell cost */ +int magiccost[NUMSPELLS]={0,100,300,300}; +/* routine to perform spells */ +void +wizardry() +{ + int i,xspt,yspt,choice,armynum,s_cost; + char line[LINELTH+1]; + void dosummon(); + + clear_bottom(0); + if(curntn->spellpts>0) + { + xspt=0; yspt=LINES-3; + /* summon only to those with summon */ + if (magic(country,SUMMON)==TRUE) i=0; + else i=1; + for (;iCOLS-20) { + xspt=0; + yspt++; + } + } + mvaddstr(LINES-4,0,"Which spell to cast:"); + refresh(); + choice=NUMSPELLS; + switch(getch()) { + case 's': + case 'S': + if (magic(country,SUMMON)==TRUE) dosummon(); + else { + clear_bottom(0); + errormsg("you do not have SUMMON power"); + } + break; + case 'f': + case 'F': + choice--; + case 'a': + case 'A': + choice--; + case 'd': + case 'D': + choice--; + /* change status of currently selected army */ + armynum = getselunit(); + clear_bottom(0); + if (armynum<0 || armynum>=MAXARM || + P_ASTAT==SCOUT || P_ASTAT==TRADED || + P_ASTAT==GENERAL || P_ASTAT>NUMSTATUS || + P_ASOLD<=0) { + errormsg("Invalid Unit for Magicking"); + } else if(P_ASTAT==ONBOARD) { + errormsg("Carried armies must be unloaded"); + } else if(P_ASTAT==magicstat[choice]) { + errormsg("Unit has already been magicked"); + } else if(P_ASTAT==MARCH) { + errormsg("That unit is too busy marching"); + } else { + /*cost of 1 spell point for magiccost men*/ + s_cost = (P_ASOLD-1) / magiccost[choice] + 1; + if (s_cost > curntn->spellpts) { + sprintf(line,"You don't have %d spell points",s_cost); + errormsg(line); + } else { + change_status(armynum,magicstat[choice]); + curntn->spellpts -= s_cost; + EDECSPL; + } + } + break; + default: + break; + } + } + else errormsg("You have no spell points for spell casting"); + makebottom(); +} +#endif /* CONQUER */ diff --git a/original/main.c b/original/main.c new file mode 100644 index 0000000..995010c --- /dev/null +++ b/original/main.c @@ -0,0 +1,1529 @@ +/*conquer : Copyright (c) 1988 by Ed Barlow. + * I spent a long time writing this code & I hope that you respect this. + * I give permission to alter the code, but not to copy or redistribute + * it without my explicit permission. If you alter the code, + * please document changes and send me a copy, so all can have it. + * This code, to the best of my knowledge works well, but it is my first + * 'C' program and should be treated as such. I disclaim any + * responsibility for the codes actions (use at your own risk). I guess + * I am saying "Happy gaming", and am trying not to get sued in the process. + * Ed + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "header.h" +#include "data.h" +#include "patchlevel.h" + +extern int armornvy,roads_this_turn,terror_adj; + +char fison[FILELTH]; +char *getpass(); +struct s_sector **sct; +struct s_nation ntn[NTOTAL]; /* player nation stats */ +struct s_world world; +char **occ; /*is sector occupied by an army?*/ +short **movecost; +long startgold=0; +long mercgot=0; + +short xoffset=0,yoffset=0; /*offset of upper left hand corner*/ +/* current cursor postion (relative to 00 in upper corner) */ +/* position is 2*x,y*/ +short xcurs=0,ycurs=0; +short redraw=FULL; /* if !DONE: redraw map */ +int done=FALSE; /* if TRUE: you are done */ +short hilmode=HI_OWN; /* hilight mode */ +short dismode=DI_DESI;/* display mode */ +short otherdismode= -(DI_MOVE); +short otherhilmode= HI_OWN; +short selector=0; /* selector (y vbl) for which army/navy... is "picked"*/ +short pager=0; /* pager for selector 0,1,2,3*/ +short country=0; /* nation id of owner*/ +struct s_nation *curntn; +short Gaudy=FALSE; +int owneruid; + +FILE *fexe, *fopen(); + +/************************************************************************/ +/* MAIN() - main loop for conquer */ +/************************************************************************/ +void +main(argc,argv) +int argc; +char **argv; +{ +#ifdef USERLOG + FILE *userlog; +#endif +#ifdef CHECKUSER + int checkuser_mod = FALSE; + int checkuser_uid = 0; + int checkuser_list = FALSE; +#endif + int geteuid(), getuid(), setuid(); + register int i,j; + char name[NAMELTH+1],filename[FILELTH]; +#ifndef __STDC__ + void srand(); +#endif + void init_hasseen(),mapprep(); + int getopt(); + char passwd[PASSLTH+1]; + long time(); + extern char *optarg, conqmail[]; +#ifdef SYSMAIL + extern char sysmail[]; +#endif /* SYSMAIL */ + int sflag=FALSE,pflag=FALSE,l,in_ch,old_ch=' '; + + char defaultdir[BIGLTH],tmppass[PASSLTH+1]; + char cq_opts[BIGLTH]; + struct passwd *getpwnam(), *pwent; + + owneruid=getuid(); + srand((unsigned) time((long *) 0)); + strcpy(name,""); + strcpy(defaultdir,""); + strcpy(cq_opts,""); + + /* check conquer options */ + if (getenv(ENVIRON_OPTS)!=NULL) { + strncpy(cq_opts, getenv(ENVIRON_OPTS), BIGLTH); + } + if (cq_opts[0] != '\0') { + l = strlen(cq_opts); + for(i=0; i\n"); + exit(FAIL); + } + if (i\n"); + exit(FAIL); + } + if (i\n",cq_opts[i]); + exit(FAIL); + break; + } + } + } + + /* set the default data directory */ + if (defaultdir[0] == '\0') { + strcpy(defaultdir, DEFAULTDIR); + } + if (defaultdir[0] != '/') { + strcpy(cq_opts, defaultdir); + sprintf(defaultdir, "%s/%s", DEFAULTDIR, cq_opts); + } + + /* process the command line arguments */ +#ifdef CHECKUSER + while((i=getopt(argc,argv,"Ghpln:u:d:s"))!=EOF) switch(i){ +#else + while((i=getopt(argc,argv,"Ghpn:d:s"))!=EOF) switch(i){ +#endif + /* process the command line arguments */ + case 'h': /* execute help program*/ + initscr(); + savetty(); + noecho(); + crmode(); /* cbreak mode */ + signal(SIGINT,SIG_IGN); /* disable keyboard signals */ + signal(SIGQUIT,SIG_IGN); + help(); + endwin(); + putchar('\n'); + exit(SUCCESS); + case 'p': /* print the map*/ + pflag++; + break; + case 'G': + Gaudy = TRUE; + break; + case 'd': + if(optarg[0]!='/') { + sprintf(defaultdir, "%s/%s", DEFAULTDIR, optarg); + } else { + strcpy(defaultdir, optarg); + } + break; + case 'n': + strcpy(name, optarg); + break; +#ifdef CHECKUSER + case 'l': + checkuser_list = TRUE; + break; + case 'u': + checkuser_mod = TRUE; /* check for god later */ + checkuser_uid = owneruid; + if (strlen (optarg) > 0) + if (getpwnam(optarg)) + checkuser_uid = getpwnam(optarg)->pw_uid; +#endif + case 's': /*print the score*/ + sflag++; + break; + case '?': /* print out command line arguments */ +#ifdef CHECKUSER + fprintf(stderr,"Command line format: %s [-Ghpls -d DIR -nNAT -u USER]\n",argv[0]); + fprintf(stderr,"\t-u USER change nation username\n"); + fprintf(stderr,"\t-l list nation owners\n"); +#else + fprintf(stderr,"Command line format: %s [-Ghps -d DIR -nNAT]\n",argv[0]); +#endif + fprintf(stderr,"\t-n NAT play as nation NAT\n"); + fprintf(stderr,"\t-d DIR to use play different game\n"); + fprintf(stderr,"\t-G gaudily highlight nation in news\n"); + fprintf(stderr,"\t-h print help text\n"); + fprintf(stderr,"\t-p print a map\n"); + fprintf(stderr,"\t-s print scores\n"); + exit(SUCCESS); + }; + + /* now that we have parsed the args, we can go to the + * dir where the files are kept and do some work. + */ + if (chdir(defaultdir)) { + fprintf(stderr,"unable to change dir to %s\n",defaultdir); + exit(FAIL); + } + + readdata(); /* read data*/ + verifydata( __FILE__, __LINE__ ); /* verify data */ + + /* now print the scores */ + if(sflag){ + printscore(); + exit(SUCCESS); + } + + /* + * Set the real uid to the effective. This will avoid a + * number of problems involving file protection if the + * executable is setuid. + */ + if (getuid() != geteuid()) { /* we are running suid */ + (void) umask(MASK); /* nobody else can read files */ + (void) setuid (geteuid ()) ; + } + + fprintf(stderr,"conquer %s.%s: Copyright (c) 1988 by Edward M Barlow\n",VERSION,PATCHLEVEL); + + /* check for update in progress */ + sprintf(filename,"%sup",isonfile); + if(check_lock(filename,FALSE)==TRUE) { + fprintf(stderr,"Conquer is updating\n"); + fprintf(stderr,"Please try again later.\n"); + exit(FAIL); + } + + /* identify player and country represented */ + /* get nation name from command line or by asking user. + * if you fail give name of administrator of game + */ + if (name[0] == '\0') { + if (pflag != FALSE) + fprintf(stderr,"Display map for what nation: "); + else fprintf(stderr,"What nation would you like to be: "); + gets(name); + } +#ifdef OGOD + if(strcmp(name,"god")==0 || strcmp(name,"unowned")==0) { + if ((owneruid != (getpwnam(LOGIN))->pw_uid ) && + ((pwent=getpwnam(ntn[0].leader)) == NULL || + owneruid != pwent->pw_uid )) { + fprintf(stderr,"Sorry -- you can not login as god\n"); + fprintf(stderr,"you need to be logged in as %s",LOGIN); + if (strcmp(LOGIN, ntn[0].leader)!=0) { + fprintf(stderr," or %s",ntn[0].leader); + } + fprintf(stderr,"\n"); + exit(FAIL); + } + strcpy(name,"unowned"); + hilmode = HI_NONE; + } +#else + if(strcmp(name,"god")==0) strcpy(name,"unowned"); +#endif /* OGOD */ + +#ifdef CHECKUSER + if ((checkuser_mod) || (checkuser_list)) { + if ((owneruid == (getpwnam(LOGIN))->pw_uid) || + (owneruid == (getpwnam(ntn[0].leader))->pw_uid)) { + /* don't change - already set */ + } + else { + checkuser_mod = FALSE; + checkuser_list = FALSE; + fprintf (stderr, "Sorry -- only god may modify/list a nation's uid\n"); + exit(FAIL); + } + } +#else + fprintf (stderr,"CHECKUSER not on\n"); + exit (FAIL); +#endif + country=(-1); + for(i=0;i not found\n",name); + fprintf(stderr,"\nFor rules type "); + fprintf(stderr,"\nFor information on conquer please contact %s.",OWNER); + fprintf(stderr,"\nTo enter this campaign please send mail to %s", LOGIN); + if (strcmp(LOGIN, ntn[0].leader)!=0) { + fprintf(stderr," or %s",ntn[0].leader); + } + fprintf(stderr,".\n"); + return; + } else if(country==0 && !pflag) { + sprintf(filename,"%sadd",isonfile); + if(check_lock(filename,FALSE)==TRUE) { + fprintf(stderr,"A new player is being added.\n"); + fprintf(stderr,"Continue anyway? [y or n]"); + while(((i=getchar())!='y')&&(i!='n')) ; + if(i!='y') exit(FAIL); + } + } + curntn = &ntn[country]; + + /*get encrypted password*/ + fprintf(stderr,"\nWhat is your Nation's Password: "); + strncpy(tmppass,getpass(""),PASSLTH+1); + strncpy(passwd,crypt(tmppass,SALT),PASSLTH+1); + if((strncmp(passwd,curntn->passwd,PASSLTH)!=0) + &&(strncmp(passwd,ntn[0].passwd,PASSLTH)!=0)) { + fprintf(stderr,"\nError: Reenter your Nation's Password: "); + strncpy(tmppass,getpass(""),PASSLTH+1); + strncpy(passwd,crypt(tmppass,SALT),PASSLTH+1); + if((strncmp(passwd,curntn->passwd,PASSLTH)!=0) + &&(strncmp(passwd,ntn[0].passwd,PASSLTH)!=0)) { + fprintf(stderr,"\nSorry:"); + fprintf(stderr,"\nFor rules type "); + fprintf(stderr,"\nFor information on conquer please contact %s.", + OWNER); + fprintf(stderr,"\nTo enter this campaign please send mail to %s", + LOGIN); + if (strcmp(LOGIN, ntn[0].leader)!=0) { + fprintf(stderr," or %s",ntn[0].leader); + } + fprintf(stderr,".\n"); + exit(FAIL); + } + } + + /* now print the maps */ + if (pflag) { /* print a map of the game */ + fprintf(stderr,"\nFor convenience, this output is to stderr,\n"); + fprintf(stderr,"while the maps will be sent to stdout.\n\n"); + fprintf(stderr,"\tThe valid options are,\n"); + fprintf(stderr,"\t\t1) altitudes\n\t\t2) vegetations\n"); + fprintf(stderr,"\t\t3) nations\n"); + fprintf(stderr,"\t\t4) designations\n\n"); + fprintf(stderr,"\tWhat type of map? "); + scanf("%hd", &dismode); + fprintf(stderr,"\n"); + switch(dismode) { + case 1: + mapprep(); + printele(); + break; + case 2: + mapprep(); + printveg(); + break; + case 3: + mapprep(); + pr_ntns(); + break; + case 4: + mapprep(); + pr_desg(); + break; + default: + fprintf(stderr,"Invalid Choice\n"); + exit(FAIL); + break; + } + exit(SUCCESS); + } + +#ifdef CHECKUSER + /* New code by "spide" */ + if (checkuser_mod) + { + fprintf (stderr, "Nation: %s\n", curntn->name); + fprintf (stderr, " Current player = %s\n", + getpwuid(curntn->uid)->pw_name);; + curntn->uid = checkuser_uid; + fprintf (stderr, " New player = %s\n", + getpwuid(curntn->uid)->pw_name); + writedata(); + exit (SUCCESS); + } + if (checkuser_list) + { + for (i=0; i < NTOTAL; i++) + if (ntn[i].active != INACTIVE) + fprintf (stderr, "%3d %15s %d %-15s\n", + i, ntn[i].name, + ntn[i].uid, + getpwuid(ntn[i].uid)->pw_name); + exit (SUCCESS); + } + if ((curntn->uid != owneruid) && + (owneruid != (getpwnam(LOGIN))->pw_uid) && + (owneruid != (getpwnam(ntn[0].leader))->pw_uid) && + (curntn->uid != (getpwnam(LOGIN))->pw_uid)) + { + fprintf (stderr,"\nSorry -- you are not the owner of %s",curntn->name); + fprintf(stderr,"\nFor information on conquer please contact %s.",OWNER); + fprintf(stderr,"\nor send mail to %s", LOGIN); + fprintf(stderr,"\n"); + exit(FAIL); + } +#endif + + initscr(); /* SET UP THE SCREEN */ + /* check terminal size */ + if (COLS<80 || LINES<24) { + fprintf(stderr,"%s: terminal should be at least 80x24\n",argv[0]); + fprintf(stderr,"please try again with a different setup\n"); + beep(); + getch(); + bye(FALSE); + } + + copyscreen(); /* copyright screen */ + /* note the getch() later - everything between + now and then is non-interactive */ + init_hasseen(); /* now we know how big the screen is, + we can init that array! */ + + strcpy(fison,"START"); /* just in case you abort early */ + crmode(); /* cbreak mode */ + + /* check if user is super-user nation[0] */ + /* else setup cursor to capitol*/ + if((country==0)||(ismonst(ntn[country].active))) { + xcurs=MAPX/2-1; + ycurs=MAPY/2-1; + redraw=FULL; + /* create gods lock file but do not limit access */ + (void) aretheyon(); + } else { + if(curntn->active==INACTIVE) { + standout(); + mvaddstr(LINES-2,0,"Sorry, for some reason, your country no longer exists."); + mvprintw(LINES-1,0,"If there is a problem, please send mail to %s", LOGIN); + if (strcmp(LOGIN, ntn[0].leader)!=0) { + printw(" or %s",ntn[0].leader); + } + printw("."); + standend(); + beep(); + refresh(); + getch(); + bye(TRUE); + } + if(aretheyon()==TRUE) { + mvaddstr(LINES-2,0,"Sorry, country is already logged in."); + mvaddstr(LINES-1,0,"Please try again later."); + beep(); + refresh(); + getch(); + bye(FALSE); + } + execute(FALSE); +#ifdef TRADE + checktrade(); +#endif /* TRADE */ + xcurs = curntn->capx; + ycurs = curntn->capy; + } + xoffset = 0; + yoffset = 0; +#ifdef USERLOG + userlog = fopen (".userlog", "a"); + fprintf (userlog, "%3d %15s %30s %15s\n", + TURN, getpwuid(owneruid)->pw_name, defaultdir, curntn->name); + fclose (userlog); +#endif + centermap(); + updmove(curntn->race,country); + + /* open output for future printing*/ + sprintf(filename,"%s%d",exefile,country); + if ((fexe=fopen(filename,"a"))==NULL) { + beep(); + mvprintw(LINES-2,0,"error opening %s",filename); + refresh(); + getch(); + bye(TRUE); + } + + + signal(SIGINT,SIG_IGN); /* disable keyboard signals */ + signal(SIGQUIT,SIG_IGN); + signal(SIGHUP,hangup); /* must catch hangups */ + signal(SIGTERM,hangup); /* likewise for cheats!! */ + + noecho(); + prep(country,FALSE); /* initialize prep array */ + whatcansee(); /* what can they see */ + + /* initialize mail files */ + (void) sprintf(conqmail,"%s%d",msgfile,country); +#ifdef SYSMAIL + if (getenv("MAIL")==0) { + (void) sprintf(sysmail,"%s/%s",SPOOLDIR,getenv("USER")); + } else { + (void) strcpy(sysmail,getenv("MAIL")); + } +#endif /* SYSMAIL */ + mvaddstr(LINES-1, COLS-20, "PRESS ANY KEY"); + refresh(); + getch(); /* get response from copyscreen */ + + while(done==FALSE) { /*main while routine*/ + coffmap(); /* check if cursor is out of bounds*/ + check_mail(); /* check for new mail */ + in_ch = getch(); + /* get commands */ + if (in_ch=='!') { + parse(old_ch); + } else { + if (parse(in_ch)) old_ch=in_ch; + } + } + + if(country==0) writedata(); + else { + fprintf(fexe,"L_NGOLD\t%d \t%d \t%ld \t0 \t0 \t%s\n", + XNAGOLD ,country,curntn->tgold,"null"); + fprintf(fexe,"L_NMETAL\t%d \t%d \t%ld \t0 \t0 \t%s\n", + XNAMETAL ,country,curntn->metals,"null"); + fprintf(fexe,"L_NJWLS\t%d \t%d \t%ld \t0 \t0 \t%s\n", + XNARGOLD ,country,curntn->jewels,"null"); + } + bye(TRUE); /* done so quit */ +} + +/************************************************************************/ +/* MAKEBOTTOM() - make the bottom of the screen */ +/************************************************************************/ +void +makebottom() +{ + standend(); + move(LINES-4,0); + clrtoeol(); + mvprintw(LINES-3,0,"Conquer: %s.%s Turn %d",VERSION,PATCHLEVEL,TURN); + clrtoeol(); + mvaddstr(LINES-1,0," type ? for help"); + clrtoeol(); + mvaddstr(LINES-2,0," type Q to save & quit"); + clrtoeol(); + + if(country==0) { + mvaddstr(LINES-3,COLS-20,"nation...GOD"); + } else { + mvprintw(LINES-3,COLS-20,"nation...%s",curntn->name); + mvprintw(LINES-2,COLS-20,"treasury.%ld",curntn->tgold); + } + mvprintw(LINES-1,COLS-20,"%s of Year %d",PSEASON(TURN),YEAR(TURN)); + + /* mail status */ +#ifdef SYSMAIL + /* display mail information */ + if (sys_mail_status==NEW_MAIL) { + mvaddstr(LINES-3,COLS/2-6,"You have System Mail"); + } + if (conq_mail_status==NEW_MAIL) { + mvaddstr(LINES-2,COLS/2-6,"You have Conquer Mail"); + } +#else + /* display mail information */ + if (conq_mail_status==NEW_MAIL) { + mvaddstr(LINES-3,COLS/2-6,"You have Conquer Mail"); + } +#endif /* SYSMAIL */ +} + +/************************************************************************/ +/* PARSE() - interpret entered character */ +/* return TRUE if command is repeatable FALSE otherwise */ +/************************************************************************/ +int +parse(ch) + int ch; +{ + char name[LINELTH+1]; + char passwd[PASSLTH+1]; + struct passwd *getpwnam(), *pwent; +#ifdef DEBUG + void sect_info(); +#endif /* DEBUG */ + int ocountry; + + switch(ch) { + case EXT_CMD: /* extended command */ + ext_cmd( -1 ); + makebottom(); + refresh(); + curntn->tgold -= MOVECOST; + return(TRUE); + break; + case ' ': /* redraw the screen */ + centermap(); + redraw=FULL; + break; +#ifdef DEBUG + case '\t': /* debugging information for god and demi-god */ + if ((owneruid != (getpwnam(LOGIN))->pw_uid ) && + ((pwent=getpwnam(ntn[0].leader))==NULL || owneruid != pwent->pw_uid )) + break; + sect_info(); + break; +#endif /* DEBUG */ + case 'a': /*army report*/ + redraw=FULL; + armyrpt(0); + curntn->tgold -= MOVECOST; + break; + case '1': + case 'b': /*move south west*/ + pager=0; + selector=0; + if (XREAL > 0) xcurs--; + if (YREAL < MAPY - 1) ycurs++; + break; + case 'B': /*budget*/ + redraw=FULL; + budget(); + curntn->tgold -= MOVECOST; + break; + case 'c': /*change nation stats*/ + redraw=FULL; + change(); + curntn->tgold -= MOVECOST; + break; + case 'C': /*construct*/ + construct(); + makebottom(); + curntn->tgold -= MOVECOST; + break; + case 'd': /*change display*/ + newdisplay(); + break; + case 'D': /*draft*/ + draft(); + curntn->tgold -= MOVECOST; + makebottom(); + return(TRUE); + break; + case 'f': /*report on ships and load/unload*/ + redraw=PART; + curntn->tgold -= MOVECOST; + fleetrpt(); + break; + case 'F': /*go to next army*/ + navygoto(); + break; + case 'g': /*group report*/ + redraw=PART; + curntn->tgold -= MOVECOST; + armyrpt(1); + break; + case 'G': /*go to next army*/ + armygoto(); + break; + case 'H': /*scroll west*/ + pager=0; + selector=0; + if (XREAL > (COLS-22)/4) xcurs-=((COLS-22)/4); + else xcurs = -xoffset; + break; + case '4': + case 'h': /*move west*/ + pager=0; + selector=0; + if (XREAL > 0) xcurs--; + break; + case 'I': /*campaign information*/ + camp_info(); + redraw=FULL; + break; + case 'J': /*scroll down*/ + pager=0; + selector=0; + if (YREAL + (SCREEN_Y_SIZE)/2 < MAPY) + ycurs+=((SCREEN_Y_SIZE)/2); + else ycurs = MAPY - yoffset - 1; + break; + case '2': + case 'j': /*move down*/ + pager=0; + selector=0; + if (YREAL < MAPY - 1) ycurs++; + break; + case '8': + case 'k': /*move up*/ + pager=0; + selector=0; + if (YREAL > 0) ycurs--; + break; + case 'K': /*scroll up*/ + pager=0; + selector=0; + if (YREAL > (SCREEN_Y_SIZE)/2) ycurs-=((SCREEN_Y_SIZE)/2); + else ycurs = -yoffset; + break; + case '6': + case 'l': /*move east*/ + pager=0; + selector=0; + if (XREAL < MAPX - 1) xcurs++; + break; + case 'L': /*scroll east*/ + pager=0; + selector=0; + if (XREAL + (COLS-22)/4 < MAPX) xcurs+=((COLS-22)/4); + else xcurs = MAPX - xoffset - 1; + break; + case 'm': /*move selected item to new x,y */ + mymove(); + makebottom(); + curntn->tgold -= MOVECOST; + return(TRUE); + break; + case 'M': /*magic*/ + redraw=FULL; + curntn->tgold -= MOVECOST; + domagic(); + break; + case '3': + case 'n': /*move south-east*/ + pager=0; + selector=0; + if (YREAL < MAPY - 1) ycurs++; + if (XREAL < MAPX - 1) xcurs++; + break; + case 'N': /*read newspaper */ + redraw=PART; + curntn->tgold -= MOVECOST; + newspaper(); + break; + case 'o': /*pick (crsr up)*/ + selector-=2; + if(selector<0) { + selector=SCRARM*2-2; + pager--; + } + /*move to last army in current sector*/ + if (pager<0) { + pager=(units_in_sector(XREAL,YREAL,country)-1)/SCRARM; + selector=((units_in_sector(XREAL,YREAL,country)-1)%SCRARM)*2; + } + break; + case 'p': /*pick*/ + selector+=2; + if(selector>=SCRARM*2) { + selector=0; + pager+=1; + } + /*current selected unit is selector/2+SCRARM*pager*/ + if((selector/2)+(pager*SCRARM)>=units_in_sector(XREAL,YREAL,country)) { + pager=0; + selector=0; + } + break; + case 'P': /*production*/ + redraw=FULL; + curntn->tgold -= MOVECOST; + produce(); + break; + case 'Q': /*quit*/ + case 'q': /*quit*/ + done=TRUE; + break; + case 'r': /*redesignate*/ + redesignate(); + curntn->tgold -= MOVECOST; + makemap(); + makebottom(); + break; + /*list*/ + case 'R': /*Read Messages*/ + redraw=PART; + curntn->tgold -= MOVECOST; + rmessage(); + refresh(); + break; + case 's': /*score*/ + redraw=FULL; + curntn->tgold -= MOVECOST; + showscore(); + break; + case 'S': /*diplomacy screens*/ + diploscrn(); + curntn->tgold -= MOVECOST; + redraw=FULL; + break; + case 't': /*fleet loading*/ + loadfleet(); + curntn->tgold -= MOVECOST; + makeside(FALSE); + makebottom(); + return(TRUE); + break; +#ifdef TRADE + case 'T': /*go to commerce section*/ + trade(); + curntn->tgold -= MOVECOST; + redraw=FULL; + break; +#endif /* TRADE */ + case '9': + case 'u': /*move north-east*/ + pager=0; + selector=0; + if (YREAL > 0) ycurs--; + if (XREAL < MAPX - 1) xcurs++; + break; + case 'U': /* scroll north-east */ + pager=0; + selector=0; + if (XREAL + (COLS-22)/4 < MAPX) xcurs+=((COLS-22)/4); + else xcurs = MAPX - xoffset - 1; + if (YREAL > (SCREEN_Y_SIZE)/2) ycurs-=((SCREEN_Y_SIZE)/2); + else ycurs = -yoffset; + break; + case 'v': /* version credits */ + credits(); + redraw=FULL; + break; + case 'w': /* spell casting */ + wizardry(); + curntn->tgold -= MOVECOST; + return(TRUE); + break; + case 'W': /*message*/ + curntn->tgold -= MOVECOST; + wmessage(); + break; + case 'X': /*jump to capitol*/ + redraw = PART; + pager=0; + selector=0; + jump_to(TRUE); + break; + case 'x': /*jump to a location*/ + redraw=PART; + pager=0; + selector=0; + jump_to(FALSE); + makebottom(); + break; + case '7': + case 'y': /*move north-west*/ + pager=0; + selector=0; + if (YREAL > 0) ycurs--; + if (XREAL > 0) xcurs--; + break; + case 'Y': /* scroll north-west */ + pager=0; + selector=0; + if (XREAL < (COLS-22)/4) xcurs = -xoffset; + else xcurs-=((COLS-22)/4); + if (YREAL < (SCREEN_Y_SIZE)/2) ycurs = -yoffset; + else ycurs-=((SCREEN_Y_SIZE)/2); + break; + case 'Z': /*move civilians up to 2 spaces*/ + moveciv(); + makebottom(); + curntn->tgold -= MOVECOST; + break; + case 'z': /*login as new user */ +#ifdef OGOD + if ((owneruid != (getpwnam(LOGIN))->pw_uid ) && + ((pwent=getpwnam(ntn[0].leader))==NULL || owneruid != pwent->pw_uid )) break; +#endif + clear_bottom(0); + if(country != 0) { + fprintf(fexe,"L_NGOLD\t%d \t%d \t%ld \t0 \t0 \t%s\n", + XNAGOLD ,country,curntn->tgold,"null"); + fprintf(fexe,"L_NMETAL\t%d \t%d \t%ld \t0 \t0 \t%s\n", + XNAMETAL ,country,curntn->metals,"null"); + fprintf(fexe,"L_NJWLS\t%d \t%d \t%ld \t0 \t0 \t%s\n", + XNARGOLD ,country,curntn->jewels,"null"); + } else + mvaddstr(LINES-4,0,"SUPER-USER: YOUR CHANGES WILL NOT BE SAVED IF YOU DO THIS!!!"); + standout(); + mvaddstr(LINES-3,0,"Change login to:"); + standend(); + addch(' '); + refresh(); + + ocountry=country; + country=get_country(); + + /* check validity of country choice */ + if( country==(-1) || country>=NTOTAL + || ( !isactive(ntn[country].active) && country!=0 )) { + country=ocountry; + makebottom(); + break; + } + if(country==ocountry){ + errormsg("What? You are already logged into that nation."); + makebottom(); + break; + } + + /*get password*/ + clear_bottom(0); + mvaddstr(LINES-4,0,"What is your Nation's Password: "); + refresh(); + (void) get_pass(passwd); + strcpy(name,crypt(passwd,SALT)); + + if((strncmp(name,ntn[country].passwd,PASSLTH)!=0) + &&(strncmp(name,ntn[0].passwd,PASSLTH)!=0)){ + errormsg("Sorry, Password Invalid."); + country=ocountry; + makebottom(); + break; + } + if(aretheyon()==TRUE) { + errormsg("Sorry, that Nation is already logged in."); + country=ocountry; + makebottom(); + break; + } + + /* remove old lock file -- new one already made */ + sprintf(fison,"%s%d",isonfile,ocountry); + unlink(fison); + + fclose(fexe); + /* open output for future printing*/ + sprintf(fison,"%s%d",isonfile,country); + sprintf(name,"%s%d",exefile,country); + if ((fexe=fopen(name,"a"))==NULL) { + beep(); + fprintf(stderr,"error opening %s\n",name); + unlink(fison); + exit(FAIL); + } + curntn = &ntn[country]; + + fprintf(stderr,"\n"); + roads_this_turn=0; + terror_adj=0; + move(LINES-3,0); + readdata(); + execute(FALSE); + + (void) sprintf(conqmail,"%s%d",msgfile,country); + updmove(curntn->race,country); + /*go to that nations capitol*/ + if((country==0)||(!isntn(ntn[country].active))) { + xcurs=MAPX/2-1; + ycurs=MAPY/2-1; + } else { + xcurs=curntn->capx; + ycurs=curntn->capy; + } + xoffset = yoffset = 0; + centermap(); + redraw=FULL; + break; + case '?': /*display help screen*/ + redraw=PART; + help(); + break; + case ' ': /*ignore, and don't beep*/ + break; + default: + beep(); + break; + } + return(FALSE); +} + +#ifdef DEBUG +/************************************************************************/ +/* SECT_INFO() - display sector debugging information */ +/************************************************************************/ +void +sect_info() +{ + int i,j,acnt1=0,acnt2=0,ncnt1=0,ncnt2=0,x,y; + + /* erase prior information */ + for(i=0;i 0 && ntn[i].arm[j].xloc == XREAL + && ntn[i].arm[j].yloc == YREAL ) x++; + } + y = 0; + for (j=0;jcount) pager=0; + + /*first army found is #0*/ + /*show armies / navies in range pager*SCRARM to pager*SCRARM + SCRARM*/ + /*so if pager=0 show 0 to 5 (SCRARM), pager=2 show 10 to 15*/ + /*current selected unit is selector/2+4*pager*/ + + if(count>(SCRARM+(pager*SCRARM))) mvaddstr(LINES-14,COLS-20,"MORE..."); + + nfound=0; + for(armynum=0;armynum0)&&(P_AXLOC==XREAL)&&(P_AYLOC==YREAL)) { + if((nfound>=pager*SCRARM)&&(nfound'); + + if(P_ATYPE= NUMSTATUS ) + mvprintw((nfound%SCRARM)*2+1,COLS-20," member group %d",P_ASTAT-NUMSTATUS); + else + mvprintw((nfound%SCRARM)*2+1,COLS-20," mv:%d st:%s",P_AMOVE,*(soldname+P_ASTAT)); + standend(); + } + nfound++; + } + if((occ[XREAL][YREAL]!=0) + &&(occ[XREAL][YREAL]!=country) + &&((sptr->owner==country)||((P_ASOLD>0)&&(P_AXLOC<=XREAL+1) + &&(P_AXLOC>=XREAL-1)&&(P_AYLOC<=YREAL+1)&&(P_AYLOC>=YREAL-1)))) + found=1; + if((occ[XREAL][YREAL]!=0)&&(country==0)) found=1; + } + + if(nfound=pager*SCRARM)&&(nfound'); + + mvprintw((nfound%SCRARM)*2,COLS-20,"nvy %d: mv:%hd cw:%hd",nvynum,P_NMOVE,P_NCREW); + mvprintw((nfound%SCRARM)*2+1,COLS-20,"war:%2hd mer:%2hd gal:%2hd", + P_NWAR(N_LIGHT)+P_NWAR(N_MEDIUM)+P_NWAR(N_HEAVY), + P_NMER(N_LIGHT)+P_NMER(N_MEDIUM)+P_NMER(N_HEAVY), + P_NGAL(N_LIGHT)+P_NGAL(N_MEDIUM)+P_NGAL(N_HEAVY)); + standend(); + } + nfound++; + } + if((occ[XREAL][YREAL]!=0)&&(occ[XREAL][YREAL]!=country) + &&(P_NWSHP!=0||P_NMSHP!=0||P_NGSHP!=0)&&(P_NXLOC<=XREAL+1) + &&(P_NXLOC>=XREAL-1)&&(P_NYLOC<=YREAL+1)&&(P_NYLOC>=YREAL-1)) + nvyfnd=1; + if((occ[XREAL][YREAL]!=0)&&(country==0)) nvyfnd=1; + } + + count=0; + nfound2=nfound; + if((found==1)||(nvyfnd==1)) for(i=0;i0)){ + if(nfound2>SCRARM) nfound2=SCRARM; + if( ntn[i].arm[armynum].unittyp>=MINMONSTER ){ + mvprintw(nfound2*2+count,COLS-20,"%s: str=%d",*(unittype+(ntn[i].arm[armynum].unittyp%UTYPE)),ntn[i].arm[armynum].sold); + count++; + } else enemy += ntn[i].arm[armynum].sold; + } + } + if(enemy>0) { + if((magic(country,NINJA)==TRUE) || country == 0 ) + mvprintw(nfound2*2+count,COLS-20,"%s: %d men ",ntn[i].name,enemy); + else if(magic(i,THE_VOID)==TRUE) + mvprintw(nfound2*2+count,COLS-20,"%s: ?? men ",ntn[i].name); + else { + srand(i*17+enemy+TURN*3); + mvprintw(nfound2*2+count,COLS-20,"%s: %ld men ",ntn[i].name,(enemy*(rand()%60+70)/100)); + srand((unsigned) time((long *) 0)); + } + count++; + } + enemy=0; + for(nvynum=0;nvynum0) { + if((magic(country,NINJA)==TRUE) || country == 0 ) + mvprintw(nfound2*2+count,COLS-20,"%s: %d ships",ntn[i].name,enemy); + else if(magic(i,THE_VOID)==TRUE) + mvprintw(nfound2*2+count,COLS-20,"%s: ?? ships",ntn[i].name); + else { + srand(i*17+enemy+TURN*3); + mvprintw(nfound2*2+count,COLS-20,"%s: %ld ships",ntn[i].name,(enemy*(rand()%60+70)/100)); + srand((unsigned) time((long *) 0)); + } + count++; + } + } + } + + standend(); + mvprintw(LINES-13,COLS-20,"x is %d",XREAL); + clrtoeol(); + mvprintw(LINES-13,COLS-11,"y is %d",YREAL); + clrtoeol(); + + if((country!=0)&&(sptr->altitude==WATER)){ + for(y=LINES-12;y<=LINES-4;y++) { move(y,COLS-20); clrtoeol();} + mvaddstr(LINES-10,COLS-9,"WATER"); + } else { + if((country!=0)&&(country!=sptr->owner) + &&(magic(sptr->owner,THE_VOID)==TRUE)){ + for(y=LINES-11;y<=LINES-4;y++) { + move(y,COLS-20); + clrtoeol(); + } + } else { + + for(y=LINES-11;y<=LINES-10;y++) { + move(y,COLS-20); + clrtoeol(); + } + + if( sptr->designation!=DNODESIG ) standout(); + for(i=0;*(des+i)!='0';i++) + if(sptr->designation== *(des+i)){ + mvprintw(LINES-11,COLS-20,"%s",*(desname+i)); + clrtoeol(); + break; + } + standend(); + + if((sptr->owner==country)||(country==0)||(magic(country,NINJA)==TRUE)) + mvprintw(LINES-9,COLS-20,"people: %6d",sptr->people); + else { + srand(country*17+TURN*3+sptr->people); + mvprintw(LINES-9,COLS-20,"people: %6d",sptr->people*(rand()%60+70)/100); + srand((unsigned) time((long *) 0)); + } + clrtoeol(); + if((sptr->owner==country) + ||(sptr->owner==0) + ||(country == 0) + ||(!isntn(ntn[sptr->owner].active))){ + /* exotic trade goods */ + if( sptr->tradegood != TG_none && tg_ok(country,sptr) ) { + standout(); + mvprintw(LINES-7,COLS-20,"item: %s",tg_name[sptr->tradegood]); + clrtoeol(); + if( *(tg_stype+sptr->tradegood) == 'x' ) + mvaddstr(LINES-7,COLS-4,"ANY"); + else + mvprintw(LINES-7,COLS-4,"(%c)",*(tg_stype+sptr->tradegood)); + standend(); + } else { + mvaddstr(LINES-7,COLS-20,"item: none"); + clrtoeol(); + } + + if( sptr->jewels != 0 && tg_ok(country,sptr)) { + standout(); + mvprintw(LINES-6,COLS-20,"gold: %2d",sptr->jewels); + standend(); + } else mvaddstr(LINES-6,COLS-20,"gold: 0"); + if( sptr->metal != 0 && tg_ok(country,sptr)) { + standout(); + mvprintw(LINES-6,COLS-10,"metal: %2d",sptr->metal); + standend(); + } else mvaddstr(LINES-6,COLS-10,"metal: 0"); + + armbonus = fort_val(sptr); + if(armbonus>0) + mvprintw(LINES-5,COLS-20,"fortress: +%d%%",armbonus); + else move(LINES-5,COLS-20); + clrtoeol(); + } + else { + for(y=LINES-7;y<=LINES-5;y++) { + move(y,COLS-20); + clrtoeol(); + } + } + } + + standout(); + if((sptr->owner==0)||(ntn[sptr->owner].active==NPC_SAVAGE)) + mvaddstr(LINES-12,COLS-20,"unowned"); + else mvprintw(LINES-12,COLS-20,"owner: %s",ntn[sptr->owner].name); + standend(); + clrtoeol(); + + for(i=0;*(veg+i)!='0';i++) + if(sptr->vegetation==*(veg+i)) + mvprintw(LINES-11,COLS-10,"%s",*(vegname+i)); + + if(((i=tofood(sptr,country)) != 0) + &&((magic(sptr->owner,THE_VOID)!=TRUE) + ||(sptr->owner==country))){ + if(i>6) standout(); +#ifndef HPUX + if(i<10) mvprintw(LINES-11,COLS-1,"%d",i); + else mvprintw(LINES-11,COLS-2,"%d",i); +#else + if(i<10) mvprintw(LINES-11,COLS-2,"%d",i); + else mvprintw(LINES-11,COLS-3,"%d",i); +#endif /* HPUX */ + standend(); + } + + if(sptr->owner!=0) for(i=1;i<=8;i++) + if(ntn[sptr->owner].race==*(races+i)[0]){ + mvprintw(LINES-10,COLS-20,"%s",*(races+i)); + clrtoeol(); + } + + for(i=0;(*(ele+i) != '0');i++) + if( sptr->altitude == *(ele+i) ){ + mvprintw(LINES-10,COLS-10,"%s",*(elename+i)); + break; + } + } + + if(movecost[XREAL][YREAL]<0) + mvaddstr(LINES-8,COLS-20,"YOU CAN'T ENTER HERE"); + else + mvprintw(LINES-8,COLS-20,"move cost: %2d ",movecost[XREAL][YREAL]); +} + +/************************************************************************/ +/* ARETHEYON() - returns TRUE if 'country' is logged on, else FALSE */ +/************************************************************************/ +int +aretheyon() +{ + /* return file descriptor for lock file */ + sprintf(fison,"%s%d",isonfile,country); + return(check_lock(fison,TRUE)); +} + +/************************************************************************/ +/* COPYSCREEN() - print copyright notice to screen */ +/* THIS SUBROUTINE MAY NOT BE ALTERED, AND THE MESSAGE CONTAINED HEREIN */ +/* MUST BE SHOWN TO EACH AND EVERY PLAYER, EVERY TIME THEY LOG IN */ +/************************************************************************/ +void +copyscreen() +{ +#ifdef TIMELOG + FILE *timefp, *fopen(); + char string[LINELTH+1]; +#endif /* TIMELOG */ + + clear(); + standout(); + mvprintw(8,COLS/2-12,"Conquer %s.%s",VERSION,PATCHLEVEL); + standend(); + mvaddstr(10,COLS/2-21, "Copyright (c) 1988 by Edward M Barlow"); + mvaddstr(11,COLS/2-22,"Written Edward M Barlow and Adam Bryant"); + mvaddstr(12,COLS/2-12,"All Rights Reserved"); + mvaddstr(LINES-8,COLS/2-21,"This version is for personal use only"); + mvaddstr(LINES-6,COLS/2-32,"It is expressly forbidden port this software to any form of"); + mvaddstr(LINES-5,COLS/2-32,"Personal Computer or to redistribute this software without"); + mvaddstr(LINES-4,COLS/2-26,"the permission of Edward Barlow or Adam Bryant"); +#ifdef TIMELOG + if ((timefp=fopen(timefile,"r"))!=NULL) { + fgets(string, 50, timefp); + mvprintw(LINES-1, 0, "Last Update: %s", string); + fclose(timefp); + } +#endif /* TIMELOG */ + mvaddstr(LINES-1, COLS-20, "PLEASE WAIT"); + refresh(); +} + +/************************************************************************/ +/* BYE() - exit gracefully from curses */ +/************************************************************************/ +void +bye(dounlink) +int dounlink; /* TRUE if want to do unlink */ +{ + if( dounlink ) if(strcmp(fison,"START")!=0) unlink(fison); + clear(); + refresh(); + nocrmode(); + endwin(); + if (fexe!=NULL) fclose(fexe); + fprintf(stderr,"quit & save\n"); + exit(SUCCESS); +} + +/************************************************************************/ +/* CREDITS() - print credits notice to screen */ +/************************************************************************/ +void +credits() +{ + clear(); + mvprintw(4,0,"Conquer %s.%s",VERSION,PATCHLEVEL); + mvaddstr(5,0,"Copyright (c) 1988 by Edward M Barlow"); + mvaddstr(6,0,"written Edward M Barlow and Adam Bryant"); + mvaddstr(12,0,"I would like to thank the following for comments,"); + mvaddstr(13,0," patches, and playtesting:"); + mvaddstr(15,0,"Derick Hirasawa Brian Rauchfuss Joe E. Powell"); + mvaddstr(16,0,"Andrew Collins Joe Nolet"); + mvaddstr(17,0,"Kenneth Moyle Brian Bresnahan"); + mvaddstr(18,0,"Paul Davison Robert Deroy"); + mvaddstr(20,0,"Also thanks to the many playtesters at Boston University"); + mvaddstr(21,0,"and at the Communications Hex"); + errormsg(""); +} + +/************************************************************************/ +/* CAMP_INFO() - display information about current data file */ +/************************************************************************/ +void +camp_info() +{ + int mercs=0,solds=0,armynum,nvynum,nontn=0; + int numarm=0,numnvy=0,numlead=0; + + clear(); + standout(); + mvaddstr(2,COLS/2-16," CONQUER CAMPAIGN INFORMATION "); + mvaddstr(5,0,"World Information"); + mvaddstr(5,COLS-40,"Player Information"); + standend(); + + /* quick statistics */ + for(armynum=0;armynum +#include +#include +#include +#include +#include +#include "header.h" +#include "data.h" + +#define HALF 2 +#define LAND 3 + +int pwater; /* percent water in world (0-100) */ +extern short country; +extern int numleaders,remake; +char datadir[FILELTH]; +char **area_map; /*Value Map of Areas*/ +char **type; + +#define TOHILL(x,y) if( nmountains != 0 ) { \ +sct[(x)][(y)].altitude=HILL; \ +nmountains--; \ +} +#define TOMT(x,y) if( nmountains != 0 ) { \ +sct[(x)][(y)].altitude=MOUNTAIN; \ +nmountains--; \ +} +#define TOPEAK(x,y) if( nmountains != 0 ) { \ +sct[(x)][(y)].altitude=PEAK; \ +nmountains--; \ +} + +void +zeroworld() +{ + int i,armynum,nvynum; + + /* initialize all countries */ + for (i = 0; i < NTOTAL; i++) { + curntn = &ntn[i]; + for (armynum=0; armynum < MAXARM; armynum++) { + P_ASOLD = (long)0; + P_AXLOC = P_AYLOC = P_ATYPE = P_AMOVE = (unsigned char)0; + P_ASTAT = DEFEND; + } + for (nvynum=0; nvynum < MAXNAVY; nvynum++) { + P_NWSHP = P_NMSHP = P_NGSHP = (unsigned short)0; + P_NCREW = P_NPEOP = P_NARMY = (unsigned char)0; + P_NXLOC = P_NYLOC = P_NMOVE = (unsigned char)0; + } + curntn->active = INACTIVE; + curntn->repro = (char)0; + curntn->jewels = curntn->tgold = curntn->metals = 0L; + curntn->powers = curntn->tciv = curntn->tmil = curntn->score = 0L; + curntn->race = TUNKNOWN; + curntn->maxmove = 0; + curntn->spellpts = 0; + curntn->class = curntn->aplus = curntn->dplus = (short)0; + curntn->inflation = curntn->tsctrs = curntn->tships = (short)0; + } +} + +void +makeworld(rflag) +int rflag; /* TRUE if you wish to read in a map from mapfiles */ +{ + char passwd[PASSLTH+1],*getpass(); + char newstring[BIGLTH],tempc[BIGLTH]; + FILE *fopen(); + struct passwd *getpwnam(); + int i,valid; + + /* conquer makeworld information */ + newinit(); + sprintf(newstring, "Datadir: %s", datadir); + errorbar("World Generator", newstring); + + mvaddstr(0,COLS/2-9,"WELCOME TO CONQUER"); + mvaddstr(2,5,"Genesis begins... Your super user login will be 'god'."); + mvaddstr(3,0,"Non-player countries will be read in from the file 'nations',"); + mvaddstr(4,0,"and will have the same password as god, which you will soon set."); + mvaddstr(5,0," To add players after world creation: conqrun -a"); + if (strcmp(datadir,"[default]")!=0) + printw(" -d %s", datadir); + addch('.'); + + newerror("..Zero out extraneous files from prior games"); + /* flush out beginning input */ + sprintf(newstring,"rm -f %s* %s* %s* %s* %s %s 2> /dev/null", + exefile, msgfile, newsfile, isonfile, tradefile, timefile); + system(newstring); + newmsg("....Initialize the nation structures"); + zeroworld(); + newmsg("Initialization complete: And there was light...."); + sleep(1); + + valid=FALSE; + while(valid==FALSE) { /* password routine */ + mvaddstr(7,0,"Enter Super-User Password: "); + clrtoeol(); + refresh(); + i = get_pass(newstring); + if (i < 4) { + newerror("Password Too Short"); + continue; + } else if (i > PASSLTH) { + newerror("Password Too Long"); + continue; + } + mvaddstr(7,0,"Reenter Super-User Password: "); + clrtoeol(); + refresh(); + i = get_pass(passwd); + + if((i<4)||(i>PASSLTH)||(strncmp(passwd,newstring,PASSLTH)!=0)){ + newerror("Invalid Password Match"); + } else valid=TRUE; + } + strncpy(ntn[0].passwd,crypt(passwd,SALT),PASSLTH); + + /* finally ask for the secondary administrator */ + mvaddstr(7,0,"You may designate an other user as an alternate \"god\" for this world."); + mvaddstr(8,0,"Enter a System Login or \"god\" to have none. [Return for default]"); +#ifdef REMAKE + if (remake==FALSE) { + (void) strcpy(ntn[0].leader,"god"); + } else if (getpwnam(ntn[0].leader)==NULL) { + (void) strcpy(ntn[0].leader,"god"); + remake=FALSE; + } +#else + (void) strcpy(ntn[0].leader,"god"); +#endif /* REMAKE */ + while(TRUE) { + mvprintw(9,0,"What demi-god shall co-rule this world? [%s]: ",ntn[0].leader); + clrtoeol(); + refresh(); + get_nname( newstring ); + if ((strcmp(newstring,"GOD")==0) + ||(strcmp(newstring,"God")==0) + ||(strcmp(newstring,"god")==0)) { + newmsg("God will personally rule this world!!!"); + sleep(1); + (void) strcpy(ntn[0].leader,LOGIN); + mvaddstr(7,0,"Demi-God: [none]"); + clrtoeol(); + break; + } + if (strlen(newstring)==0) { +#ifdef REMAKE + if (remake==FALSE) { +#endif /*REMAKE*/ + newmsg("God will personally rule this world!!!"); + sleep(1); + (void) strcpy(ntn[0].leader,LOGIN); + mvaddstr(7,0,"Demi-God: [none]"); + clrtoeol(); + break; +#ifdef REMAKE + } else { + (void) sprintf(tempc,"The demi-god %s will continue to reign.",ntn[0].leader); + newmsg(tempc); + sleep(1); + mvprintw(7,0,"Demi-God: [%s]",ntn[0].leader); + clrtoeol(); + break; + } +#endif /*REMAKE*/ + } else if (strlen(newstring) <= LEADERLTH) { + if (getpwnam(newstring)!=NULL) { + (void) sprintf(tempc,"The demi-god %s may administrate this new world.",newstring); + newmsg(tempc); + (void) strncpy(ntn[0].leader,newstring,LEADERLTH); + mvprintw(7,0,"Demi-God: %s",ntn[0].leader); + clrtoeol(); + break; + } else { + (void) sprintf(tempc,"Their is no mortal named %s on this system.",newstring); + newerror(tempc); + } + } else { + newerror("That Name is Too long."); + } + } +#ifdef CHECKUSER + ntn[0].uid = getuid(); +#endif + mvaddstr(8,0,"Please Enter the Size of the World. [Divisible by 8 and > 23]"); + clrtoeol(); + while(TRUE) { + mvaddstr(9,0,"Enter number of X sectors: "); + clrtoeol(); + refresh(); + world.mapx = get_number(); + if(((world.mapx % 8) != 0 ) || (world.mapx<24)){ + newerror("Invalid X Value Entered"); + continue; + } + break; + } + while (TRUE) { + mvaddstr(10,0,"Enter number of Y sectors: "); + clrtoeol(); + refresh(); + world.mapy = get_number(); + if(((world.mapy % 8) != 0 ) || (world.mapy<24)){ + newerror("Invalid Y Value Entered"); + continue; + } + break; + } + mvprintw(8,0,"Map Size: %dx%d", (int)world.mapx, (int)world.mapy); + clrtoeol(); + move(10,0); + clrtoeol(); + + getspace(); /* malloc space for this world */ + + /* get amount of water to have in the world */ + while(TRUE) { + mvaddstr(9,0,"Enter percent water to have in world (0-100): "); + clrtoeol(); + refresh(); + pwater = get_number(); + if((pwater<0) || (pwater>100 )){ + newerror("Invalid Percentage Entered"); + continue; + } + break; + } + mvprintw(9,0,"Percentage Water: %d", pwater); + clrtoeol(); + refresh(); + + if( rflag==FALSE ) createworld(); + else readmap(); /* read map in from mapfiles */ + rawmaterials(); + + verifydata(__FILE__,__LINE__); + writedata(); + + /* initialize news file */ + sprintf(newstring,"%s0",newsfile); + if( (fm=fopen(newstring,"w"))!=(FILE *)NULL ) { + fprintf(fm,"1\tIMPORTANT WORLD NEWS\n"); + fprintf(fm,"5\tGLOBAL ANNOUNCEMENTS\n"); + fclose(fm); + } else { + sprintf(tempc,"error opening news file <%s>\n",newstring); + newerror(tempc); + } + newreset(); +} + +void +createworld() /* create world */ +{ + int i,j; + register int x,y; + int n; /*count used in string searches*/ + float avvalue; /*Average water tvalue of sectors*/ + int number[5]; /*Number of sectors with type=[0-4]*/ + int alloc = NUMAREAS * 2; /*Value Allocated*/ + char **tplace; /*Temp: to see if an area is placed*/ + int X, Y, chance; + int X1,Y1; + int X2,Y2; + int valid; + int rnd; + long nmountains; + + tplace = (char **) m2alloc(MAPX,MAPY,sizeof(char)); + area_map = (char **) m2alloc(MAPX,MAPY,sizeof(char)); + type = (char **) m2alloc(MAPX,MAPY,sizeof(char)); + + mvaddstr(11,0,"Creating world"); + mvaddstr(12,5,"In the beginning, the world was a set of bits ordered in"); + mvaddstr(13,0,"a random way. Then the conquer game administrator (hereafter"); + mvaddstr(14,0,"known as god) decreed 'conqrun -m'!!!"); + + /*initialize variables */ + newmsg("Day 1... And the variables were initialized."); + sleep(1); + move(11,0); + clrtoeol(); + move(12,0); + clrtoeol(); + move(13,0); + clrtoeol(); + move(14,0); + clrtoeol(); + avvalue = (((float) (100-pwater)/25.0)); /*Average water tvalue of sectors*/ + for(i=0;ialloc) { + /*have not allocated high enough so Allocate more */ + x = rand()%4; /*0 to 3*/ + if(number[x]>0) { + number[x] = number[x] - 1; + number[x+1] = number[x+1] + 1; + alloc = alloc + 1; + } + } + else { + /*have allocated too much Allocate less */ + x = (rand()%4) +1; /*1 to 4*/ + if(number[x]>0) { + number[x] = number[x] - 1; + number[x-1] = number[x-1] + 1; + alloc = alloc - 1; + } + } + } + + i=0; + while((number[4]>0)&&(i<500)) { + i++; + /*place a full land sector anywhere but on edge*/ + X = ((rand()%(MAXX-2))+1); /*1 to MAXX-2)*/ + Y = ((rand()%(MAXY-2))+1); /*1 to MAXY-2)*/ + if(tplace[X][Y] == 0) { + tplace[X][Y]=1; + area_map[X][Y]=4; + number[4]=number[4] - 1; + /*place surrounding sectors*/ + if(tplace[X+1][Y] == 0) { + rnd = rand()%100 + 1; /*1 to 100*/ + if((rnd<25) && (number[4]>0)) { + area_map[X+1][Y]=4; + number[4]=number[4]-1; + tplace[X+1][Y]=1; + } + if(rnd>25 && number[3]>0) { + area_map[X+1][Y]=3; + number[3]=number[3]-1; + tplace[X+1][Y]=1; + } + } + if(tplace[X-1][Y] == 0) { + rnd = rand()%100 + 1 ; /*(1 to 100)*/ + if(rnd<25 && number[4]>0) { + area_map[X-1][Y]=4; + number[4]=number[4]-1; + tplace[X-1][Y]=1; + } + if(rnd>25 && number[3]>0) { + area_map[X-1][Y]=3; + number[3]=number[3]-1; + tplace[X-1][Y]=1; + } + } + if(tplace[X][Y+1] == 0) { + rnd = rand()%100 + 1 ; /*(1 to 100)*/ + if(rnd<25 && number[4]>0) { + area_map[X][Y+1]=4; + number[4]=number[4]-1; + tplace[X][Y+1]=1; + } + if(rnd>25 && number[3]>0) { + area_map[X][Y+1]=3; + number[3]=number[3]-1; + tplace[X][Y+1]=1; + } + } + if(tplace[X][Y-1] == 0) { + rnd = rand()%100 + 1 ; /*(1 to 100)*/ + if(rnd<25 && number[4]>0) { + area_map[X][Y-1]=4; + number[4]=number[4]-1; + tplace[X][Y-1]=1; + } + if(rnd>25 && number[3]>0) { + area_map[X][Y-1]=3; + number[3]=number[3]-1; + tplace[X][Y-1]=1; + } + } + } + } + + /* place all other areas*/ + for(X=0;X0) { + area_map[X][Y]=rnd; + number[rnd]=number[rnd]-1; + tplace[X][Y]=1; + } + } + } + + /*ALL AREAS PLACED, NOW DETERMINE SECTOR TYPE + *fill in each area with sectors + * 1) water + * 2) water with major islands (25% land) + * 3) 50/50 water/land + * 4) land with major water (75% Land) + * 5) land + */ + for(Y=0;Y= (100-pwater)) { + type[X][Y] = LAND; + } + else type[X][Y] = WATER; + } + + chance=0; + for(X=0;X5 && nmountains> (NUMSECTS*avvalue)/3) { + X1 = rand()%(MAPX-8); /* Place one endpoint of range */ + Y1 = rand()%(MAPY-8); + X2 = (rand()%8) + X1; /* Place second endpoint */ + Y2 = (rand()%8) + Y1; + + valid = FALSE; + for(x=X1;x<=X2;x++){ + if(X1=0) + if( type[x][j] != LAND && rand()%2==0 ) { + valid = TRUE; + break; + } + } + if( valid==TRUE) continue; + + /*fill in mountain range: + y-2 y-1 y y+1 y+2 + %peak 0 10 20 10 0 + %mtn 10 40 80 40 10 + %hill 40 30 0 30 40 + */ + for(x=X1;x<=X2;x++) { + if(X180) { TOPEAK(x,y); + } else { TOMT(x,y) + } + } + + if((y < MAPY - 1) && type[x][y+1] == LAND) { + rnd=rand()%100+1; + if(rnd>90) { TOPEAK(x,y+1); + } else if(rnd>50) { TOMT(x,y+1); + } else if(rnd>20) { TOHILL(x,y+1); + } + } + if((y!=0) && type[x][y-1] == LAND ) { + rnd=rand()%100+1; + if(rnd>90) { TOPEAK(x,y-1); + } else if(rnd>50) { TOMT(x,y-1); + } else if(rnd>20) { TOHILL(x,y-1); + } + } + if((y>=2) + &&(type[x][y-2] == LAND )) { + rnd=rand()%100+1; + if(rnd>90) { TOMT(x,y-2); + } else if(rnd>50){ TOHILL(x,y-2); + } + } + if((y < MAPY - 2) + &&(type[x][y+2] == LAND )) { + rnd=rand()%100+1; + if(rnd>90) { TOMT(x,y+2); + } else if(rnd>50) { TOHILL(x,y+2); + } + } + } + } + + /*fill in random hills to work out,not to left of to water*/ + while(nmountains>0) { + x = rand()%(MAPX-1); + y = rand()%(MAPY-1); + if((type[x][y]==LAND)&&(type[x+1][y]==LAND)) + TOHILL(x,y); + } + + /*make sure no peak or mountain is next to water*/ + for(y=1;yMAPY/2+8)||(yMAPY/2+8)||(ydesignation=DNODESIG; + sptr->tradegood = TG_none; + + /* default setup of sector */ + sptr->owner = sptr->metal = sptr->jewels = sptr->fortress = 0; + sptr->people = 0l; + + if( is_habitable(x,y)==FALSE ) continue; + + /* exotic trade goods !!! */ + if(rand()%100 < TRADEPCT) { + valid = FALSE; + if((rand()%100 < METALPCT )||sptr->altitude==MOUNTAIN){ + getmetal( sptr ); /* metal */ + } else if((rand()%(100-METALPCT))vegetation!=FOREST) + &&(sptr->vegetation!=WOOD)) continue; + + valid = TRUE; + sptr->tradegood = i; + } + if(sptr->tradegood == TG_none) + newerror("??? DEBUG -tradegood==NONE"); + } + } + + mvaddstr(13,5,"All manner of creatures were created: big ones, little ones,"); + mvaddstr(14,0,"fat ones, skinny ones, orange ones, turquois ones, bright blue ones."); + mvaddstr(15,0,"WAIT!!! God has suddenly realized that smurfs were taking things"); + mvaddstr(16,0,"too far and stopped creating new ones to place everybody on the map..."); + newmsg("Day 5... God decreed that world would be populated"); + sleep(1); + move(14,0); + clrtoeol(); + move(15,0); + clrtoeol(); + move(16,0); + clrtoeol(); + populate(); + MERCMEN = ST_MMEN; + MERCATT = ST_MATT; + MERCDEF = ST_MDEF; + newmsg("Day 6... God, believing in long weekends, went and got smashed"); + sleep(1); + newmsg("Day 7... God rested (to get rid of that stupid hangover)"); + sleep(1); + sprintf(newstring," ...Log in via 'conquer -n god"); + if (strcmp(datadir,"[default]")!=0) { + strcat(newstring," -d "); + strcat(newstring,datadir); + } + strcat(newstring,"'"); + newerror(newstring); + sprintf(newstring," ...Players may be added via 'conqrun -a"); + if (strcmp(datadir,"[default]")!=0) { + strcat(newstring," -d "); + strcat(newstring,datadir); + } + strcat(newstring,"'"); + newerror(newstring); +} + +/*fill: subroutine to fill in a square edges with land or sea*/ +void +fill_edge(AX,AY) +{ +/* 1) water + * 2) water with major islands (25% land) + * 3) 50/50 water/land + * 4) land with major water (75% Land) + * 5) land + */ + register int i; + int edgearea, X0, Y0, X1, Y1, X2, Y2, X3, Y3, X4, Y4; + int area; + + X0=AX; + Y0=AY; + X1=X0-1; + Y1=Y0; + X2=X0+1; + Y2=Y0; + X3=X0; + Y3=Y0-1; + X4=X0; + Y4=Y0+1; + + /*NORMALIZE FOR EDGE OF WORLD*/ + if( X1 < 0 ) X1 = MAXX - 1; + if( X2 >= MAXX ) X2 = 0; + if( Y3 < 0 ) Y3 = MAXY - 1; + if( Y4 >= MAXY ) Y4 = 0; + + area=area_map[X0][Y0]; + /*fill in south*/ + edgearea=area_map[X4][Y4]; + if(area + edgearea > 6) for(i=0;i<8;i++) type[X0*8+i][Y0*8+7] = LAND; + else if((area + edgearea)>3) { + for(i=0;i<8;i++) + if(rand()%2 == 0) type[(X0*8)+i][Y0*8+7] = LAND; + else type[(X0*8)+i][Y0*8+7] = WATER; + } + else for(i=0;i<8;i++) type[(X0*8)+i][Y0*8+7] = WATER; + /*fill in east*/ + edgearea=area_map[X2][Y2]; + if(area + edgearea > 6) for(i=0;i<8;i++) type[X0*8+7][Y0*8+i] = LAND; + else if((area + edgearea)>3) { + for(i=0;i<8;i++) + if(rand()%2==0) type[X0*8+7][Y0*8+i] = LAND; + else type[X0*8+7][Y0*8+i] = WATER; + } + else for(i=0;i<8;i++) type[X0*8+7][Y0*8+i] = WATER; + /*fill in west*/ + edgearea=area_map[X1][Y1]; + if(area + edgearea > 6) for(i=0;i<=7;i++) type[X0*8][Y0*8+i] = LAND; + else if((area + edgearea)>3) { + for(i=0;i<8 ;i++) + if(rand()%2==0) type[X0*8][Y0*8+i] = LAND; + else type[X0*8][Y0*8+i] = WATER; + } + else for(i=0;i<8 ;i++) type[X0*8][Y0*8+i] = WATER; + /*fill in north*/ + edgearea=area_map[X3][Y3]; + if(area + edgearea > 6) for(i=0;i<8 ;i++) type[X0*8+i][Y0*8] = LAND; + else if((area + edgearea)>3) { + for(i=0;i<8 ;i++) + if(rand()%2==0) type[(X0*8)+i][Y0*8] = LAND; + else type[(X0*8)+i][Y0*8] = WATER; + } + else for(i=0;i<8 ;i++) type[(X0*8)+i][Y0*8] = WATER; +} + +/* ALLOCATE POPULATIONS OF THE WORLD*/ +void +populate() +{ + int i=0,x=0,y=0,j=0,xloc,yloc,xpos,ypos; + int nvynum=0,armynum=0,points,shipsize,temp,cnum; + short short1,short2; /*temporary short variables */ + short class; + + int loopcnt=0; + int pirarmy=0,barbarmy=0,nomadarmy=0,lizarmy=0; + short npirates=0,nbarbarians=0,nnomads=0,nlizards=0; + + FILE *fp, *fopen(); + char line[LINELTH+1],allign; + char fname[FILELTH]; + + /*set up god but dont place -- do not change leader name*/ + curntn = &ntn[0]; + strcpy(curntn->name,"unowned"); + curntn->race=GOD; + curntn->location=GOD; + curntn->powers=KNOWALL; /* so god can see the map */ + curntn->powers|=NINJA; /* so god can see exact unit numbers */ + curntn->mark='-'; + + for( country=1; countryactive )) { + newerror("THIS SHOULDNT HAPPEN"); + continue; + } + strcpy(curntn->passwd,ntn[0].passwd); + curntn->powers=0; + curntn->repro=0; + curntn->active=INACTIVE; + curntn->maxmove=0; + curntn->mark='-'; + } + + for( country=0; country=NTOTAL-4; country-- ) { + curntn = &ntn[country]; + if( country==NTOTAL-1 ) { + strncpy(curntn->name,"lizard",10); + strncpy(curntn->leader,"dragon",10); + curntn->active=NPC_LIZARD; + curntn->race=LIZARD; + } else if( country==NTOTAL-2 ) { + strcpy(curntn->name,"savages"); + strcpy(curntn->leader,"shaman"); + curntn->active=NPC_SAVAGE; + curntn->race=SAVAGE; + } else if( country==NTOTAL-3 ) { + strcpy(curntn->name,"nomad"); + strcpy(curntn->leader,"khan"); + curntn->active=NPC_NOMAD; + curntn->race=NOMAD; + } else if( country==NTOTAL-4 ) { + strcpy(curntn->name,"pirate"); + strcpy(curntn->leader,"captain"); + curntn->active=NPC_PIRATE; + curntn->race=PIRATE; + } + + curntn->aplus=0; + curntn->dplus=0; + curntn->powers=KNOWALL; + curntn->mark='*'; + curntn->maxmove=12; + curntn->repro=5; + + /* everybody hates monster nations */ + if(ismonst(ntn[country].active)) + for(i=1;i0 ) switch( rand()%4 ) { + case 0: if(npirates < MAXNAVY ) npirates++; + break; + case 1: if(nbarbarians < MAXARM ) nbarbarians++; + break; + case 2: if(nnomads < MAXARM ) nnomads++; + break; + case 3: if(rand()%3==0) { + if(nlizards < MAXARM/2 ) nlizards++; + } else if(nnomads < MAXARM ) nnomads++; + break; + } + mvprintw(13,0,"Placing %d lizard cities, %d pirates, %d savages, and %d nomad tribes",nlizards,npirates,nbarbarians,nnomads); + clrtoeol(); + refresh(); + + while((nlizards+npirates+nbarbarians+nnomads > 0 )&&(loopcnt++ <5000)) { + if( nlizards>0 ) { + for(country=1;country0 ) { + for(country=1;country0 ) { + for(country=1;country0 ) { + for(country=1;countryactive!=NPC_LIZARD)){ + if(rand()%2==0) { + x=(rand()%20); + y=(rand()%20); + } else { + x=(MAPX-(rand()%20)-1); + y=(MAPY-(rand()%20)-1); + } + if(rand()%2==0) x = rand()%MAPX; + else y = rand()%MAPY; + } else { + x = rand()%MAPX; + y = rand()%MAPY; + } + + if(sct[x][y].owner!=0) continue; + if(!is_habitable(x,y)) continue; + + sct[x][y].owner = country; + + /* now place people*/ + switch( curntn->active ) { + case NPC_LIZARD: + nlizards--; + sct[x][y].designation = DFORT; + sct[x][y].metal = 0; + sct[x][y].jewels = 8 + (i=rand()%30); + sct[x][y].tradegood = TG_platinum; + /* make fortificaton consistant with gold */ + sct[x][y].fortress = 6+i/5; + for(i=x-1;i<=x+1;i++) for(j=y-1;j<=y+1;j++) + if((ONMAP(i,j))&&(sct[i][j].altitude!=WATER)) + sct[i][j].owner = country; + P_AMOVE=0; + P_AXLOC=x; + P_AYLOC=y; + P_ASTAT=GARRISON; + P_ASOLD=750+100*(rand()%10); + P_ATYPE=defaultunit(country); + armynum++; + lizarmy++; + P_AMOVE=8; + P_AXLOC=x; + P_AYLOC=y; + P_ASTAT=ATTACK; + P_ASOLD=750+100*(rand()%10); + P_ATYPE=defaultunit(country); + lizarmy++; + break; + case NPC_PIRATE: + /* pirates must be on islands */ + temp=TRUE; + for(i=x-1;i<=x+1;i++) for(j=y-1;j<=y+1;j++) + if((ONMAP(i,j)) && ( x!=i || y!=j) + &&( sct[i][j].altitude!=WATER)) { + /* fifty percent chance of failure */ + /* for every non-land sector */ + if (sct[i][j].owner!=0 || rand()%2==0) + temp=FALSE; + } + + if(temp==FALSE) { + sct[x][y].owner = 0; + break; + } + + /* build the island */ + for(i=x-1;i<=x+1;i++) for(j=y-1;j<=y+1;j++) + if((ONMAP(i,j)) && ( x!=i || y!=j)) + if( sct[i][j].altitude!=WATER ) { + sct[i][j].altitude=WATER; + sct[i][j].vegetation=WATER; + sct[i][j].tradegood=TG_none; + sct[i][j].jewels=0; + sct[i][j].metal=0; + } + + npirates--; + sct[x][y].designation = DBASECAMP; + P_AMOVE=8; + P_AXLOC=x; + P_AYLOC=y; + P_ASTAT=ATTACK; + P_ASOLD=150+100*(rand()%3); + P_ATYPE=defaultunit(country); + pirarmy++; + P_NXLOC=x; + P_NYLOC=y; + P_NPEOP=0; + P_NARMY=MAXARM; + shipsize = N_LIGHT; + (void) NADD_WAR( rand()%5+2 ); + shipsize = N_MEDIUM; + (void) NADD_WAR( rand()%3+1 ); + shipsize = N_HEAVY; + (void) NADD_WAR( rand()%2 ); + P_NCREW=SHIPCREW; + nvynum++; + break; + case NPC_NOMAD: + nnomads--; + P_AXLOC=x; + P_AYLOC=y; + P_ASTAT=ATTACK; + P_ASOLD=100+100*(rand()%8); + P_ATYPE=defaultunit(country); + nomadarmy++; + break; + case NPC_SAVAGE: + nbarbarians--; + P_AXLOC=x; + P_AYLOC=y; + P_ASTAT=ATTACK; + P_ASOLD=100+100*(rand()%4); + P_ATYPE=defaultunit(country); + barbarmy++; + break; + } + } + + /* put random monsters around the world */ + for(country=1;country.",fname); + newerror(tempc); + } + } + +#ifdef NPC + mvaddstr(14,0,"Do you want NPC nations in this campaign? (y or n)"); + clrtoeol(); + refresh(); + while( ((i=getch()) != 'y')&&(i != 'n') ) ; + if( i!='y' ) { + newmsg("OK; no NPC nations used"); + sleep(1); + return; + } + if((fp=fopen(npcsfile,"r"))==NULL) { + mvaddstr(14,0,"Do you wish to use default NPC nations file (y or n)?"); + clrtoeol(); + refresh(); + while( ((i=getchar()) != 'y')&&(i != 'n') ) ; + if( i=='y'){ + sprintf(line,"%s/%s",DEFAULTDIR,npcsfile); + if ((fp=fopen(line,"r"))==NULL) { + newerror("Cannot read nation file... no NPCs added"); + return; + } else newmsg("OK; default nations used"); + } else { + newmsg("OK; no NPC nations used"); + sleep(1); + return; + } + } + + cnum=1; + mvaddstr(14,0,"ADDING NATIONS:"); + clrtoeol(); + refresh(); + xpos = 16; + ypos = 14; + while(fgets(line,LINELTH,fp)!=NULL) { + /*read and parse a new line*/ + if(line[0]!='#') { + xloc = yloc = -1; + sscanf(line,"%s %s %c %c %c %hd %hd %hd %ld %ld %d %hd %c %d %d %hd", + ntn[cnum].name,ntn[cnum].leader,&ntn[cnum].race, + &ntn[cnum].mark,&ntn[cnum].location,&ntn[cnum].aplus, + &ntn[cnum].dplus,&short1,&ntn[cnum].tgold, + &ntn[cnum].tmil,&points,&short2,&allign,&xloc,&yloc, + &class); + + country=cnum; + curntn = &ntn[country]; + curntn->class = (short)class; + sprintf(line," %s (%s)",curntn->name,*(Class+curntn->class)); + mvaddstr(ypos,xpos,line); + xpos += strlen(line); + if (xpos > COLS-20) { + xpos = 5; + ypos++; + } + refresh(); + if( cnum > MAPX*MAPY/NPC*(100-pwater)/100 ) { + sprintf(line,"World too small to add npc nation %d %s",cnum,curntn->name); + newerror(line); + continue; + } + if( isactive(ntn[cnum].active) ) { + sprintf(line,"Not enough available nations to add npc nation %d %s",cnum,curntn->name); + newerror(line); + continue; + } + curntn->maxmove = short1; + curntn->repro = short2; + if( allign == 'G' ) + curntn->active = PC_GOOD; + else if( allign == 'N' ) + curntn->active = PC_NEUTRAL; + else if( allign == 'E' ) + curntn->active = PC_EVIL; + else if( allign == 'g' ) + curntn->active = GOOD_6FREE; + else if( allign == 'n' ) + curntn->active = NEUTRAL_6FREE; + else if( allign == 'e' ) + curntn->active = EVIL_6FREE; + else if( allign == 'i' ) + curntn->active = ISOLATIONIST; + else { + sprintf(line,"invalid nation alignment (%c)"); + newerror(line); + newreset(); + abrt(); + } + strcpy(curntn->passwd,ntn[0].passwd); + + points -= doclass( class, FALSE ); + points -= startcost(); + if(points < 10 ) { + newerror("ERROR: nation doesn't have enough points left for 10000 civilians"); + newreset(); + abrt(); + } + curntn->tciv = 1000L * points; + + if(curntn->race==HUMAN){ + curntn->powers|=WARRIOR; + exenewmgk(WARRIOR); + } else if(curntn->race==DWARF){ + curntn->powers|=MINER; + exenewmgk(MINER); + } else if(curntn->race==ELF){ + curntn->powers|=THE_VOID; + exenewmgk(THE_VOID); + } else if(curntn->race==ORC){ + curntn->powers|=MI_MONST; + exenewmgk(MI_MONST); + } else { + curntn->powers|=WARRIOR; + exenewmgk(WARRIOR); + } + curntn->tfood= curntn->tciv * 3; + curntn->metals=10000L; + curntn->jewels=10000L; + if (cnum < NTOTAL) cnum++; + place(xloc,yloc); + att_setup(country); /* nation attributes */ + } + } + att_base(); /* get nation attributes */ + newmsg("All NPC nations placed"); + sleep(1); +#endif /* NPC */ +} diff --git a/original/man.pag b/original/man.pag new file mode 100644 index 0000000..96f1dcd --- /dev/null +++ b/original/man.pag @@ -0,0 +1,248 @@ +.TH CONQUER 6 +.SH NAME +conquer \- multiuser game of strategy +.SH SYNOPSIS +.B conquer +[-Ghps -nNAT -dDIR] +.sp +.B conqrun +[-max -dDIR ] +.SH DESCRIPTION +.I CONQUER +is a multi player computer game designed to run under the UNIX +operating system. In +.I CONQUER, +each player is the leader of a nation, +composed of people (humans, orcs, elves, dwarves), recourses, and land. +Rulers customize their nation at creation by chosing their race and by giving +their nation special powers (magic, combat factor, location, speed...) +and resources (civilians, troops, metal, gold...). Play involves building, +moving, and controlling armies and navies, diplomacy with other players, +and adjusting economic activity, which is primarily geared to the production +of gold for your treasury. Metal is needed, however to build ships & armies, +and food is needed to prevent revolts and keep people alive. +.SH ENVIRONMENT +Conquer now supports the environment variable CONQ_OPTS. This allows +the setting of default values for nation name and data directory. The +format is as follows: +.sp +.nf +setenv CONQ_OPTS "G,nation=MyLand,datadir=this_game" +.fi +.sp +If you then type just +.I conquer +to enter conquer, it will be equivalent to typing +.I conquer -G -n MyLand -d this_game. +.sp +The data directory and nation settings through the environment are +just defaults and maybe overridden by actually entering a different +option using '-d' or '-n'. [Note: to specify the default directory, +you may simply specify '-d ""'.] +.sp +The CONQ_OPTS environment variable combined with the use of shell +aliases should allow quick access for players in multiple campaigns. +.fi +.SH ON LINE HELP +For detailed information, run conquer with the -h option (see below). +.SH GAME OPTIONS +.B conquer +[-Ghps -nNAT -dDIR] +.IP \-h +display the conquer help files. +.IP "\-n NTN" +run as nation NTN +.IP "\-d DIR" +Run on data in directory DIR. Each game has its own data directory. The +default is set up at compile time and should only be used if only one game +is run. +.IP \-G +Gaudily highlight country name when reading the world news. +.IP \-p +Output a map of the world as visible by a nation. The map is sent +to the standard output and interactive prompting is done through standard +error. Therefore, the command: +.I conquer -p > foo +will create a file called foo containing the map. +.IP \-s +print out scores +.SH CONTROL OPTIONS +.B conqrun +[-max -dDIR ] +.IP \-a +add new player +.IP \-m +make a world +.IP \-x +execute program +.IP "\-d DIR " +run on data in directory DIR. If DIR does not begin with a '/' +character then the directory will be considered a sub directory of the +default directory. +.SH CURSOR MOVEMENT +.nf +h: move west +y: move north-west +k: move north +u: move north-east +l: move east +n: move south-east +j: move south +b: move south west +J: scroll south +K: scroll north +L: scroll east +H: scroll west +.fi +.SH COMMANDS +.TP +\'a\': +.B army report: +Gives army details & permits changing army status, merging 2 armies, +splitting armies, and disbanding armies. +.TP +\'c\': +.B administration: +Report on nation status and then change name, password, +add to combat bonus, or (if god) destroy a nation. +.TP +\'d\': +.B change display: +Change display mode. Numbers in gold screens... are +relative values of the materials. People are displayed +by hundreds as arabic digits and by thousands with roman +numerals. +.TP +\'f\': +.B fleet report: +Report on the status of your fleets. +.TP +\'g\': +.B group report: +Gives army details on current sector & permits changing army status, +merging 2 armies, splitting armies, and disbanding armies. +.TP +\'m\': +.B move unit: +move selected unit. The unit will stop when it runs out +of move points or runs into an army larger than it. +.TP +\'o\': +.B pick previous item: +allows you to select the previous army or navy in the +sector. Other commands will operate on that unit. +.TP +\'p\': +.B pick next item: +allows you to select the next army or navy in the +sector. Other commands will operate on that unit. +.TP +\'r\': +.B redesignate: +you can change habitable sectors you own to other +designations. Cities require 500+ people & Capitols +require cities. God can redesignate anything. +.TP +\'s\': +.B score: +print out a screen showing the scores. +.TP +\'t\': +.B transport: +unload or load a fleet with soldiers or civilians. +.TP +\'w\': +.B wizardry: +you may cast spell to allow flight, increase battle +performance or summon monsters if you have the ability. +.TP +\'?\': +.B help screen: +print out help text +.TP +\'B\': +.B budget : +ESTIMATE your nations budget statistics +.TP +\'C\': +.B construct: +If you have cash, you can build fortifications and +ships in your cities. Ships can only be built in cities +located on the water. +.TP +\'D\': +.B draft: +You may draft a quarter of the population of your +cities (those with more than a certain percent of +your population in it) if you have the gold. You +need 10 per man iron for this. +.TP +\'F\': +.B next fleet: +Move cursor to your next fleet +.TP +\'G\': +.B next army: +Move cursor to your next army +.TP +\'M\': +.B magic: +Prints your magic powers & offers you the option to +purchase more (cost doubles each power). Monster Power +gives you the chance to take over NPC nations. +.TP +\'N\': +.B newspaper: +Briefs you on world happenings. Note the News has 4 pages. +.TP +\'P\': +.B production: +ESTIMATE your nations production statistics +.TP +\'S\': +.B diplomacy: +Alloy you to see and alter your diplomatic status. +.TP +\'Q\': +.B quit: +Save your move and quit the game. Note there is no +means supported to quit without saving your moves. +.TP +\'R\': +.B read mail: +Read mail messages +.TP +\'W\': +.B write mail: +Write mail messages +.TP +\'Z\': +.B move people: +Civilians can move between two of your sectors at a cost +of 50 per civilian. Civilians move naturally in the update. +.SH FILES +/usr/games/lib/conquerdir/data default datafile for the running game +.SH MAILING LIST +I have established a mailing list to provide a location for discussion +of conquer, and for a place where I will bounce my ideas and test +patches off of people. If you would like to be added to the mailing +list, send mail to +.I conquer-news-request@bu-cs.bu.edu. +.SH BUGS +Probably lots, if you find any please mail them to either: +.br +.I adb@bu-cs.bu.edu +or +.I conquer-bugs@bu-cs.bu.edu. +.sp +1) Security is not as tight as it should be. People might be able to alter +the data of others nations... this is cheating and unacceptable. +.br +2) Naval battles may not work properly. +.br +3) NPC nations can not build navies or move over water. God should be +sure that all NPC nations have a minimum of 5 sectors to move to. +.br +4) Documentation is becoming too large. A better method for updating +it and reading it should be implemented. Some sections need sprucing +up. diff --git a/original/misc.c b/original/misc.c new file mode 100644 index 0000000..99fab34 --- /dev/null +++ b/original/misc.c @@ -0,0 +1,1903 @@ +/* Conquer: Copyright (c) 1988 by Edward M Barlow */ +#include +#include +#include +#include +#include +#ifdef CONQUER +#include +#include +#endif /*CONQUER*/ +#include "header.h" +#include "data.h" + +extern FILE *fnews; +extern short country,redraw; + +extern char *HVegcost, *OVegcost, *EVegcost, *DVegcost, *FVegcost; +extern char *HElecost, *OElecost, *EElecost, *DElecost, *FElecost; + +#ifdef SYSV +char *memset(); +#endif + +#ifdef CONQUER +int +move_file( from, to ) +register char *from; +register char *to; +{ + if( unlink( to ) < 0 ) { + fprintf( stderr, "unlink( %s ) failed \n", to ); + sleep( 2 ); + return( -1 ); + } + + if( link( from, to ) < 0 ) { + fprintf( stderr, "link( %s, %s ) failed \n", from, to ); + sleep( 2 ); + return( -1 ); + } + + if( unlink( from ) < 0 ) { + fprintf( stderr, "unlink( %s ) failed \n", from ); + sleep( 2 ); + return( -1 ); + } + + return( 0 ); +} /* move_file() */ +#endif /* CONQUER */ + +/* returns integer input greater than zero or */ +/* -1 for no input. */ +long +get_number() +{ + long sum=0; + char ch; + int done=FALSE,count=0,xpos,ypos; + /* this routine totally redone to allow deleting */ + while(!done) { + ch=getch(); + if(isdigit(ch) && count<12) { + /* only print numbers to the screen */ + addch(ch); + refresh(); + sum *= 10L; + count++; + sum += (long)(ch-'0'); + } else if ((ch=='\b' || ch=='\177')&&(count)) { + /* only delete what was printed */ + getyx(stdscr,ypos,xpos); + move(ypos,--xpos); + addch(' '); + move(ypos,xpos); + refresh(); + sum /= 10L; + count--; + } else if((ch=='\n')||(ch=='\r')) { + done=TRUE; + } + } + if (count==0) { + return(-1); + } + return( sum ); +} + +#define INFINITE 1000 + +int bx; /* destination 'x' coordinate */ +int by; /* destination 'y' coordinate */ +int moving_country; /* country that is moving */ + +#define MAX_MOVE_UNITS 0x7f +unsigned char **history_reachp; +int level; + +/* + * land_2reachp() + */ + +int +land_2reachp( ax, ay, move_points ) +int ax; +int ay; +int move_points; +{ + register int i = 0; + int delta_x, delta_y; + int x_abs_delta, y_abs_delta; + int own; + int dx[ 8 ]; + int dy[ 8 ]; + + delta_x = bx - ax; + delta_y = by - ay; + + /* Have we got where we are going? */ + if( delta_x == 0 && delta_y == 0 ) { + return( 1 ); + } + + /* Any move points left? (optimization) */ + if( move_points == 0 ) { + return( 0 ); + } + + x_abs_delta = (delta_x < 0) ? -delta_x : delta_x; + y_abs_delta = (delta_y < 0) ? -delta_y : delta_y; + + /* couldn't reach if all moves cost 1 (optimization) */ + if( max( x_abs_delta, y_abs_delta ) > move_points ) { + return( 0 ); + } + + { + register int inc_x; + register int inc_y; + + inc_x = (delta_x < 0 ) ? -1 : 1; + inc_y = (delta_y < 0 ) ? -1 : 1; + + /*I HAVE CHANGED THIS CODE FROM THE ORIGINAL TO OPTIMIZE IT*/ + /*I think it should work well*/ + if( y_abs_delta == 0) { + /* try 'x' movements first */ + dx[i] = inc_x; dy[i++] = 0; + dx[i] = inc_x; dy[i++] = inc_y; + dx[i] = inc_x; dy[i++] = -inc_y; + dx[i] = 0; dy[i++] = inc_y; + dx[i] = 0; dy[i++] = -inc_y; + dx[i] = -inc_x; dy[i++] = inc_y; + dx[i] = -inc_x; dy[i++] = 0; + dx[i] = -inc_x; dy[i++] = -inc_y; + } else if( x_abs_delta == 0 ) { + /* try 'y' movements first */ + dx[i] = 0; dy[i++] = inc_y; + dx[i] = inc_x; dy[i++] = inc_y; + dx[i] = -inc_x; dy[i++] = inc_y; + dx[i] = inc_x; dy[i++] = 0; + dx[i] = -inc_x; dy[i++] = 0; + dx[i] = inc_x; dy[i++] = -inc_y; + dx[i] = 0; dy[i++] = -inc_y; + dx[i] = -inc_x; dy[i++] = -inc_y; + } else { /* x_abs_delta != 0, 0 != y_abs_delta */ + /* try diagonal movements first */ + dx[i] = inc_x; dy[i++] = inc_y; + + dx[i] = 0; dy[i++] = inc_y; + dx[i] = inc_x; dy[i++] = 0; + + dx[i] = -inc_x; dy[i++] = inc_y; + dx[i] = inc_x; dy[i++] = -inc_y; + + dx[i] = -inc_x; dy[i++] = 0; + dx[i] = 0; dy[i++] = -inc_y; + + dx[i] = -inc_x; dy[i++] = -inc_y; + } /* if */ + } /* block */ + + { + register int x, y; + register int new_mp; + + for( i = 0; i < 8; i++ ) { + if( (x = ax + dx[i]) < 0 || x >= MAPX ) + continue; + if( (y = ay + dy[i]) < 0 || y >= MAPY ) + continue; + + if ( movecost[ x ][ y ] < 0 ) /* just in case */ + continue; + if( sct[x][y].altitude == PEAK) + continue; + if( sct[x][y].altitude == WATER) + continue; + + new_mp = move_points - movecost[ x ][ y ]; + if( new_mp < 0 ) + continue; + + /* + * If we have been to this sector before + * in fewer move points this path is not + * going to do any better. + */ + if( history_reachp[x][y] >= new_mp ) { + continue; + } + history_reachp[x][y] = new_mp; + + /* + * Test for a hostile army + */ + /* BUG: should engage if army is hostile but does not own sector */ + /* BUG: take into account THE_VOID, HIDDEN, and NINJA */ + if( (own = sct[x][y].owner) > 0 && + ntn[own].dstatus[moving_country] >= WAR && + x != bx && y != by && + solds_in_sector( x, y, own ) > 0 ) { + continue; /* at war with the owner, may not pass */ + } + + if( own > 0 && + ntn[moving_country].dstatus[own] < WAR && + ntn[own].dstatus[moving_country] > ALLIED && + ntn[own].dstatus[moving_country] < WAR) { + /* not at war with owner & owner is neutral,no passing*/ + continue; + } + + level++; + if( land_2reachp( x, y, new_mp ) ) { + level--; + return( 1 ); + } /* if */ + level--; + } /* for */ + } /* block */ + return( 0 ); +} /* land_2reachp() */ + +/* + * land_reachp() + */ +#ifdef ADMIN +int +land_reachp( ax, ay, gx, gy, move_points, movee ) +int ax; +int ay; +int gx; +int gy; +int move_points; +int movee; +{ + int result; + + if( move_points >= MAX_MOVE_UNITS ) { + fprintf( stderr, "land_reachp(): move_points = %d\n", + move_points ); + + abrt(); + } + + /* Are we starting or ending in the water or on a peak? */ + if( sct[ax][ay].altitude == WATER || sct[ax][ay].altitude == PEAK ) + return( 0 ); + if( sct[gx][gy].altitude == WATER || sct[gx][gy].altitude == PEAK ) + return( 0 ); + + history_reachp = (unsigned char **) m2alloc(MAPX,MAPY,sizeof(char)); +#ifdef BSD + bzero((char *) *history_reachp,MAPX*MAPY); +#else + memset((char *) *history_reachp, 0, MAPX*MAPY ); +#endif + + history_reachp[ax][ay] = move_points; + + bx = gx; + by = gy; + moving_country = movee; + + level = 1; + result = land_2reachp( ax, ay, move_points ); + free(history_reachp); + return( result ); +} /* land_reachp() */ +#endif /* ADMIN */ +#ifdef ADMIN +/* + * water_2reachp() + */ + +int +water_2reachp( ax, ay, move_points ) +int ax; +int ay; +int move_points; +{ + register int i = 0; + int delta_x; + int delta_y; + int dx[ 8 ]; + int dy[ 8 ]; + + /* this path uses too many move units */ + if( move_points < 0 ) + return( 0 ); + + /* + * If we have been to this sector before in fewer move points + * this path is not going to do any better. + */ + if( history_reachp[ ax ][ ay ] <= move_points ) + return( 0 ); + + history_reachp[ ax ][ ay ] = move_points; + + delta_x = ax - bx; + delta_y = ay - by; + + /* Have we got where we are going? */ + if( delta_x == 0 && delta_y == 0 ) + return( 1 ); + + /* Have we run into ground, but not reached our destination? */ + if( sct[ax][ay].altitude != WATER ) + return( 0 ); + + /* Any move points left? (optimization) */ + if( move_points == 0 ) + return( 0 ); + + /* couldn't reach if all moves cost 1 (optimization) */ + if( max( abs( delta_x ), abs( delta_y ) ) > move_points ) + return( 0 ); + + /* BUG: test for an enemy navy */ + + { + register int inc_x; + register int inc_y; + + inc_x = (delta_x < 0 ) ? -1 : (delta_x > 0) ? 1 : 0; + inc_y = (delta_y < 0 ) ? -1 : (delta_y > 0) ? 1 : 0; + + if( abs(delta_x) > abs(delta_y) ) { + /* try 'x' movements first */ + dx[i] = inc_x; dy[i++] = 0; + dx[i] = inc_x; dy[i++] = inc_y; + dx[i] = inc_x; dy[i++] = -inc_y; + dx[i] = 0; dy[i++] = inc_y; + dx[i] = 0; dy[i++] = -inc_y; + dx[i] = -inc_x; dy[i++] = inc_y; + dx[i] = -inc_x; dy[i++] = 0; + dx[i] = -inc_x; dy[i++] = -inc_y; + } else { /* abs(delta_x) < abs(delta_y) */ + /* try 'y' movements first */ + dx[i] = 0; dy[i++] = inc_y; + dx[i] = inc_x; dy[i++] = inc_y; + dx[i] = -inc_x; dy[i++] = inc_y; + dx[i] = inc_x; dy[i++] = 0; + dx[i] = -inc_x; dy[i++] = 0; + dx[i] = inc_x; dy[i++] = -inc_y; + dx[i] = 0; dy[i++] = -inc_y; + dx[i] = -inc_x; dy[i++] = -inc_y; + } /* if */ + } /* block */ + + { + register int x, y; + register int new_mp; + + for( i = 0; i < 8; i++ ) { + if( (x = ax + dx[i]) < 0 || x >= MAPX ) + continue; + if( (y = ay + dy[i]) < 0 || y >= MAPY ) + continue; + + new_mp = move_points - 1; + if( new_mp < 0 ) + continue; + + if( water_2reachp( x, y, new_mp ) ) + return( 1 ); + } /* for */ + } /* block */ + + return( 0 ); +} /* water_2reachp() */ +#endif /* ADMIN */ +#ifdef XYZ /* XYZ never is defined */ +/* + * water_reachp() + */ + +int +water_reachp( ax, ay, gx, gy, move_points, movee ) +int ax; +int ay; +int gx; +int gy; +int move_points; +int movee; +{ + if( move_points >= MAX_MOVE_UNITS ) { + fprintf( stderr, "water_reachp(): move_points = %d\n", + move_points ); + + abrt(); + } + +#ifdef SYSV + memset(history_reachp, MAX_MOVE_UNITS, MAPX*MAPY*sizeof(history_reachp)); +#else + { register int i,j; + for (i=0; i < MAPX ; i++) + for (j=0; j < MAPY ; j++ ) + history_reachp [i] [j] = MAX_MOVE_UNITS ; + }/* eof memset replacement block */ +#endif + + history_reachp[ ax ][ ay ] = 0; + + bx = gx; + by = gy; + moving_country = movee; + + return( water_2reachp( ax, ay, move_points ) ); +} /* water_reachp() */ +#endif /* 0 */ + +/* + * solds_in_sector() + */ + +long +solds_in_sector( x, y, nation ) +int x; +int y; +int nation; +{ + register struct s_nation *nptr = &ntn[nation]; + register int j; + long total = 0; + + for( j = 0; j < MAXARM; j++ ) { + if( nptr->arm[j].sold == 0 ) + continue; + + if( nptr->arm[j].xloc == x && nptr->arm[j].yloc == y ) + total += nptr->arm[j].sold; + } + + return( total ); +} /* solds_in_sector() */ +#ifdef ADMIN + +/* score_one() */ +struct wght { + int sectors; + int civilians; + int soldiers; + int gold; + int jewels; + int metal; + int magics; + int ships; +} weights[] = { +/* Per 2 1000 1000 100K 100K 100K Magic 10 */ +/* Races Sector People Soldiers Gold Jewels Iron Power Ship */ +/* NPC */ { 2, 1, 0, 0, 1, 1, 1, 0 }, +/* kingdom */ { 2, 1, 2, 3, 0, 0, 0, 0 }, +/* empire */ { 3, 0, 0, 1, 1, 0, 0, 0 }, +/* wizard */ { 0, 2, 1, 0, 3, 5, 7, 0 }, +/* theocracy */ { 2, 1, 0, 0, 3, 0, 3, 0 }, +/* pirate */ { 0, 0, 5, 0, 10, 10, 1, 5 }, +/* trader */ { 2, 1, 0, 0, 1, 1, 1, 8 }, +/* warlord */ { 2, 1, 2, 0, 1, 1, 1, 0 }, +/* demon */ { 2, 0, 1, 0, 1, 0, 5, 0 }, +/* dragon */ { 0, 0, 0, 10, 20, 0, 0, 0 }, +/* shadow */ { 2, 0, 0, 0, 0, 5, 0, 0 }, +/* miner */ { 0, 0, 5, 0, 10, 10, 1, 5 }, +}; + +long +score_one( nation ) +int nation; +{ + struct s_nation *nptr = &ntn[ nation ]; + long total = 0; + int bonus; + struct wght *wght = &weights[ nptr->class ]; + + total += wght->sectors * nptr->tsctrs / 2L; + total += wght->civilians * nptr->tciv / 1000L; + total += wght->soldiers * nptr->tmil / 1000L; + if(nptr->tgold > 0 ) total += wght->gold * (nptr->tgold / 100000L); + total += wght->jewels * nptr->jewels / 100000L; + total += wght->metal * nptr->metals / 100000L; + total += wght->magics * num_powers(nation,M_MIL); + total += wght->magics * num_powers(nation,M_CIV); + total += wght->magics * num_powers(nation,M_MGK); + total += wght->ships * nptr->tships / 10L; + switch( nptr->class ) { + case C_KING: + bonus=(nptr->popularity+nptr->prestige-nptr->poverty); + break; + case C_EMPEROR: + bonus=(nptr->power+nptr->prestige-nptr->poverty); + break; + case C_WIZARD: + bonus=(nptr->knowledge+nptr->power-50); + break; + case C_PRIEST: + bonus=(nptr->wealth+nptr->terror-nptr->poverty); + break; + case C_PIRATE: + bonus=(nptr->reputation+nptr->wealth-50); + break; + case C_TRADER: + bonus=(nptr->wealth+nptr->prestige-nptr->tax_rate*5); + break; + case C_WARLORD: + bonus=(nptr->reputation+nptr->prestige-50); + break; + case C_DEMON : + bonus=(nptr->knowledge+nptr->terror-50); + break; + case C_DRAGON: + bonus=(nptr->wealth+nptr->terror-50); + break; + case C_SHADOW: + bonus=(nptr->power+nptr->terror-50); + break; + default: bonus=0; + } + total += bonus/10; + return( total ); +} /* score_one() */ +#endif /* ADMIN */ +/* + * print_accum() + */ + + /* max number of print_accum() calls in one printf() */ +#define MAX_BUFFER 4 +#define BUFFER_SIZE 20 + +/* is_habitable() - returns TRUE/FALSE if habitable */ +int +is_habitable( x, y ) +int x; +int y; +{ + char temp; + + if(( (temp=sct[x][y].altitude)==WATER )||( temp==PEAK )) return(FALSE); + + if(((temp=sct[x][y].vegetation)==BARREN ) + || ( temp==LT_VEG ) + || ( temp==GOOD ) + || ( temp==WOOD ) + || ( temp==FOREST )) return( TRUE ); + + return( FALSE ); +} + +#ifdef CONQUER +int +units_in_sector(x,y,nation) +int x; +int y; +{ + int count=0, armynum, nvynum; + struct s_nation *nptr = curntn; + + curntn = &ntn[nation]; + for(armynum=0;armynum0)&&(P_AXLOC==x)&&(P_AYLOC==y)) count++; + for(nvynum=0;nvynumvegetation != *(veg+i) ) i++; + foodvalue = *(vegfood+i) - '0'; + if( cntry != 0 ) { + if(foodvalue == 0) { +#ifdef DERVDESG + if ((magic(cntry,DERVISH)||magic(cntry,DESTROYER)) + &&(sptr->vegetation==DESERT || sptr->vegetation==ICE)) + return(6); +#endif /* DERVDESG */ + return( 0 ); + } + if(ntn[cntry].race == ELF){ + if(sptr->vegetation == FOREST) foodvalue+=3; + else if(sptr->vegetation == BARREN) foodvalue--; + } + } + if(( sptr->tradegood <= END_EATRATE ) + &&( sptr->tradegood > END_COMMUNICATION )) + foodvalue += *(tg_value+sptr->tradegood) - '0'; + return( foodvalue ); +} + +/*jewel cost for civilian power = Base * 2**( #mgk/2 + #civ + #mil/2 ) */ +/*race magical civilian military */ +/* elves - 50K 50K 50K */ +/* dwarves - 80K 40K 40K */ +/* humans - 100K 25K 50K */ +/* orcs - 100K 50K 25K */ + +/* returns cost of magic power - returns -1 if invalid */ +long +getmgkcost(type,nation) +int type, nation; +{ + int i; + long cost; + long base=BASEMAGIC; + int npowers; + switch(type) { + case M_MGK: + if(ntn[nation].race==DWARF) base=DWFMAGIC; + else if(ntn[nation].race==HUMAN) base=HUMMAGIC; + else if(ntn[nation].race==ORC) base=ORCMAGIC; + npowers=num_powers(nation,M_CIV)+num_powers(nation,M_MIL)+1 + +2*num_powers(nation,M_MGK); + npowers/=2; + break; + case M_CIV: + if(ntn[nation].race==DWARF) base=DWFCIVIL; + else if(ntn[nation].race==HUMAN) base=HUMCIVIL; + else if(ntn[nation].race==ORC) base=ORCCIVIL; + npowers=num_powers(nation,M_MGK)+num_powers(nation,M_MIL)+1 + +2*num_powers(nation,M_CIV); + npowers/=2; + break; + case M_MIL: + if(ntn[nation].race==DWARF) base=DWFMILIT; + else if(ntn[nation].race==ORC) base=ORCMILIT; + npowers=num_powers(nation,M_CIV)+num_powers(nation,M_MGK)+1 + +2*num_powers(nation,M_MIL); + npowers/=2; + break; + default: + return(-1); + } + cost = base; + for (i=1; i BIG) + return(BIG/2L); + } + return(cost); +} + +int +todigit(character) +register int character; +{ + if( character >= '0' && character <= '9' ) + return( character - '0' ); + return( -1 ); +} + +/* set up occ[][] for country. + * if leader==true, only for leader sectors plus ntn.communicatins range + * if leader==(-1), do not include ships on the sector search + */ +void +prep(nation,leader) +int nation,leader; +{ + short armynum,nvynum; + int save,i,j,x,y,start,end,com; + + /*set occ to 0*/ + for(i=0;i=MINMONSTER) + ||(P_ASOLD<=0)) continue; + i=P_AXLOC; + j=P_AYLOC; + com = P_NTNCOM; /* do communications radius */ + for(x=i-com;x<=i+com;x++) + for(y=j-com;y<=j+com;y++) + if(ONMAP(x,y)) occ[x][y]=nation; + } else if((P_ASOLD>0)&&(P_ASTAT!=SCOUT)){ + i=P_AXLOC; + j=P_AYLOC; + if((occ[i][j]== 0)||(occ[i][j]== nation)) + occ[i][j]= nation; + else occ[i][j]= NTOTAL; + } + } + if( leader==FALSE ) for(nvynum=0;nvynum0) { + /* first disband PDEPLETE% of the military */ + if (P_ATYPEactive)) { + if (mailopen(nation)!=(-1)) { + fprintf(fm,"Message to %s from Conquer\n\n",curntn->name); + fprintf(fm,"\tYour %s Army %d disperses into the population\n",*(unittype+(P_ATYPE%UTYPE)),armynum); + mailclose(nation); + } + } + } else if(P_ATYPE>=MINMONSTER) { + /* disbanding of ALL monsters should take place */ + P_ASOLD=0; + if(ispc(curntn->active)) { + if (mailopen(nation)!=(-1)) { + fprintf(fm,"Message to %s from Conquer\n\n",curntn->name); + fprintf(fm,"\tYour %s (unit %d) leaves due to the loss of your jewels.\n",*(unittype+(P_ATYPE%UTYPE)),armynum); + mailclose(nation); + } + } + } + } + + /* check for sectors breaking away -- not capx, capy */ + if(ispc(curntn->active)) { + /* create a summarized mail message of sectors effected */ + if (mailopen(nation)!=(1)) { + fprintf(fm,"Message to %s from Conquer\n\n",curntn->name); + fprintf(fm,"Riots and Rebellion flourish:\n"); + } + } + for(i=0;i0) { + if(rand()%100 < PDEPLETE) { + /* sector riots */ + flee(i,j,TRUE,FALSE); + DEVASTATE(i,j); + if(ispc(curntn->active)) { + /* add to listing */ + fprintf(fm,"\tsector %d, %d has massive riots\n",i,j); + } + } else { + /* sector becomes owned by another nation */ +#ifdef NOTDONE + /* must work on this still */ + giveaway(i,j,&nation); + if(ispc(curntn->active)) { + fprintf(fm,"\tsector %d, %d joins nation %s\n",ntn[nation].name); + } +#endif /* NOTDONE */ + } + } + } + if(ispc(curntn->active)) { + mailclose(nation); + } else if(isnpc(curntn->active)) { + if(sct[curntn->capx][curntn->capy].owner==nation) { + /* reset capitol for npcs */ + sct[curntn->capx][curntn->capy].designation=DCAPITOL; + if(sct[curntn->capx][curntn->capy].fortress<1) + sct[curntn->capx][curntn->capy].fortress=1; + } + } + /* restore */ + curntn = saventn; +} + + +/*routine to sack a nation's captiol */ +void +sackem(cntry) + int cntry; +{ + struct s_nation *saventn=curntn; + int x,y,i,j,foundcap,nation; + + /* hail the conquerer */ + curntn = &ntn[cntry]; + x = curntn->capx; + y = curntn->capy; + nation = sct[x][y].owner; + if(nation==cntry || nation==0) return; + + /* advertise */ + fprintf(fnews,"1.\tCapitol of %s sacked by %s\n",ntn[cntry].name,ntn[nation].name); + + /* Remove goods from trade board */ + fixtrade(cntry); + + /* first give all prizes to the conquerer */ + if(curntn->tgold > 0) { /* all gold */ + ntn[nation].tgold += curntn->tgold; + curntn->tgold=0; + } + ntn[nation].jewels += curntn->jewels; /* all jewels */ + curntn->jewels=0; + ntn[nation].metals += curntn->metals; /* all metals */ + curntn->metals=0; + ntn[nation].tfood += curntn->tfood/5L; /* 20% of food */ + curntn->tfood -= curntn->tfood/5L; + + /* fix the designation */ + if(sct[x][y].designation==DCAPITOL) { + if(isntn(ntn[nation].active)) { + sct[x][y].designation = DCITY; + } else { + DEVASTATE(x,y); + sct[x][y].owner=cntry; + } + } + + /* set another sector to the capx, capy to make sure that */ + /* sacking does not occur next update for same sacking. */ + foundcap=FALSE; + for(i=0;foundcap==FALSE && icapx)&&(y==curntn->capy)) + ||(sct[x][y].designation!=DTOWN))) { + x = i; y = j; + } else if((x==curntn->capx)&&(y==curntn->capy)) { + x = i; y = j; + } + } + + if ((x!=curntn->capx)||(y!=curntn->capy)) { + /* assign new pseudo capitol */ + if(ispc(curntn->active)) { + if(mailopen(cntry)!=(-1)) { + fprintf(fm,"Message to %s from Conquer\n\n",ntn[cntry].name); + fprintf(fm,"\tYour Capitol at sector location %d,%d\n",curntn->capx,curntn->capy); + fprintf(fm,"\t was overrun by nation %s.\n\n",ntn[nation].name); + fprintf(fm,"\tA temporary headquarters is now in sector %d,%d,\n",x,y); + fprintf(fm,"\t but designation of a new Capitol is recommended.\n"); + mailclose(cntry); + } + } + curntn->capx=x; + curntn->capy=y; + } else { + /* no new capitol assignment */ + if(ispc(curntn->active)) { + if(mailopen(cntry)!=(-1)) { + fprintf(fm,"Message to %s from Conquer\n\n",ntn[cntry].name); + fprintf(fm,"\tYour Capitol at sector location %d,%d\n",curntn->capx,curntn->capy); + fprintf(fm,"\t was overrun by nation %s.\n\n",ntn[nation].name); + fprintf(fm,"\tNo other land remains. The destruction\n"); + fprintf(fm,"\t of your nation seems imminent.\n"); + mailclose(cntry); + } + } + } + /* restore */ + curntn = saventn; +} +#endif /* ADMIN */ + +/*destroy nation--special case if capitol not owned by other nation*/ +void +destroy(cntry) +int cntry; +{ + short armynum, nvynum; + int i, x, y; + char buf[LINELTH]; + struct s_nation *nptr; + + nptr = &ntn[cntry]; + if( !isactive(nptr->active) ) return; + + if( !ismonst(nptr->active) ) { + fprintf(fnews,"1.\tNation %s was destroyed ",nptr->name); + if(cntry!=sct[nptr->capx][nptr->capy].owner){ + fprintf(fnews,"(their capitol is now owned by %s)\n",ntn[sct[nptr->capx][nptr->capy].owner].name); + /*get +5% to combat skill*/ + ntn[sct[nptr->capx][nptr->capy].owner].aplus+=5; + } + else fprintf(fnews,"(they owned their capitol)\n"); + } + + nptr->active=INACTIVE; + nptr->score=0; + sprintf(buf,"%s%d",msgfile,cntry); + unlink(buf); + + for(armynum=0;armynum0) { + if(ntn[sct[AXLOC][AYLOC].owner].race==nptr->race) + sct[AXLOC][AYLOC].people+=ASOLD; + ASOLD=0; + } + for(nvynum=0;nvynumdstatus[i]=UNMET; + } else { + ntn[i].dstatus[cntry]=WAR; + nptr->dstatus[i]=WAR; + } + } + + /*if take them you get their gold*/ + if(cntry!=sct[nptr->capx][nptr->capy].owner){ + if(nptr->tgold>0) ntn[sct[nptr->capx][nptr->capy].owner].tgold+=nptr->tgold; + if(nptr->jewels>0) ntn[sct[nptr->capx][nptr->capy].owner].jewels+=nptr->jewels; + if(nptr->metals>0) ntn[sct[nptr->capx][nptr->capy].owner].metals+=nptr->metals; + if(nptr->tfood>0) ntn[sct[nptr->capx][nptr->capy].owner].tfood+=nptr->tfood; + sct[nptr->capx][nptr->capy].designation=DCITY; + } + + /*if god destroys then kill all population*/ + if(cntry==sct[nptr->capx][nptr->capy].owner){ + for(x=0;xcapx][nptr->capy].owner].race!=nptr->race){ + for(x=0;xcapx][nptr->capy].owner; + if( !ISCITY( sct[x][y].designation )) { + if(tofood( &sct[x][y],0)altitude==WATER) { + movecost[x][y] = -4; + for(i=x-1;i<=x+1;i++) for(j=y-1;j<=y+1;j++) + if( ONMAP(i,j) ) + if( sct[i][j].altitude != WATER) { + movecost[x][y] = -1; + i=x+2; + j=y+2; + } + } else { + if( veg_cost[ sptr->vegetation ] == -1 + || ele_cost[ sptr->altitude ] == -1 ) + movecost[x][y] = -2; + else + movecost[x][y] = veg_cost[ sptr->vegetation ] + ele_cost[ sptr->altitude ]; + } /* if */ + if (sptr->designation == DROAD) + movecost[x][y] = (movecost[x][y] + 1) / 2; + } /* for */ +} /* updmove() */ + +#ifdef CONQUER +/* calculations for cost of movement during flight */ +int +flightcost(i,j) +int i,j; +{ + int cnt,hold=(-1),hold2=(-1); + + for (cnt=0; ele[cnt]!='0'; cnt++ ) { + if (sct[i][j].altitude==ele[cnt]) + hold = (FElecost[cnt] - '0'); + } + for (cnt=0; veg[cnt]!='0'; cnt++ ) { + if (sct[i][j].vegetation==veg[cnt]) + hold2 = (FVegcost[cnt] - '0'); + } + if (hold==(-1) || hold2==(-1)) { + hold=(-1); + } + else hold+=hold2; + + return(hold); +} +#endif /* CONQUER */ +#ifdef ADMIN +/* determines whether or not a unit has the ability to fly */ +int +avian(typ) +unsigned char typ; +{ + switch(typ) { + case A_ROC: + case A_GRIFFON: + case SPIRIT: + case DJINNI: + case DEMON: + case DRAGON: + return(TRUE); + default: + return(FALSE); + } +} +#endif /* ADMIN */ + +void +spreadsheet(nation) +int nation; +{ + register struct s_sector *sptr; + register struct s_nation *nptr; + long product; + long city_pop, cap_pop; + int x,y,i,j,foundmill; + + nptr = &ntn[ nation ]; + + spread.revothr = spread.revfood = spread.revjewels = spread.revmetal = spread.revcap = spread.revcity = 0L; + spread.inothr = spread.incity = spread.incap = spread.ingold = spread.infarm = spread.inmetal = 0; + spread.food = nptr->tfood; + spread.gold = nptr->tgold; + spread.metal = nptr->metals; + spread.jewels = nptr->jewels; + spread.sectors = 0; + spread.civilians = 0L; + + for(x=0;xowner!=nation) continue; + + /*update nation file for owner*/ + spread.sectors++; + spread.civilians += sptr->people; + + product = 0; + /*PRODUCE*/ + /*increase tmin based on mined stuff...*/ + if(sptr->designation==DMINE) { + if( !tg_ok( nation, sptr )) continue; + spread.inmetal += sptr->people; + if(sptr->people>TOMANYPEOPLE) { + product = sptr->metal * TOMANYPEOPLE; + product += sptr->metal * (sptr->people-TOMANYPEOPLE)/2L; + } else product = sptr->metal * sptr->people; + + if(magic(sptr->owner,MINER)==1) product*=2L; + if(magic(sptr->owner,STEEL)==1) product*=2L; + spread.metal += product; + spread.revmetal += product*TAXMETAL*nptr->tax_rate/100L; + } + /*harvest food*/ + else if(sptr->designation==DFARM) { + spread.infarm += sptr->people; + if(sptr->people>TOMANYPEOPLE) { + product = (long)tofood(sptr,sptr->owner) * TOMANYPEOPLE; + product += (long)tofood(sptr,sptr->owner) * (sptr->people-TOMANYPEOPLE)/2L; + } else product = (long)tofood(sptr,sptr->owner) * sptr->people; + + switch(SEASON(TURN)) { + case SPRING: + product/=2; + break; + case SUMMER: + break; + case FALL: + product*=5; + product/=2; + break; + case WINTER: + product=0; + break; + } + /* search for neighboring mills */ + foundmill=FALSE; + for(i=x-1;foundmill==FALSE && i<=x+1;i++) + for(j=y-1;foundmill==FALSE && j<=y+1;j++) + if((ONMAP(i,j)) + &&(sct[i][j].owner==sptr->owner) + &&(sct[i][j].designation==DMILL) + &&(sct[i][j].people>=MILLSIZE)) { + product *= 12L; + product /= 10L; + /* must break this way... two for() loops */ + foundmill=TRUE; + } + spread.food += product; + spread.revfood += product*TAXFOOD*nptr->tax_rate/100L; + } + /*gold mines produce gold*/ + else if(sptr->designation==DGOLDMINE) { + if( !tg_ok( nation, sptr )) continue; + spread.ingold += sptr->people; + if(sptr->people>TOMANYPEOPLE) { + product = sptr->jewels * TOMANYPEOPLE; + product += sptr->jewels * (sptr->people-TOMANYPEOPLE)/2L; + } else product = sptr->jewels * sptr->people; + + if(magic(sptr->owner,MINER)==1) product*=2; + + spread.jewels += product; + spread.revjewels += product*TAXGOLD*nptr->tax_rate/100L; + } + else if((sptr->designation==DCITY) + ||(sptr->designation==DCAPITOL)) { + cap_pop = sptr->people; + spread.incap += cap_pop; + + if( magic(sptr->owner, ARCHITECT ) ) { + cap_pop *= 2L; + } + + spread.revcap += cap_pop * TAXCITY*nptr->tax_rate / 100L; + } else if(sptr->designation==DTOWN) { + spread.incity += sptr->people; + city_pop = sptr->people; + if( magic(sptr->owner, ARCHITECT ) ) + city_pop *= 2L; + + spread.revcity += city_pop*TAXTOWN*nptr->tax_rate/100L; + } +#ifndef DERVDESG + else if(((magic(sptr->owner,DERVISH)==1) + ||(magic(sptr->owner,DESTROYER)==1)) + &&((sptr->vegetation==ICE) ||(sptr->vegetation==DESERT)) + &&(sptr->people>0)) { + if(sptr->people>TOMANYPEOPLE) { + product = 6L * TOMANYPEOPLE; + product += 3L * (sptr->people-TOMANYPEOPLE); + } else product = 6L * sptr->people; + + spread.food += product; + /* desert food production mostly static */ + if (sptr->vegetation==DESERT) { + /* harsh summer in desert; good winter */ + if (SEASON(TURN)==SUMMER) product/=2; + else if (SEASON(TURN)==WINTER) { + product*=5; + product/=4; + } + } else { + /* opposite in ice */ + if (SEASON(TURN)==WINTER) product/=2; + else if (SEASON(TURN)==SUMMER) { + product*=5; + product/=4; + } + } + spread.revfood += product*TAXFOOD*nptr->tax_rate/100L; + } +#endif /* DERVDESG */ + else { /* other sectors */ + spread.inothr += sptr->people; + if(sptr->people>TOMANYPEOPLE) { + product = (long)tofood(sptr,sptr->owner) * TOMANYPEOPLE; + product += (long)tofood(sptr,sptr->owner) * (sptr->people-TOMANYPEOPLE)/2L; + } else product = (long)tofood(sptr,sptr->owner) * sptr->people; + + spread.revothr += product*TAXOTHR*nptr->tax_rate/100L; + } + } + spread.gold += spread.revfood + spread.revjewels + spread.revmetal + spread.revcity + spread.revcap + spread.revothr; +} + +/* string inputing routine to allow deleting */ +void +get_nname(str) +char str[]; +{ + char ch; + int done=0,count=0,xpos,ypos; + + while(!done) { + ch=getch(); + if (isprint(ch)) { + if (count '9' ) { + errormsg("There is no nation by that name."); + return(NTOTAL); + } else { + hold *= 10; + hold += (ch-'0'); + } + } + if (hold>NTOTAL) hold=NTOTAL; + } + /* send back result */ + return(hold); +} + +/* finds a nation for god to be, returns 1 on failure */ +int +get_god() +{ + clear_bottom(0); + mvaddstr(LINES-4,0,"Super User; For what nation? "); + refresh(); + + /* return on no entry or bad entry */ + if ((country=get_country())==(-1) || country==NTOTAL) { + country = 0; + redraw=DONE; + makebottom(); + return(1); + } + + curntn = &ntn[country]; + return(0); +} + +/* quick routine to reassign god and gods nations */ +void +reset_god() +{ + /* simple routine; but improves readibility */ + country=0; + curntn= &ntn[country]; +} +#endif /* CONQUER */ + +#ifdef ADMIN +int +getleader(class) +int class; +{ + switch(class){ + case C_NPC: + case C_KING: + case C_TRADER: return(L_BARON); + case C_EMPEROR: return(L_PRINCE); + case C_WIZARD: return(L_MAGI); + case C_PRIEST: return(L_BISHOP); + case C_PIRATE: return(L_CAPTAIN); + case C_WARLORD: return(L_LORD); + case C_DEMON: return(L_DEVIL); + case C_DRAGON: return(L_WYRM); + case C_SHADOW: return(L_NAZGUL); + default: + printf("ERROR-national class (%d) undefined\n",class); + exit(0); + } + return(-1); /* shut lint up */ +} +#endif /* ADMIN */ + +/* name of the currently open mail file */ +char tmp_mail_name[LINELTH]; + +int +mailopen(to) +{ +#ifdef CONQUER + char line[LINELTH]; +#endif /*CONQUER*/ + if(mailok != DONEMAIL) mailclose(ABORTMAIL); + + if (to != NEWSMAIL) { +#ifdef CONQUER + struct stat fst; + /* check if the player is currently reading messages */ + sprintf(line,"%s%hd.tmp",msgfile,to); + if (stat(line,&fst)==0) { + long now; + now = time(0); + if (now - fst.st_mtime < TIME_DEAD) { + if (to>=0 && to=0 && to= 0) { + fputs("END\n",fm); + } + fclose(fm); + +#ifdef CONQUER + if((to!=ABORTMAIL)&&(to==mailok)) { + char line[BIGLTH]; + if (to==NEWSMAIL) { + /* send to the current newspaper */ + sprintf(line,"cat %s >> news%d",tmp_mail_name,TURN-1); + } else { + /* send to the player now */ + sprintf(line,"cat %s >> %s%d",tmp_mail_name,msgfile,to); + } + system(line); + } + if (tmp_mail_name!=NULL) { + (void) unlink(tmp_mail_name); + } +#endif /*CONQUER*/ + mailok=DONEMAIL; +} + +#ifdef ADMIN +/* markok returns TRUE if mark is ok as a nation mark */ +int +markok(mark,prtflag) +char mark; +int prtflag; /* if true printf reason */ +{ + register int i; + char temp[LINELTH]; + + if((isprint(mark)==0)||(isspace(mark)!=0)) { + if(prtflag) { + sprintf(temp,"%c is white space",mark); + newerror(temp); + } + return(FALSE); + } + + for(i=0;ele[i]!='0';i++) if(mark==(*(ele+i))) { + if(prtflag) { + sprintf(temp,"%c is an elevation character",mark); + newerror(temp); + } + return(FALSE); + } + + for(i=0;veg[i]!='0';i++) if(mark==(*(veg+i))) { + if(prtflag) { + sprintf(temp,"%c is a vegetation character",mark); + newerror(temp); + } + return(FALSE); + } + + for(i=1;itradegood != TG_none)&&(sptr->tradegood != 0)) return; + if( randval < 20 ) { + sptr->tradegood = TG_copper; + sptr->metal = rand()%2 + 1; + } else if( randval < 30 ) { + sptr->tradegood = TG_lead; + sptr->metal = rand()%4 + 1; + } else if( randval < 40 ) { + sptr->tradegood = TG_tin; + sptr->metal = rand()%4 + 2; + } else if( randval < 55 ) { + sptr->tradegood = TG_bronze; + sptr->metal = rand()%4 + 2; + } else if( randval < 80 ) { + sptr->tradegood = TG_iron; + sptr->metal = rand()%7 + 2; + } else if( randval < 95 ) { + sptr->tradegood = TG_steel; + sptr->metal = rand()%8 + 3; + } else if( randval < 99 ) { + sptr->tradegood = TG_mithral; + sptr->metal = rand()%11 + 5; + } else { + sptr->tradegood = TG_adamantine; + sptr->metal = rand()%13 + 8; + } +} + +void +getjewel( sptr ) +struct s_sector *sptr; +{ + int randval; + if((sptr->tradegood != TG_none)&&(sptr->tradegood != 0)) return; + randval = rand()%100; + if( randval < 20 ) { + sptr->tradegood = TG_spice; + sptr->jewels = rand()%2 + 1; + } else if( randval < 40 ) { + sptr->tradegood = TG_silver; + sptr->jewels = rand()%3 + 1; + } else if( randval < 48 ) { + sptr->tradegood = TG_pearls; + sptr->jewels = rand()%3 + 1; + } else if( randval < 56 ) { + sptr->tradegood = TG_dye; + sptr->jewels = rand()%5 + 1; + } else if( randval < 64 ) { + sptr->tradegood = TG_silk; + sptr->jewels = rand()%5 + 1; + } else if( randval < 84 ) { + sptr->tradegood = TG_gold; + sptr->jewels = rand()%6 + 1; + } else if( randval < 91 ) { + sptr->tradegood = TG_rubys; + sptr->jewels = rand()%6 + 1; + } else if( randval < 96 ) { + sptr->tradegood = TG_ivory; + sptr->jewels = rand()%7 + 2; + } else if( randval < 99 ) { + sptr->tradegood = TG_diamonds; + sptr->jewels = rand()%11 + 2; + } else { + sptr->tradegood = TG_platinum; + sptr->jewels = rand()%17 + 4; + } +} +#endif /* ADMIN */ + +/* tg_ok returns true if a trade good can be seen by the owner of sector */ +int +tg_ok( nation, sptr ) +int nation; +struct s_sector *sptr; +{ + if(( nation == 0)||(nation>=NTOTAL)) return(TRUE); + + switch( sptr->tradegood ) { + case TG_lead: if(ntn[nation].mine_ability < 8) return(0); break; + case TG_tin: if(ntn[nation].mine_ability < 11) return(0); break; + case TG_bronze: if(ntn[nation].mine_ability < 15) return(0); break; + case TG_iron: if(ntn[nation].mine_ability < 25) return(0); break; + case TG_steel: if(ntn[nation].mine_ability < 30) return(0); break; + case TG_mithral: if(ntn[nation].mine_ability < 30) return(0); break; + case TG_adamantine: if(ntn[nation].mine_ability < 40) return(0); break; + case TG_spice: + case TG_silver: + case TG_pearls: break; + case TG_dye: + case TG_silk: if(ntn[nation].wealth < 5) return(0); break; + case TG_gold: + case TG_rubys: if(ntn[nation].wealth < 8) return(0); break; + case TG_ivory: if(ntn[nation].wealth < 15) return(0); break; + case TG_diamonds: if(ntn[nation].wealth < 20) return(0); break; + case TG_platinum: if(ntn[nation].wealth < 25) return(0); break; + default: break; + }; + + if(tofood(sptr,nation) >= DESFOOD) return(TRUE); + return(FALSE); +} + +/* this routine computes the fortification value of a sector */ +int +fort_val(sptr) + struct s_sector *sptr; +{ + if(sptr->designation==DSTOCKADE) { + return(DEF_BASE); + } + if(sptr->designation==DFORT){ + if(magic(sptr->owner,ARCHITECT)==1){ + return(DEF_BASE + 2*FORTSTR * sptr->fortress); + } + else return(DEF_BASE + FORTSTR * sptr->fortress); + } + if (sptr->designation==DTOWN){ + if(magic(sptr->owner,ARCHITECT)==1){ + return(DEF_BASE + 2*TOWNSTR * sptr->fortress); + } else return(DEF_BASE + TOWNSTR * sptr->fortress); + } + if((sptr->designation==DCAPITOL) + ||(sptr->designation==DCITY)){ + if(magic(sptr->owner,ARCHITECT)==1){ + return(2*DEF_BASE + 2*CITYSTR * sptr->fortress); + } + else return(2*DEF_BASE + CITYSTR * sptr->fortress); + } + return(0); +} + +/* routine to determine compass direction of x1,y1 from x0,y0 */ +int +compass(x0,y0,x1,y1) + int x0,y0,x1,y1; +{ + int dx=x1-x0, dy=y1-y0; /* diplacements */ + int hold; + + if(10*abs(dx) > abs(dy)) { + if(10*abs(dy) > abs(dx)) { + /* four off-quadrants */ + if(dx>0) { + if(dy<0) hold=NORTHEAST; + else hold=SOUTHEAST; + } else { + if(dy<0) hold=NORTHWEST; + else hold=SOUTHWEST; + } + } else { + /* east or west */ + if(dx>0) hold=EAST; + else hold=WEST; + } + } else { + /* north or south or same point */ + if(dy==0) hold=CENTERED; + else if(dy<0) hold=NORTH; + else hold=SOUTH; + } + return(hold); +} + +#ifdef CONQUER +extern short xcurs; +extern short ycurs; +off_t conq_mail_size=0; +#ifdef SYSMAIL +static off_t sys_mail_size=0; +#endif /* SYSMAIL */ +void +check_mail() +{ + struct stat info; +#ifdef SYSMAIL + int osys_mail=sys_mail_status; +#endif + int oconq_mail=conq_mail_status; + + /* check conquer mail box */ + if (stat(conqmail,&info)==(-1)) { + conq_mail_status=NO_MAIL; + conq_mail_size=0; + } else { + if (info.st_size > conq_mail_size) { + conq_mail_status=NEW_MAIL; + conq_mail_size=info.st_size; + } else if (info.st_size < conq_mail_size) { + conq_mail_status=NO_MAIL; + conq_mail_size=info.st_size; + } + } + +#ifdef SYSMAIL + /* check system mail box */ + if (stat(sysmail,&info)==(-1)) { + sys_mail_status=NO_MAIL; + sys_mail_size=0; + } else { + if(info.st_atime>info.st_mtime) { + sys_mail_status=NO_MAIL; + sys_mail_size=info.st_size; + } else if (info.st_size > sys_mail_size) { + sys_mail_status=NEW_MAIL; + sys_mail_size=info.st_size; + } else if (info.st_size < sys_mail_size) { + sys_mail_status=NO_MAIL; + sys_mail_size=info.st_size; + } + } + + /* display mail information */ + if(sys_mail_status!=osys_mail) { + if (sys_mail_status==NEW_MAIL) { + mvaddstr(LINES-3,COLS/2-6,"You have System Mail"); + } else { + mvaddstr(LINES-3,COLS/2-6," "); + } + move(ycurs,2*xcurs); + refresh(); + } + if (conq_mail_status!=oconq_mail) { + if (conq_mail_status==NEW_MAIL) { + mvaddstr(LINES-2,COLS/2-6,"You have Conquer Mail"); + } else { + mvaddstr(LINES-2,COLS/2-6," "); + } + move(ycurs,2*xcurs); + refresh(); + } +#else + /* display mail information */ + if (conq_mail_status!=oconq_mail) { + if (conq_mail_status==NEW_MAIL) { + mvaddstr(LINES-3,COLS/2-6,"You have Conquer Mail"); + } else { + mvaddstr(LINES-3,COLS/2-6," "); + } + move(ycurs,2*xcurs); + refresh(); + } +#endif /* SYSMAIL */ +} +#endif /* CONQUER */ diff --git a/original/move.c b/original/move.c new file mode 100644 index 0000000..db3476f --- /dev/null +++ b/original/move.c @@ -0,0 +1,645 @@ +/*conquer : Copyright (c) 1988 by Ed Barlow. + * I spent a long time writing this code & I hope that you respect this. + * I give permission to alter the code, but not to copy or redistribute + * it without my explicit permission. If you alter the code, + * please document changes and send me a copy, so all can have it. + * This code, to the best of my knowledge works well, but it is my first + * 'C' program and should be treated as such. I disclaim any + * responsibility for the codes actions (use at your own risk). I guess + * I am saying "Happy gaming", and am trying not to get sued in the process. + * Ed + */ + +#include +#include +#include +#include +#include +#include "header.h" +#include "data.h" + +extern FILE *fexe; +extern short redraw; +extern short selector; +extern short pager; +extern short xcurs,ycurs,xoffset,yoffset; +extern short hilmode; /*highlight modes: 0=owned sectors, 1= armies, 2=none*/ + +extern short country; +int armornvy=AORN; + +void +mymove() +{ + int mveleft; /* movement remaining to army group */ + long groupmen; /* infantry types in current army group */ + long othermen; /* leader & monster strength in current group */ + int i,j,x; + int total,Tarmynum,Tnation,fmove; + int valid=FALSE; /* TRUE if move was a valid move */ + short armynum; + short nvynum; + int oldxcurs,oldycurs,mvused; + int done=FALSE; /*done is TRUE if done with this move*/ + + armornvy=AORN; + clear_bottom(0); + + if((armynum=getselunit())<0) { /*get selected army or navy*/ + errormsg("Invalid Unit Selected"); + armornvy=AORN; + return; + } + + if(armynum>=MAXARM) { /*navy*/ + nvynum = armynum-MAXARM; + armynum=(-1); + mvprintw(LINES-4,0,"NAVY %d: move %d",nvynum,P_NMOVE); + standend(); + clrtoeol(); + if((P_NMOVE==0)) { + errormsg("That Fleet is Not Able Move Any Farther"); + redraw=DONE; + armornvy=AORN; + return; + } + mvused=P_NMOVE; + } else { /*army*/ + mvprintw(LINES-4,0,"ARMY %d: ",armynum); + clrtoeol(); + if (P_ASTAT>=NUMSTATUS) { + groupmen = P_ASTAT - NUMSTATUS; + P_AMOVE = curntn->arm[groupmen].smove; + } + if(P_AMOVE==0){ + errormsg("That Unit is Not Able to Move"); + redraw=DONE; + armornvy=AORN; + return; + } + + /* check if ok to continue if part of army group */ + if(P_ASTAT>=NUMSTATUS) { + mvprintw(LINES-4,10,"Member of Army Group %d!! Continue? ",P_ASTAT-NUMSTATUS); + refresh(); + if( getch() == 'y' ) { + P_ASTAT=ATTACK; + AADJSTAT; + } else { + redraw=DONE; + armornvy=AORN; + return; + } + } + + /* add up infantry types in army group */ + othermen = groupmen = 0; + if(P_ASTAT==GENERAL) { + x=armynum; + for(armynum=0;armynumarm[armynum].stat==x+NUMSTATUS){ + if(P_ATYPEarm[i].sold>0){ + standout(); + see((int)curntn->arm[i].xloc-xoffset,(int)curntn->arm[i].yloc-yoffset); + } + for(i=0;invy[i].merchant+curntn->nvy[i].warships+curntn->nvy[i].galleys!=0){ + standout(); + see((int)curntn->nvy[i].xloc-xoffset,(int)curntn->nvy[i].yloc-yoffset); + + } + } else for(i=XREAL-xoffset-1;i<=XREAL-xoffset+1;i++){ + for(j=YREAL-yoffset-1;j<=YREAL-yoffset+1;j++){ + highlight(i,j,hilmode); + see(i,j); + } + } + move(ycurs,xcurs*2); + refresh(); + break; + case ' ': + valid=FALSE; + if(mveleft>0 && armornvy==ARMY && sct[XREAL][YREAL].altitude==WATER && P_ASTAT==FLIGHT) + errormsg("Please Sir! If we stop here we'll drown"); + else done=TRUE; + break; + default: + beep(); + valid=FALSE; + } + + if (!ONMAP(XREAL,YREAL)) { + errormsg("We refuse to go off the edge of the world"); + valid=FALSE; + xcurs=oldxcurs; + ycurs=oldycurs; + } + /*if valid move check if have enough movement points*/ + if(valid==TRUE) + if(armornvy==ARMY) { + if (P_ASTAT==FLIGHT) { + fmove=flightcost(XREAL,YREAL); + if (movecost[XREAL][YREAL]>0 && fmove>movecost[XREAL][YREAL]) + fmove=movecost[XREAL][YREAL]; + if (fmove<0 || fmove>mveleft) { + beep(); + valid=FALSE; + xcurs=oldxcurs; + ycurs=oldycurs; + } else { + P_AMOVE-=fmove; + if(P_AMOVE==0) done=TRUE; + } + } + else if((movecost[XREAL][YREAL]<0) + ||(movecost[XREAL][YREAL]>mveleft)) { + if(movecost[XREAL][YREAL]>mveleft) + errormsg("Costs Too Much To Move Here!!!"); + else errormsg("Can't Move Here"); + valid=FALSE; + xcurs=oldxcurs; + ycurs=oldycurs; + } else { + + /* CANT MOVE IN NON ALLIED / NON WAR/JIHAD COUNTRIES */ + if((P_ASTAT!=SCOUT) + &&(P_ATYPE!=A_NINJA) + &&(P_ATYPE=MINMONSTER || P_ASTAT==GENERAL) + &&(sct[XREAL][YREAL].owner!=0) + &&(sct[XREAL][YREAL].owner!=country) + &&(sct[XREAL][YREAL].people>100) + &&(ntn[sct[XREAL][YREAL].owner].dstatus[country]>ALLIED) + &&(curntn->dstatus[sct[XREAL][YREAL].owner]dstatus[sct[XREAL][YREAL].owner]==UNMET)){ + errormsg("Can't Enter Unmet Nations Land"); + valid=FALSE; + xcurs=oldxcurs; + ycurs=oldycurs; + } else { + P_AMOVE-=movecost[XREAL][YREAL]; + if(P_AMOVE==0) done=TRUE; + } + } + } else if(armornvy==NAVY) { + + if(abs(movecost[XREAL][YREAL])>mveleft){ + errormsg("Costs Too Much To Move Here!!!"); + valid=FALSE; + xcurs=oldxcurs; + ycurs=oldycurs; + } else if(movecost[XREAL][YREAL] >= 0 + || movecost[XREAL][YREAL] == -2){ + /* LAND OF SOME TYPE */ + valid=FALSE; + /* check for nearby water */ + for(i=XREAL-1;i<=XREAL+1;i++) + for(j=YREAL-1;j<=YREAL+1;j++) + if(ONMAP(i,j) && sct[i][j].altitude==WATER) valid=TRUE; + + if(valid==FALSE) { + errormsg("There isn't a waterway over there!"); + xcurs=oldxcurs; + ycurs=oldycurs; + } else + if(((sct[XREAL][YREAL].designation==DTOWN) + ||(sct[XREAL][YREAL].designation==DCAPITOL) + ||(sct[XREAL][YREAL].designation==DCITY)) + &&(sct[XREAL][YREAL].owner==country + ||(ntn[SOWN].dstatus[country]!=UNMET&& + ntn[SOWN].dstatus[country]<=NEUTRAL))) { + /* harbor */ + if(P_NMOVE>=3) P_NMOVE-=3; + else { + errormsg("You need 3 move points for that"); + valid=FALSE; + xcurs=oldxcurs; + ycurs=oldycurs; + } + } else { /* coastland */ + standout(); + if (sct[XREAL][YREAL].owner==country) mvaddstr(LINES-3,0,"Do you wish to land?"); + else mvaddstr(LINES-3,0,"Do you wish to invade?"); + standend(); + clrtoeol(); + refresh(); + if(getch()=='y') { + move(LINES-3,0); + clrtoeol(); + if(P_NMOVE>=4) P_NMOVE=0; + else { + beep(); + valid=FALSE; + xcurs=oldxcurs; + ycurs=oldycurs; + errormsg("You need 4 move points to land"); + move(ycurs,xcurs*2); + refresh(); + } + } else { + move(LINES-3,0); + clrtoeol(); + valid=FALSE; + xcurs=oldxcurs; + ycurs=oldycurs; + move(ycurs,xcurs*2); + refresh(); + } + } + } else if((movecost[XREAL][YREAL]!=(-1)) + &&(P_NGAL(N_LIGHT)!=0||P_NWAR(N_LIGHT)!=0||P_NMER(N_LIGHT)!=0)) { + /* warship going into deep water */ + errormsg("Light Ships May Not Go Into Deep Water!"); + valid=FALSE; + xcurs=oldxcurs; + ycurs=oldycurs; + } else { + P_NMOVE -= abs( movecost[XREAL][YREAL] ); + } + + if(P_NMOVE==0) done=TRUE; + + } else if(armornvy==AORN){ + errormsg("ERROR - NOT ARMY OR NAVY"); + return; + } + + /*if moved and not done*/ + if((valid==TRUE)&&(done==FALSE)){ + /*check if offmap and correct*/ + coffmap(); + + /*calc enemy soldiers */ + total=0; + if(armornvy==ARMY) { + for(Tnation=0;Tnation0) + &&(ntn[Tnation].arm[Tarmynum].xloc==XREAL) + &&(ntn[Tnation].arm[Tarmynum].yloc==YREAL) + &&((curntn->dstatus[Tnation]>=HOSTILE) + ||(ntn[Tnation].dstatus[country]>=HOSTILE)) + &&(ntn[Tnation].arm[Tarmynum].stat!=SCOUT) + &&(ntn[Tnation].arm[Tarmynum].unittyp!=A_NINJA)) + total+=ntn[Tnation].arm[Tarmynum].sold; + } else { + /*naval total is number of at war WARSHIPS within one sector*/ + for(Tnation=0;Tnation=XREAL-1) + &&(ntn[Tnation].nvy[Tarmynum].yloc<=YREAL+1) + &&(ntn[Tnation].nvy[Tarmynum].yloc>=YREAL-1) + &&(ntn[Tnation].dstatus[country]>=HOSTILE)) { + total+=SHIPS(ntn[Tnation].nvy[Tarmynum].warships,N_LIGHT); + total+=SHIPS(ntn[Tnation].nvy[Tarmynum].warships,N_MEDIUM); + total+=SHIPS(ntn[Tnation].nvy[Tarmynum].warships,N_HEAVY); + } + } + + move(LINES-3,0); + clrtoeol(); + + /*scouts/ninja and flying units ignore zoc's */ + if((armornvy==ARMY) + &&(P_ASTAT!=SCOUT) + &&(P_ATYPE!=A_NINJA) + &&((P_ATYPE=MINMONSTER)) + &&(P_ASTAT!=FLIGHT)){ + if(groupmen+othermen < total){ + /*stop if you have < total*/ + P_AMOVE=0; + AADJMOV; + errormsg("Zone Of Control - Stopping Movement!"); + } else if(total>0) { + /* remove proportion of starting move */ + P_AMOVE-= total * curntn->maxmove * *(unitmove+(P_ATYPE%UTYPE))/(10*(groupmen+othermen)); + if( P_AMOVE>150 ) + P_AMOVE=0; + AADJMOV; + if( P_AMOVE==0 ) + errormsg("Zone Of Control - Stopping Movement"); + else errormsg("Zone Of Control - Reducing Movement"); + } + if( P_AMOVE==0 ) done=TRUE; + } else if((armornvy==NAVY)&&(total>0)){ + /*25% stop if they have > total*/ + if((P_NWAR(N_LIGHT)+P_NWAR(N_MEDIUM)+ + P_NWAR(N_HEAVY) < total) + &&(rand()%4==0)){ + P_NMOVE=0; + NADJMOV; + mvprintw(LINES-3,0,"%d Enemy Warships Sighted ",total); + beep(); + done=TRUE; + } + } + } + + if( done==FALSE ) { + standout(); + if(armornvy==ARMY){ + mvprintw(LINES-2,0,"MOVESCREEN: move left: %d",P_AMOVE); + if (P_ASTAT==FLIGHT) { + fmove=flightcost(XREAL,YREAL); + if (movecost[XREAL][YREAL]>0 && fmove>movecost[XREAL][YREAL]) + fmove=movecost[XREAL][YREAL]; + printw(" move cost is %d", fmove); + } else printw(" move cost is %d", movecost[XREAL][YREAL]); + } else mvprintw(LINES-2,0,"MOVESCREEN: move left: %d move cost is %d",P_NMOVE,abs(movecost[XREAL][YREAL])); + clrtoeol(); + standend(); + mvaddstr(LINES-1,0,"HIT SPACE IF DONE"); + clrtoeol(); + + /*see within one sector of unit*/ + for(i=XREAL-1;i<=XREAL+1;i++) + for(j=YREAL-1;j<=YREAL+1;j++) if(ONMAP(i,j)) + if(!canbeseen((int)i,(int)j)) { + highlight(i-xoffset,j-yoffset,hilmode); + see(i-xoffset,j-yoffset); + } + } + makeside(TRUE); + move(ycurs,xcurs*2); + refresh(); + } + + /*at this point you are done with move*/ + /*move unit now to XREAL,YREAL*/ + selector=0; + pager=0; + mvaddstr(LINES-1,0,"DONE MOVEMENT"); + clrtoeol(); + if(armornvy==ARMY){ + + P_AXLOC=XREAL; + P_AYLOC=YREAL; + AADJLOC; + if (P_ASTAT==FLIGHT) { + P_ASTAT=DEFEND; /* landed; must stay on ground */ + AADJSTAT; + /* check for drowning */ + if (sct[XREAL][YREAL].altitude==WATER) { + clear_bottom(0); + mvprintw(LINES-3,0,"Army #%d drowns in water",armynum); + if( P_ATYPE==A_MERCENARY) { + mvprintw(LINES-2,0,"Paying mercenary families %ld talons", *(u_encost+(P_ATYPE%UTYPE)) * P_ASOLD); + curntn->tgold -= *(u_encost+(P_ATYPE%UTYPE)) * P_ASOLD; + } + mvaddstr(LINES-1,60,"HIT ANY KEY"); + refresh(); + getch(); + groupmen=0; + P_ASOLD=0; + AADJMEN; + } + } + AADJMOV; + /*if sector unowned take it*/ + /*first check if occupied*/ + /* if (other owner and unoccupied) or (no owner) you take*/ + if(((P_ATYPE0)){ + /*calc enemy soldiers */ + total=0; + for(Tnation=0;Tnation0) + &&(ntn[Tnation].arm[Tarmynum].xloc==XREAL) + &&(ntn[Tnation].arm[Tarmynum].yloc==YREAL) + &&((curntn->dstatus[Tnation]>=HOSTILE) + ||(ntn[Tnation].dstatus[country]>=HOSTILE)) + &&(ntn[Tnation].arm[Tarmynum].stat!=SCOUT) + &&(ntn[Tnation].arm[Tarmynum].unittyp!=A_NINJA)) + total+=ntn[Tnation].arm[Tarmynum].sold; + if((groupmen>=TAKESECTOR)&&(SOWN==0 )){ + mvaddstr(LINES-2,0,"Taking Unowned Sector"); + clrtoeol(); + refresh(); + sleep(2); + SOWN=country; + curntn->popularity++; + SADJOWN; + P_AMOVE=0; + AADJMOV; + } else if((sct[P_AXLOC][P_AYLOC].owner!=country) + &&((sct[P_AXLOC][P_AYLOC].designation==DTOWN) + ||(sct[P_AXLOC][P_AYLOC].designation==DCAPITOL) + ||(sct[P_AXLOC][P_AYLOC].designation==DCITY))){ + mvaddstr(LINES-2,0,"Entering Town/City sector"); + clrtoeol(); + refresh(); + sleep(2); + } else if((SOWN!=country) + &&(groupmen>=TAKESECTOR) + &&((occ[XREAL][YREAL]==0) + ||(occ[XREAL][YREAL]==country) + ||(groupmen+othermen > 7*total)) + &&(curntn->dstatus[SOWN]>HOSTILE) + &&(P_ASTAT>=DEFEND)) { /* atk, def, and group */ + /*people flee if not of same race*/ + if((sct[XREAL][YREAL].people>0) + &&(ntn[sct[XREAL][YREAL].owner].race!=curntn->race)) + if(magic(country,SLAVER)==TRUE) { + flee(XREAL,YREAL,0,TRUE); + } else{ + flee(XREAL,YREAL,0,FALSE); + } + mvaddstr(LINES-2,0,"TAKING SECTOR"); + clrtoeol(); + refresh(); + sleep(2); + SOWN=country; + curntn->popularity++; + SADJOWN; + P_AMOVE=0; + AADJMOV; + } else if(( sct[XREAL][YREAL].owner!=country ) + &&(total>0) + &&(groupmen=0)&&(P_ASTAT==GENERAL)) { + x=armynum; + for(armynum=0;armynumarm[armynum].stat==x+NUMSTATUS){ + P_AXLOC=XREAL; + P_AYLOC=YREAL; + AADJLOC; + P_AMOVE=curntn->arm[x].smove; + AADJMOV; + } + armynum=x; + } + } else if(armornvy==AORN){ + errormsg("Error in move.c"); + return; + } else { + /*else navy*/ + mvaddstr(LINES-1,0,"NAVY DONE: "); + clrtoeol(); + P_NXLOC=XREAL; + P_NYLOC=YREAL; + NADJLOC; + NADJMOV; + armynum=P_NARMY; + /* move army but do not take land -- still in ship */ + if((armynum>=0)&&(armynum LONGTRIP) mvused=LONGTRIP; + if (magic(country,SAILOR)==TRUE) mvused/=2; + if (mvused!=0) mvused= (rand()%mvused); + P_NPEOP = (unsigned char) (P_NPEOP*(LONGTRIP-mvused)/LONGTRIP); + mvaddstr(LINES-1,60,"HIT ANY KEY"); + refresh(); + getch(); + } + redraw=DONE; + prep(country,FALSE); + whatcansee(); + move(0,0); + clrtobot(); + makemap(); + armornvy=AORN; + pager=0; + selector=0; +} + +/************************************************************************/ +/* GETSELUNIT() returns id of selected unit (army or navy) */ +/* if navy, number is MAXARM+nvynum. set armornvy */ +/* current selected unit is selector/2+4*pager */ +/************************************************************************/ +int +getselunit() +{ + int selunit=(-1); + short armynum=0, nvynum=0; + int count=0; + for(armynum=0;armynum0)&&(P_AXLOC==XREAL)&&(P_AYLOC==YREAL)) { + if((SCRARM*pager)+(selector/2)==count) selunit=armynum; + count++; + } + } + + if(selunit==(-1)){ + for(nvynum=0;nvynum=0){ + if(selunit>=MAXARM) armornvy=NAVY; + else armornvy=ARMY; + } + return(selunit); +} diff --git a/original/nations b/original/nations new file mode 100644 index 0000000..9032847 --- /dev/null +++ b/original/nations @@ -0,0 +1,69 @@ +# GAME MASTERS FILE ON NPC NATIONS: COMPILE TIME ONLY +# comments are offset by a # sign in the first column +# +# The following nations will be added to the world when it is created. +# This works for up to to MAXNTN nations (but then there is no room +# for players) and one nation is placed per MONSTER (see header.h) +# sectors. +# +# name :nations name +# :examples include Darboth Ummaya Rugar Jute Atlantis Iberia +# :Kuybyshev Avar Grodor Bantanya Fung Codor Delph Macitania +# leader : permitted leaders are "dwarfking","elfking","elfdruid", +# "elfwizard","demon","dragon","wizard","priest", +# "shadow","king","priestking","wizard","demigod" +# race :Character, ORC='O',ELF='E',DWARF='D',LZARD='L',HUMAN='H' +# :BRIGAND='P' BARBARIAN='B' +# mark :unique mark for race (ie & or ! or 1 or H...) +# loc :G,F,R location (good,fair,random) +# aplus :attack percentage plus (multiples of 10 (ie 10,20,30)) +# dplus :defence percentage plus (multiples of 10 (ie 10,20,30)) +# maxmove :movement rate +# gold :total gold at start +# mil :total military at start +# points :total point score at start -> civilians are calculated from +# : points not allcoated to other things. See Maxpts. The +# : default is 40 points per nation +# repro-rate :reproduction rate of nation (percentage) +# allignment :(g)ood, (n)eutral, (e)vil, (i)solationist - for NPC Nations. +# :(G)ood, (N)eutral, (E)vil - for PC Nations. +# x,y :x and y values - read if you have read in a map to makeworld +# : good idea to keep -1s here for now. +# +# THE NATIONS LISTED BELOW ARE CALIBRATED AS FOLLOWS +# +# isolationist: 320 good: 250 neutral: 320 evil: 335 +# human: 420 elf: 260 dwarf: 260 orc: 285 +# +# This represents a world geared to GOOD player nations +# +# Npc nations can have classes too (as follows): +# NPC 0 KING 1 EMPEROR 2 +# WIZARD 3 PRIEST 4 PIRATE 5 TRADER 6 +# WARLORD 7 DEMON 8 DRAGON 9 SHADOW 10 +# Entering these values assures that class. +# But leaders are of the appropriate types, as is scoring... +# +# format: (note that offset by a space) +# +# name leader race mark loc atk def move gold mil pts repro allign x y class +######################################################################### +argos The_Ed H A F 10 10 9 50000 1000 60 8 i -1 -1 1 +anorian Anudil E a F 30 40 8 70000 1500 60 8 g -1 -1 3 +bobland Dogon O B G 20 0 6 12000 1500 70 12 i -1 -1 9 +darboth balrog O D R 0 0 7 70000 1500 70 12 e -1 -1 8 +edland Debbra H E R 10 15 12 30000 1000 60 8 g -1 -1 1 +fung Fungus E F G 10 40 8 50000 1000 70 8 i -1 -1 1 +goldor Train D G F 10 15 8 30000 1000 70 8 n -1 -1 2 +haro Cesear H H R 10 10 9 30000 1500 60 7 i -1 -1 1 +jodoba Ganalf H J R 10 10 2 30000 1500 60 8 n -1 -1 3 +#lint Lynne E L F 20 30 8 50000 1500 70 10 g -1 -1 3 +muldor Gilur D M F 10 30 6 160000 1500 70 9 n -1 -1 1 +#noria Gloin D N R 10 30 6 50000 1000 60 8 n -1 -1 1 +tokus Sumu H T R 10 10 8 30000 1000 60 8 e -1 -1 1 +woooo Nastus O W F 10 10 10 60000 3500 75 11 e -1 -1 10 +#zaos Dragonus O Z R 20 0 8 12000 1500 70 12 e -1 -1 9 +frika Frik D f F 10 10 8 50000 1200 60 10 n -1 -1 1 +amazon Diana E X F 10 10 8 50000 1200 60 10 e -1 -1 2 +#tasman Obilisk H t F 10 10 8 50000 1200 60 10 g -1 -1 3 +sahara Barbar H S F 10 10 8 50000 1200 60 10 i -1 -1 4 diff --git a/original/navy.c b/original/navy.c new file mode 100644 index 0000000..8eb9285 --- /dev/null +++ b/original/navy.c @@ -0,0 +1,549 @@ +/* conquer : Copyright (c) 1988 by Ed Barlow. */ +/* this code was initially written in January, 1989 by Adam Bryant */ + +#include +#include +#include +#include +#include "header.h" +#include "data.h" + +/* increase fleet by nships of given type */ +int +addwships (nvynum, shipsize, nships) + short nvynum, shipsize, nships; +{ + short hold=nships; + + /* return FALSE if fails, TRUE otherwise */ + + /* check for valid input */ + if (nvynum<0 || nvynum>=MAXNAVY || + shipsizeN_HEAVY) + return(FALSE); + + hold += P_NWAR(shipsize); + if (hold > N_MASK) { + return(FALSE); + } + + /* place new value in proper place */ + hold <<= (N_BITSIZE*shipsize); + + /* set it in variable */ + P_NWSHP |= hold; + + /* form mask so other values won't be changed */ + hold |= ~(N_MASK<<(N_BITSIZE*shipsize)); + + /* now change the variable */ + P_NWSHP &= hold; + return(TRUE); +} + +int +addmships (nvynum, shipsize, nships) + short nvynum, shipsize, nships; +{ + short hold=nships; + + /* return FALSE if fails, TRUE otherwise */ + + /* check for valid input */ + if (nvynum<0 || nvynum>=MAXNAVY || + shipsizeN_HEAVY) + return(FALSE); + + hold += P_NMER(shipsize); + if (hold > N_MASK) { + return(FALSE); + } + + /* place new value in proper place */ + hold <<= (N_BITSIZE*shipsize); + + /* set it in variable */ + P_NMSHP |= hold; + + /* form mask so other values won't be changed */ + hold |= ~(N_MASK<<(N_BITSIZE*shipsize)); + + /* now change the variable */ + P_NMSHP &= hold; + return(TRUE); +} + +int +addgships (nvynum, shipsize, nships) + short nvynum, shipsize, nships; +{ + short hold=nships; + + /* return FALSE if fails, TRUE otherwise */ + + /* check for valid input */ + if (nvynum<0 || nvynum>=MAXNAVY || + shipsizeN_HEAVY) + return(FALSE); + + hold += P_NGAL(shipsize); + if (hold > N_MASK) { + return(FALSE); + } + + /* place new value in proper place */ + hold <<= (N_BITSIZE*shipsize); + + /* set it in variable */ + P_NGSHP |= hold; + + /* form mask so other values won't be changed */ + hold |= ~(N_MASK<<(N_BITSIZE*shipsize)); + + /* now change the variable */ + P_NGSHP &= hold; + return(TRUE); +} + +/* remove nships of given shipsize for a given fleet */ +void +subwships (nvynum, shipsize, nships) + short nvynum, shipsize, nships; +{ + short hold; + + /* return FALSE if fails, TRUE otherwise */ + + /* check for valid input */ + if (nvynum<0 || nvynum>=MAXNAVY || + shipsizeN_HEAVY) + return; + + hold = P_NWAR(shipsize) - nships; + if (hold < 0) { + return; + } + + /* place new value in proper place */ + hold <<= (N_BITSIZE*shipsize); + + /* set it in variable */ + P_NWSHP |= hold; + + /* form mask so other values won't be changed */ + hold |= ~(N_MASK<<(N_BITSIZE*shipsize)); + + /* now change the variable */ + P_NWSHP &= hold; +} + +void +submships (nvynum, shipsize, nships) + short nvynum, shipsize, nships; +{ + short hold; + + /* return FALSE if fails, TRUE otherwise */ + + /* check for valid input */ + if (nvynum<0 || nvynum>=MAXNAVY || + shipsizeN_HEAVY) + return; + + hold = P_NMER(shipsize) - nships; + if (hold < 0) { + return; + } + /* place new value in proper place */ + hold <<= (N_BITSIZE*shipsize); + + /* set it in variable */ + P_NMSHP |= hold; + + /* form mask so other values won't be changed */ + hold |= ~(N_MASK<<(N_BITSIZE*shipsize)); + + /* now change the variable */ + P_NMSHP &= hold; +} + +void +subgships (nvynum, shipsize, nships) + short nvynum, shipsize, nships; +{ + short hold; + + /* return FALSE if fails, TRUE otherwise */ + + /* check for valid input */ + if (nvynum<0 || nvynum>=MAXNAVY || + shipsizeN_HEAVY) + return; + + hold = P_NGAL(shipsize) - nships; + if (hold < 0) { + return; + } + /* place new value in proper place */ + hold <<= (N_BITSIZE*shipsize); + + /* set it in variable */ + P_NGSHP |= hold; + + /* form mask so other values won't be changed */ + hold |= ~(N_MASK<<(N_BITSIZE*shipsize)); + + /* now change the variable */ + P_NGSHP &= hold; + return; +} + +/* this function finds the total number of ships in a given fleet */ +int +fltships(country,nvynum) + int country, nvynum; +{ + struct s_nation *savntn=curntn; + int i, hold=0; + + curntn= &ntn[country]; + for(i=N_LIGHT;i<=N_HEAVY;i++) { + hold += (int) P_NWAR(i); + hold += (int) P_NMER(i); + hold += (int) P_NGAL(i); + } + curntn= savntn; + return(hold); +} + +#ifdef ADMIN +/* this function returns the speed of a given fleet */ +/* which is the speed of the slowest member. */ +unsigned short +fltspeed(nvynum) + int nvynum; +{ + int i,hold=99; + + /* light ships faster than heavy ships */ + for (i=N_LIGHT;i<=N_HEAVY && hold>N_WSPD;i++) + if (P_NWAR(i)>0) hold=N_WSPD+(2-i)*N_SIZESPD; + + for (i=N_LIGHT;i<=N_HEAVY && hold>N_MSPD;i++) + if (P_NMER(i)>0) hold=N_MSPD+(2-i)*N_SIZESPD; + + for (i=N_LIGHT;i<=N_HEAVY && hold>N_GSPD;i++) + if (P_NGAL(i)>0) hold=N_GSPD+(2-i)*N_SIZESPD; + + if (hold==99) hold=N_NOSPD; + return(hold); +} +#endif /* ADMIN */ + +/* this function returns the amount of storage space in a */ +/* given fleet. heavy+=3 medium+=2 light+=1. */ +int +flthold(nvynum) + int nvynum; +{ + int i,hold=0; + + /* light ships faster than heavy ships */ + for (i=N_LIGHT;i<=N_HEAVY;i++) + { + hold += (i+1) * (int)P_NWAR(i); + hold += (i+1) * (int)P_NMER(i); + hold += (i+1) * (int)P_NGAL(i); + } + return(hold); +} + +#ifdef ADMIN +/* this function returns the amount of storage space in warships */ +int +fltwhold(nvynum) + int nvynum; +{ + int i,hold=0; + + for (i=N_LIGHT;i<=N_HEAVY;i++) + { + hold += (i+1) * (int)P_NWAR(i); + } + return(hold); +} +#endif /* ADMIN */ + +/* this function returns the amount of storage space in galleys */ +int +fltghold(nvynum) + int nvynum; +{ + int i,hold=0; + + for (i=N_LIGHT;i<=N_HEAVY;i++) + { + hold += (i+1) * (int)P_NGAL(i); + } + return(hold); +} + +/* this function returns the amount of storage space in merchants */ +int +fltmhold(nvynum) + int nvynum; +{ + int i,hold=0; + + for (i=N_LIGHT;i<=N_HEAVY;i++) + { + hold += (i+1) * (int)P_NMER(i); + } + return(hold); +} + +#ifdef CONQUER +extern short country; +extern short selector, pager; +extern short xcurs, ycurs, xoffset, yoffset; +extern FILE *fexe; + +/* function to ask for cargo choice */ +static int +get_cargo(str) + char *str; +{ + int choice=(-1); + + mvprintw(LINES-3,0,"%s (A)rmy or (P)eople?",str); + clrtoeol(); + refresh(); + switch(getch()) { + case 'a': + case 'A': + choice=TRUE; + break; + case 'p': + case 'P': + choice=FALSE; + break; + default: + break; + } + + return(choice); +} + +/* this function returns false if loading is invalid */ +int +loadstat(status) + int status; +{ + switch(status) { + case TRADED: + case GENERAL: + case MILITIA: + case GARRISON: + case ONBOARD: + return(FALSE); + break; + default: + break; + } + return(TRUE); +} + +/* this function loads a fleet with an item */ +void +loadfleet() +{ + short nvynum; + /* merchant holding unused */ + int ghold, mhold, unload, doarmy; + int gcargo, mcargo, amount, armynum; + + clear_bottom(0); + if((nvynum=getselunit()-MAXARM)>=0){ + if(nvynum>=MAXNAVY){ + errormsg("Invalid Navy"); + return; + } + } else { + errormsg("Invalid Navy"); + return; + } + + if(sct[XREAL][YREAL].altitude==WATER) { + errormsg("Fleet must be landed"); + return; + } + + /* process loading or unloading */ + ghold = fltghold(nvynum); + mhold = fltmhold(nvynum); + if((ghold==0)&&(mhold == 0)) { + errormsg("No storage space available"); + return; + } else if((P_NARMY==MAXARM)&&(P_NPEOP==0)) { + unload=FALSE; + } else { + mvprintw(LINES-4,0,"Cargo: People %d",P_NPEOP*mhold); + if(P_NARMY==MAXARM) mvaddstr(LINES-4,25,"Army (none)"); + else mvprintw(LINES-4,25,"Army (%d)",P_NARMY); + mvaddstr(LINES-3,0,"Do you wish to (L)oad or (U)nload?"); + refresh(); + switch(getch()) { + case 'l': + case 'L': + unload=FALSE; + break; + case 'u': + case 'U': + unload=TRUE; + break; + default: + return; + } + } + + if(unload==TRUE) { + if(P_NARMY==MAXARM) doarmy=FALSE; + else if(P_NPEOP==0) doarmy=TRUE; + else { + doarmy=get_cargo("Unload"); + } + if(doarmy==TRUE) { + armynum=P_NARMY; + if(sct[XREAL][YREAL].owner==0 + && P_ATYPE!=A_MARINES + && P_ATYPE!=A_SAILOR) { + errormsg("Only sailors or marines may disembark in unowned land"); + return; + } else if (sct[XREAL][YREAL].owner!=country + && sct[XREAL][YREAL].owner!=0 + && P_ATYPE!=A_MARINES) { + errormsg("Only marines may disembark in someone else's land"); + return; + } + P_ASTAT=DEFEND; + P_NARMY=MAXARM; + if (!((sct[XREAL][YREAL].designation==DCITY + || sct[XREAL][YREAL].designation==DCAPITOL) + && (sct[XREAL][YREAL].owner==country + || (!ntn[sct[XREAL][YREAL].owner].dstatus[country]!=UNMET + && ntn[sct[XREAL][YREAL].owner].dstatus[country]<=NEUTRAL))) + || P_NMOVE < N_CITYCOST) { + P_NMOVE=0; + } else { + P_NMOVE-= N_CITYCOST; + } + NADJMOV; + NADJHLD; + AADJSTAT; + } else if(doarmy==FALSE){ + if (sct[XREAL][YREAL].owner!=country) { + mvaddstr(LINES-3,0,"Unload in a sector you don't own? (y or n)"); + clrtoeol(); + refresh(); + if (getch()!='y') { + return; + } + } + mvaddstr(LINES-2,0,"Unload how many people?"); + refresh(); + amount=get_number(); + if(amount > mhold*P_NPEOP) { + errormsg("There are not that many on board"); + } else if (amount > 0) { + sct[XREAL][YREAL].people += amount; + P_NPEOP=(unsigned char)((mhold*P_NPEOP-amount)/mhold); + NADJHLD; + if ((sct[XREAL][YREAL].designation!=DCITY + && sct[XREAL][YREAL].designation!=DCAPITOL) + || P_NMOVE < N_CITYCOST) { + P_NMOVE=0; + } else { + P_NMOVE-= N_CITYCOST; + } + NADJMOV; + SADJCIV; + } + } + } else { + clear_bottom(0); + mcargo = mhold*(SHIPHOLD-P_NPEOP); + if(P_NARMY==MAXARM) { + gcargo = ghold*SHIPHOLD; + mvprintw(LINES-4,0,"Available Space: %d soldiers %d people", gcargo, mcargo); + } else { + gcargo = 0; + mvprintw(LINES-4,0,"Available Space: 0 soldiers %d people", mcargo); + } + if(gcargo==0) doarmy=FALSE; + else if(mcargo==0) doarmy=TRUE; + else { + doarmy=get_cargo("Load"); + } + if(doarmy==TRUE) { + mvaddstr(LINES-2,0,"Load what army?"); + refresh(); + armynum = get_number(); + if(armynum<0) { + ; + } else if((armynum>=MAXARM)||(P_ASOLD<=0) + ||(loadstat(P_ASTAT)==FALSE)) { + errormsg("Invalid Army"); + } else if((P_AXLOC!=XREAL)||(P_AYLOC!=YREAL)) { + errormsg("Army not in sector"); + } else if(P_ASOLD > gcargo && + (P_ATYPE=MINMONSTER)) { + errormsg("Army too large for fleet"); + } else { + P_ASTAT=ONBOARD; + P_AMOVE=0; + P_NARMY=armynum; + if (!((sct[XREAL][YREAL].designation==DCITY + || sct[XREAL][YREAL].designation==DCAPITOL) + && (sct[XREAL][YREAL].owner==country + || (!ntn[sct[XREAL][YREAL].owner].dstatus[country]!=UNMET + && ntn[sct[XREAL][YREAL].owner].dstatus[country]<=NEUTRAL))) + || P_NMOVE < N_CITYCOST) { + P_NMOVE=0; + } else { + P_NMOVE-= N_CITYCOST; + } + NADJMOV; + NADJHLD; + AADJMOV; + AADJSTAT; + } + } else if(doarmy==FALSE && mcargo!=0){ + mvaddstr(LINES-2,0,"Load how many people?"); + refresh(); + amount=get_number(); + if(sct[XREAL][YREAL].owner!=country) { + errormsg("The people refuse to board"); + } else if(amount > mcargo) { + errormsg("Not enough room on fleet"); + } else if(sct[XREAL][YREAL].people < amount) { + errormsg("Not enough people in sector"); + } else if (amount > 0) { + sct[XREAL][YREAL].people -= amount; + P_NPEOP += (unsigned char)(amount / mhold); + SADJCIV; + if ((sct[XREAL][YREAL].designation!=DCITY + && sct[XREAL][YREAL].designation!=DCAPITOL) + || P_NMOVE < N_CITYCOST) { + P_NMOVE=0; + } else { + P_NMOVE-= N_CITYCOST; + } + NADJMOV; + NADJHLD; + } + } else if (mcargo==0) { + errormsg("No more room onboard fleet"); + } + } +} +#endif /* CONQUER */ diff --git a/original/newhelp.c b/original/newhelp.c new file mode 100644 index 0000000..201f12d --- /dev/null +++ b/original/newhelp.c @@ -0,0 +1,324 @@ +/*conquer : Copyright (c) 1988 by Ed Barlow. + * I spent a long time writing this code & I hope that you respect this. + * I give permission to alter the code, but not to copy or redistribute + * it without my explicit permission. If you alter the code, + * please document changes and send me a copy, so all can have it. + * This code, to the best of my knowledge works well, but it is my first + * 'C' program and should be treated as such. I disclaim any + * responsibility for the codes actions (use at your own risk). I guess + * I am saying "Happy gaming", and am trying not to get sued in the process. + * Ed +*/ + +/*include files*/ +#include +#include "header.h" +#include "data.h" +#include "patchlevel.h" + +void +main() +{ + FILE *fp, *fp2, *fopen(); + if((fp=fopen("sed.1","w"))==NULL) { + printf("cannot open sed.1 file\n"); + exit(FAIL); + } + /* needed as sed was reaching its limit on number of commands */ + if((fp2=fopen("sed.2","w"))==NULL) { + printf("cannot open sed.2 file\n"); + exit(FAIL); + } + + /* create sed script */ + fprintf(fp,"s/XOWNER/%s/g\n",OWNER); + fprintf(fp,"s/XLOGIN/%s/g\n",LOGIN); + fprintf(fp,"s/XVERSION/%s.%s/g\n",VERSION,PATCHLEVEL); + fprintf(fp,"s/XPVULCAN/%d/g\n",PVULCAN); + fprintf(fp,"s/XPMOUNT/%d/g\n",PMOUNT); + fprintf(fp,"s/XDEPLETE/%d/g\n",PDEPLETE); + fprintf(fp,"s/XPSTORM/%d/g\n",PSTORM); + fprintf(fp,"s/XNTOTAL/%d/g\n",NTOTAL); + fprintf(fp,"s/XMAXPTS/%d/g\n",MAXPTS); + fprintf(fp,"s/XMAXARM/%d/g\n",MAXARM); + fprintf(fp,"s/XTRADEPCT/%d/g\n",TRADEPCT); + fprintf(fp,"s/XMAXNAVY/%d/g\n",MAXNAVY); + fprintf(fp,"s/XBREAKJIHAD/%ld/g\n",BREAKJIHAD); + fprintf(fp,"s/XCONQENV/%s/g\n",ENVIRON_OPTS); + fprintf(fp,"s/XNCITYCOST/%d/g\n",N_CITYCOST); + fprintf(fp,"s/XREBUILDCOST/%d/g\n",REBUILDCOST); + + /* check all the defined options */ +#ifdef OGOD + fprintf(fp,"s/XOGOD/(True )/g\n"); +#else + fprintf(fp,"s/XOGOD/(False)/g\n"); +#endif +#ifdef DERVDESG + fprintf(fp,"s/XDERVDESG/Dervish can/g\n"); +#else + fprintf(fp,"s/XDERVDESG/Dervish cannot/g\n"); +#endif +#ifdef SYSMAIL + fprintf(fp,"s/XSYSMAIL/(True )/g\n"); +#else + fprintf(fp,"s/XSYSMAIL/(False)/g\n"); +#endif +#ifdef SYSV + fprintf(fp,"s/XSYSV/(True ) /g\n"); +#endif +#ifdef BSD + fprintf(fp,"s/XSYSV/(False:BSD)/g\n"); +#endif +#ifdef MONSTER + fprintf(fp,"s/XMONSTER/(True )/g\n"); +#else + fprintf(fp,"s/XMONSTER/(False)/g\n"); +#endif +#ifdef NPC + fprintf(fp,"s/XNPC/(True )/g\n"); +#ifdef CMOVE + fprintf(fp,"s/XCMOVE/(True )/g\n"); +#else + fprintf(fp,"s/XCMOVE/(False)/g\n"); +#endif +#else + fprintf(fp,"s/XCMOVE/(False)/g\n"); + fprintf(fp,"s/XNPC/(False)/g\n"); +#endif +#ifdef CHEAT + fprintf(fp,"s/XCHEAT/(True )/g\n"); +#else + fprintf(fp,"s/XCHEAT/(False)/g\n"); +#endif +#ifdef RANEVENT + fprintf(fp,"s/XRANEVENT/(True )/g\n"); +#else + fprintf(fp,"s/XRANEVENT/(False)/g\n"); +#endif +#ifdef VULCANIZE + fprintf(fp,"s/XVULCANIZE/(True )/g\n"); +#else + fprintf(fp,"s/XVULCANIZE/(False)/g\n"); +#endif +#ifdef STORMS + fprintf(fp,"s/XSTORMS/(True )/g\n"); +#else + fprintf(fp,"s/XSTORMS/(False)/g\n"); +#endif +#ifdef ORCTAKE + fprintf(fp,"s/XORCTAKE/(True )/g\n"); +#else + fprintf(fp,"s/XORCTAKE/(False)/g\n"); +#endif +#ifdef HIDELOC + fprintf(fp,"s/XHIDELOC/(True )/g\n"); +#else + fprintf(fp,"s/XHIDELOC/(False)/g\n"); +#endif +#ifdef TRADE + fprintf(fp,"s/XTRADE/(True )/g\n"); +#else + fprintf(fp,"s/XTRADE/(False)/g\n"); +#endif + /* map sectors */ + fprintf(fp,"s/ZMOUNTAIN/MOUNTAIN (%c)/g\n",MOUNTAIN); + fprintf(fp,"s/ZHILL/HILL (%c)/g\n",HILL); + fprintf(fp,"s/ZCLEAR/CLEAR (%c)/g\n",CLEAR); + fprintf(fp,"s/ZWATER/WATER (%c)/g\n",WATER); + fprintf(fp,"s/ZPEAK/PEAK (%c)/g\n",PEAK); + fprintf(fp,"s/ZVOLCANO/VOLCANO (%c)/g\n",VOLCANO); + fprintf(fp,"s/ZDESERT/DESERT (%c)/g\n",DESERT); + fprintf(fp,"s/ZJUNGLE/JUNGLE (%c)/g\n",JUNGLE); + fprintf(fp,"s/ZTUNDRA/TUNDRA (%c)/g\n",TUNDRA); + fprintf(fp,"s/ZICE/ICE (%c)/g\n",ICE); + fprintf(fp,"s/ZSWAMP/SWAMP (%c)/g\n",SWAMP); + fprintf(fp,"s/ZGOOD/GOOD (%c)/g\n",GOOD); + fprintf(fp,"s/ZFOREST/FOREST (%c)/g\n",FOREST); + fprintf(fp,"s/ZLIGHT/LIGHT VEG (%c)/g\n",LT_VEG); + fprintf(fp,"s/ZWOOD/WOOD (%c)/g\n",WOOD); + fprintf(fp,"s/ZBARREN/BARREN (%c)/g\n",BARREN); + + /* designations */ + fprintf(fp,"s/ZMINE/MINE (%c)/g\n",DMINE); + fprintf(fp,"s/ZFARM/FARM (%c)/g\n",DFARM); + fprintf(fp,"s/ZGOLD/GOLD MINE (%c)/g\n",DGOLDMINE); + fprintf(fp,"s/ZFORT/FORT (%c)/g\n",DFORT); + fprintf(fp,"s/ZDEVASTATED/DEVASTATED(%c)/g\n",DDEVASTATED); + fprintf(fp,"s/ZTOWN/TOWN (%c)/g\n",DTOWN); + fprintf(fp,"s/ZCITY/CITY (%c)/g\n",DCITY); + fprintf(fp,"s/ZCAPITOL/CAPITOL (%c)/g\n",DCAPITOL); + fprintf(fp,"s/ZSPECIAL/SPECIAL (%c)/g\n",DSPECIAL); + if (DRUIN=='&') + fprintf(fp,"s/ZRUIN/RUIN (\\%c)/g\n",DRUIN); + else + fprintf(fp,"s/ZRUIN/RUIN (%c)/g\n",DRUIN); + fprintf(fp,"s/ZUNIVERSITY/UNIVERSITY(%c)/g\n",DUNIVERSITY); + fprintf(fp,"s/ZBLACKSMITH/BLACKSMITH(%c)/g\n",DBLKSMITH); + fprintf(fp,"s/ZLUMBERYARD/LUMBERYARD(%c)/g\n",DLUMBERYD); + fprintf(fp,"s/ZROAD/ROAD (%c)/g\n",DROAD); + fprintf(fp,"s/ZMILL/MILL (%c)/g\n",DMILL); + fprintf(fp,"s/ZGRANARY/GRANARY (%c)/g\n",DGRANARY); + fprintf(fp,"s/ZCHURCH/CHURCH (%c)/g\n",DCHURCH); + fprintf(fp,"s/ZSTOCKADE/STOCKADE (%c)/g\n",DSTOCKADE); + fprintf(fp,"s/ZSTOCKCOST/%d/g\n",STOCKCOST); + + /* other defines */ +#ifdef RANEVENT + fprintf(fp,"s/XNORANDEVENTS/%d/g\n",RANEVENT); +#else + fprintf(fp,"s/XNORANDEVENTS/0/g\n"); +#endif + fprintf(fp,"s/XLANDSEE/%d/g\n",LANDSEE); + fprintf(fp,"s/XNAVYSEE/%d/g\n",NAVYSEE); + fprintf(fp,"s/XARMYSEE/%d/g\n",ARMYSEE); + fprintf(fp,"s/XTAXFOOD/%ld/g\n",TAXFOOD); + fprintf(fp,"s/XTAXMETAL/%ld/g\n",TAXMETAL); + fprintf(fp,"s/XTAXGOLD/%ld/g\n",TAXGOLD); + fprintf(fp,"s/XTAXCITY/%ld/g\n",TAXCITY); + fprintf(fp,"s/XTAXTOWN/%ld/g\n",TAXTOWN); + fprintf(fp,"s/XSHIPMAINT/%ld/g\n",SHIPMAINT); + fprintf(fp,"s/XSHIPCP/%ld/g\n",SHIPHOLD); + fprintf(fp,"s/XDESCOST/%ld/g\n",DESCOST); + fprintf(fp,"s/XFORTCOST/%ld/g\n",FORTCOST); + fprintf(fp,"s/XWARSHPCOST/%ld/g\n",WARSHPCOST); + fprintf(fp,"s/XMERSHPCOST/%ld/g\n",MERSHPCOST); + fprintf(fp,"s/XGALSHPCOST/%ld/g\n",GALSHPCOST); + fprintf(fp,"s/XSHIPCREW/%ld/g\n",SHIPCREW); + fprintf(fp,"s/XSHIPHOLD/%d/g\n",SHIPHOLD); + fprintf(fp,"s/XWARSPD/%d/g\n",N_WSPD); + fprintf(fp,"s/XGALSPD/%d/g\n",N_GSPD); + fprintf(fp,"s/XMERSPD/%d/g\n",N_MSPD); + fprintf(fp,"s/XSIZESPD/%d/g\n",N_SIZESPD); + fprintf(fp,"s/XNMASK/%d/g\n",(int)N_MASK); + fprintf(fp,"s/XCITYLIMIT/%d/g\n",CITYLIMIT); + fprintf(fp,"s/XMILRATIO/%d/g\n",MILRATIO); + fprintf(fp,"s/XMILINCAP/%d/g\n",MILINCAP); + fprintf(fp,"s/XBRIBE/%ld/g\n",BRIBE); + fprintf(fp,"s/XDESFOOD/%d/g\n",DESFOOD); + fprintf(fp,"s/XTOMUCHMINED/%d/g\n",TOMUCHMINED); + fprintf(fp,"s/XTOMANYPEOPLE/%d/g\n",TOMANYPEOPLE); + fprintf(fp,"s/XABSMAXPEOPLE/%d/g\n",ABSMAXPEOPLE); + fprintf(fp,"s/XFINDPERCENT/%d/g\n",FINDPERCENT); +#ifdef ORCTAKE + fprintf(fp,"s/XTAKEPRICE/%d/g\n",ORCTAKE); +#endif /* ORCTAKE */ + + fprintf(fp,"s/XTGATTR/%d/g\n",TGATTR); + fprintf(fp,"s/XOTHRATTR/%d/g\n",OTHRATTR); + fprintf(fp2,"s/XGOLDATTR/%d/g\n",GOLDATTR); + fprintf(fp2,"s/XFARMATTR/%d/g\n",FARMATTR); + fprintf(fp2,"s/XMINEATTR/%d/g\n",MINEATTR); + fprintf(fp2,"s/XTOWNATTR/%d/g\n",TOWNATTR); + fprintf(fp2,"s/XCITYATTR/%d/g\n",CITYATTR); + fprintf(fp2,"s/XCAPATTR/%d/g\n",CITYATTR); + + fprintf(fp2,"s/XDMNTNATTR/%3d/g\n",DMNTNATTR); + fprintf(fp2,"s/XDHILLATTR/%3d/g\n",DHILLATTR); + fprintf(fp2,"s/XDCLERATTR/%3d/g\n",DCLERATTR); + fprintf(fp2,"s/XDCITYATTR/%3d/g\n",DCITYATTR); + fprintf(fp2,"s/XDTOWNATTR/%3d/g\n",DTOWNATTR); + fprintf(fp2,"s/XDGOLDATTR/%3d/g\n",DGOLDATTR); + fprintf(fp2,"s/XDMINEATTR/%3d/g\n",DMINEATTR); + fprintf(fp2,"s/XDFOREATTR/%3d/g\n",DFOREATTR); + fprintf(fp2,"s/XDWOODATTR/%3d/g\n",DWOODATTR); + + fprintf(fp2,"s/XEMNTNATTR/%3d/g\n",EMNTNATTR); + fprintf(fp2,"s/XEHILLATTR/%3d/g\n",EHILLATTR); + fprintf(fp2,"s/XECLERATTR/%3d/g\n",ECLERATTR); + fprintf(fp2,"s/XECITYATTR/%3d/g\n",ECITYATTR); + fprintf(fp2,"s/XETOWNATTR/%3d/g\n",ETOWNATTR); + fprintf(fp2,"s/XEGOLDATTR/%3d/g\n",EGOLDATTR); + fprintf(fp2,"s/XEMINEATTR/%3d/g\n",EMINEATTR); + fprintf(fp2,"s/XEFOREATTR/%3d/g\n",EFOREATTR); + fprintf(fp2,"s/XEWOODATTR/%3d/g\n",EWOODATTR); + + fprintf(fp2,"s/XOMNTNATTR/%3d/g\n",OMNTNATTR); + fprintf(fp2,"s/XOHILLATTR/%3d/g\n",OHILLATTR); + fprintf(fp2,"s/XOCLERATTR/%3d/g\n",OCLERATTR); + fprintf(fp2,"s/XOCITYATTR/%3d/g\n",OCITYATTR); + fprintf(fp2,"s/XOTOWNATTR/%3d/g\n",OTOWNATTR); + fprintf(fp2,"s/XOGOLDATTR/%3d/g\n",OGOLDATTR); + fprintf(fp2,"s/XOMINEATTR/%3d/g\n",OMINEATTR); + fprintf(fp2,"s/XOFOREATTR/%3d/g\n",OFOREATTR); + fprintf(fp2,"s/XOWOODATTR/%3d/g\n",OWOODATTR); + + fprintf(fp2,"s/XHMNTNATTR/%3d/g\n",HMNTNATTR); + fprintf(fp2,"s/XHHILLATTR/%3d/g\n",HHILLATTR); + fprintf(fp2,"s/XHCLERATTR/%3d/g\n",HCLERATTR); + fprintf(fp2,"s/XHCITYATTR/%3d/g\n",HCITYATTR); + fprintf(fp2,"s/XHTOWNATTR/%3d/g\n",HTOWNATTR); + fprintf(fp2,"s/XHGOLDATTR/%3d/g\n",HGOLDATTR); + fprintf(fp2,"s/XHMINEATTR/%3d/g\n",HMINEATTR); + fprintf(fp2,"s/XHFOREATTR/%3d/g\n",HFOREATTR); + fprintf(fp2,"s/XHWOODATTR/%3d/g\n",HWOODATTR); + + /* magical power costs for races */ +#ifdef ELFMAGIC + fprintf(fp2,"s/XEMMAG/%3ldK/g\n",ELFMAGIC/1000L); +#else + fprintf(fp2,"s/XEMMAG/%3ldK/g\n",BASEMAGIC/1000L); +#endif +#ifdef DWFMAGIC + fprintf(fp2,"s/XDMMAG/%3ldK/g\n",DWFMAGIC/1000L); +#else + fprintf(fp2,"s/XDMMAG/%3ldK/g\n",BASEMAGIC/1000L); +#endif +#ifdef HUMMAGIC + fprintf(fp2,"s/XHMMAG/%3ldK/g\n",HUMMAGIC/1000L); +#else + fprintf(fp2,"s/XHMMAG/%3ldK/g\n",BASEMAGIC/1000L); +#endif +#ifdef ORCMAGIC + fprintf(fp2,"s/XOMMAG/%3ldK/g\n",ORCMAGIC/1000L); +#else + fprintf(fp2,"s/XOMMAG/%3ldK/g\n",BASEMAGIC/1000L); +#endif + + /* civilian power costs for races */ +#ifdef ELFCIVIL + fprintf(fp2,"s/XECMAG/%3ldK/g\n",ELFCIVIL/1000L); +#else + fprintf(fp2,"s/XECMAG/%3ldK/g\n",BASEMAGIC/1000L); +#endif +#ifdef DWFCIVIL + fprintf(fp2,"s/XDCMAG/%3ldK/g\n",DWFCIVIL/1000L); +#else + fprintf(fp2,"s/XDCMAG/%3ldK/g\n",BASEMAGIC/1000L); +#endif +#ifdef HUMCIVIL + fprintf(fp2,"s/XHCMAG/%3ldK/g\n",HUMCIVIL/1000L); +#else + fprintf(fp2,"s/XHCMAG/%3ldK/g\n",BASEMAGIC/1000L); +#endif +#ifdef ORCCIVIL + fprintf(fp2,"s/XOCMAG/%3ldK/g\n",ORCCIVIL/1000L); +#else + fprintf(fp2,"s/XOCMAG/%3ldK/g\n",BASEMAGIC/1000L); +#endif + + /* military power costs for races */ +#ifdef ELFMILIT + fprintf(fp2,"s/XEWMAG/%3ldK/g\n",ELFMILIT/1000L); +#else + fprintf(fp2,"s/XEWMAG/%3ldK/g\n",BASEMAGIC/1000L); +#endif +#ifdef DWFMILIT + fprintf(fp2,"s/XDWMAG/%3ldK/g\n",DWFMILIT/1000L); +#else + fprintf(fp2,"s/XDWMAG/%3ldK/g\n",BASEMAGIC/1000L); +#endif +#ifdef HUMMILIT + fprintf(fp2,"s/XHWMAG/%3ldK/g\n",HUMMILIT/1000L); +#else + fprintf(fp2,"s/XHWMAG/%3ldK/g\n",BASEMAGIC/1000L); +#endif +#ifdef ORCMILIT + fprintf(fp2,"s/XOWMAG/%3ldK/g\n",ORCMILIT/1000L); +#else + fprintf(fp2,"s/XOWMAG/%3ldK/g\n",BASEMAGIC/1000L); +#endif + fclose(fp); + fclose(fp2); + exit(SUCCESS); +} diff --git a/original/newlogin.c b/original/newlogin.c new file mode 100644 index 0000000..fbcec99 --- /dev/null +++ b/original/newlogin.c @@ -0,0 +1,1386 @@ +/*conquer : Copyright (c) 1988 by Ed Barlow. + * I spent a long time writing this code & I hope that you respect this. + * I give permission to alter the code, but not to copy or redistribute + * it without my explicit permission. If you alter the code, + * please document changes and send me a copy, so all can have it. + * This code, to the best of my knowledge works well, but it is my first + * 'C' program and should be treated as such. I disclaim any + * responsibility for the codes actions (use at your own risk). I guess + * I am saying "Happy gaming", and am trying not to get sued in the process. + * Ed + */ + +/*create a new login for a new player*/ +#include +#include +#include +#include +#include +#include +#include "patchlevel.h" +#include "header.h" +#include "data.h" +#include "newlogin.h" + +/* information about national classes */ +char *Classwho[]= { "DEHO", "DEH", "DEH", "EH", "H", "DHO", "HE", "DHO", + "O", "O", "O" }; +char *CPowlist[]= { "None", "None", "None", "SUMMON", "RELIGION", "SAILOR", + "URBAN", "WARLORD", "DESTROYER", "MA_MONST", "THE_VOID"}; +int Classcost[]= { 0, 0, 0, 4, 2, 2, 2, 6, 4, 4, 2 }; +long Classpow[]= { 0x0L, 0x0L, 0x0L, SUMMON, RELIGION, SAILOR, + URBAN, 0x000000007L, DESTROYER, 0x00000700L, THE_VOID }; + +char *Mprompt[]= { "" }; +char *LType[]={ "Random", "Fair", "Great" }; + +char *Mlabels[]= { "Population", "Treasury", "Location", + "Military", "Attack Bonus", "Defense Bonus", "Reproduction", + "Movement", "Magic Powers", "Leaders", "Raw Materials" }; + +char *Mitems[]= { "people", "gold talons", "location", "soldiers", + "percent", "percent", "percent", "move points", "powers", + "nation leaders", "units of food" }; + +char *Mhelp[]= { "Population: Amount of citizens in your nation", + "Treasury: Amount of monetary wealth in your nation", + "Location: Relative value of nation placement in world", + "Soldiers: Number of men in the national army, not counting leaders", + "Attack Bonus: Skill level of your troops when attacking", + "Defense Bonus: Skill level of your troops when defending", + "Reproduction: Yearly rate of civilian population increase", + "Movement: Number of movement points per normal army unit", + "Magic Powers: Randomly obtain a new magical power", + "Leaders: Number of leader units, including national ruler", + "Raw Materials: Starting values for jewels, metal, and food" }; + +extern int pwater; /* percent water in world (0-100) */ +extern FILE *fexe, *fopen(); +extern short country; +int numleaders; +int spent[CH_NUMBER]; + +/* Teraform the area around somebodies capitol */ +/* this gives everybody some chance of success */ +void +teraform( x,y,range, chance ) +int x,y; +int range,chance; +{ + int i,j; + switch(curntn->race) { + case DWARF: + sct[x][y].altitude=MOUNTAIN; + for(i=x-range;i<=x+range;i++) + for(j=y-range;j<=y+range;j++) + if((i!=x)&&(j!=y)&&(ONMAP(i,j)) + &&(sct[i][j].altitude!=WATER)){ + if (rand()%3==0) + sct[i][j].altitude=MOUNTAIN; + else sct[i][j].altitude=HILL; + + if( rand()%100 < chance ) getmetal( &sct[i][j] ); + } + return; + case ELF: + sct[x][y].vegetation = FOREST; + for(i=x-range;i<=x+range;i++) + for(j=y-range;j<=y+range;j++) + if((i!=x)&&(j!=y)&&(ONMAP(i,j)) + &&(sct[i][j].altitude!=WATER)) { + if (rand()%3==0) + sct[i][j].vegetation=FOREST; + else sct[i][j].vegetation=WOOD; + if( rand()%100 < chance ) getjewel( &sct[i][j] ); + } + return; + case ORC: + sct[x][y].altitude=MOUNTAIN; + for(i=x-range;i<=x+range;i++) + for(j=y-range;j<=y+range;j++) + if((i!=x)&&(j!=y)&&(ONMAP(i,j)) + &&(sct[i][j].altitude!=WATER)) { + if (rand()%3==0) + sct[i][j].altitude=MOUNTAIN; + else sct[i][j].altitude=HILL; + + if( rand()%100 < chance ) { + if(rand()%2==0) + getmetal( &sct[i][j] ); + else getjewel( &sct[i][j] ); + } + } + return; + case HUMAN: + sct[x][y].altitude = CLEAR; + for(i=x-range;i<=x+range;i++) + for(j=y-range;j<=y+range;j++) + if((i!=x)&&(j!=y)&&(ONMAP(i,j)) + &&(sct[i][j].altitude!=WATER)) { + if (rand()%2==0) + sct[i][j].altitude = CLEAR; + + if (rand()%2==0) + sct[i][j].vegetation=WOOD; + else sct[i][j].vegetation=GOOD; + + if( rand()%100 < chance ) { + if (rand()%2==0) + getmetal( &sct[i][j] ); + else getjewel( &sct[i][j] ); + } + } + return; + } +} + +void +mailtopc(string) +char *string; +{ + int ctry; + for( ctry=0; ctrytciv = Mvalues[CH_PEOPLE] * spent[CH_PEOPLE]; + curntn->tgold = Mvalues[CH_TREASURY] * spent[CH_TREASURY]; + switch(spent[CH_LOCATE]) { + case 2: + curntn->location = GREAT; + break; + case 1: + curntn->location = FAIR; + break; + case 0: + default: + curntn->location = RANDOM; + break; + } + curntn->tmil = Mvalues[CH_SOLDIERS] * spent[CH_SOLDIERS]; + curntn->aplus = (short) Mvalues[CH_ATTACK] * spent[CH_ATTACK]; + curntn->dplus = (short) Mvalues[CH_DEFEND] * spent[CH_DEFEND]; + curntn->repro = (char) Mvalues[CH_REPRO] * spent[CH_REPRO]; + curntn->maxmove = (unsigned char) Mvalues[CH_MOVEMENT] + * spent[CH_MOVEMENT]; + for(i = 0; i < spent[CH_MAGIC]; i++) { + /* purchase magic */ + loop = TRUE; + while (loop == TRUE) { + if((x=getmagic((rand()%M_MGK+M_MIL)))!=0L){ + CHGMGK; + loop = FALSE; + } + } + } + numleaders = (int) Mvalues[CH_LEADERS] * spent[CH_LEADERS]; + curntn->tfood = Mvalues[CH_RAWGOODS] * spent[CH_RAWGOODS]; + curntn->jewels = NLJEWELS * spent[CH_RAWGOODS]; + curntn->metals = NLMETAL * spent[CH_RAWGOODS]; +} + +void +newlogin(realuser) + int realuser; +{ + /* use points to create empire, add if late starter*/ + int points, clr; + int pccount; + int choice, direct; + int valid=TRUE; /*valid==FALSE means continue loop*/ + int temp,ypos,xpos; + int more=TRUE; /*0 if add another player*/ + long x; + char tempc[LINELTH]; + char passwd[PASSLTH+1]; + register i; + + /* setup curses display */ + newinit(); + + /*find valid nation number type*/ + country=0; + pccount=0; + for(i=1;i=NTOTAL-REVSPACE)) { + newerror("No more nations available"); + newreset(); + return; + } + + /* open output for future printing*/ + mvprintw(0,0,"Building Country Number %d",country); + sprintf(tempc,"%s%d",exefile,i); + if ((fexe=fopen(tempc,"w"))==NULL) { + sprintf(tempc,"Error opening <%s>",tempc); + newerror(tempc); + newbye(FAIL); + } + + /* begin purchasing */ + points=MAXPTS; + for (i=0; iNAMELTH)){ + newerror("Invalid Name Length"); + valid=FALSE; + } + + /*check if already used*/ + if((strcmp(tempc,"god")==0) + ||(strcmp(tempc,"unowned")==0)){ + newerror("Name already used"); + valid=FALSE; + } + + for(i=1;iname,tempc); + move(0,0); + clrtoeol(); + move(1,0); + clrtoeol(); + standout(); + mvprintw(0,COLS/2-15-strlen(curntn->name)/2, + "< Building Country %s >",curntn->name,country); + standend(); + clrtoeol(); + + valid=FALSE; + while(valid==FALSE) { /* password routine */ + mvaddstr(2,0,"Enter National Password: "); + clrtoeol(); + refresh(); + i = get_pass(tempc); + if (i < 2) { + newerror("Password Too Short"); + continue; + } else if (i > PASSLTH) { + newerror("Password Too Long"); + continue; + } + mvaddstr(2,0,"Reenter National Password: "); + clrtoeol(); + refresh(); + i = get_pass(passwd); + + if((i<2)||(i>PASSLTH)||(strncmp(passwd,tempc,PASSLTH)!=0)){ + newerror("Invalid Password Match"); + } else valid=TRUE; + } + strncpy(curntn->passwd,crypt(tempc,SALT),PASSLTH+1); + + /*get your name*/ + valid=FALSE; + while(valid==FALSE) { + valid=TRUE; + mvaddstr(2,0,"Enter the name of your country's leader (Ex. The Ed, Gandalf, Conan)"); + clrtoeol(); + mvprintw(3,0," [maximum %d characters]: ",LEADERLTH); + refresh(); + get_nname(tempc); + if((strlen(tempc)>LEADERLTH)||(strlen(tempc)<2)) { + newerror("Invalid Name Length"); + valid=FALSE; + } + else strcpy(curntn->leader,tempc); + } + + mvprintw(2,0,"Leader Name: %s", curntn->leader); + clrtoeol(); + mvaddstr(3,0,"Enter your Race [ (D)warf (E)lf (H)uman (O)rc ]:"); + clrtoeol(); + refresh(); + valid=FALSE; + while(valid==FALSE) { + valid=TRUE; + switch(getch()) { + case 'D': + case 'd': + /*MINER POWER INATE TO DWARVES*/ + newmsg("Dwarves have MINING skills"); + mvaddstr(3,0,"National Race: Dwarf"); + clrtoeol(); + curntn->powers=MINER; + x=MINER; + CHGMGK; + points -= getclass(DWARF); + curntn->race=DWARF; + spent[CH_TREASURY]=NLDGOLD; + spent[CH_RAWGOODS]=NLDRAW; + spent[CH_PEOPLE]= NLDCIVIL; + spent[CH_SOLDIERS]= NLDMILIT; + spent[CH_REPRO]= NLDREPRO; + spent[CH_MOVEMENT]= NLDMMOVE; + spent[CH_ATTACK]= NLDAPLUS; + spent[CH_DEFEND]= NLDDPLUS; + spent[CH_LOCATE]= NLRANDOM; + points-=nstartcst(); + break; + case 'E': + case 'e': + newmsg("Elves are magically cloaked (VOID power)"); + mvaddstr(3,0,"National Race: Elf"); + clrtoeol(); + curntn->powers=THE_VOID; + x=THE_VOID; + CHGMGK; + points -= getclass(ELF); + curntn->race=ELF; + spent[CH_TREASURY]=NLEGOLD; + spent[CH_RAWGOODS]=NLERAW; + spent[CH_PEOPLE]= NLECIVIL; + spent[CH_SOLDIERS]= NLEMILIT; + spent[CH_REPRO]= NLEREPRO; + spent[CH_MOVEMENT]= NLEMMOVE; + spent[CH_ATTACK]= NLEAPLUS; + spent[CH_DEFEND]= NLEDPLUS; + spent[CH_LOCATE]= NLFAIR; + points-=nstartcst(); + break; + case 'O': + case 'o': + /*MINOR MONSTER POWER INATE TO ORCS*/ + newmsg("Your leader is a Monster!"); + mvaddstr(3,0,"National Race: Orc"); + clrtoeol(); + curntn->powers=MI_MONST; + x=MI_MONST; + CHGMGK; + points -= getclass(ORC); + curntn->race=ORC; + spent[CH_TREASURY]=NLOGOLD; + spent[CH_RAWGOODS]=NLORAW; + spent[CH_PEOPLE]= NLOCIVIL; + spent[CH_SOLDIERS]= NLOMILIT; + spent[CH_REPRO]= NLOREPRO; + spent[CH_MOVEMENT]= NLOMMOVE; + spent[CH_ATTACK]= NLOAPLUS; + spent[CH_DEFEND]= NLODPLUS; + spent[CH_LOCATE]= NLRANDOM; + points-=nstartcst(); + break; + case 'H': + case 'h': + curntn->race=HUMAN; + newmsg("Humans have the combat skill of a WARRIOR"); + mvaddstr(3,0,"National Race: Human"); + clrtoeol(); + curntn->powers = WARRIOR; + x=WARRIOR; + CHGMGK; + points -= getclass(HUMAN); + spent[CH_TREASURY]=NLHGOLD; + spent[CH_RAWGOODS]=NLHRAW; + spent[CH_PEOPLE]= NLHCIVIL; + spent[CH_SOLDIERS]= NLHMILIT; + spent[CH_REPRO]= NLHREPRO; + spent[CH_MOVEMENT]= NLHMMOVE; + spent[CH_ATTACK]= NLHAPLUS; + spent[CH_DEFEND]= NLHDPLUS; + spent[CH_LOCATE]= NLRANDOM; + points-=nstartcst(); + break; + default: + valid=FALSE; + } + } + mvprintw(4,0,"Nation Class: %s",Class[curntn->class]); + clrtoeol(); + + valid=FALSE; + if( curntn->race == ORC ) { /* orcs are always evil */ + valid=TRUE; + curntn->active=PC_EVIL; + } else { + mvaddstr(5,0,"Please Enter Alignment [ (G)ood, (N)eutral, (E)vil ]"); + refresh(); + } + while (valid==FALSE) { + valid=TRUE; + switch(getch()) { + case 'G': + case 'g': + curntn->active=PC_GOOD; + break; + case 'N': + case 'n': + curntn->active=PC_NEUTRAL; + break; + case 'E': + case 'e': + curntn->active=PC_EVIL; + break; + default: + valid=FALSE; + break; + } + } + mvprintw(2,COLS/2,"Alignment: %s", alignment[curntn->active]); + clrtoeol(); + + + /* get new nation mark */ + curntn->mark = ' '; + while(TRUE) { + temp = 30; + mvaddstr(6,0,"This can be any of the following:"); + for (tempc[0]='!';tempc[0]<='~';tempc[0]++) { + if( markok( tempc[0], FALSE ) ) { + temp += 2; + if (temp>COLS-20) { + printw("\n "); + temp = 8; + } + printw(" %c",tempc[0]); + } + } + mvaddstr(5,0,"Enter National Mark (for maps): "); + clrtoeol(); + refresh(); + tempc[0] = getch(); + if( markok( tempc[0], TRUE ) ){ + curntn->mark=(*tempc); + break; + } + } + + mvprintw(3,COLS/2,"National Mark [%c]",curntn->mark); + clrtoeol(); + move(5,0); + clrtoeol(); + move(6,0); + clrtoeol(); + move(7,0); + clrtoeol(); + refresh(); + + ypos = 6; + mvprintw(ypos,0," %-13s %s", "ITEM", "CURRENTLY HAVE" ); + mvprintw(ypos++,COLS/2+5,"%4s %s", "COST", "AMOUNT" ); + for(i=0; irace==ORC) { + switch(i) { + case CH_MOVEMENT: + mvaddstr(ypos++,COLS/2+5," - --------"); + continue; + case CH_REPRO: + x = 2*Munits[i]*Mvalues[i]; + break; + case CH_ATTACK: + case CH_DEFEND: + x = Munits[i]*Mvalues[i]/2; + break; + default: + x = Munits[i]*Mvalues[i]; + break; + } + mvprintw(ypos,COLS/2+5,"%3d for",Mcost[i]); + printw(" %ld %s", x, Mitems[i]); + } else { + mvprintw(ypos,COLS/2+5,"%3d for",Mcost[i]); + printw(" %ld %s", Munits[i]*Mvalues[i], Mitems[i]); + } + } + ypos++; + } + + /* show everything before menu */ + direct = ADDITION; + choice = CH_PEOPLE; + xpos = COLS/2; + ypos = 7; + valid = FALSE; + clr = 1; + standout(); + mvaddstr(LINES-4,2,"DONE=ESC EXEC=SPACE INFO=\"?\" ADD=\"<+h\" SUBtract=\">+l\" UP=\"k\" DOWN=\"j\""); + standend(); + + while(valid==FALSE) { + if (clr==1) { + standout(); + mvprintw(4,COLS/2,"Points Left: %d", points); + standend(); + clrtoeol(); + clr++; + } else if (clr==2) { + newmsg(""); + clr = 0; + } + standout(); + mvaddstr(ypos+choice,xpos,Mprompt[direct]); + standend(); + refresh(); + switch(getch()) { + case ' ': + /* redraw */ + wrefresh(stdscr); + break; + case '?': + /* help on topic */ + newerror(Mhelp[choice]); + break; + case '\033': + /* exit option */ + if (points > 0) { + newmsg("Use remaining points for population? [ny]"); + if (getch()!='y') { + newerror("All points must be spent prior to exiting"); + break; + } + temp = points * Munits[CH_PEOPLE] / Mcost[CH_PEOPLE]; + x = temp * Mvalues[CH_PEOPLE]; + spent[CH_PEOPLE] += temp; + showitem(ypos+CH_PEOPLE,CH_PEOPLE); + points = 0; + sprintf(tempc,"Buying %ld more civilians", x); + newerror(tempc); + } + newmsg("Is the modification complete? (y or n)"); + while (((temp=getch())!='y')&&(temp!='n')) ; + if (temp == 'y') { + valid = TRUE; + } + clr = 1; + break; + case '-': + case '>': + case 'l': + case 'L': + /* subtraction */ + direct = SUBTRACTION; + break; + case '+': + case '<': + case 'h': + case 'H': + /* addition */ + direct = ADDITION; + break; + case '\b': + case '\177': + /* decrease choice -- with wrap */ + mvaddstr(ypos+choice,xpos," "); + if (choice==CH_PEOPLE) { + choice = CH_RAWGOODS; + } else { + choice--; + if (choice==CH_MOVEMENT && curntn->race==ORC) { + choice--; + } + } + break; + case 'k': + case 'K': + /* move choice up one */ + if (choice > CH_PEOPLE) { + mvaddstr(ypos+choice,xpos," "); + choice--; + if (choice==CH_MOVEMENT && curntn->race==ORC) { + choice--; + } + } + break; + case '\r': + case '\n': + /* increase choice -- with wrap */ + mvaddstr(ypos+choice,xpos," "); + if (choice==CH_RAWGOODS) { + choice = CH_PEOPLE; + } else { + choice++; + if (choice==CH_MOVEMENT && curntn->race==ORC) { + choice++; + } + } + break; + case 'j': + case 'J': + /* move choice down one */ + if (choice < CH_RAWGOODS) { + mvaddstr(ypos+choice,xpos," "); + choice++; + if (choice==CH_MOVEMENT && curntn->race==ORC) { + choice++; + } + } + break; + case ' ': + case '.': + /* make the selection */ + if (curntn->race == ORC) { + switch(choice) { + case CH_REPRO: + temp = 2*Munits[choice]; + break; + case CH_ATTACK: + case CH_DEFEND: + temp = Munits[choice]/2; + break; + default: + temp = Munits[choice]; + break; + } + } else temp = Munits[choice]; + if (direct == ADDITION) { + if (Mcost[choice] > points) { + sprintf(tempc, "You do not have %d points to spend", + Mcost[choice]); + newerror(tempc); + } else if ((choice == CH_REPRO)&&(curntn->race==ORC) + &&(spent[choice] + temp > 12)) { + newerror("You may not purchase any more of that item"); + } else if ((spent[choice] + temp > Maxvalues[choice]) + &&((curntn->race!=ORC)||(choice!=CH_REPRO))) { + newerror("You may not purchase any more of that item"); + } else { + spent[choice] += temp; + newmsg("You now have "); + dispitem(choice,spent[choice]*Mvalues[choice]); + showitem(ypos+choice,choice); + points -= Mcost[choice]; + clr = 1; + } + } else if (direct == SUBTRACTION) { + if (spent[choice] - temp < Minvalues[choice]) { + newerror("You may not sell back any more of that item"); + } else { + spent[choice] -= temp; + newmsg("You now have "); + dispitem(choice,spent[choice]*Mvalues[choice]); + showitem(ypos+choice,choice); + points += Mcost[choice]; + clr = 1; + } + } + break; + default: + break; + } + } + + /* check for save */ + newmsg("Save this nation? [ny]"); + if(getch()!='y'){ + curntn->active=INACTIVE; + curntn->powers=0; + newerror("Ok, Nation Deleted"); + fclose(fexe); + } else { + convert(); + place(-1,-1); + newerror("Ok, Your Nation has been Added to the World"); + att_setup(country); /* setup values ntn attributes */ +#ifdef CHECKUSER + curntn->uid = realuser; +#endif + fclose(fexe); + pccount++; + sprintf(tempc,"NOTICE: Nation %s added to world on turn %d\n",curntn->name,TURN); + mailtopc(tempc); + /* cannot clear until after placement and initializing */ + curntn->powers=0; + } +#ifndef CHECKUSER + country=0; + for(i=1;i=NTOTAL-REVSPACE)) { + newmsg("Do you wish to Add another Nation? [ny]"); + if (getch()!='y') more = FALSE; + else more = TRUE; + } else { + more = FALSE; + newerror("No More Available Nations"); + } +#else + more = FALSE; +#endif + } + newreset(); + att_base(); /* calculate base nation attributes */ + writedata(); +} + +/*****************************************************************/ +/* PLACE(): put nation on the map. Fill out army structures too */ +/*****************************************************************/ +void +place(xloc,yloc) +int xloc,yloc; /* if not -1,-1 should place in this spot */ +{ + int placed=0,armysize=100; + short armynum=0; + long people; + char tempo[LINELTH+1]; + int x,y,i,j,temp,t; + int n=0, leadtype; + long soldsleft; /* soldiers left to place */ + + if( xloc != -1 && yloc != -1 && is_habitable(xloc,yloc)) { + placed=1; + x = xloc; + y = yloc; + } + + switch(curntn->location) { + case OOPS: + while((placed == 0)&&(n++<2000)){ + if(ispc(curntn->active)){ + x = (rand()%(MAPX-8))+4; + y = (rand()%(MAPY-8))+4; + } else { + x = (rand()%(MAPX-2))+1; + y = (rand()%(MAPY-2))+1; + } + if(is_habitable(x,y)) placed=1; + + for(i=x-1;i<=x+1;i++) for(j=y-1;j<=y+1;j++) + if(sct[i][j].owner!=0) placed=0; + temp=0; + for(i=x-1;i<=x+1;i++) for(j=y-1;j<=y+1;j++) + if(sct[i][j].altitude==WATER) temp++; + if(temp>=7) placed=0; + } + if(placed) teraform( x,y,1,25 ); + break; + case RANDOM: + while ((placed == 0)&&(n++<2000)){ + if(ispc(curntn->active)){ + if(MAPX>12){ + x = rand()%(MAPX-12)+6; + y = rand()%(MAPY-12)+6; + } else { + x = rand()%(MAPX-8)+4; + y = rand()%(MAPY-8)+4; + } + if(is_habitable(x,y)) placed=1; + /*important that no countries near*/ + for(i=x-2;i<=x+2;i++) for(j=y-2;j<=y+2;j++) + if((isntn(ntn[sct[i][j].owner].active)) + &&(sct[i][j].owner!=0)) placed=0; + } else { + x = (rand()%(MAPX-6))+3; + y = (rand()%(MAPY-6))+3; + if(is_habitable(x,y)) placed=1; + /*important that no countries near*/ + for(i=x-2;i<=x+2;i++) for(j=y-2;j<=y+2;j++) + if((isntn(ntn[sct[i][j].owner].active)) + &&(sct[i][j].owner!=0)) placed=0; + } + temp=0; + for(i=x-1;i<=x+1;i++) for(j=y-1;j<=y+1;j++) + if(sct[i][j].altitude==WATER) temp++; + if(temp>=7) placed=0; + for(i=x-1;i<=x+1;i++) for(j=y-1;j<=y+1;j++) + if(sct[i][j].owner!=0) placed=0; + } + if(placed) teraform( x,y,1,40 ); + break; + case FAIR: + while ((placed == 0)&&(n++<2000)) { + if(ispc(curntn->active)){ + if(MAPX>24) { + x = rand()%(MAPX-24)+12; + } else { + x = rand()%(MAPX-14)+7; + } + if(MAPY>24) { + y = rand()%(MAPY-24)+12; + } else { + y = rand()%(MAPY-14)+7; + } + } else { + x = rand()%(MAPX-10)+5; + y = rand()%(MAPY-10)+5; + } + + if(!is_habitable(x,y)) continue; + if(tofood( &sct[x][y],country)50) { + temp=0; + for(i=x-1;i<=x+1;i++) for(j=y-1;j<=y+1;j++) + if(sct[i][j].altitude==WATER) temp++; + if(temp>=7) placed=0; + + /*important that no countries near*/ + for(i=x-3;i<=x+3;i++) for(j=y-3;j<=y+3;j++){ + if((isntn(ntn[sct[i][j].owner].active)) + &&(sct[i][j].owner!=0)) placed=0; + } + } else { + temp=0; + for(i=x-1;i<=x+1;i++) for(j=y-1;j<=y+1;j++) + if(sct[i][j].altitude==WATER) temp++; + if(temp>=5) placed=0; + + /*important that no countries near*/ + for(i=x-3;i<=x+3;i++) for(j=y-3;j<=y+3;j++){ + if((isntn(ntn[sct[i][j].owner].active)) + &&(sct[i][j].owner!=0)) placed=0; + } + } + } + + if(placed) teraform( x,y,1,65 ); + break; + case GREAT: + placed = 0; + while ((placed == 0) && (n++<2000)){ + if(ispc(curntn->active)){ + if (MAPX>40){ + x = rand()%(MAPX-40)+20; + }else{ + x = rand()%(MAPX-18)+9; + } + if (MAPY>40){ + y = rand()%(MAPY-40)+20; + }else{ + y = rand()%(MAPY-18)+9; + } + + if(is_habitable(x,y)) placed=1; + /*important that no countries near*/ + for(i=x-4;i<=x+4;i++) for(j=y-4;j<=y+4;j++){ + if((isntn(ntn[sct[i][j].owner].active)) + &&( sct[i][j].owner!=0)) placed=0; + } + } else { + if(MAPX>24){ + x = rand()%(MAPX-24)+12; + }else { + x = rand()%(MAPX-12)+6; + } + if(MAPY>24){ + y = rand()%(MAPY-24)+12; + }else { + y = rand()%(MAPY-12)+6; + } + if(is_habitable(x,y)) placed=1; + /*important that no countries near*/ + for(i=x-4;i<=x+4;i++) for(j=y-4;j<=y+4;j++){ + if((isntn(ntn[sct[i][j].owner].active)) + &&(sct[i][j].owner!=0)) placed=0; + } + } + + for(i=x-1;i<=x+1;i++) for(j=y-1;j<=y+1;j++) + if(sct[i][j].owner!=0) placed=0; + + temp=0; + /*if any water within 2 sectors placed = 0*/ + for(i=x-2;i<=x+2;i++) for(j=y-2;j<=y+2;j++) + if(tofood( &sct[x][y],country)<=0) + temp++; + + if( pwater>50 ) { + if(temp>=18) placed=0; + } else { + if(temp>=15) placed=0; + } + } + if(placed) teraform( x,y,1,100 ); + } + + /*done with one try*/ + if(placed==1) { + curntn->capx = x; + curntn->capy = y; + sct[x][y].designation=DCAPITOL; + sct[x][y].tradegood=rand()%(END_KNOWLEDGE-END_SPOILRATE)+END_SPOILRATE+1; + sct[x][y].jewels=0; + sct[x][y].metal=0; + sct[x][y].owner=country; + sct[x][y].people=curntn->tciv; + sct[x][y].fortress=5; + + /* put all military into armies of armysize */ + armysize = (TAKESECTOR*12)/10; + if(armysize<100) armysize=100; + /* cant have more than 50% leaders */ + if( MAXARM < numleaders * 2 ) numleaders = MAXARM / 2; + armynum=0; + soldsleft = curntn->tmil; + P_ASOLD = curntn->tmil/MILINCAP; + soldsleft-=P_ASOLD; + P_ATYPE=defaultunit(country); + P_ASTAT=GARRISON; + P_AMOVE=0; + P_AXLOC=curntn->capx; + P_AYLOC=curntn->capy; + armynum++; + + armysize = max( armysize, soldsleft / (MAXARM-numleaders-1)); + + /* give you your leaders */ + leadtype = getleader(curntn->class); + P_ATYPE = leadtype-1; /* This is the national leader */ + P_ASOLD = *(unitminsth+((leadtype-1)%UTYPE)); + P_AXLOC = curntn->capx; + P_AYLOC = curntn->capy; + P_ASTAT = DEFEND; + P_AMOVE = 2*curntn->maxmove; + armynum++; + numleaders--; + while ((armynum < MAXARM)&&(numleaders>0)) { + P_ATYPE=leadtype; + P_ASOLD= *(unitminsth+(leadtype%UTYPE)); + P_AXLOC=curntn->capx; + P_AYLOC=curntn->capy; + P_ASTAT=DEFEND; + P_AMOVE=2*curntn->maxmove; + armynum++; + numleaders--; + } + + /* give you the rest of your armies */ + while((armynum < MAXARM)&&(soldsleft >0)) { + P_ATYPE=defaultunit(country); + if(soldsleft >= armysize){ + P_ASOLD=armysize; + soldsleft -=armysize; + } else { + P_ASOLD=soldsleft ; + soldsleft=0; + } + P_AXLOC=curntn->capx; + P_AYLOC=curntn->capy; + P_ASTAT=DEFEND; + P_AMOVE=curntn->maxmove; + armynum++; + } + + if(soldsleft >0) { + curntn->arm[0].sold += soldsleft; + curntn->arm[0].unittyp = A_INFANTRY; + } + + /* give you some terain to start with: pc nations get more*/ + if (isnotpc(curntn->active)) t=1; + else if (curntn->location==OOPS) t=0; + else if (curntn->location==RANDOM) t=0; + else if (curntn->location==FAIR) t=1; + else if (curntn->location==GREAT) t=2; + else { + if (ispc(curntn->active)) + newerror("Error in finding placement"); + t=0; + } + if( t==1 ) + people = sct[x][y].people / 12; + else if( t==2 ) + people = sct[x][y].people / 30; + + curntn->tsctrs=1; + for(i=x-t;i<=x+t;i++) for(j=y-t;j<=y+t;j++) + if((tofood( &sct[i][j],country)>=DESFOOD) + &&(sct[i][j].owner==0) + &&(is_habitable(i,j)==TRUE) + &&(sct[i][j].people==0)) { + curntn->tsctrs++; + sct[i][j].owner=country; + sct[i][j].designation=DFARM; + sct[i][j].people=people; + sct[x][y].people-=people; + } + /* make sure status is set properly */ + for(i=0;ilocation==OOPS) { + newerror("MAJOR ERROR IN PLACEMENT"); + } else if(curntn->location==RANDOM) { + newerror("Random Place Failed, trying to place again"); + curntn->location=OOPS; + place(-1,-1); + } else if(curntn->location==FAIR) { + sprintf(tempo,"Fair Place Failed, trying again - Adding %ld people to nation",Munits[CH_PEOPLE]*Mvalues[CH_PEOPLE]/Mcost[CH_PEOPLE]); + newerror(tempo); + /*give back one point -> NLPOP people*/ + curntn->tciv += Munits[CH_PEOPLE] * Mvalues[CH_PEOPLE] + / Mcost[CH_PEOPLE]; + curntn->location=RANDOM; + place(-1,-1); + } else if(curntn->location==GREAT) { + sprintf(tempo,"Great Place Failed, trying again - Adding %ld people to nation",Munits[CH_PEOPLE]*Mvalues[CH_PEOPLE]/Mcost[CH_PEOPLE]); + newerror(tempo); + /*give back one point -> NLPOP people*/ + curntn->tciv+= Munits[CH_PEOPLE] * Mvalues[CH_PEOPLE] + / Mcost[CH_PEOPLE]; + curntn->location=FAIR; + place(-1,-1); + } + } +} + +/*get class routine*/ +/* return the number of points needed */ +int +getclass(race) + int race; +{ + short chk=FALSE; + short tmp; + short ypos=4; + int i,j; + + mvaddstr(ypos,0,"The List of Possible Nation Classes:"); + ypos+=2; + mvprintw(ypos++,0," %-8s %4s %15s %8s %4s", "class", "who", + "", "magic", "cost"); + mvprintw(ypos++,0," %-8s %4s %15s %8s %4s", "--------", "----", + "", "-------", "----"); + for(i=1;i NUMCLASS) { + newerror("Invalid Choice"); + } else if (in_str(race,Classwho[tmp])==TRUE) { + chk = TRUE; + } else { + newerror("That Class is Invalid for your Race"); + } + } + curntn->class=tmp; + for(tmp=ypos; tmp>4; tmp--) { + move(tmp,0); + clrtoeol(); + } + + return( doclass( curntn->class, TRUE ) ); +} + +int +doclass( tmp, isupd ) +short tmp; +int isupd; /* true if update, false if interactive */ +{ + int cost; + long x; + + /* determine number of leaders you want */ + if((tmp == C_TRADER) || (tmp <= C_WIZARD)) { + numleaders = spent[CH_LEADERS] = 5; + } else { + numleaders = spent[CH_LEADERS] = 7; + } + + /* assign the powers */ + x=Classpow[tmp]; + + /* check for special case */ + if (tmp==C_WARLORD && curntn->race==HUMAN) { + x ^= WARRIOR; + cost = Classcost[tmp]*2/3; + } else { + cost = Classcost[tmp]; + } + curntn->powers |= x; + + if ( isupd ) CHGMGK; + return(cost); +} + +int +nstartcst() /* to be used for new method */ +{ + float points=0.0; + char temp[LINELTH]; + int i; + + /* calculate cost for all so far */ + for (i=0; i 0.0 ) { + sprintf(temp,"%.1f points added for starting late", + (float) (TURN-1) / LATESTART); + newerror(temp); + } + points += 1.0; /* round up */ + return((int)points); +} + +int +startcost() /* cant be used for npc nations yet!!! see below */ +{ + float points; /* points */ + + points = ((float)curntn->tciv)/ONLPOP; + points += ((float)curntn->tgold)/ONLGOLD; + points += ((float)curntn->tmil)/ONLSOLD; + if(curntn->race==ORC) { + points += ((float)curntn->repro)*ONLREPCOST/(ONLREPRO_ORC); + points += ((float)curntn->aplus*2)/ONLATTACK; + points += ((float)curntn->dplus*2)/ONLDEFENCE; + } else { + points += ((float)curntn->aplus)/ONLATTACK; + points += ((float)curntn->dplus)/ONLDEFENCE; + points += ((float)curntn->repro)*ONLREPCOST/ONLREPRO; + } + points += ((float)curntn->maxmove)/ONLMOVE; + if(curntn->location==FAIR) + points += ONLLOCCOST; + else if(curntn->location==GREAT) + points += 2*ONLLOCCOST; + /* points+=ONLDBLCOST*curntn->tfood/ONLHFOOD; */ + points -= (TURN-1) / LATESTART; /* extra points if you start late */ + if( TURN > 1 ) + printf("point cost for nation %d is %.2f (bonus for latestart is %f)\n",country,points,(float) (TURN-1)/LATESTART); + + points += 1.0; /* round up */ + return((int) points); +} diff --git a/original/newlogin.h b/original/newlogin.h new file mode 100644 index 0000000..1392123 --- /dev/null +++ b/original/newlogin.h @@ -0,0 +1,104 @@ +/*conquer : Copyright (c) 1988 by Ed Barlow. */ + +/*selection defines */ +#define CH_PEOPLE 0 +#define CH_TREASURY 1 +#define CH_LOCATE 2 +#define CH_SOLDIERS 3 +#define CH_ATTACK 4 +#define CH_DEFEND 5 +#define CH_REPRO 6 +#define CH_MOVEMENT 7 +#define CH_MAGIC 8 +#define CH_LEADERS 9 +#define CH_RAWGOODS 10 +/* how many selections there are */ +#define CH_NUMBER 11 + +/* location defines */ +#define NLRANDOM 0 +#define NLFAIR 1 +#define NLGOOD 2 + +/* direction defines */ +#define ADDITION 0 +#define SUBTRACTION 1 + +/* number of units for dwarf nations */ +#define NLDGOLD 1 +#define NLDRAW 1 +#define NLDCIVIL 6 +#define NLDMILIT 2 +#define NLDREPRO 4 +#define NLDMMOVE 6 +#define NLDAPLUS 20 +#define NLDDPLUS 20 + +/* number of units for elf nations */ +#define NLEGOLD 1 +#define NLERAW 1 +#define NLECIVIL 7 +#define NLEMILIT 1 +#define NLEREPRO 5 +#define NLEMMOVE 8 +#define NLEAPLUS 10 +#define NLEDPLUS 40 + +/* number of units for orc nations */ +#define NLOGOLD 0 +#define NLORAW 1 +#define NLOCIVIL 8 +#define NLOMILIT 2 +#define NLOREPRO 8 +#define NLOMMOVE 6 +#define NLOAPLUS 0 +#define NLODPLUS 0 + +/* number of units for human nations */ +#define NLHGOLD 0 +#define NLHRAW 1 +#define NLHCIVIL 6 +#define NLHMILIT 2 +#define NLHREPRO 5 +#define NLHMMOVE 10 +#define NLHAPLUS 20 +#define NLHDPLUS 10 + +/* the following has been placed in the header for clarity in configuration */ +/* since newlogin.c is the only file to include this file, there should */ +/* be no problems; even though it is probably not a good idea. */ + +/* the minimum/maximum levels for each selection */ +int Minvalues[]= { 6, 0, 0, 1, 0, 0, 4, 6, 0, 4, 1 }; +int Maxvalues[]= { 50, 10, 2, 20, 80, 80, 10, 30, 5, MAXARM/2, 10 }; + +/* the number of points spent on each selection */ +int Mcost[]= { 1, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1 }; + +/* the number of units per cost */ +int Munits[]= { 1, 1, 1, 1, 8, 8, 1, 2, 1, 3, 1 }; + +/* The list of corresponding values of each unit */ +long Mvalues[]= { 1000L, 100000L, 1L, 1000L, 1L, 1L, 1L, + 1L, 1L, 1L, 30000L }; + +/* values for jewels and metal (food is last in array above) */ +#define NLJEWELS 15000L +#define NLMETAL 15000L + +/* the old definitions */ +#define ONLPOP 1000L +#define ONLGOLD 100000L +#define ONLLOCCOST 1 +#define ONLSOLD 900L +#define ONLATTACK 10 +#define ONLDEFENCE 10 +#define ONLREPRO_ORC 2 /* repro points per ONLREPCOST for orcs */ +#define ONLREPRO 1 /* repro points per ONLREPCOST for others */ +#define ONLREPCOST 3 +#define ONLMOVE 2 +#define ONLDBLCOST 1 +#define ONLMAGIC 3 +/* get ONLEADER leaders for ONLEADPT points */ +#define ONLEADER 3 +#define ONLEADPT 1 diff --git a/original/notes.v4 b/original/notes.v4 new file mode 100644 index 0000000..7601f74 --- /dev/null +++ b/original/notes.v4 @@ -0,0 +1,1237 @@ +------------------------------------------------------------------------------ +| THIS FILE CONTAINS RELEASE NOTES FOR CONQUER V4.0 | +| It is broken into 3 sections. Section 3 reflects changes from v3.5 to v4. | +| Section 1 reflects bugs in v4.0. Section 2 reflects future ideas. | +------------------------------------------------------------------------------ +------------------------------------------------------------------------- +| 1.0 == Bugs Fixed From Conquer Version 4.0 ========================== | +------------------------------------------------------------------------- + 1. increased newstring[] array from 40 to 100 in makeworl.c. + 2. corrected a mispelling of irrigation. + 3. line 830 of makeworl.c, added a y=(rand()%20); statement. + 4. corrected some bugs in newlogin() routine. Fixed orc repro buying. + 5. made the -d flag be a subdirectory of DEFAULTDIR if not beginning + with a '/'. + 6. fixed overruns of NTOTAL throughout the game. + 7. new function to decrease size of a test statement in extcmds.c. + 8. changed newlogin routine for detection of available countries. + 9. merged do_lizard() and updlizard(). [used name do_lizard()]. + 10. fixed bug with getchar querys in makeworl.c. + 11. fixed bug with y < MAPX mistype in randeven.c. +===4.0 patch number one released => 4.1 ========================== + 12. fixed underflow problems with unsigned chars xloc,yloc,xcap,ycap. + 13. misc.c(834): changed "owner=DCAPITOL" to "designation=DCAPITOL". + 14. npc.c(171,172): changed rand()%2-1 to rand()%3-1. + 15. randeven.c: put #ifdef MONSTER around nomad raid section. + 16. reports.c(618): changed flthold() to fltmhold(). + 17. combat.c(488,510): changed "-=0" to "=0". + 18. newlogin.c(507): changed temp < points to temp > points. + 19. newlogin.c(795): added "& MAPY > 24". + 20. extcmds.c(365): fixed check on same location for merging groups. + 21. newhelp.c(163): added #ifdef for RANEVENT to newhelp.c. + 22. altered map printing routines to send to stdout, and have stderr be + for communicating with the user. so now "conqrun -p > foo" works. + 23. removed password checking under -p option. would only be useful if + OGOD was defined, and if that was the case, only god could get + to that point anyway. + 24. made copyright screen variable with screen size. + 25. added TIMELOG feature to use system date command to show last update time. + 26. made errormsg display on COLS-20 instead of 60. fixed up display bugs. + 27. added more names to rebel name list. + 28. worked on Makefile. [made sure of parallelism; ready to distribute] + 29. reworded treasury display on budget screen for clarity. +===4.0 patch number two released => 4.2 ========================== + 30. worked more on Makefile. trying to fix others problems with .SUFFIXES. + 31. line 142 of commands.c: fixed bug with assignment of designation. + 32. main.c: added environment variable CONQ_NATION. overridden by '-n'. + 33. main.c: added environment variable CONQ_DATA. overridden by '-d'. + 34. patch to magic.c to extend printable user magics. [Bob Earl]. + 35. added BIGLTH, and FILELTH character string size constants. + 36. made NPC a number as with MONSTER. + 37. added new option '-G' for gaudy news country highlights. [T. Kivinen]. + 38. fixed bug with clearing WAR declarations in destroy. [T. Kivinen]. + 39. Added a CONQ_OPTS environment variable... can contain many options. + Format: setenv CONQ_OPTS "G,nation=foo,data=1" + so far only G (Gaudy News), nation, and data supported, may now + remove the redundant CONQ_NATION, CONQ_DATA. + 40. patched newlogin.c to fix check of new nation name [Bob Earl]. + 41. added LOCKF portion to FILELOCK for NFS systems [Richard Caley]. + 42. added routine to print designations with '-p' [Richard Caley]. + 43. added variations on 'data' or 'nation' to CONQ_OPTS (ex. 'name'). + 44. NEAT NEW FEATURE! DEMI-GOD! Now, ntn[0].leader holds the login name + of a user who has update and god priveledge on that data file. + It is set during world creation and changable from the 'c' command + during the game. ['c' for nation '0' to view name]. + This allows people to run their own games without owning conquer. + 45. Neatened the nation mark selection display in newlogin.c. + 46. Decided to remove default setting of nation mark.... always ask now. + 47. Fixed bugs in newlogin: 'points <= 0' where it should be 'temp <= 0'. + 48. Shortened name of monsters to 7 characters to prevent screen wrap. + 49. newlogin.c (916): decreased amount allocated for population dispersal. + 50. added command to select prior unit ['o'] like 'p' [Kianush Sayah-Karadji]. + 51. extcmds.c (174,178) fix to allow switching out of march. [Kevin Murray]. + 52. added a #define XENIX for some XENIX 386 specific bugs. [Jonathan Bayer]. + 53. reworked the make new_game in the Makefile. + 54. fixed the calculation of available nations in the campaign info screen. + 55. made slight adjustment to required wealth for gold mines. + 56. big redo on the Makefile. hopefully this is now static. + 57. completed change of Barbarians to Savages. Only makeworl.c vars now. + 58. removed the CONQ_DATA and CONQ_NATION environment variables since + the CONQ_OPTS covers them and can even be expanded more later. + 59. big revamp of the helpfiles. caught a few errors. + 60. added ntn[0].leader to the 'please contact' messages in admin and main. + 61. added monsters and peasants to the '-s' display. [Doesn't show size]. + 62. changed get_number() to return -1 for no input... fixed all occurances. + 63. reinstated ship and food trading. NOTE!!! Nothing has really been + done to fix it... use at own risk. Perhaps someone will find the + bugs and fix them. [these trading routines are only temp anyway.] + 64. added CONQ_OPTS to admin.c, ignore everything but "datadir=". + 65. spent ENTIRE weekend and rewrote newlogin.c. NEW NEWLOGIN HAS: + - curses screen interface. + - entire input is character by character. + - nice sliding arrow menu selection for final menu. + - may add or subtract from final menu. + - information on each selection is available via '?'. + - move up and down via 'hjkl', 'DEL', or 'RET'. + - in order to weaken orc population a little, set max repro. + during nation build to 12. [May still reach 14 through magic]. + - almost all selections are handled in the same manor, this. + allows for easier debugging and better code. + - the following routines will be available for a future makeworld. + interface: newinit(), newbye(), newmsg(), newerror(), newreset(). + 66. rewrote all routines that were called during a newlogin so that print + statments use the newerror() or newmsg() interface. +===4.0 patch number three released => 4.3 ========================== + 67. fixed a bug reported long ago.. negative treasury and charity. + I get too damn much mail. [I just sent #3 out!!!!] + 68. main.c(798): "%s%s" to "%s%d"... fixes bug in sprintf. + 69. added sprinf(defaultdir,"") to main.c and admin.c. + 70. put test on error messages in place() to make sure it won't call newerror. + 71. moved the '-p' option from admin.c to main.c. + 72. made error messages in main.c go to stderr instead of stdout. + 73. made the '-p' flag display world as seen by nations eyes. + 74. made the designation portion of the display print elevation when NODESIG. + 75. added fix to make sure that demi-god exists. [Richard Caley] + 76. added check to makeworld to make sure given demi-god name exists. + 76. also added a check to forms.c for demi-god name change. + 76. added checks for ORCTAKE definitions to newhelp.c [Jerome Marella] + 77. added a CURRENT directory definition to Makefile. [Kevin Coombes] + 78. fixed bugs in XENIX defines. [Jonathan Bayer] + 79. display.c(301): "+" -> '+'; I thought I fixed this *sigh*. [Richard Caley] + 80. added a REMAKE compiler option to allow destruction of currently running + games. This is usable by demi-god to restart a campaign. + 81. fixed up the man page. + 82. wrote a non-echo string entry routine for curses password entry. + 83. added above routine to newlogin.c, makeworl.c, and forms.c. + 84. removed restriction on changing to NPC after making moves. + This makes sense... since players may move NPC pieces anyway. + 85. changed the makeworld routine to curses interface. This is still + rather rudimentary, and will be worked on prior to Version 5.0. + 86. added NADJLOC; to the two split sections in reports.c:fleetrpt(). + 87. corrected misspelling of alignment throughout code. + 88. added check to land_reachp() for neutral status. [Michael D. Smith] + 89. added MORE_MONST compiler option to decide whether or not empty + monster armies should be filled during the game. + 90. fixed misspelling of 'defence' in npc.c and txt4. + 91. fixed overflow of jewels and metal displaying in newlogin.c. + 92. *&$%! fixed a stupid bug with checking if leader is really dead. + 93. added a 'shipchk' to the prep routine. hopefully will fix land taking. + 94. added a redraw after movement if in army highlight mode. + 95. added in new method for displaying anything in 2nd column. [Richard Caley] + 96. tweeked the prompting for the second column display method. + 97. rewrote the section in the help files on the display mode. + 98. fixed major bug with destroying any army in water. [Ben Herman] + Another bug I thought I fixed long ago. *sigh* + 99. newlogin.c(1034): typo caused nations to be too close. [Wes Shreiner] +100. decrease range of nomad movement to 1 sector from locaton. +101. removed the shipchk from prep()... didn't do jack anyway. +102. hacked at the display code some to fix redeclarations and unused vars. +103. fixed the bug with not being able to take sectors. involved status + of nations not being at WAR with nomads. fixed this by setting + statuses in three places: destroy(), place(), check(). +104. fixed seg fault when entering change() for savages. +105. removed the printing to fp in change() routine. +106. changed npctype to detect monsters, otherwise it core dumps. +107. changed the alignment printing for savages back to what it was. +108. made sure that NPCs do not group or disband ZOMBIES. +109. added a NOSCORE compiler option to allow only god to see full score list. +110. changed the class name NPC to monster. +===4.0 patch number four released => 4.4 =========================== +111. fixed bug with scouts being grouped by NPCs. +112. fixed bug that did not provide NPCs with leaders. +113. reworked cexecute.c to allow multiple magic initializations. +114. touched up newlogin() and makeworld(). +115. installed routines to limit NPCs by following the VOID and HIDDEN + powers. [] +116. altered the killmagk() routine to allow addition and removal: god_magk(). +117. commented out some nations from the nations file. +118. tinkered with makeworl.c again. +119. added in the conqps functions by Martin Forrsen. +120. rewrote cheat() routine to verify that nation hadn't been touched by + a player during that turn. +121. made a 'PLEASE WAIT' message appear on login, since response of some + computers is slower than expected during startup. [T. Kivinen] +122. made sure fison was changed properly during 'z' command. [T. Kivinen] +123. changed monster capture statements to go to end of page. [T. Kivinen] +124. altered newpaper() to allow quick scaning. [T. Kivenen] +125. added a rudimentary repeat command to repeat last unit affecting command. +126. altered the 'reading ....' statements in DEBUG mode to go to stderr. +127. ships now lose only N_CITYCOST movepoints when unloading in cities. +128. shifted movement below xloc,yloc in army reports for readability. +129. fixed the redrawing of sectors after movement. +130. added a patch to avoid a compiler bug in display.c [Richard Caley] +131. improved screen clearing routine installed. [T. Kivinen] +132. revamped display under the move people command. +133. added fix to make sure '-p' command checks void properly. [D. Caplinger] +134. inserted a check for allowing extra clear when redrawing. +135. renamed all of the conqps source files to 'psmap'. +===4.0 patch number five released => 4.5 =========================== +136. changed situations of string printing mvprintw's to mvaddstr's. +137. moved a 'makebottom()' from 'm'ove command to parse routine. +138. npc.c (1339): added a check for ntn[country].tciv > 0 [T. Kivinen] +139. reset both roads_this_turn and terror_adj in login change. [T. Kivinen] +140. fixed overflow on wealth calculations [K. Bera] +141. adjusted flee() code for incremental people adjustment [K. Bera] +142. added patch to include XENIX header file in update.c [J. Bayer] +143. fixed passing of a parameter in god_magk() call. +144. fixed highlight function call three places in move.c. +145. fixed prep function call in move.c and io.c. +146. fixed get_display_for function call in display.c. +147. adjusted txt1 to clarify attractiveness calculation. {9 per jewels + was written as 9 / jewels. Changed it to 9 * jewels.} [T. Kivenen] +148. implemented the command 'X' to center screen around a nations capitol. +149. implemented the command 'x' to center screen around given sector. +150. in god mode, the 'X' command jumps between active nations' capitols. +151. centered screen about captitol during initial login. +152. gave god the ability to move civilians using 'Z' {#ifdef OGOD}. +153. altered calcuation of both poverty and inflation and added to txt5. +154. changed F_OK to 00 in update.c. +155. rewrote the isinstr() function in psmap.c to avoid the use of index(). +156. implemented tests throughout find_avg_sector() for zero division. +157. changed astr,dstr to floats in combat.c (198). [Bob Earl] +158. added use of indicator instead of using MGKNUM in combat.c. [T. Kivinen] +159. added extra check in land_reachp() for movecost < 0. [Dean Brooks] +160. removed MOVECOST from 'd'isplay command. +161. altered bottom display of move() after error messages. +162. added makebottom() to civilian movement, was accidently removed(?) +163. big adjustment to mining_ability and wealth: + -if it is lowered, it decreases by only a quarter of the difference. +164. fixed typo and checking of placed in terraform() [Dean Brooks] +165. added in dgod_make flag to indicate if the demi-god is remaking. +166. added setting of spell points to zero in zeroworld(). +167. renamed dgod_make to remake and made demi-god be default for any remake. +168. changed the clear(); in change() to move(0,0); clrtobot(); +169. added move(0,0), etc. to fleetrpt() and armyrpt(). +170. moved the makebottom(); to parse after the EXT_CMD entry. +171. added move(0,0), etc. to fleetrpt() and armyrpt(). +172. added move(0,0), etc. to trade() in trade.c. +173. made major adjustments to the mailing routines mailopen() mailclose(). +174. rewrote the mail interface to be a little more robust. +175. the mail writing and reading routines now prevent most conflicts. +176. made the mail writer a little spiffier. +177. fixed a bug in detection of leader death and recreation in update.c. +178. no longer charge BREAKJIHAD for breaking one-sided treaties. +179. added in fix to ruin redesignation when DERVISH or DESTROYER. +180. allow redesignation of ruin to a non-city type at REBUILDCOST cost. +181. altered the god_mgk() display routine a little. +182. added in a limit of 16% to charity creeping for democracy. +183. added a check for a line with a period on it to end mail. +===4.0 patch number six released => 4.6 ================================= +184. fixed bug in checking of sector population in construction of ships. +185. fixed bug with reversed if statement in god vegetation redesignation. +186. adjusted get_god routine to display prompt at bottom of screen only. +187. adjusted lizard fortress creation routine to increase gold and fort value. +188. fixed some display bugs with the god_magk() routines. +189. made spoilrate calculation floating point to avoid overflow. +190. fixed a bug with checking of password for 'z' command. +191. made the "DESTROY NATION" message in forms.c not clear screen. +192. made sure that WYZARD was not removable in random events. +193. fixed bug with randevent.c calculation of sector locations [D. Brooks] +194. implemented check to assure that MORE_MONST isn't too strong [R. Caley] +195. made sure god could destroy of monster nations in forms.c. +196. moved the 'z' command to the bottom portion of the screen. +197. fixed bug with get_nname(); accidently allowed up to NAMELTH+1 chars. +198. adjusted bottom of diplomacy screen to be more like other screens. +199. made the 'W' prompt appear at the bottom of the screen. +200. combat.c [636,637]: owner[k] -> UOWNER(k). [Ken Dalka] +201. added a break to the nation name detection in main.c [Brad Isley] +202. fixed mistype of '<' to '>' reports.c (647) [Richard Kennaway] +203. adjusted calculation of attack bonus cost to avoid overflow [R. Kennaway] +204. fixed bug in printing nation name, update.c (579) [R. Kennaway] +205. adjusted output in wdisaster(). [R. Kennaway] +206. implemented check for limit of 12 in fortification. [should be #define] +207. removed a number of local variable declarations of country in misc.c. +208. allow changing of status of other nation is non-unmet. +209. added the option to change population for god in (r)edesignate command. +210. added time check on mail lock files to avoid old files lying around. +211. added ability for god to change combat statuses of nations. +212. added time check to lock files as well, (thrice mail lock death time). +213. fixed bug in prep so that ships do not protect sectors from capture. +214. fixed overflow bug in GOLDTHRESH jewel purchase during update. +215. added new method for calculation of MORE_MONSTers (R. Caley) +216. for the 100th time, made sure that volcano victims are not revealed. +217. more adjustments to make sure sector locations are correct in randeven.c. +218. removed restrictions on mill and granary redesignating. +219. fixed spelling of "rebelion" to "rebellion" in two places in randeven.c. +220. changed inflation to be a yearly rate (where did I leave my head?). +221. adjusted offmap() in io.c to be consistent with coffmap(). +222. putzed around in npc.c trying to catch a bug. +223. recenter new display upon going off screen. +224. update.c[821]: ">" to ">=" take with exact number of men. [Dave Flowers] +225. update.c[1017]: "min(" to "max(" (woops!! major typo) [Dave F.] +226. trade.c: altered visibility of items for sale. [Dave F.] +227. misc.c[498]: fixed overflow on gold scoring [Kenneth J Dalka] +228. adjusted inflation calculation in update.c and reports.c. +229. added the inflation estimation to the budget report. +230. fixed bug with division of charity by population. [Charles C. Fu] +231. prevent passage of fleets through hostile cities. +232. added some checks in npc.c for ownership in drafting in some sectors. +233. removed destruction of troops on peaks, now that flight is possible. +234. changed to min zero in attractiveness, now drift will no longer occur + for sectors with "zero" attractiveness. [Dave F.] +===4.0 patch number seven released => 4.7 =============================== +235. update.c[1327]: "ispc(country)" => "ispc(curntn->active)" +236. added a note to README and fixed credit in notes.v4 file. +237. made sure npcs do not change scout status. +238. fixed bug with include files in check.c. [J. Bayer] +239. update.c[1073]: declare items as unsigned char [Rodney Orr] +240. update.c[1541]: rewrote move_people() routine to avoid memory leak + and to use only 5 / MAPX as much memory. +241. adjusted casting in propuction screen for food consumption. +242. trade.c: added check for unexpected end of file in trade [R. Orr] +243. newlogin.c: removed the check() in the routine. +244. added news notification during update if npc/pc mode is changed. +245. removed useless ifdef REMAKE statement in admin.c. +246. added check for edge of screen unnecessarily redrawing. +247. added check for motion beyond edge of screen. +248. added stoppage for going beyond map edges. +249. checked for invalid reads of commerce file in trade.c. +250. changed float casting back to longs at line 1052 of update.c. +251. did the same for the calculations in function budget() of report.c. +252. fixed display.c designation to show tofood(sctptr, country). +253. made Dragyn the nation leader name and Dragon the monster name. +254. restricted marching troops from being grouped. (could get into + defend mode this way; even when they had marched too far). +255. allow recombination of troops with same status and same type + unless the type is TRADED or ON_BOARD. +===4.0 patch number eight released => 4.8 =============================== +256. made sure that minor leaders lived before becoming major leaders. +257. fixed major bug on not resetting status of moved grouped unit. +258. set a grouped movement to be equal to the movement of the leader. +259. added missing return to commands.c (1341) [Paul Waterman] +260. made sure only to ask for splitting warships when warships are there. +261. no longer ask to split ships that are not in fleet. +262. allow god to manipulate a fleet up for trade. +263. fixed bug that -1 population may accidently be set by god. +264. fixed bug that caused missetting of gold/jewel value by god. +265. allow god to manipulate an army that is up for trade. +266. added check to assure that navies do not carry invalid troops. +267. added check for onboard armies to be sure they were actually on fleets. +268. reformated the bottom of the display on the read message display. +269. made sure that stones had the designation of '?' to allow them to work. +270. increased reduction on movement in desert for DERVISH to avoid confusion. +271. made sure that blank input would not be taken on redesignate owner. +272. fiddled and diddled (sorry Johnny!) with the charity change check. +273. fixed bug with providing movement to unmovable when having ROADS power. +274. added ifdef's around srand declarations for ANSI compilers. [C. Fu] +275. removed error message for people relocation. too common an occurance. +276. allow naval battles along shore. [Charles C. Fu] +277. prevent sailors or marines from retreating. [Charles C. Fu] +278. redid the retreat code... made the test much simpler. +279. slight adjustment to ONMAP macro [Charles C. Fu] +280. keep random value of army sizes the same for when seen. [Charles C. Fu] +281. keep random value of ship sizes the same when seen. [Charles C. Fu] +282. keep random value of people in sector the same. [Charles C. Fu] +283. do not allow navies to pass into impassible land [partial fix: C. Fu] +284. make it harder to unload armies in enemy cities [Charles C. Fu] +285. make it harder to load armies in enemy cities [Charles C. Fu] +286. fixed mistype "P_ASOLD" => "P_ATYPE" npc.c [Charles C. Fu] +287. check for division by zero with metals cost for troops +288. make NPC pay metal for troops. [Charles C. Fu] +289. have NPC nations adjust tax rates as appropriate. [Charles C. Fu] +290. give rebel nations a tax rate of 10. [Charles C. Fu] +291. extend view of tradeing list for long screens [Charles C. Fu] +292. refresh() added to end of trade input routine [Charles C. Fu] +293. do not process invalid country is takeback [Charles C. Fu] +294. cause trade to fail for destroyed army or fleet. [Charles C. Fu] +295. fixed mistype which prevented sale of land. [Charles C. Fu] + {Darn!, My sabotage was caught! :-) adam} +296. fixed missetting of curntn which blocked ship trades [Charles C. Fu] + {Foiled Again! :-) Actually that code predated curntn use, so + we were bound to miss some in the conversion, adam} +297. fixed bug with returning bids to losing nations [Charles C. Fu] +298. let land trades fail during trade, not before [Charles C. Fu] (whatever) +299. convert to doubles for calculation of treasury overflow. [C. Fu] +300. relocated adjustment to MARCHer movment when changing statuses. +301. added in a routine to give the items up for trade to a nation if + it captures a nations capitol. [David Soleno] +302. fixed error messages generated by the orc takeover routine. +303. made the rules file be read in from the default directory. +304. made spell point gain for MONST powers additive. +305. put a 25% cap on user defined charity. +306. adjusted the combat routine to separate naval and army combat checks. +307. added in a check to assure that combining overlarge fleets is checked. +308. verified input checks in various locations in report.c. +309. made god adjustment of ships to allow keeping of previous values on '\n'. +310. gave god the ability to adjust army unit types. +311. gave god the ability to adjust army move values. +312. gave god the ability to adjust navy move values. +313. fixed bug in reporting side during newspaper for naval battles. +314. gave god the ability to adjust an army status. +===4.0 patch number nine released => 4.9 =============================== +315. adjusted the combat code so a unit must be on attack to attack. +316. "#ifdef __STDC__" to "#ifndef __STDC__" typo fix. [Charles C. Fu] +317. fixed summon documentation for Heros and Superheros. +318. adjusted test stat in tradeit function of trade.c [Charles C. Fu] +319. fixed password length termination bugs. +320. raised the limit of nation destruction to under 250 civs and 50 mil. +321. adjusted method of i_people calculation to improve accounting. [D. Brooks] +322. fixed check on limit in cities [D. Brooks] +323. make nation destruction occur for <100 people and 4.11 ==(spide)==================== +WARNING: This patch may require re-creation of any worlds from scratch + (not compatible with worlds created under 4.10 if CHECKUSER set) + -spide (mcy1580@ultb.isc.rit.edu) +327. added LASTADD + o the last turn that players may add w/o the god password +328. added CHECKUSER to enable uid locking on nations + o checks the uid of the player against the one who + created the nation - to prevent a player from creating + two nations and using one to take over another. +329. added USERLOG to turn on logging of game/nation usage + o sorta useful info - creates a .userlog file +330. added MASK/umask in admin.c to allow group read/write as well + o so people in same group (games) could look at files +331. added REVSPACE to be able to leave room in nation list for revolts + o allow space in nation list for revolts - to discourage + players from setting take rate to 20% when no room for + revolts - leaves room at the beginning of game for them. +332. modified spell sector effect to be 1 pt / 1000 people as documented + o something we wanted +333. added -l (-ngod) option so god can list owners of nations (CHECKUSER) + added -u (-nNATION) option so god can modify owner of nations (CHECKUSER) + o necesary tools to go w/ CHECKUSER + o requires/uses god password +334. made the CHECKUSER option change data structure only if enabled. +335. changed all "#endif FOO" statements to "#endif /* FOO */". + +------------------------------------------------------------------------- +| 2.0 POSSIBLE SHORT-TERM ENHANCEMENTS/FIXES FOR CONQUER V5 | +------------------------------------------------------------------------- +o allow god to alter more nation status values... combat bonus, score, + other things. +o new functions: + - status_value() = returns base values of attack.defend,etc. + - sect_movecost() = returns move cost for given unit in given sector. +o adding to grouped soldiers with ZERO movement should not change status. +o changes to zombies: + - should need less food. + - some should decay each turn. [5% or so] + - drafting zombies should decrease popularity. [just killed people!] + - zombie formation could be a factor of nation being in battle not + neccesarily having zombies in battle. OR limit number of zombies + created to be half or third size of zombie armies, since zombies + are needed to create other zombies. +o new display options: + - highlight units who haven't moved since start of turn. +o multiple leaders in a unit? [then experience is not able to be + added in later.] +o limit spell points via knowledge, or cause lose based on knowledge factor. +o might scroll screen without moving sector. [What keys? Needed?] +o implement automatic updates through use of checking what nations have + moved. +o additional extended commands: [ESC prefix] + 'r' = Renumber an army. [new army structure could facilitate] + 'j' = Jump to location of given army number. +o additional commands: + 'O' = go to previous army. +o implement interface for 'Z' command. [Movement locator] +o email to real diety. [hmmm... needed or not? I would actually vote + for allowing mail to both the diety and the demi-god. -adb] +o make land capture only occur during update. +o some problems due to two nations capturing same land. should fix by above. +o some problems with MINER not providing initial stats on first turn after + nation has been added. +o fix the helpfiles to reflect current changes in game as noted later in this + file. +o there is some overflow somewhere, which creates a huge amount of gold + sometimes when your treasury is negative... +o wizard/others should get an additional bonus for knowledge (extra spell pts?) +o work on reputation and other nation attributes... they might not work as + advertised +o adjust spew.c and write new rules files for + 1) random npc mail + 2) npc delcarations of war +o Treaty war delcarations only last one turn ???? It seems to revert sometimes. +o reward for killing monsters 10K Gold and 1K Jewels per 50 men-equivalent. +o implement new method for detection of captured lands. if any allies of + sector owner in sector, prevent taking of sector; otherwise, award + sector to nation with more troops if troops are twice the remaining + troops in sector. +o provide a way for displaying monster nations properly... must also assure + accurate information in tmil and tciv. +-------------------------------------------------------------------------- +| 2.5 The Following are Good Ideas, But are not going to be done soon | +-------------------------------------------------------------------------- +o Ruling leaders can ruthlesly supress revolts... + + Gorbag (leader 1) ruthlessly kill off the revolt. + 1000 civilian rebel leaders and their wives and children exterminated. + Gorbag get experience for stopping revolt. + +o Ruling leaders work to the benefit of the nation. Each leader in ruling + in a city will have a 50% (+5% for added leader) chance of stopping a bad + event. +o All units should have loyalty ratings, and can revolt. +o Revamp user help interface to allow searching through help files. +o leader experience. mail to nation if happen. This has untold impacts on + combat... and i dont want to touch it yet. sorry. +o You should not be able to use captured sectors right away. +o Religions. Evil nations could serve Baal by sacrificing people +o Add Halfling, Gnome, Hobgoblin npc nations. Would be under elf restrictions + but would print differently. +o Add expertise level for players. Set yourself when YOU LOG IN. + novice +5 points at beginning + learner + skilled + expert 10% chance of met NPC going to war per turn + guru only get 30% of civilians in captured sctr. +o Some npcs should have insane rulers +o nomad generator (from nations file - place in given turn) This will simulate + random attack by nomad nations. nomad nations should have teritorial + objectives (a hex id), and will move as straight as possible towards + that objective, blowing anybody in their path away. Nomad NATIONS + will exist, and they will never designatie to towns/cities and can + never be destroyed. Nomads should have civilians, but their race + is nomad so these civilians can not be captured. +o Diplomatic ability could be an atribute of leaders. + Perhaps a player could have several different types of leaders. + Minor ones (appointees, and real ones). Leaders could have stats + as GENERAL/LIEUTENANT, AMBASADOR/EMMISARIES, RULER/SPY, WIZARD/MAGI + a group leader is a general/lieutenant. Diplomats can be + use against any nation, and they add + to chance of friendliness. They are same cost... as spys! + can disband minor leaders... and can recruit them as you would spys. + you can use diplomat/ambassador/emmisary/courier to alter diplomacy + with nations. They might be killed by the enemy nation if war is + declared or on a random chance (and your reputation is reduced if you + dont declare war back)... might be ambassadors give +20% on diplomacy + emmisaries +5%. Must have an ambasador to get a treaty signed. +o ADDITIONAL SPELLS THAT COULD BE CAST +Spell Id Description Spell Pts +1 Kill 50% of civilians in non city sector 10 +2 Kill all civilians in non city sector 20 +3 Kill 50% of civilians in city sector 20 +4 Kill all civilians in city sector 36 +5 Kill all military in any sector 40 +6 Kill 50% of military in any sector 15 +7 Freeze movement of 1 npc nation for turn 36 +9 Slow movement of 1 npc nation for turn (-2 move) 7 +10 Slow movement of 1 pc nation for turn (-2 move) 10 +11 Strengthen fort walls 10% (any sector) 4 +12 Destroy fort walls 5% (any sector) 8 +13 Destroy forts walls (any sector) 7 +14 Summon undead army (VAMPIRE ONLY, 500 skeletons) 8 +15 Summon undead legion (VAMPIRE ONLY, 1500 skeletons) 13 +16 Warm Permanently (+1 vegitation to sector) 12 +17 Freeze Permanently (-1 vegitation to sector) 12 +18 Teleport one army (up to 100 men) 6 +19 Teleport one army (up to 1000 men) 10 +20 Teleport one army (any # men) 14 +21 Transmute iron to jewels (per 1000) 1 +21 Transmute gold to jewels (per 1000) 3 +21 Transmute gold to iron (per 1000) 3 +22 Cause fear (route 1 oposing army to home capitol) 2 + +o Rewrite weather() routine (randevent.c) and make more seasonal effects. +o Possible idea for future designations: + have lower order bits represent number ( 0 - 2*n-1 ) for 2*n-1 + possible MAJOR designations. The remaining 16-n bits are used + for MINOR designations. This is an increase in size. Worth it? +MAJOR DESIGNATIONS: + capitol mine + city goldmine + town stockade + fort special + nodesig farm + ruin devastated [total bits: 4 bits] +MINOR DESIGNATIONS: [ THESE REPRESENT PRODUCTS OF THE PLACE ] + church university harbor + roads blacksmith traded + mill granary + lumberyard trading post + seiged + [total bits: 12 bits] [overal bits: 16 bits] +o HAVE ONLY PARTIALLY IMPLEMENT TREATIES. THEY SHOULD END AT END OF TURN IF + BOTH SIDES DONT HAVE. NPC's should be given an option to accept treaty. + PC's should get mail - forcing them to make a decision then and there. + p_requesttreaty(), n_requesttreaty(), breaktreaty() + Offer treaty, Accept Treaty... Bribe only one level per turn. Variable + bribe costs. +o spies should give you more details than normal troops +o scouts should have a chance of being captured when going into occupied areas +o experience for leaders +o names for leaders, cities, regions +o Modem wars - remote login supported +o Scenarios - napoleonic, roman, middle earth +o Clocked Turns - updates when clock runs out +o Screen Front End +o Auto Generated Graphics Front End +o Reduce Sector Datacount by improving looping and going to more pointers +o Add nomad objectives - to capture their capx,capy. Any nation that has + the right types tries to capture a given sector. +o Change trading to have an open market for prices (ie. Market price + of iron is 20 gold up from 18 last turn, (you can sell it for 10 + percent less). + +----------------------------------------------------------------- +| 3.0 Release notes for V4.0. Changes from v3.5 | +----------------------------------------------------------------- +1) gave god NINJA power to see troops on the map +2) fixed message bug (printed blanks). +3) changed ONMAP to onmap(x,y) (in data.h). Used it several new places. +4) fixed fact that i_people (being short) broke if you had too many people + by having i_people store 1/256th of the people in the sector. +5) changed 'R' message when nation has no messages +6) changed password not to echo +7) changed 'Z' command to not redraw whole screen +8) added absolute maximum people per sector +9) changed trade.c +10) fixed peasant rebellion bug +11) changed 'Z' command +13) conquer -s prints version & patchlevel: version number is now v3.patchlevel +14) changed lrand48 to extern long +15) turn is now displayed next to version number +17) placed standend() in hilight... so random sectors are no longer lit +18) modified help file code into 4 sections +19) added fix to updcapture for randomly taken land. +20) added fix so destroyer power only impacts in an update +21) changed update procedure so it only tries each nation once (faster) +22) Change combat: The rolls can go from -30 to 130. (I add 30 to +make the calculations based on 0 to 160, and therefore easier) +removed the "combat table" array and changed to a simple formula. +take the roll from 0 to 100 and add the average attackers bonus and subtract +the defenders average bonus. calculate for the losses based on a 1:1 battle. + + PAloss = (160 - roll) * MAXLOSS / 160 + PDloss = roll * MAXLOSS / 160 + +Where MAXLOSS is #defined as 60. The odds then increase the damage +to the weaker opponent by 10% per ratio. + +if(odds>100) PDloss += odds / 10 - 10; +else PAloss += 1000 / odds - 10; + +So, a roll of 50 for two evenly matched armys will result in a 30% +loss for each army. (I found this a more reasonable method than your +proposal that each army lose 50%). And, an adjusted roll of -30 for +a battle with 2:1 odds will result in an attacker loss of 60% and a +defender loss of 10%. +formulas over arrays will result +in % values that vary by 1% increments as opposed to 5 or 10 like the +array system, and the percentages are much more in line with actual +battle styles, ie, it would take luck and a large army to totally +erradicate a side with no losses. But, as this system is setup, an +army will be totally wiped out if the odds are 11:1. (most likely +with odds a little lower since it would take great defense to obtain +that) +23) eliminated leading tabs from reports +24) Forts are now damaged by combat +25) Fix for catapult additions to combat +26) Change mercenary code: 15% of disbanded become mercenaries. Mercenaries + have global average bonus based on disband type. Each nation can draft + #mercenaries/MAXNTN each turn, and every time an army is disbanded + 15% of the troops will join the mercenaries +27) keep backups of news files. Allow reading them. +28) Added flight army status +29) to summon a CENTAUR, need CAVALRY power. +30) added new command called 'w'izardy where the following + spells are possible: summon (moved from magic board), flight (give + flight to a unit), enhance attack and enhance defense (enhance the + combat by 30% if attacking or defending respectively). +31) fixed misdeclaration of fison (didn't matter much) +32) made input of adjust army status quicker. +33) makes sure that an UNMET nation isn't bribed. +34) adjusted mail reader ( 'R' command ) to take longer than screen + length messages +35) changed reading of helpfile to take place from DEFAULTDIR + changed checking of helpfile to just making sure it was installed in + DEFAULTDIR... no longer moves it into the current working directory. +36) Change attractiveness ratios for civilians into #defines +37) changed the army and navy reports so that it doesn't fill whole screen + for no armies or navies, errormsg in bottom. +38) repro now on a yearly basis (ie divided everything by 4) +39) made newlogin.c be insensitive to changes in values in newlogin.h +40) allowed redesignation to devastated, stockades, castles, and ruins +41) fixed bugs with gods removal of magic +42) fixed display to avoid random characters shown in lower right of screen +43) added standend() to makebottom so it will always be unhighlighted + [still need to find the loose standout()] +44) separated out the "SUPER USER; WHAT NATION..." into a subroutine that + checks that the nation is valid and returns a 1 if it isn't +45) altered the data structures for future enhancements; must look later +46) adjusted the combat routines for navies; will upgrade with new + ship types later +47) adjusted randomevents to fix bugs with peasant revolt +48) adjusted randomevents to make selection of iron and gold mines random +49) added check for users if the game is being updated +50) added check for update if users are logged in. #ifdef RUNSTOP + not recommeded for use with automatic updates. +51) fixed some problems with the help.txt1 documentation. Especially + since the & is used by sed as a command. +52) made major changes to the Makefile; note that ln or ln -s will not + work properly on this system. +53) added whatever ONMAP(x,y) calls I could find. +54) fixed scrolling bug. Now scrolls one sector from edge. +55) fixed misdefinition of WINTER, SPRING, SUMMER and FALL. +56) fixed integer division bug in mercenary code; would lose a point + in attack and defense if entered values were less. Now it + will only recalculate to increase the attack or defense. +57) changed requirements to take sector to be based on minimum of + 75 and tciv/250. +58) changed ntn[country] to curptr-> in many places. +58) shortened code which reads in unit types from case statemtnt to for loop +59) added leader units -> just like monsters only born. +60) changed startup code for NPC's to use points from newlogin.h +61) fixed combat code so that odds also effect %loss of side favored + by odds to decrease by %4 for each odds level. Note that + there is a limit of roll/10 as a minimum for decrease. +62) fixed bug in magic.c (#ifdef HIDLOC -> #ifdef HIDELOC) +63) fixed bug in update.c resulting from non-assignment of curntn->. +64) fixed bug in SEASON and PSEASON #defines (x%4 != (x)%4). +65) accounted for integer division in reproduction calculation. +66) made sure to exclude LEADER and MONSTER troops from vampire + calculations in combat.c. +67) made sure that vampires collect dead NON-vampire men not dead vampire men. +68) add dates to mail messages and battle reports. +69) reduces fortification values due to change in combat; fort/town -> + 10 + 5 * fort, and city -> 10+ 8 * fort. Double for Architect; +70) changed code to allow for multiple cities. +71) added TURN to output of conquer -s option. +72) added trade items of iron, jewels, and food available for gold put + up for sale by the game itself. +73) set the fortification values to be #define in the header.h file +74) added exotic trade goods. added special sector designation. changed + structures to accommodate national abilities. +75) detoned leaders by a factor of 2. reduced starting # by 1/3; +76) changed screen layout for trade goods +77) put conditional on "unable to take sector" message so only now have zombie units. changed democracy + eat rate. made elite units require armor power. made monster power + give you monsters each spring. +102) redesignate as ? converts to appropriate trade good type. +103) reordered the random events file +104) black plague only effects your cities/towns/forts and capitol +105) added npc and pc allignments. changed diplomacy again. added macros + for npc types. +106) added (killed) in combat mail for leaders and monsters +107) eliminated combat divisor. added rand%11*rand%11 / 25 (average = 1) + multiplier to all combat losses. NEED TO DOCUMENT THIS. +108) eliminated bug that allowed bribing unmet nations +109) eliminated printing of extraneous revolts and events. added revolt + percent in case formulae are not adequate (PREVOLT). +110) improved npc algorithm to attack cities towns and capitols - they + now only go in if armed to the teeth. They now defend also based + on population. npc nations now act more aggressively if you are + next to their capitol. never defend in your own capitol. +110) can only be garrison in your own city/town/fort sector +111) add -r option to conqrun. This option allows you to + read in mapfile at create time. It will read in as follows: + scene.veg - vegetation, scene.ele - elevation, scene.nat - nation marks + Also permitted the addition of x,y locations to nations file. + if -1, dont use, else place capitol there if not water. The order + the files are read in is elevation, followed by veg, followed by + marks. The only error detection is that veg must be ~ in ele ~ + sectors, and mark must be ~ in ele ~ sectors. NEED TO ADD READ + NATION MARKS STUFF!!! NEED TO ALLOW CHANGING FROM NPC TO PC. +112) made magic costs #defines. modified rates so mines run out quicker. + make new magic dependent on both jewels and magic ability. + changed healer power to religion power. magic screens auto regen. +113) Must be at war to enter sector. added errormsg in move.c. prevented + npc nations from tresspassing too. +114) added initial screen, fixed bug with cursor placement when starting as + god/nomad... +115) BIG BUG FIX - Some monsters would not fit in unsigned char... changed + divisor for unit type throughtout (to 75 from 100) this seems to + have fixed the problem. +116) ARMY GROUPS. All units in group move together. Break out of group + if you move by yourself. Will check this! +20% to combat if in + group. +2 move in group but all move at speed of slowest unit. + Moved leaders to low numbered units!!! +117) put some error correction into execute() - cant take others land + like you used to be able to do. Added adjustable tax rate (0-20). + made spreadsheet() to taxes right +118) made combat more bloody in cities. loss increased 20%, so 40% loss + converts to 48% loss. +119) increased leader birth rate. decreased lizard repro to 8% per year, + and nomad repro to 12% per year. +120) PORTED TO MY EPSON PC... + FIXED UP MAKEWORLD + anybody can add nation if turn <= 5 + added to makefile structure to make it redundant + tested & played with graphics & history routines. made directory. + played with new fractal algorithm +121) Mercenaries should run away from battles + 1) if odds are worse than 2:1 + 2) 15% of the time + for npc types. +122) npc nations now efficiently utilize unit types. fixed bug so that + npcs now get appropriate numbers of leaders. +123) added checks to make sure report screens for army, navy and nations do + not print out a blank page. +124) added check to make sure "Battle occurs, defender, attacker...." + does not overflow screen. +125) added fix to allow newspaper function to access last paper (MAXNEWS) +126) if you lose your main leader - you freeze your move for the turn + works for npcs too (no armies move). There is now a 30% chance per + turn that you get your leader back per turn. NPC armies with 0 + move cant move now (used to be only militia). +127) added spy and scout unit types. drafted on 1 or 2. spys put in + particular nations capitol. removed magic roll. changed a bunch + of minor bugs. added status MILITIA. changed printf for population + (IVXL... roman numerals). must draft in multiples of 10 men (but + scout and spy units). basically eliminated scout status. fixed + some printing stuff in makeside. made npc types not use goods in + areas they cant use. +128) made sure all returns from subroutines in GODMODE are performed correctly +129) fixed bug in detection of lowercase/uppercase characters for + country mark. +130) fixed highlighting of helpfile topic so leading spaces are dark. +131) fixed killmagk routine so displayed magic numbers are correct. +132) fixed up the help files so they were up to date and properly formatted. +133) made number of pirates, etc. created more consistant with map size. +134) changed naval code throughout... still have to fix loading and combat +135) fixed loading and movement for ships +136) fixed a bug which caused nations food to be multiplied by 100. +137) switched ships around so that galleys hold armies and merchants + hold people... warships just fight (still not done, *sigh*) +138) fixed bug which caused npc's to change all statuses (even TRADED) + to DEFEND. +139) made sure that statuses like TRADED/ONBOARD remain. +140) added attrition for naval transportation of civilians. +141) improved npc redesignation algorithm. Fixed food*=100 bug. Fixed + tradegood not allowing redesignation bug. Fixed random metals + and jewels showing up bug. Playtested some more. Putzed around. + Changed several calculations for nation attributes. Happiness. +142) made it so that towns could no longer build heavy ships. +143) made it so that only MARINE units could be unloading in unowned sectors. +144) made corrections to man.page +145) changed format for attack/defense bonus to %+4d%% so that +/- is right. +146) fixed overflow chances in att_bonus routine +147) changed wealth calculation to be based on percentage of positive wealth +148) changed calculation for spoilrate and eatrate to match help screen. +149) minepts too harshly treated... adjusted to allow any mining at all. +150) made cities and capitols contain university if proper tradegood. +151) fixed bug with tradegoods and DESFOOD sectors not working. +152) made sure that armies with zero soldiers where not used in movement + calculations for groups. +153) SCOUT status units no longer get "cannot take sector" message. +154) made sure that HIDELOC was in effect for volcano eruptions +155) fixed bug in print statement "30% die" should be "30%% die". +156) fixed bug in pwrname array reference in randeven.c +157) fixed bug which did not set militia status to MILITIA +158) fixed modulus by zero bug for movement of ships +159) adjusted 'r'edesignation command to only display possible designations +160) added new help file for designations only +161) if have destroyer, cant get dervish power + made light cavlry better than dragoons. Made dragoons weaker and not + require cavalry power. allowed god to change sectors tradegoods. + allowed players to add themselves. +162) reordered metals. +163) change orctake to only vs neutral+. orctake now + takes 10 spell points, and if you fail, nation goes one spot more + hostile. Major monster gives 2 spell pts per turn. Average gives 1, + Minor gives 1/2. +164) added move mode for display purposes. +165) moved spot to change taxes. added inflation rate and charity as a + percent of taxes. inflation is 0-2% if tax rate is 10% about +1 + per tax rate increase. + it will devalue your currency & lower your nations popularity +166) changed random event method to be % chance per nation (modified) + tradegoods no longer modify eatrate, but now modify food value of + a sector. changed tofood to take tradegoods into account. + added a few food trade goods. eliminated a few magic ones +167) made tradegoods, gold and metals hidden if wealth and mining + ability are too low. +168) made sure retreat message is only displayed during actual retreat +169) made sure report for new leader being made was correct +170) added ability to toggle from PC to npc nation. Added NPC nations + having classes (with associated abilities at start of game). +171) fixed godmode display of mercenary information in file forms.c +172) made sure dwarves cannot become wizards... dwarves are anti-magical. +173) made sure that MINOR_MONSTERS/Orc nations could not get Infantry. +174) fixed bug in god redesignation to allow normal designations. +175) fixed bugs with NAMELTH in get_nname and scenario declaration. +176) adjusted display of budget and production reports. +177) adjusted wizardry to allow MI_MONST power to cast spells. +178) changed formula for eatrate to prior eatrate/2 + tfood/5*tciv. +179) made get_nname() void and fixed it to not overstep NAMELTH. +180) made magics for classes cost same as purchased magic in making new nation. +181) fixed armyrpt so it would not print out blank pages. +182) fixed charity calculation and effect. +183) fixed major bug in spreadsheet; would break out for all !tg_ok(), + including even farm designations. +184) added alignment to 's'core display of nations. (not yet in conquer -s) +185) added alignment to 'conquer -s' display.... (may need more touch up) +186) changed cost of 'trader' and 'theocracy' for 2*NLMAGIC to 1*NLMAGIC + to make them more attractive. +187) reduced MILITIA defense but gave them GARRISON protection for realism. +188) FINISHED NAVAL COMBAT!!!!! (debug time) +189) fixed bug in SPY request for null spy name. +190) fixed division by zero bug in fleetrpt join option. +191) fixed other bugs in fleetrpt section. +192) fixed bugs in naval combat... especially with battle tracking. +193) fixed bugs in npc routines which unset TRADED or ON_BOARD status. +194) made sure update destroys ships without crew. +195) fixed many possible overflows on password entries. +196) you can only get infantry units if that is your default unit type now. +197) changed people distribution slightly (away from farms to cities). +198) fixed problem with inflation rate. +199) changed budget report to only show actual troops +200) changed display options to remove (i)ron item. +201) added hilight trade good sectors option +202) added ability of people to want to move to non mine/city... sectors +203) added npcs in army groups +204) changed tax rates - added tax other +205) eliminated charity multiplier - it is done wrong +206) civilians to farms changed - was based on eatrate - it always thought + your nation was starving though +207) road and special had the same names +208) couldnt use any good with mine required - couldnt redecignate to mines +209) added some road stuff - two max per turn. Cant des to mine/gold if + not enough metals in sector +210) Changed hasseen to be dynamically allocated +211) Changed diplomacy screen so that it pages between 2 screens worth +212) Raised max no of nations (I notice you've already done the bit about +having more nation marks). +213) Added a trap for SIGTERM as well as SIGHUP. to stop cheating +214) Set a umask in main.c if the game is running setuid. This is to +ensure people can't access the data file etc +215) Fixed what seems to me to be a bug in mailing PCs when NPCs go to war +or whatever with them. +216) Changed the reading mail bit so that now pressing any key EXCEPT for +return saves the message. This was after complaints from people on noisy +modem lines, where spurious characters made the messages flash past and +get lost. Also it makes the user interface a bit more consistent with +the news reader, say. +217) Added a facility for people to post messages to the news board. To do +this they write a message to "news" which gets appended to the news +file. These messages can then be read using the 'N' command. I think +this is great fun. +218) Added ability for the NPC's to mail players from time to time, based +on the "spew" program I told you about. If an NPC is HOSTILE or worse +towards a player, then on a 25% chance it will send a random message to +that player. These messages are composed using the "rules" file. This +file is obviously open to amendment; at the moment it contains one or +two things specific to QMC and possibly the UK which you wouldn't want! +A couple of example messages: + +What a paltry nation of street-cleaners you have! +Your puny peasants are only good at sleeping. +Even Dickie Davies could make a better job of controlling your nation! +If I were you I'd give up. +Even Edwina Currie could make a better job of running your nation! +Your nation should be holding a free rock festival. +Go stick your private parts up a large purple elephant +What a useless nation of tiolet-cleaners you have! + +219) Finally I have the "-z" option; +allows a player to ignore their lock file and play regardless +(dangerous, I know, perhaps it should be an #ifdef). This is essential +for us since we have people dotted all over the place using workstations +that go down a lot. +220) changed news reader... does not read blank pages! +221) elimiated TRADEGOOD compiler option + changed attractiveness some more + takeover - must be at least met + Eliminate Orc-take if 0 to allow GARRISON in stockades. +281) changed TAXCAP to TAXCITY and TAXCITY to TAXTOWN for accuracy in names. +282) rewrote diplomacy screen to support all screen sizes; fixed paging. +283) fixed various bugs throughout. (many caused by bad patching). +284) adjusted the wmessage() function slightly. (don't go into zero column) +285) adjusted various displays to match side. (Ie., only voids show '?') +286) fixed bug with RULE in battle alone that caused exit from battle. +287) implemented file locks on all lock files so players may ignore if + the process is dead. +288) removed zflag stuff since it is not neccesary and a definite cheat. +289) added check to make sure that there was only one capitol per nation. +290) added "chicken" armies to battle report. only sends full report + to that nation if others units actually participate. + [Made sure that army leaves sector... unfair to leave army there] +291) added check in wmessage() for GOD writing to news. +292) fixed bug with vegetation display not being show for VOID owners. +293) fixed bug with sending to non-pcs in siege notification. (woops) +294) did the above for losing monsters. (double woops) +295) switched space bar from toggle to exit in the diplomacy screen. + [To be consistant with all of the other displays] +296) fixed % in string error for lack of leader message. +297) wrote conqsort program to implement sorting only on 1st two characters. +298) fixed misalignment of displaying of output for magic removal. +299) cleared bottom after selection of troop type to remove unwanted display. +300) fixed promblems with information being kept with chicken orcs/mercs. +301) fixed hard coded lines in diplomacy display. +302) raised min strgth for WARLORD & LORD since they should be better soldiers. +303) fixed error with 'else' on SIEGED status that removed fort_bonus(). +304) changed variable 'cbonus' to 'intval' to avoid confusion with cbonus(). +305) restructured armyrpt() to be independent of screen size. +306) added check that terminal size was at least 80x24. +307) added mail checking routine to watch conquer and system mail. + system mail is checked only given that SYSMAIL is defined. +308) changed 'treasury' displays to show initial (startgold) value. +309) added malloc for sector read and write +310) added 1 sector range for npc nations +311) putzed a little - added adams name to copyscreen, moved conqsort in, + added bits here and there +312) worked on poverty and charity +313) redid classs limits (who can be whom) +314) people limit raised so you can start with all people in one sector +315) modified some stuff for HP-UX +316) add nation attribute - poverty & charity - MUST CHANGE + TO CHARACTERS (from shorts) PRIOR TO RELEASE +317) Added nation ability bonus as per txt5. +318) Slow you down to change status (1MPs) +319) Cant go from march to other so easilly - costs unit march bonus +320) Overrun not work - eliminated it. +321) Increased garrison for npc nations. +322) Made payment for mercenaries that are drowned. +323) add variable pwater - entered at world creation time not compile time. +324) made fleetrpt() independent of screen size. +325) fixed error in calculation of NET INCOME in budget(). +326) restructured change() routine to be variable with screensize. +327) restructured makeside() routine to be variable with screensize. +328) fixed bug in movement routine that subtracted move on unmet movement. +329) changed combat routine: + - moved bonus adjustment from roll to odds. + - fixed bug in tracking neutral troops. +330) fixed little display bugs in form.c file. +331) fixed charity display in budget. (should be percent of income not + percent of treasury). Also, charity is >= 0. +332) placed FINDLOCK #ifdefs in for support of BSD flock. Must investigate + system V and also PC before doing anything else with it. +333) added camp_info() routine to display some statistics to users. +334) adjusted calculation of 50% mercenaries in commands.c +335) changed fight() and navalcbt() "rolls" to be yield 0 to 100 with + a bell curve probability. +336) removed limitation on drafting only multiples of 10 men and instead added + a limitation that armies must be greater than 25 unless scout or spy. +337) added checks on changing of terror. imposed the 5% limit and may + use once per turn only. +338) fixed major bug in clearing of magic before finishing with it in newlogin. +339) fixed magic stones +340) made slightly more likely that only 1 npc army ends in spot in their + own nation (unless city...) +341) repair now an option from construct... not a suboption +342) fixed bribery - based on number of 1000 troops in the nation now. +343) add to attractiveness of owned sectors based on people/4. Subtract + this number before leaders move. +344) changed routines to add monsters to world. Must check them. +345) tidied up many of the screen display functions in a number of files. +346) fixed bug with P_ATYPE==MARCH instead of P_ASTAT==MARCH. +347) changed limitation on deep water from warships to light ships. +348) fixed major bugs in MONSTER creation code. should work properly now. +349) AAAARRRRGGGGHHH!!!! I had a big error in my code. never gave any gold + from spreadsheets if the charity was zero. Sorry about that Ed. +350) fixed bug with calling of prep() with country value improperly set. +351) redid prep routine for speedup sake and for sake of bug catching. +352) fixed one (hopely final) bug in combat... adjustment for attacker odds + bonus was wrong. It was accidently only 2% adjustment. +353) fixed some bugs in the rebuilding code and changed some messages. +354) added two new constant definitions MEETNTN and PRTZONE. see header.h. +355) added prevention of god overwriting data file during player addition. +356) separated out locking routine into a subroutine check_lock and placed + it in check.c. Now all FILELOCKing is done in just this routine. +357) leaders no longer have size consideration in loading onto ships. +358) big fix of npc nations. THEY DIDNT KNOW HOW VALUABLE THEIR OWN LAND + REALLY WAS! It was a massive oversite!!! If you wish to work + on the npc code, there are come commented out printf statements + in npc.c around line 793. They will print attractivenss of sctrs + around your capitol, so you can see if npcs are working right. +359) gave wandering pirate fleets a base of operations... now stay around that. +360) fixed navy movement core dump. +361) allowed sailors to disembark from a fleet in unowned land. changed msgs. +362) corrected display of move cost in "MOVESCREEN" for flight. +363) putzed around with status messages. now prevent setting of same status. +364) reduced odds bonuses in fight(). will test with 8% and 6%. +365) fixed bug with fison instead of filename in check_lock() for non FLOCK. +366) altered movement to allow scouts into unmet land. +367) allow spys to disband anywhere, but they now must be payed twice the + enlistment cost to be encouraged to remain quiet. +368) added query for creation of NPC nations in makeworl.c. +369) changed wizardry() function to work on characters instead of numbers. +370) wrote routine compass() to return compass direction given from and to. +371) used compass() routine in new starting routine for spys. +372) implemented capturing of scouts: PFINDSCOUT now set to 50%. + - alone with a hostile army [PFINDSCOUT% chance] + - alone in someone else's territory with one of + their armies (non-allied) [(PFINDSCOUT/5)% chance] +373) in draft() made it so both spys and scouts are assumed to be separate + armies of 1 man each. Useless for nations to have otherwise. +374) implemented mills. farm may only be effected by one mill. + MILLSIZE people needed in a mill to have it function. +375) no fix +376) added mail information display to make_bottom() routine. should + work fine from now on. +377) made it cost no metal to redesignate a capitol from a city. + [This makes sense, since no increase in fortification is needed] +378) implemented sackem() routine for loss of Capitol. Must add info in txt4. +379) implemented deplete() routine for nations without Capitol. +380) doubled movement rate of scouts and spys. (usually not near leaders) +381) fixed bug in check_lock(); would accidently remove locks after checking. +382) Zones of control: slow you down - inverse ratio 100 men through 50 - lose + 1/2 starting movement points +383) Fixed GOLDTHRESH conversion of gold to jewels - automatic now at current + tradgood rate. +384) sailor nations dont get hit by storms. +385) fixed getnewname in randevent.c +386) performance enhancements to tofood, prep, is_habitable. +387) added EXEDIR to compile time definitions +388) reduced power of zombies. may not longer MARCH or follow a + leader. This is realistic since they should be braindead. +389) fixed a bug with drowning flyers taking land in move.c. +390) removed the restriction on the number of men drafted being > 25. The + battle calculations now handle that properly. +391) fixed a division by zero bug for tciv in npc.c +392) TRADING BUNGED.... suspended trading for food, land, and ships. Will + probably restore ship and food trading in the future, but for now + they are broken in such a way to damage nations. Trading as a whole + also sucks. Will fix for 5.0 when actual carrying of goods is needed. +393) made mail messages being read wrap at LINES-3 instead of the constant 21. +394) draft: made subtraction of population take place after spy verification. +395) revamped combat once again. should be all fixed except for the + one bug with retreat of monsters being reported. +396) gave ability to draft dragoons without any magic requirments as per txt2. +397) made sure zombie losses do not add to 1/3 zombie additions. +398) made many fixes to patch as I put it in place: + - little bug fixes throughout. + - fixed curntn misassignment during monster placement in makeworl.c. + - fixed diplomacy screen detection of monsters. +399) made it so that any grouped army that gets drafted into is set to ATTACK. +400) changed Spy and Scout to singular in *unittype[], file data.c. +401) fixed bug with isactive(country) != isactive(curntn->active) in sackem(). +402) only give half bonus to zombies for fortification; too stupid to use well. +403) made sure that zombies only earned dead if they survived. + (all of my zombie changes are because zombies would never die) +404) had to change "Guards" back into "Elite" because "Goblin" and "griffon" + could not fit into a non-'g' name while Elite was viable. +405) added season to conquer -s output. +406) added a line telling what nation the peasant rebellions join if it doesn't + form a new nation. +407) added weighting of prior eatrate and seasonal variation to eatrate. +408) added change to budget/production flip flop +409) make NPCRANGE create start_x,y end_x,y for n_ routine speedup +410) everybody on your side can participate in battle. This permits + defense even if have general in sector. +411) higher number nations now are the default attackers... means nomads... + atacking +412) The order of combat is high nation to low. This is very disadvantageous + to PCs. The owner of land is now defender. If that isnt clear, + it is 50/50; +413) orcs are a little weaker... they got too many initial points. +414) played with code a little in newlogin... cleaned it up a touch. +415) cleaned up location adding in newlogin.c +416) can now go to war with peasants. +417) added revolt percent chance to change screen diff --git a/original/npc.c b/original/npc.c new file mode 100644 index 0000000..5350b0a --- /dev/null +++ b/original/npc.c @@ -0,0 +1,1720 @@ +/*conquer : Copyright (c) 1988 by Ed Barlow. + * I spent a long time writing this code & I hope that you respect this. + * I give permission to alter the code, but not to copy or redistribute + * it without my explicit permission. If you alter the code, + * please document changes and send me a copy, so all can have it. + * This code, to the best of my knowledge works well, but it is my first + * 'C' program and should be treated as such. I disclaim any + * responsibility for the codes actions (use at your own risk). I guess + * I am saying "Happy gaming", and am trying not to get sued in the process. + * Ed + */ + +#include +#include +#include +#include +#include +#include "header.h" +#include "data.h" + +extern FILE *fnews; + +int stx, sty, endx, endy; /* npc range of operations */ +extern short country; +extern int **attr; /*sector attactiveness*/ +extern int dissarray; /* has nation lost its leader */ +int peace; /*is 8 if at peace, 12 if at war*/ +static int Avg_food; +static int Avg_soldiers[NTOTAL]; +static int Avg_tradegood; + +/* macros that indicate what the country can see */ +#ifdef NPC_SEE_SECTORS +#define SEE_SECTOR(x,y,country) TRUE +#else /* NPC_SEE_SECTORS */ +#define SEE_SECTOR(x,y,country) \ + ( (magic(sct[x][y].owner,THE_VOID)!=TRUE) \ + || (magic(country,NINJA)==TRUE) ) +#endif /* NPC_SEE_SECTORS */ + +#ifdef NPC_SEE_CITIES +#define SEE_CITIES(city_nation,country) TRUE +#else /* NPC_SEE_CITIES */ +#define SEE_CITIES(city_nation,country) \ + ( (magic(city_nation,THE_VOID)!=TRUE) \ + || (magic(country,NINJA)==TRUE) ) +#endif /* NPC_SEE_CITIES */ + +#ifdef NPC_COUNT_ARMIES +#define COUNT_ARMIES(army_nation,country) TRUE +#else /* NPC_COUNT_ARMIES */ +#define COUNT_ARMIES(army_nation,country) \ + ( ( (magic(army_nation,THE_VOID)!=TRUE) \ + && (magic(army_nation,HIDDEN)!=TRUE) \ + ) || (magic(country,NINJA)==TRUE) ) +#endif /* NPC_COUNT_ARMIES */ + +/* When a sector cannot be seen by an npc nation because of + * THE_VOID, a value must still be given to the + * sector, because there MIGHT be something there. + * The following unseen (UNS_) value represents this. + */ +#define UNS_CITY_VALUE 10 /* If there is an under-defended City + * the value is 500 + */ + +void +prtattr() +{ +#ifdef DEBUG + int x,y; +/* FOR TESTING OF WHAT THE ATTRACTIVENESS ENDS UP LIKE */ + printf("Attractiveness for sectors around CAPITAL at %d %d veg alt des\n",curntn->capx,curntn->capy); + for(y=(int)curntn->capy-3;y<(int)curntn->capy+4;y++) { + printf("\n"); + for(x=(int)curntn->capx-3;x<(int)curntn->capx+4;x++) if(ONMAP(x,y)) { + if( sct[x][y].altitude != WATER ) { + printf("[%2d,%2d] ",x,y); + } + } + printf("\n"); + for(x=(int)curntn->capx-3;x<(int)curntn->capx+4;x++) if(ONMAP(x,y)) { + if( sct[x][y].altitude != WATER ) { + printf("%5d %c%c%c " + ,attr[x][y] + ,sct[x][y].vegetation + ,sct[x][y].altitude + ,sct[x][y].designation); + } else printf("0 ~ "); + } + printf("\n"); + } +#endif /* DEBUG */ +} + +/*newdip() diplomacy if unmet - ntn 1 is nation you are updating*/ +void +newdip(ntn1,ntn2) +int ntn1,ntn2; +{ + if( ispc( ntn[ntn1].active ) ) { + if( ntn[ntn2].race==ORC ) + ntn[ntn1].dstatus[ntn2]=HOSTILE; + else ntn[ntn1].dstatus[ntn2]=NEUTRAL; + return; + } + if((ntn[ntn1].race==ORC) + ||( ntn[ntn2].race==ORC)) { + if(ntn[ntn1].dstatus[ntn2]==UNMET) + if((rand()%2==0)|| ispc(ntn[ntn1].active)) + ntn[ntn1].dstatus[ntn2]=HOSTILE; + else + ntn[ntn1].dstatus[ntn2]=WAR; + } else if(ismonst(ntn[ntn2].active)) { + ntn[ntn1].dstatus[ntn2]=WAR; + } else if(ispc(ntn[ntn1].active)) { + if(ntn[ntn1].dstatus[ntn2]==UNMET) + ntn[ntn1].dstatus[ntn2]=NEUTRAL; + } else if(ntn[ntn1].race==ntn[ntn2].race){ + if(rand()%2<1) ntn[ntn1].dstatus[ntn2]=FRIENDLY; + else ntn[ntn1].dstatus[ntn2]=NEUTRAL; + } else ntn[ntn1].dstatus[ntn2]=NEUTRAL; +} + +#ifdef MONSTER +void +monster() +{ + for(country=1;countryactive==NPC_NOMAD ) do_nomad(); + else if( curntn->active==NPC_PIRATE ) do_pirate(); + else if( curntn->active==NPC_SAVAGE ) do_savage(); + else if( curntn->active==NPC_LIZARD ) do_lizard(); /* update.c */ + } +#ifdef MORE_MONST + { + int neededtroops; + int actualtroops; + int savages,nomads; + int i,x,y; + int nomad_space=1, savage_space=1; + + for(i=1;i 0) + actualtroops += ntn[nomads].arm[i].sold; + if (ntn[savages].arm[i].sold > 0) + actualtroops += ntn[savages].arm[i].sold; + } + +#ifdef DEBUG + printf("monsters: need %d have %d\n",neededtroops,actualtroops); +#endif /* DEBUG */ + + neededtroops= neededtroops-actualtroops; + + while(neededtroops>0&& (nomad_space||savage_space)) + { +#ifdef DEBUG + printf("\t need %d monster troops\n",neededtroops); +#endif /* */ + if ( (rand()%8)<5 && nomad_space) + { + while(!is_habitable((x=(rand()%(MAPX-8))+4), + (y=(rand()%(MAPY-8))+4))) + ; + for(i=0;i= 50 ) ); + + for(i=0;i0){ + P_ASTAT=ATTACK; + P_AMOVE=(curntn->maxmove * *(unitmove+P_ATYPE%UTYPE))/10; + if(P_ATYPE 100 ) { + P_ASOLD=0; + break; + } + /* nomads cannot stay in the same spot */ + if(( x==P_AXLOC && y==P_AYLOC ) + ||(!ONMAP(x,y) + ||(!is_habitable(x,y))) + ||(!land_reachp((int)P_AXLOC,(int)P_AYLOC, + x,y,curntn->maxmove,country))) continue; + + P_AXLOC=x; + P_AYLOC=y; + /*if owned & unoccupied you take & people flee*/ + if( ((sct[x][y].owner) == 0 + || solds_in_sector( x, y, sct[x][y].owner) == 0 ) + && (ntn[sct[x][y].owner].active!=NPC_NOMAD) ) { + fprintf(fnews,"3:\tnomads capture sector %d,%d\n",x,y); + if(sct[x][y].owner!=0) flee(x,y,1,FALSE); + sct[x][y].owner=country; + DEVASTATE(x,y); + } + break; + } + } +} + +void +do_savage() +{ + short armynum; + int x, y; + + printf("updating savage (nation %d)\n",country); + for(armynum=0;armynum0){ + P_ASTAT=ATTACK; + if(P_ATYPEmaxmove * *(unitmove+P_ATYPE%UTYPE))/10; + x=(int)P_AXLOC+rand()%3-1; + y=(int)P_AYLOC+rand()%3-1; + if(ONMAP(x,y)&&(is_habitable(x,y)) + &&(land_reachp((int)P_AXLOC,(int)P_AYLOC,x,y,P_AMOVE,country))){ + P_AXLOC=x; + P_AYLOC=y; + /*if owned & unoccupied you take & people flee*/ + if( ((sct[x][y].owner == 0) + || (solds_in_sector( x, y, sct[x][y].owner) == 0)) + && (ntn[sct[x][y].owner].active != NPC_SAVAGE)) { + fprintf(fnews,"3:\tsavages capture sector %d,%d\n",x,y); + if(P_ATYPEdesignation == DCAPITOL) + ||(sptr->designation == DCITY)) return; + + /*large enough for a city now?*/ + if(((sptr->people > (spread.civilians/CITYLIMIT)) + ||((spread.civilians<30000)&&(sptr->people>1000))) + &&( hunger > P_EATRATE*1.5 ) + &&( spread.incity+spread.incap < spread.civilians * CITYPERCENT / 100) + &&( spread.sectors > 10) + &&( sptr->tradegood == TG_none )){ + sptr->designation=DTOWN; + spread.incity+=sptr->people; + spread.infarm-=sptr->people; + } + + /* large enough for city and not enough food*/ + if((sptr->designation==DTOWN) + &&( hunger < P_EATRATE) + &&( tofood(sptr,sptr->owner) > citythresh )){ + sptr->designation=DFARM; + spread.incity-=sptr->people; + spread.infarm+=sptr->people; + } + + if((sptr->designation==DTOWN) + &&( spread.incity+spread.incap > spread.civilians * CITYPERCENT / 66)){ + sptr->designation=DFARM; + spread.incity-=sptr->people; + spread.infarm+=sptr->people; + } + + /*what if it is not a city*/ + if((sptr->designation!=DTOWN) + &&(sptr->designation!=DCITY) + &&(sptr->designation!=DCAPITOL)){ + if(( sptr->tradegood != TG_none ) + &&( tg_ok( sptr->owner, sptr ))) { + if(( metalthresh+goldthresh > 8 ) + ||(( sptr->metal < metalthresh ) + &&( sptr->metal != 0 )) + ||(( sptr->jewels < goldthresh ) + &&( sptr->jewels != 0 ))) { + sptr->designation = DFARM; + } else sptr->designation= *(tg_stype+sptr->tradegood); + + if(( sptr->metal < metalthresh ) + &&( sptr->metal != 0 )) + sptr->designation=DBLKSMITH; + + if(( sptr->designation== 'x' ) + ||(( sptr->designation== DCITY )&&(sptr->people<1000))) + sptr->designation=DFARM; + } else if( tofood(sptr,sptr->owner) >= 4 ){ + sptr->designation=DFARM; + } else sptr->designation=DSTOCKADE; + } + if(( sptr->designation==DFARM) + &&( hunger > P_EATRATE*1.5 ) + &&( tofood(sptr,sptr->owner) <= 6 )){ + if(( rand()%2 == 0 )&&( curntn->mine_ability<30 )) + sptr->designation=DBLKSMITH; + else if(( rand()%2 == 0 ) + &&( sptr->people<100 ) + &&( curntn->spoilrate >15)) + sptr->designation=DGRANARY; + else if(( rand()%2 == 0 )&&( curntn->popularity<50 )) + sptr->designation=DCHURCH; + else if( sptr->people>1000 ) + sptr->designation=DTOWN; + } +} + +void +redomil() +{ + short x,y,armynum,nvynum; + int i, free, done; + long ideal; + long diff=0l; + int ok; + + check(); + /* check out any ship crews */ + for(nvynum=1;nvynumtmil = 0L; + for(armynum=1;armynum0){ + /* move army back if too far out */ + ok = 0; + if (P_ATYPE < MINLEADER && P_ASOLD!=A_MILITIA) { + curntn->tmil += P_ASOLD; + } + for(x=(int)P_AXLOC-3;x<=(int)P_AXLOC+3;x++) + for(y=(int)P_AYLOC-3;y<=(int)P_AYLOC+3;y++) + if((ONMAP(x,y))&&(sct[x][y].owner==country)) ok=1; + if(ok==0){ + P_AXLOC=curntn->capx; + P_AYLOC=curntn->capy; + } + + /* verify militia */ + if(P_ATYPE==A_MILITIA) { + /* eliminate invalid militia */ + if(((sct[P_AXLOC][P_AYLOC].designation!=DTOWN) + &&(sct[P_AXLOC][P_AYLOC].designation!=DCAPITOL) + &&(sct[P_AXLOC][P_AYLOC].designation!=DCITY)) + ||(sct[P_AXLOC][P_AYLOC].owner!=country)){ +#ifdef DEBUG + printf("\teliminating %s army %d as %d %d is des:%c alt:%c own:%d\n",unittype[P_ATYPE],armynum,P_AXLOC,P_AYLOC,sct[P_AXLOC][P_AYLOC].designation,sct[P_AXLOC][P_AYLOC].altitude,sct[P_AXLOC][P_AYLOC].owner); +#endif /* DEBUG */ + if(sct[P_AXLOC][P_AYLOC].owner == country) + sct[P_AXLOC][P_AYLOC].people+=P_ASOLD; + else sct[curntn->capx][curntn->capy].people+=P_ASOLD; + P_ASOLD=0; + } + } + + /* set default status */ + if(P_ASTAT=MINLEADER && P_ASOLD>0)) { + armynum++; + } + /* oh well... wipe out army zero; c'est la vie */ + if (armynum == MAXARM) armynum = 0; + P_ATYPE=defaultunit(country); + P_ASTAT=GARRISON; + P_AXLOC=curntn->capx; + P_AYLOC=curntn->capy; + + /*Ideally P_ASOLD[0]*MILINCAP=tmil*peace/10*/ + ideal = curntn->tmil * peace / (10L*MILINCAP); + if(curntn->tgold < 0) ideal/=2L; +#ifdef DEBUG + if(peace==8) + printf("\t%s IS AT PEACE - garrison in cap is %ld, ideal is %ld\n",curntn->name,P_ASOLD,ideal); + else if(peace==12) + printf("\t%s IS AT WAR - garrison in cap is %d, ideal is %ld\n",curntn->name,P_ASOLD,ideal); + else printf("error - incap is %d ideal is %ld\n",P_ASOLD,ideal); +#endif /* DEBUG */ + + /*MILRATIO ratio mil:civ for non player countries*/ + /*MILINCAP ratio (mil in cap):mil for NPCs*/ + check(); + + if((P_ASOLD*10) < (9*ideal)){ + + /*too few soldiers on garrison*/ + /*diff is number to change mil in cap (>0)*/ + if (*(u_enmetal + (P_ATYPE%UTYPE)) > 0) + diff = (long) min(ideal-P_ASOLD,(int) (curntn->metals / *(u_enmetal + (P_ATYPE%UTYPE)))); + + diff=(long) min((int) diff, sct[curntn->capx][curntn->capy].people/2L); + + if ((curntn->tgold<0L || curntn->metals<0L) && (diff > 0L)) diff=0L; + if (sct[curntn->capx][curntn->capy].owner != country) diff=0L; + +#ifdef DEBUG + printf("\tadding %d men to garrison (too few men on garrison)\n",diff); +#endif /* DEBUG */ + + sct[curntn->capx][curntn->capy].people-=diff; + P_ASOLD+=diff; + curntn->tciv-=diff; + curntn->tmil+=diff; + if(magic(country,WARRIOR)==1) /* take WARRIOR power into account */ + curntn->tgold -= (diff * *(u_encost + (P_ATYPE%UTYPE))) / 2; + else curntn->tgold-=diff* *(u_encost + (P_ATYPE%UTYPE)); + curntn->metals-=(diff* *(u_enmetal + (P_ATYPE%UTYPE))); +#ifdef DEBUG + if(P_ASOLD < 0L) printf("error 2... P_ASOLD=%d <0\n",P_ASOLD); +#endif /* DEBUG */ + } + /*else split garrison army if 1.25* needed number*/ + else if(P_ASOLD *4L > 5L*ideal){ + /*diff here is a negative number*/ + diff=((4L*P_ASOLD)-(5L*ideal))/4L; +#ifdef DEBUG + printf("\tsplit garrison of %d men\n",diff); +#endif /* DEBUG */ + free=FALSE; + P_ASOLD-=diff; +#ifdef DEBUG + if(P_ASOLD < 0) printf("error... subtracting %d from %d\n",diff,P_ASOLD); +#endif /* DEBUG */ + curntn->tmil-=diff; + curntn->tciv+=diff; + sct[curntn->capx][curntn->capy].people+=diff; + /*I add back gold as armies get redone anyway*/ + curntn->metals += (diff* *(u_enmetal + (P_ATYPE%UTYPE))); + if(magic(country,WARRIOR)==TRUE) { /* WARRIOR power */ + curntn->tgold+=(diff* *(u_encost + (P_ATYPE%UTYPE))) / 2; + } else curntn->tgold+=diff* *(u_encost + (P_ATYPE%UTYPE)); + } +#ifdef DEBUG + else printf("\tno action - P_ASOLD (%d) ~= ideal (%d)\n",P_ASOLD,ideal); + printf("\tFinal Garrison Army %d (%s) type is %s men is %d\n",armynum,curntn->name,*(unittype+(P_ATYPE)),P_ASOLD); +#endif /* DEBUG */ + + /*build ships and/or armies*/ + done=FALSE; + ideal = curntn->tciv * peace / (10 * MILRATIO); + if(curntn->tgold<0) { ideal*=4; ideal/=5; } +#ifdef DEBUG + printf("\t%s total military is %d -> ideal is %d\n",curntn->name,curntn->tmil,ideal); +#endif /* DEBUG */ + check(); + + /* find leader and place on RULE in capitol */ + for(armynum=0;armynumclass)-1) { + P_ASTAT=RULE; + P_AXLOC=curntn->capx; + P_AYLOC=curntn->capy; + break; + } + + /* add to partial armies */ + for(armynum=1;armynum0) + &&( P_ATYPE!=A_MILITIA ) + &&( P_ATYPEtgold > 0 ) + &&(curntn->metals >= (TAKESECTOR+20-P_ASOLD)* *(u_enmetal + (P_ATYPE%UTYPE))) + &&( fort_val(&sct[P_AXLOC][P_AYLOC]) > 0) + &&( sct[P_AXLOC][P_AYLOC].owner == country )) { +#ifdef DEBUG + printf("\tadding %d men to weakened army %d\n",TAKESECTOR+20-P_ASOLD,armynum); +#endif /* DEBUG */ + if(magic(country,WARRIOR)==TRUE) /* WARRIOR power */ + curntn->tgold-=((TAKESECTOR+20-P_ASOLD)* + *(u_encost + (P_ATYPE%UTYPE))) / 2; + else curntn->tgold-=(TAKESECTOR+20-P_ASOLD)* + *(u_encost + (P_ATYPE%UTYPE)); + curntn->tmil += TAKESECTOR+20-P_ASOLD; + curntn->metals -= ((TAKESECTOR+20-P_ASOLD)* *(u_enmetal + (P_ATYPE%UTYPE))); + P_ASOLD = TAKESECTOR+20; + } + + /*if < ideal build new army in the capitol - if possible*/ + if(curntn->tmil < ((4*ideal)/5)) { + for(armynum=1;armynumtmil), (int) (curntn->metals/ (*(u_enmetal + (P_ATYPE%UTYPE))))); + + P_ASOLD = min (P_ASOLD,sct[curntn->capx][curntn->capy].people/2); + P_ASOLD = min (P_ASOLD, (int) (curntn->tgold/ *(u_encost+(P_ATYPE%UTYPE)))); + if(P_ASOLD>0){ +#ifdef DEBUG + printf("\tnot enough soldiers - build new army %d with %d men\n",armynum,P_ASOLD); +#endif /* DEBUG */ + curntn->metals-=(P_ASOLD* *(u_enmetal + (P_ATYPE%UTYPE))); + P_AXLOC= curntn->capx; + P_AYLOC= curntn->capy; + curntn->tmil += P_ASOLD; + curntn->tciv -= P_ASOLD; + if(magic(country,WARRIOR)==TRUE) /* WARRIOR power */ + curntn->tgold-=(P_ASOLD* *(u_encost + (P_ATYPE%UTYPE))) / 2; + else curntn->tgold-=P_ASOLD* *(u_encost + (P_ATYPE%UTYPE)); + sct[P_AXLOC][P_AYLOC].people-=P_ASOLD; + P_ASTAT= DEFEND; + P_AMOVE=0; + } + else P_ASOLD=0; + } + check(); + } else if(curntn->tmil > (6*ideal/5)){ + check(); + /*disband a pseudo-random army*/ + done=FALSE; + diff=curntn->tmil-(6*ideal/5); + for(armynum=1;done==FALSE && armynum=MINLEADER) + ||(P_ASTAT==ONBOARD) + ||(P_ASTAT==TRADED)) continue; + + if((sct[P_AXLOC][P_AYLOC].owner==country) + &&((sct[P_AXLOC][P_AYLOC].jewels>4) + ||(sct[P_AXLOC][P_AYLOC].metal>4) + ||(ISCITY(sct[P_AXLOC][P_AYLOC].designation)))){ +#ifdef DEBUG + printf("\ttoo many soldiers eliminate army %d (%d men)\n",armynum,P_ASOLD); +#endif /* DEBUG */ + diff-=P_ASOLD; + sct[P_AXLOC][P_AYLOC].people+=P_ASOLD; + curntn->tmil -= P_ASOLD; + curntn->tciv += P_ASOLD; + P_ASOLD=0; + if(diff<=50) done=TRUE; + } + } + } + check(); +#ifdef DEBUG + printf("\twhew... new tmil is %d\n",curntn->tmil); +#endif /* DEBUG */ + + /*resize armies */ + for(armynum=1;armynum(2*TAKESECTOR)) + &&(P_ATYPE!=A_MILITIA && P_ASTAT!=ONBOARD && P_ASTAT!=TRADED)) { + free=FALSE; + for(i=1;free==FALSE && iarm[i].sold==0){ + free=TRUE; + P_ASOLD/=2; +#ifdef DEBUG + printf("\tSplitting %ld troops from army %d forming %s army %d \n" + ,P_ASOLD,armynum,unittype[P_ATYPE],i); +#endif /* DEBUG */ + curntn->arm[i].sold = P_ASOLD; + curntn->arm[i].unittyp = P_ATYPE; + curntn->arm[i].smove = P_AMOVE; + curntn->arm[i].stat = P_ASTAT; + curntn->arm[i].xloc = P_AXLOC; + curntn->arm[i].yloc = P_AYLOC; + } + } + } + /*minimum npc army is TAKESECTOR, merge them*/ + else if(P_ASOLD>0 && (P_ASOLDarm[i].sold>0) + &&(curntn->arm[i].stat!=ONBOARD) + &&(i!=armynum) /* don't use same army */ + /* or it will be deleted */ + &&(curntn->arm[i].stat!=TRADED) + &&(curntn->arm[i].xloc==P_AXLOC) + &&(curntn->arm[i].yloc==P_AYLOC) + &&(curntn->arm[i].unittyp==P_ATYPE)) { + free=TRUE; + curntn->arm[i].sold += P_ASOLD; +#ifdef DEBUG + printf("\tMerge %ld men from army %d to make %ld troops in %s army %d \n" + ,P_ASOLD,armynum,curntn->arm[i].sold,unittype[P_ATYPE],i); +#endif /* DEBUG */ + P_ASOLD=0; + } + + } + } + } + check(); + + /* assure that a militia unit resides in each city */ + if(curntn->tgold > 0) + for(x=stx;x0) + &&(P_AXLOC==x)&&(P_AYLOC==y) + &&(P_ATYPE==A_MILITIA)) { + free=TRUE; + break; + } + } + if(free==FALSE) { /* draft new militia army */ + for(armynum=0;armynum0){ + if(magic(country,WARRIOR)==TRUE){ /* WARRIOR power */ + curntn->tgold-= + ((ideal-P_ASOLD)* *(u_encost+P_ATYPE))/2; + } else { + curntn->tgold-= + (ideal-P_ASOLD)* *(u_encost + P_ATYPE); + } + } +#ifdef DEBUG + printf("\tnow in sector %d,%d\n",x,y); + printf("\tadding %ld troops to %s army %d (now %ld men - populace %ld)\n",ideal-P_ASOLD,unittype[P_ATYPE%UTYPE],armynum,ideal,sct[x][y].people); +#endif /* DEBUG */ + P_ASOLD=ideal; + P_ASTAT=MILITIA; + } + } + check(); +#ifdef DEBUG + printf("\tnow setting all units to default type of %s\n",unittype[defaultunit(country)]); +#endif /*DEBUG*/ + + /* setup default units */ + for(armynum=1;armynum0)&&(P_ATYPE!=A_MILITIA)&&(P_ATYPEactive)) return; + + if(( curntn->active==GOOD_6FREE ) + ||( curntn->active==ISOLATIONIST ) + ||( curntn->active==NEUTRAL_6FREE ) + ||( curntn->active==EVIL_6FREE )) svhostile=5; + else if(( curntn->active==GOOD_4FREE ) + ||( curntn->active==NEUTRAL_4FREE ) + ||( curntn->active==EVIL_4FREE )) svhostile=10; + else if(( curntn->active==GOOD_2FREE ) + ||( curntn->active==NEUTRAL_2FREE ) + ||( curntn->active==EVIL_2FREE )) svhostile=20; + else if(( curntn->active==GOOD_0FREE ) + ||( curntn->active==NEUTRAL_0FREE ) + ||( curntn->active==EVIL_0FREE )) svhostile=35; + else svhostile=5; + + for(x=1;xactive) != npctype(ntn[x].active)) + hostile+=20; /* not same alignment */ + friendly = 60-hostile; + if( curntn->active==ISOLATIONIST ) friendly -= 20; + /* negate impact of above line on neutrals */ + if(isneutral(ntn[x].active)) { + friendly-=10; + hostile-=10; + } + if(ntn[x].race==curntn->race){ + friendly+=10; + hostile-=10; + } + if(isneutral(curntn->active)) { + friendly-=20; + hostile-=20; + } + /* if next to capitol, they dont like you */ + for(X=(int)curntn->capx-1;X<=(int)curntn->capx+1;X++) + for(Y=(int)curntn->capy-1;Y<=(int)curntn->capy+1;Y++) + if(ONMAP(X,Y)) { + if(sct[X][Y].owner == x) { + friendly-=10; + hostile +=10; + } + } + + if( friendly < 0 ) friendly=0; + if( hostile < 0 ) hostile=0; + + oldstat[x] = curntn->dstatus[x]; + + /* break bad treaties */ + if(curntn->dstatus[x] == TREATY) { + if(ntn[x].dstatus[country]>=WAR) + curntn->dstatus[x] = JIHAD; + continue; + } + + if((curntn->dstatus[x] == JIHAD) + ||(curntn->dstatus[x]==UNMET) + ||(ispc(curntn->active))) + continue; + + /*if 4* mil and 4* score then not like them*/ + if((ntn[x].tmil>4*curntn->tmil) + &&(ntn[x].score>4*curntn->score)){ + if(curntn->dstatus[x]dstatus[x]++; + } + } + /*adjust based on your status with them*/ + if((curntn->dstatus[x]==WAR) + &&(ntn[x].dstatus[country]dstatus[x]--; + + if((curntn->dstatus[x]dstatus[x]>ALLIED)){ + if(ntn[x].dstatus[country]>1+curntn->dstatus[x]){ + if(rand()%100<=hostile) + curntn->dstatus[x]++; + } else if(ntn[x].dstatus[country]+1dstatus[x]){ + if(rand()%100<=friendly) + curntn->dstatus[x]--; + } + } + if(rand()%100<= hostile) { + if((curntn->dstatus[x]!=JIHAD) + &&(curntn->dstatus[x]!=TREATY)) + curntn->dstatus[x]++; + } + if((rand()%100<= friendly) + &&(curntn->dstatus[x]!=TREATY) + &&(curntn->dstatus[x]!=JIHAD) + &&(curntn->dstatus[x]!=WAR)) curntn->dstatus[x]--; + } + + for(x=1;xdstatus[x]==WAR)) { + ntn[x].dstatus[country]=HOSTILE; + curntn->dstatus[x]=HOSTILE; + fprintf(fnews,"2.\tnation %s and %s announce ceasefire\n",curntn->name,ntn[x].name); + if( isnotpc(ntn[x].active) ) continue; + if (mailopen(x)!=(-1)) { + fprintf(fm,"Message from Conquer\n\n"); + fprintf(fm,"Nation %s and you negotiate a ceasefire\n",curntn->name); + mailclose(x); + } + } else if((oldstat[x]==WAR)&&(curntn->dstatus[x]==WAR)){ + fprintf(fnews,"2.\tnation %s stays at war with %s\n",curntn->name,ntn[x].name); + } else if((oldstat[x]dstatus[x]==WAR)){ + fprintf(fnews,"2.\tnation %s goes to war with %s\n",curntn->name,ntn[x].name); + if( isnotpc(ntn[x].active) ) continue; + if (mailopen(x)!=(-1)) { + fprintf(fm,"Message from Conquer\n\n"); + fprintf(fm,"Nation %s goes to war with you\n",curntn->name); + mailclose(x); + } + } else if((oldstat[x]!=JIHAD)&&(curntn->dstatus[x]==JIHAD)){ + fprintf(fnews,"2.\tnation %s announces a jihad with %s\n",curntn->name,ntn[x].name); + if( isnotpc(ntn[x].active) ) continue; + if(mailopen(x)!=(-1)) { + fprintf(fm,"Message from Conquer\n\n"); + fprintf(fm,"nation %s announces a jihad with you\n",curntn->name); + mailclose(x); + } + } + } +} + + +/* Find the average world food value per sector + * and the average tradegood value per sector. + * This is used for unseen sectors and unseen + * armies. + */ +static void +find_avg_sector () +{ + int armynum, i, nation, repeat, total_sectors, total_food = 0; + struct s_sector *sptr; /* used to speed up this function */ + register int x,y; + register long total_tg = 0; + register long useable_land = 0; + + for(x=0;xaltitude!=WATER )&&( sptr->altitude!=PEAK )) { + useable_land++; + total_food += tofood(sptr,country); + if(sptr->tradegood != TG_none) { + if(sptr->metal != 0) total_tg +=500; + else if(sptr->jewels != 0) total_tg +=500; + else total_tg +=300; + } + } + } + if (useable_land>0) { + Avg_food = total_food / useable_land; + Avg_tradegood = total_tg / useable_land; + } else { + /* for stupidities sake */ + Avg_food = 0; + Avg_tradegood = 0; + } + + for(nation=1;nation 0) { + x = ntn[nation].arm[armynum].xloc; + y = ntn[nation].arm[armynum].yloc; + repeat = FALSE; + for (i=1; (i 0) + Avg_soldiers[nation] = ntn[nation].tmil / total_sectors; + else Avg_soldiers[nation] = 0; + } + } +} + +void +nationrun() +{ + int goldthresh,metalthresh,citythresh,useful; + int armynum,loop; + int x,y,i,p; + float hunger; + long zz; + check(); + prep(country,FALSE); + + for(x=0;xcapx][curntn->capy].owner==country) + &&(sct[curntn->capx][curntn->capy].designation!=DCAPITOL)){ + sct[curntn->capx][curntn->capy].designation=DCAPITOL; + } + + if( ispc( curntn->active )) { + stx=sty=0; + endx=MAPX; + endy=MAPY; + } else { + if( curntn->capx > NPCTOOFAR ) + stx=(int)curntn->capx-NPCTOOFAR; + else stx=0; + if( curntn->capy > NPCTOOFAR ) + sty=(int)curntn->capy-NPCTOOFAR; + else sty=0; + if( (int)curntn->capx + NPCTOOFAR < MAPX ) + endx=(int)curntn->capx+NPCTOOFAR; + else endx=MAPX; + if( (int)curntn->capy + NPCTOOFAR < MAPY ) + endy=(int)curntn->capy+NPCTOOFAR; + else endy=MAPY; + } + + getdstatus(); + + find_avg_sector (); + +#ifdef SPEW + for(x=1;xdstatus[x] >= HOSTILE) + && (ispc(ntn[x].active))) + if (rand()%4 == 0) { /* send the message!! */ + if (mailopen(x)!=(-1)) { + fprintf(fm,"Message to %s from %s (%s of year %d)\n\n" + ,ntn[x].name,curntn->name,PSEASON(TURN),YEAR(TURN)); + makemess(rand()%5 +1,fm); + mailclose(x); + printf("Sent message to %s\n",ntn[x].name); + } + } + } +#endif /* SPEW */ + /*move units */ + /*are they at war with any normal countries*/ + peace=0; + for(i=1;idstatus[i]>peace)) { + peace=curntn->dstatus[i]; + if( peace>= WAR) break; + } + + if(peacetmil==0) defattr(); + else for(x=0;xdstatus[x]>HOSTILE)){ + if(100*(curntn->tmil*(curntn->aplus+100))/((curntn->tmil*(curntn->aplus+100))+(ntn[x].tmil*(ntn[x].dplus+100)))>rand()%100){ + /*attacker*/ + for(armynum=1;armynum0)&&(P_ATYPE!=A_MILITIA) + &&(P_ASTAT!=ONBOARD)&&(P_ASTAT!=TRADED) + &&(P_ASTAT0)&&(P_ATYPE!=A_MILITIA) + &&(P_ASTAT!=ONBOARD)&&(P_ASTAT!=TRADED) + &&(P_ASTAT=MINLEADER)) loop+=armymove(armynum); + + /* NPC ACTIVE STATUS CHANGE */ + if(isnpc(curntn->active) + &&(curntn->active != ISOLATIONIST)) { + if(isgood(curntn->active)) { + if(loop<=1) curntn->active=GOOD_0FREE; + else if(loop>=6) curntn->active=GOOD_6FREE; + else if(loop>=4) curntn->active=GOOD_4FREE; + else curntn->active=GOOD_2FREE; + } else if(isneutral(curntn->active)) { + if(loop<=1) curntn->active=NEUTRAL_0FREE; + else if(loop>=6) curntn->active=NEUTRAL_6FREE; + else if(loop>=4) curntn->active=NEUTRAL_4FREE; + else curntn->active=NEUTRAL_2FREE; + } else if(isevil(curntn->active)) { + if(loop<=1) curntn->active=EVIL_0FREE; + else if(loop>=6) curntn->active=EVIL_6FREE; + else if(loop>=4) curntn->active=EVIL_4FREE; + else curntn->active=EVIL_2FREE; + } + } + + if( curntn->tgold > curntn->tciv ) curntn->charity=10; + else curntn->charity=0; + if( (curntn->tsctrs < 20) || (curntn->score < 20) ) { + if( curntn->tax_rate < 10 ) + curntn->tax_rate = 10; + } else { + curntn->tax_rate = (int)min((int)(curntn->prestige/5),(int)((curntn->popularity+curntn->terror+3*curntn->charity)/10)); + curntn->tax_rate = (int)min(curntn->tax_rate,20); + if(curntn->tax_rate < 4) + curntn->tax_rate = 4; + } + + /* INTELLIGENT SECTOR REDESIGNATION */ + /* note that only redesignate pc's if not designated yet */ + goldthresh=4; + metalthresh=4; + citythresh=10; + hunger = 5.0; + for(loop=1;loop<5;loop++) { +#ifdef DEBUG + printf("\tnpcredes(): country %s gold=%d metal=%d, city=%d hunger=%f\n",curntn->name,goldthresh,metalthresh,citythresh,hunger); +#endif /* DEBUG */ + + useful=FALSE; + for(x=stx;xactive)) + ||(sct[x][y].designation==DNODESIG))) { + n_redes(x,y,goldthresh,metalthresh,citythresh,hunger); + useful=TRUE; + } + if(useful==FALSE) break; + + spreadsheet(country); + + if (spread.civilians+2*curntn->tmil > 0) { + hunger = spread.food/((float)(spread.civilians+2*curntn->tmil)); + } else hunger = 0.0; + if(hunger < P_EATRATE ) { + goldthresh++; + metalthresh++; + citythresh--; + } else if(hunger > 2*P_EATRATE) { + if( goldthresh==1 && metalthresh==1 ) break; + goldthresh-=2; + metalthresh-=2; + citythresh+=2; + } else { + if( goldthresh==1 && metalthresh==1 ) break; + if(rand()%2==0) goldthresh--; + else metalthresh--; + if(goldthresh==0) goldthresh=1; + if(metalthresh==0) metalthresh=1; + citythresh++; + } + if(goldthresh<=0) goldthresh=1; + if(metalthresh<=0) metalthresh=1; + } + + /*build forts in any cities*/ + if(isnotpc(curntn->active)) for(x=stx;xtgold>10000) + &&(rand()%5==0) + &&(sct[x][y].fortress<(sct[x][y].people%1000))) + sct[x][y].fortress++; + check(); + /*redo mil*/ + if(isnotpc(curntn->active)) redomil(); + check(); + + /*buy new powers and/or new weapons*/ + if(getmgkcost(M_MIL,country) < getmgkcost(M_CIV,country)){ + if(curntn->jewels > getmgkcost(M_MIL,country)) { + curntn->jewels-=getmgkcost(M_MIL,country); + if((zz=getmagic(M_MIL))!=0){ + for(p=S_MIL;pname,pwrname[p]); + printf("\tnation %s gets combat power %s\n",curntn->name,pwrname[p]); + break; + } + exenewmgk(zz); + } else if((zz=getmagic(M_MIL))!=0){ + for(p=S_MIL;pname,pwrname[p]); + printf("\tnation %s gets combat power %s\n",curntn->name,pwrname[p]); + break; + } + exenewmgk(zz); + } + else curntn->jewels+=getmgkcost(M_MIL,country); + } + } else { + if(curntn->jewels > getmgkcost(M_CIV,country)) { + curntn->jewels-=getmgkcost(M_CIV,country); + if((zz=getmagic(M_CIV))!=0){ + for(p=S_CIV;pname,pwrname[p]); + printf("\tnation %s gets civilian power %s\n",curntn->name,pwrname[p]); + break; + } + exenewmgk(zz); + } + else if((zz=getmagic(M_CIV))!=0){ + for(p=S_CIV;pname,pwrname[p]); + printf("\tnation %s gets civilian power %s\n",curntn->name,pwrname[p]); + break; + } + exenewmgk(zz); + } + else curntn->jewels+=getmgkcost(M_CIV,country); + } + } + + check(); + if(magic(country,VAMPIRE)!=TRUE) { + i=0; + if(magic(country,WARLORD)==TRUE) i=30; + else if(magic(country,CAPTAIN)==TRUE) i=20; + else if(magic(country,WARRIOR)==TRUE) i=10; + x = max ( curntn->aplus-i, 10 ) / 10; + x *= x; + if( curntn->race==ORC) x*=2; + /* SHOULD USE spread.metal but it didnt work right */ + if(rand()%2==0) + if(curntn->metals > 3 * METALORE * curntn->tmil*x){ + curntn->aplus+=1; + curntn->metals-=METALORE*curntn->tmil*x; + printf("\tnation %s buys +1 percent attack\n",curntn->name); + } + x = max ( curntn->dplus-i, 10 ) / 10; + x *= x; + if( curntn->race==ORC) x*=2; + if(curntn->metals > 3 * METALORE * curntn->tmil*x){ + curntn->dplus+=1; + curntn->metals-=METALORE*curntn->tmil*x; + printf("\tnation %s buys +1 percent defense\n",curntn->name); + } + } + /* don't allow status ATTACK from own city */ + for(armynum=0;armynum 0)) { + if(rand()%2==0) P_ASTAT=DEFEND; + else P_ASTAT=GARRISON; + } + } +} + +/* dont allow npcs to trespass onto other nations land */ +void +n_trespass() +{ + register int x,y; + for(x=stx;xcapx)>2 ) + &&( abs(y-(int)curntn->capy)>2 ) + &&( ntn[country].dstatus[sct[x][y].owner]ALLIED)) + attr[x][y]=1; + } +} + +/* you are too far from capitol */ +void +n_toofar() +{ + register int x,y; + for(x=0;x=endx || y>=endy ) + attr[x][y]=1; + } +} + +/* take undefended land */ +void +n_unowned() +{ +#ifdef XENIX + register int z; +#endif /*XENIX*/ + register int x,y; + + /* around capitol */ + for(x=(int)curntn->capx-4;x<=(int)curntn->capx+4;x++){ + for(y=(int)curntn->capy-4;y<=(int)curntn->capy+4;y++){ + if((ONMAP(x,y))&&(sct[x][y].owner==0)) { + attr[x][y] += 450; + } + } + } + + for(x=stx;x 0) + if(sct[ntn[natn].arm[x].xloc][ntn[natn].arm[x].yloc].owner==country) + attr[ntn[natn].arm[x].xloc][ntn[natn].arm[x].yloc] += + ntn[natn].arm[x].sold/10; + } + else { + /* For every of this country's sectors that has a 'natn' army + * in it, add 1/10 of the average number of soldiers in that + * 'natn' army. + */ + for(j=1;j 0) { + x = ntn[natn].arm[j].xloc; + y = ntn[natn].arm[j].yloc; + if(sct[x][y].owner==country) { + /* insure the average soldiers is only added + * once per sector */ + repeat = FALSE; + for (i=1; (icapx-1;x<=(int)curntn->capy+1;x++){ + for(y=(int)curntn->capy-1;y<=(int)curntn->capy+1;y++){ + if(ONMAP(x,y)) attr[x][y]+=80; + } + } + + /*plus based on defensive value and population */ + for(x=stx;x0) + attr[x][y]+=3000*sct[x][y].people/ntn[country].tciv; + } + } +} + +void +n_attack(nation) +register short nation; +{ + register int x,y; + int armynum; + long solds; /* solds within 1 of capitol or city */ + + for(x=stx;x 0) + &&(abs(AXLOC-x)<=1) + &&(abs(AYLOC-y)<=1)) solds+=ASOLD; + + if (COUNT_ARMIES(nation,country)) { + if(solds_in_sector(x,y,nation)*2 < 3*solds) + attr[x][y]+=500; + } + else { + if((solds_in_sector(x,y,nation) != 0) + &&(Avg_soldiers[nation]*2 < 3*solds)) + attr[x][y]+=400; + } + } + } + else + /* Give some value: the sector MIGHT be an under-defended city */ + attr[x][y] += UNS_CITY_VALUE; + } + } +} + +/* +100 if undefended sectors of nation, +60 if not */ +void +n_undefended( nation ) +{ + register int x,y; + for(x=stx;xcapx){ + x1=ntn[nation].capx; + x2=curntn->capx; + } else { + x1=curntn->capx; + x2=ntn[nation].capx; + } + if (ntn[nation].capy < curntn->capy){ + y1=ntn[nation].capy; + y2=curntn->capy; + } + else { + y1=curntn->capy; + y2=ntn[nation].capy; + } + + for(x=x1;x<=x2;x++) for(y=y1;y<=y2;y++) { + if(ONMAP(x,y)) attr[x][y]+=60; + } +} + +/* if in jeopardy, move to survive + * if within two of cap add 1/5th of men + * if on cap and war and 2x your garrison go jihad and + 1/2 men + */ +void +n_survive() +{ + int i; + int nation,armynum; + int capx,capy; + int repeat; + int x,y; + + capx=curntn->capx; + capy=curntn->capy; + + if(sct[capx][capy].owner!=country){ + attr[capx][capy]=1000; + } + + /*defend your capitol if occupied, +50 more if with their army*/ + for(nation=1;nation=WAR) + ||(curntn->dstatus[nation]>=WAR))){ + if (COUNT_ARMIES(nation,country)) { + for(armynum=1;armynum 0) + &&( ntn[nation].arm[armynum].xloc<=capx+2) + &&( ntn[nation].arm[armynum].xloc>=capx-2) + &&( ntn[nation].arm[armynum].yloc<=capy+2) + &&( ntn[nation].arm[armynum].yloc>=capy-2)){ + if((ntn[nation].arm[armynum].xloc==capx) + &&(ntn[nation].arm[armynum].yloc==capy)){ + attr[capx][capy]+=2*ntn[nation].arm[armynum].sold; + } + else { + attr[ntn[nation].arm[armynum].xloc][ntn[nation].arm[armynum].yloc]+=ntn[nation].arm[armynum].sold; + } + } + } else { + /* The next line might be more accurate to take into account + * the actual number of armies that natn has, but I don't + * think that VOID or HIDDEN should allow that to be known. + */ + for(armynum=1;armynum 0) { + x = ntn[nation].arm[armynum].xloc; + y = ntn[nation].arm[armynum].yloc; + if((capx-2<=x && x<=capx+2) + &&( capy-2<=y && y<=capy+2)){ + /* insure the average soldiers is only added + * once per sector + */ + repeat = FALSE; + for (i=1; (idstatus[nation]>=WAR)) { + n_defend(nation); + n_between(nation); + n_undefended(nation); + } + + n_trespass(); + n_toofar(); + n_survive(); +} + +/*calculate attractiveness of attacking sectors*/ +void +atkattr() +{ + int nation; +#ifdef DEBUG + printf("atkattr()\n"); +#endif /* DEBUG */ + + n_unowned(); + + /*adjust for each nation that you are at war with*/ + for(nation=1;nationdstatus[nation]==WAR) { + n_between(nation); + n_undefended(nation); + n_attack(nation); + } else if(curntn->dstatus[nation]==JIHAD) { + n_attack(nation); + n_attack(nation); + n_between(nation); + n_undefended(nation); + n_attack(nation); + n_between(nation); + n_undefended(nation); + n_attack(nation); + } + } + + n_toofar(); + n_trespass(); + n_survive(); +} + +/*calculate attractiveness when at peace*/ +void +pceattr() +{ +#ifdef DEBUG + printf("pceattr()\n"); +#endif /* DEBUG */ + n_unowned(); + n_unowned(); + n_unowned(); + n_trespass(); + n_toofar(); + n_survive(); +} +#endif /* NPC */ diff --git a/historical/oMakefile b/original/oMakefile similarity index 90% rename from historical/oMakefile rename to original/oMakefile index fbb804e..45af7bc 100644 --- a/historical/oMakefile +++ b/original/oMakefile @@ -1,24 +1,3 @@ -/* - * oMakefile - Build system configuration - * - * This file is part of Conquer. - * Originally Copyright (C) 1988-1989 by Edward M. Barlow and Adam Bryant - * Copyright (C) 2025 Juan Manuel Méndez Rey (Vejeta) - Licensed under GPL v3 with permission from original authors - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - # conquer: Copyright (c) 1989 by Edward M Barlow # # BY CHANGING THIS FILE, YOU AGREE TO ABIDE BY THE LIMITATIONS STATED IN diff --git a/original/patchlevel.h b/original/patchlevel.h new file mode 100644 index 0000000..7088234 --- /dev/null +++ b/original/patchlevel.h @@ -0,0 +1 @@ +#define PATCHLEVEL "11a" diff --git a/original/psmap.c b/original/psmap.c new file mode 100644 index 0000000..6ff07a0 --- /dev/null +++ b/original/psmap.c @@ -0,0 +1,514 @@ + +/* + * A program to convert conquer-maps to postscript Feel free to hack'n slash + * Comments should be sent to d8forma@dtek.chalmers.se + * + */ + +#include +#include +#include +#include "psmap.h" + +char buffer[BUFSIZ]; +int c, xsize, ysize; +int xmin, ymin, xmax, ymax, centx, centy; +FILE *infile, *outfile, *fh, *fopen(); +int grid = TRUE, sqsize = 9, maptype = SIMPLE, onepage = FALSE; +int verbose = FALSE, coords = TRUE, center = TRUE, note = FALSE; +int pagewidth, pageheight, xoffset, yoffset; +char title[81] = "", foot[81], fontname[81]; +char progname[80]; + +int +parsepagesize(buf) + char *buf; +{ + if (!strcmp(buf, "A4")) + return (1); + if (!strcmp(buf, "a4")) + return (1); + if (!strcmp(buf, "LETTER")) + return (2); + if (!strcmp(buf, "letter")) + return (2); + return (0); +} + +void +setpagesize(defpag) + int defpag; +{ + switch (defpag) { + case 1: + pagewidth = PAGEWIDTH_A4; + pageheight = PAGEHEIGHT_A4; + xoffset = XOFFSET_A4; + yoffset = YOFFSET_A4; + break; + case 2: + pagewidth = PAGEWIDTH_LETTER; + pageheight = PAGEHEIGHT_LETTER; + xoffset = XOFFSET_LETTER; + yoffset = YOFFSET_LETTER; + break; + default: + pagewidth = PAGEWIDTH_OTHER; + pageheight = PAGEHEIGHT_OTHER; + xoffset = XOFFSET_OTHER; + yoffset = YOFFSET_OTHER; + break; + } +} + +void +get_pagesize() +{ + char *buf; + int defpag = DEFAULTPAGE; + + buf = (char *) getenv("CONQ_PSMAPDEFAULTPAGE"); + if (buf != NULL) + defpag = parsepagesize(buf); + setpagesize(defpag); +} + +void +psstring(fh, str) + FILE *fh; + char *str; +{ + fprintf(fh, "("); + while (*str != '\0') { + switch (*str) { + case ('('): + fprintf(fh, "\\("); + break; + case (')'): + fprintf(fh, "\\)"); + break; + case ('\\'): + fprintf(fh, "\\\\"); + break; + case ('\n'): + case ('\f'): + break; + default: + fputc(*str, fh); + break; + } + str++; + } + fprintf(fh, ")"); +} + +int +isinstr(string, word) + char *string, *word; +{ + int i,l1=strlen(string),l2=strlen(word); + + if (l1 < l2) return(FALSE); + for(i = 0; i < l1; i++ ) { + if (l1-i -1) && (ymin == -1)) + ymin = ysize; + ysize++; + fprintf(outfile, ")\n"); + none = TRUE; + break; + case (' '): + x++; + if (none) { + fprintf(outfile, "("); + none = FALSE; + } + fprintf(outfile, " "); + break; + default: + if (x < xmin) + xmin = x; + if (x > xmax) + xmax = x; + if (ysize > ymax) + ymax = ysize; + x++; + if (none) { + fprintf(outfile, "("); + none = FALSE; + } + fprintf(outfile, "%c", c); + break; + } + } + + fprintf(outfile, "] def\n\n"); + + /* Did I get anything ? */ + if (xmax == -1) { + fprintf(stderr, "Empty input file\n"); + exit(1); + } + if (verbose) { + fprintf(stderr, "Map is %d * %d squares\n", xsize, ysize); + fprintf(stderr, "You can see %d * %d squares\n", + xmax - xmin + 1, ymax - ymin + 1); + } +} + +void +buildps() +{ + int xbeg, ybeg, xnumb, ynumb, x, y, xpages, ypages, xcorr, ycorr; + + /* + * The map should be dumped to the outfile now. Maybe we should tell the + * printer what to do with it? + */ + + xpages = 1 + (xmax - xmin) * sqsize / (pagewidth - XMARGINS); + ypages = 1 + (ymax - ymin) * sqsize / (pageheight - YMARGINS); + + if (verbose) + fprintf(stderr, "The map will be %d * %d pages\n", xpages, ypages); + + fprintf(outfile, "/xmin %d def\n", xmin); + fprintf(outfile, "/ymin %d def\n", ymin); + fprintf(outfile, "/xmax %d def\n", xmax); + fprintf(outfile, "/ymax %d def\n", ymax); + fprintf(outfile, "/xpages %d def\n", xpages); + fprintf(outfile, "/ypages %d def\n", ypages); + fprintf(outfile, "/sqsize %d def\n", sqsize); + fprintf(outfile, "/title "); + psstring(outfile, title); + fprintf(outfile, " def\n"); + fprintf(outfile, "/foot "); + psstring(outfile, foot); + fprintf(outfile, " def\n"); + fprintf(outfile, "/foot2 (ConqPS Version %s) def\n", VERSION); + fprintf(outfile, "/PAGEWIDTH %d def\n", pagewidth); + fprintf(outfile, "/PAGEHEIGHT %d def\n", pageheight); + fprintf(outfile, "/XMARGINS %d def\n", XMARGINS); + fprintf(outfile, "/YMARGINS %d def\n", YMARGINS); + fprintf(outfile, "/XOFFSET %d def\n", xoffset); + fprintf(outfile, "/YOFFSET %d def\n", yoffset); + fprintf(outfile, "/maptype %d def\n", maptype); + fprintf(outfile, "/font /%s def\n", fontname); + fprintf(outfile, "/grid "); + if (grid) { + fprintf(outfile, "true def\n"); + } else + fprintf(outfile, "false def\n"); + fprintf(outfile, "/coords "); + if (coords) { + fprintf(outfile, "true def\n"); + } else + fprintf(outfile, "false def\n"); + fprintf(outfile, "/noteq "); + if (note) { + fprintf(outfile, "true def\n"); + } else + fprintf(outfile, "false def\n"); + + fprintf(outfile, "\n\n"); + + fh = fopen(PSFILE, "r"); + + if (fh == NULL) { + perror(progname); + exit(-10); + } + while ((c = fgetc(fh)) != EOF) + fputc(c, outfile); + + fclose(fh); + + fprintf(outfile, "\n %% Here we start the magic\n"); + + xnumb = (int) ((pagewidth - XMARGINS) / sqsize); + ynumb = (int) ((pageheight - YMARGINS) / sqsize); + + if (center) { + xcorr = (int) ((xpages * xnumb - (xmax - xmin)) / 2); + ycorr = (int) ((ypages * ynumb - (ymax - ymin)) / 2); + } else { + xcorr = 0; + ycorr = 0; + } + + if (onepage) { + fprintf(outfile, "%d %d %d %d %d %d DoPage\n", + 1, 1, centx - xnumb / 2, xnumb, centy - ynumb / 2, ynumb); + } else + for (x = 0; x < xpages; x++) + for (y = 0; y < ypages; y++) { + xbeg = x * xnumb + x + xmin - xcorr; + ybeg = y * ynumb + y + ymin - ycorr; + fprintf(outfile, "%d %d %d %d %d %d DoPage\n", + x + 1, y + 1, xbeg, xnumb, ybeg, ynumb); + } +} + +main(argc, argv) + int argc; + char **argv; +{ + extern char *optarg; + extern int optind; + char *buf, firstline[81]; + + strcpy(progname, argv[0]); + infile = stdin; + outfile = stdout; + buf = (char *) getenv("CONQ_PSFONT"); + if (buf != NULL) { + strncpy(fontname, buf, 80); + fontname[79] = '\0'; + } else + strcpy(fontname, "Times-Roman"); + get_pagesize(); + + while ((c = getopt(argc, argv, "nuf:gs:t:vcho:p:lW:L:X:Y:")) != -1) + switch (c) { + case 'h': + fprintf(stderr, "%s version %s\n", progname, VERSION); + fprintf(stderr, "Default pagesize is "); + switch (DEFAULTPAGE) { + case 1: + fprintf(stderr, "A4\n"); + break; + case 2: + fprintf(stderr, "LETTER\n"); + break; + default: + fprintf(stderr, "OTHER\n"); + break; + } + fprintf(stderr, USAGE, progname); + fprintf(stderr, "\t-c Turn off coordinates\n"); + fprintf(stderr, "\t-f Set the font\n"); + fprintf(stderr, "\t-g Turn off grid\n"); + fprintf(stderr, "\t-h Show this text\n"); + fprintf(stderr, "\t-l Print large maps\n"); + fprintf(stderr, "\t-L Set the pagelength\n"); + fprintf(stderr, "\t-n Turn off map centering\n"); + fprintf(stderr, "\t-o Show one page centered around x,y\n"); + fprintf(stderr, "\t-p Set pagesize (A4,LETTER or OTHER)\n"); + fprintf(stderr, "\t-s Set size of square (default: %d)\n", sqsize); + fprintf(stderr, "\t-t Set the title of the map\n"); + fprintf(stderr, "\t-u Force simple map output (just letters)\n"); + fprintf(stderr, "\t-v Verbose mode\n"); + fprintf(stderr, "\t-W Set the pagewidth\n"); + fprintf(stderr, "\t-X Set the X-offset\n"); + fprintf(stderr, "\t-Y Set the Y-offset\n"); + exit(1); + case 'u': + maptype = FORCED; + break; + case 'o': + onepage = TRUE; /* Mode one of onepage */ + if (2 != sscanf(optarg, "%d,%d", ¢x, ¢y)) { + fprintf(stderr, "Error in coordinates to o-option\n"); + exit(1); + } + break; + case 'l': + note = TRUE; + break; + case 'p': + setpagesize(parsepagesize(optarg)); + break; + case 'n': + center = FALSE; + break; + case 'g': + grid = FALSE; + break; + case 's': + sscanf(optarg, "%d", &sqsize); + break; + case 'f': + strncpy(fontname, optarg, 80); + fontname[79] = '\0'; + break; + case 't': + strncpy(title, optarg, 80); + title[79] = '\0'; + break; + case 'v': + verbose = TRUE; + break; + case 'c': + coords = FALSE; + break; + case 'W': + sscanf(optarg, "%d", &pagewidth); + break; + case 'L': + sscanf(optarg, "%d", &pageheight); + break; + case 'X': + sscanf(optarg, "%d", &xoffset); + break; + case 'Y': + sscanf(optarg, "%d", &yoffset); + break; + default: + fprintf(stderr, USAGE, argv[0]); + exit(1); + } + if (optind < argc) + infile = fopen(argv[optind], "r"); + + if (infile == NULL) { + perror(progname); + exit(-10); + } + if (++optind < argc) + outfile = fopen(argv[optind], "w"); + + if (outfile == NULL) { + perror(progname); + exit(-10); + } + setbuf(outfile, buffer); /* They recomended this on the net today */ + + if (++optind < argc) { + fprintf(stderr, USAGE, argv[0]); + exit(1); + } + /* If verbose identify program */ + + if (verbose) + fprintf(stderr, "Psmap version %s\n", VERSION); + + + /* First we check if the infile is a valid conquer map file */ + + if (NULL == fgets(firstline, 80, infile)) { + fprintf(stderr, "Empty input file\n"); + exit(1); + } + if (0 != strncmp(firstline, MATCHSTRING, strlen(MATCHSTRING))) { + fprintf(stderr, "Not a Conquer Map file\n"); + exit(1); + } + for (c = 0; c < strlen(firstline); c++) { + if (firstline[c] == ':') + break; + } + + strncpy(foot, firstline, c); + foot[c] = '\0'; + if (title[0] == '\0') { + strncpy(title, &firstline[c + 1], 80); + title[79] = '\0'; + } + /* Find out which type of map it is */ + + if (maptype != FORCED) { + maptype = getmaptype(&firstline[c + 1]); + } else + maptype = SIMPLE; + + if (verbose) { + fprintf(stderr, "Maptype is "); + switch (maptype) { + case (SIMPLE): + fprintf(stderr, "simple\n"); + break; + case (ALTITUDES): + fprintf(stderr, "altitudes\n"); + break; + case (DESIGNATIONS): + fprintf(stderr, "designations\n"); + break; + case (NATIONS): + fprintf(stderr, "nations\n"); + break; + case (VEGETATIONS): + fprintf(stderr, "vegetations\n"); + break; + default: + break; + } + } + /* Send the first part of the postscript file to outfile */ + + fprintf(outfile, "%%!\n"); + fprintf(outfile, "%% Created by conqps version %s\n\n", VERSION); + if (note) + fprintf(outfile, "\nnote\n\n"); + fprintf(outfile, "%% Here comes the map data:\n"); + + /* Parse the map */ + + readmap(); + + /* Build the last part of postscript file */ + + buildps(); + + /* Phu that was it. */ + + if (infile != NULL) + fclose(infile); + if (outfile != NULL) + fclose(outfile); + + return (0); +} + diff --git a/original/psmap.h b/original/psmap.h new file mode 100644 index 0000000..127a81d --- /dev/null +++ b/original/psmap.h @@ -0,0 +1,56 @@ +/* + * Header file for conqps by MaF + * Feel free to modify + * Comments should be sent to d8forma@dtek.chalmers.se + * + */ + +/* Page size hassle */ +#ifdef OTHER +#define DEFAULTPAGE 0 +#endif + +#ifdef A4 +#define DEFAULTPAGE 1 +#endif + +#ifdef LETTER +#define DEFAULTPAGE 2 +#endif + +/* Printer dependant entries */ +#define PAGEWIDTH_A4 540 +#define PAGEHEIGHT_A4 820 +#define XOFFSET_A4 30 +#define YOFFSET_A4 10 + +#define PAGEWIDTH_LETTER 575 +#define PAGEHEIGHT_LETTER 760 +#define XOFFSET_LETTER 15 +#define YOFFSET_LETTER 10 + +#define PAGEWIDTH_OTHER 450 +#define PAGEHEIGHT_OTHER 700 +#define XOFFSET_OTHER 40 +#define YOFFSET_OTHER 30 + +/* Cosmetics */ +#define XMARGINS 30 +#define YMARGINS 50 + +/* Version specific defines */ +#define VERSION "1.0" +#define USAGE "Usage: %s [cghlnvu] [p pagesize] [f font] [o x,y] [s size]\n\t[W n] [L n] [X n] [Y n] [t title] [infile [outfile]]\n" +#define MATCHSTRING "Conquer Version" + +/* Mathematical definitions */ +#define TRUE 1 +#define FALSE 0 + +/* Types of maps possible to be printed */ +#define SIMPLE 0 +#define ALTITUDES 1 +#define DESIGNATIONS 2 +#define NATIONS 3 +#define VEGETATIONS 4 +#define FORCED 5 diff --git a/original/psmap.ps b/original/psmap.ps new file mode 100644 index 0000000..9030078 Binary files /dev/null and b/original/psmap.ps differ diff --git a/original/randeven.c b/original/randeven.c new file mode 100644 index 0000000..e71c21b --- /dev/null +++ b/original/randeven.c @@ -0,0 +1,1135 @@ +/* Conquer: Copyright (c) 1988 by Edward M Barlow */ +#include +#include +#include +#include +#include +#include +#include "header.h" +#include "data.h" + +#ifdef RANEVENT +char *names[] = { /* must end in single character name */ + "groo","brok","vul","poin","srop","hoga","nobi","bonz","gail", + "lynn","zorb","theed","urda","anima","bedlam","delos","quin", + "xynd","putz","erde","clym","fanz","ilth","X" +}; + +extern FILE *fnews; +extern short country; + +char eventstr[LINELTH+1]; +int xpos,ypos; /* saved x and y position */ + +char *randevents[] = { +/* 0 */ "a military rebellion", +/* 1 */ "a cult breaks with you", +/* 2 */ "a province rebels", +/* 3 */ "an evil wizard sets up", +/* 4 */ "a tax revolt occurs", +/* 5 */ "open rebellion flares", +/* 6 */ "an army revolts", +/* 7 */ "religions schism", +/* 8 */ "peasants revolt", +/* 9 */ "dragons raid", +/* 10 */ "a famine rages", +/* 11 */ "a hurricane blows over", +/* 12 */ "a tornado hits", +/* 13 */ "a volcano erupts", +/* 14 */ "a royal wedding occurs", +/* 15 */ "new alloy discovered", +/* 16 */ "royal advisor discovered to be spy", +/* 17 */ "gold strike in one sector", +/* 18 */ "gold strike in one sector", +/* 19 */ "gold vein runs out in one goldmine sector", +/* 20 */ "gold vein runs out in one goldmine sector", +/* 21 */ "a flood ravishes", +/* 22 */ "an earthquake quakes", +/* 23 */ "severe frost destroys crops", +/* 24 */ "feared dragon killed", +/* 25 */ "several nomad armies raid", +/* 26 */ "fire ravishes town", +/* 27 */ "black plague rages", +/* 28 */ "pirates raid", +/* 29 */ "savages raid", +/* 30 */ "wizard grants power", +/* 31 */ "magic item grants magic power", +/* 32 */ "ores in one mine run out", +/* 33 */ "new architect strengthens castle walls", +/* 34 */ "new ores discovered + 4-10 metal one sector", +/* 35 */ "skilled diplomacy obtains peace", +/* 36 */ "powerful magi curses nation", +/* 37 */ "severe winter hits", +/* 38 */ "tidal wave -- abandon all coastlands ", +/* 39 */ "ninja destroy general staff", +/* 40 */ "general found to be spy", +/* 41 */ "general prosperity +20% gold", +/* 42 */ "disease kills 20% of soldiers", +/* 43 */ "poor conditions kill 20% of soldiers" +}; +#define MAXRANEVENT 43 + +/*finds unused nation and sets it up partially*/ +int +findnew() +{ + int newntn=0,nationis; + for ( nationis=NTOTAL-1; nationis >= 1; nationis--) + if(ntn[nationis].active == INACTIVE) newntn=nationis; + if (newntn == 0) return (0); + strcpy(ntn[newntn].leader,"rebel"); + strcpy(ntn[newntn].passwd,ntn[0].passwd); + ntn[newntn].score=0L; + ntn[newntn].tsctrs=0; + ntn[newntn].active=NEUTRAL_6FREE; + return(newntn); +} + +/* returns unused character for nation mark */ +char +getnewmark() +{ + char tmpchr='A'-1; /* cap letters first */ + while (TRUE) { + tmpchr++; + if( markok( tmpchr, FALSE )) break; + if(tmpchr=='Z') tmpchr='a'-1; /* then small letters */ + if(tmpchr=='z') break; /* otherwise it will loop forever */ + } + return(tmpchr); +} + +/* disolve 'percent' of nation 'target; returns index of new nation */ +int +disolve(percent, target, ispsnt) +int target; +int percent; +int ispsnt; /* true/false */ +{ + int new; /* new nation number */ + int split; /* number of sectors split */ + int defaultx=(-1), defaulty=(-1), realx=(-1), realy=(-1), dist; + int i=0,j,armynum,narmynum; + + split = ntn[target].tsctrs * percent / 100; + if((split<=7)&&(!ispsnt)) { + strcpy(eventstr,"nation too small->no sectors will be split"); + return(0); + } + /* find starting town */ + if( ispsnt ) { + for( new=0; new=300) break; + } + if( i==300 ) { + strcpy(eventstr,"no sectors available"); + return(0); + } + printf("TMP peasant centered on %d,%d\n",xpos,ypos); + country = new; + realx = xpos; + realy = ypos; + } else for(i=0; i=2000)&&(sct[i][j].designation!=DCAPITOL))){ + if( rand()%3 == 0 ) { + realx = i; + realy = j; + } else { + defaultx = i; + defaulty = j; + } + } + } + } + if(realx == (-1)){ + realx = defaultx; + realy = defaulty; + } + if(realx == (-1)) { + strcpy(eventstr,"no cities available"); + return(0); + } + if((new=findnew()) == 0) { + strcpy(eventstr,"no nations available"); + return(0); + } + if(getnewname(new) == 0) { + strcpy(eventstr,"no names available"); + return(0); + } + +#ifdef HIDELOC + sprintf(eventstr,"new nation %s created",ntn[new].name); +#else + sprintf(eventstr,"new nation %s created at %d,%d",ntn[new].name,realx,realy); +#endif /* HIDELOC */ + printf("TMP new nation %s created at %d,%d",ntn[new].name,realx,realy); + sct[realx][realy].owner=new; +#ifdef CHECKUSER + ntn[new].uid = getpwnam(LOGIN)->pw_uid; +#endif /* CHECKUSER */ + ntn[new].capx=realx; + ntn[new].capy=realy; + sct[realx][realy].designation=DCAPITOL; + ntn[new].class=ntn[target].class; + ntn[new].race= ntn[target].race; + if( !ispsnt ) { + ntn[new].tgold= ntn[target].tgold* percent / 100; + ntn[new].tfood= ntn[target].tfood* percent / 100; + ntn[new].jewels= ntn[target].jewels* percent / 100; + ntn[new].metals= ntn[target].metals* percent / 100; + ntn[target].tgold -= ntn[new].tgold; + ntn[target].tfood -= ntn[new].tfood; + ntn[target].jewels -= ntn[new].jewels; + ntn[target].metals -= ntn[new].metals; + } + ntn[new].tciv= ntn[target].tciv* percent / 100; + ntn[new].tmil= ntn[target].tmil* percent / 100; + ntn[target].tciv -= ntn[new].tciv; + ntn[target].tmil -= ntn[new].tmil; + ntn[new].repro= ntn[target].repro; + ntn[new].maxmove= ntn[target].maxmove; + if( ispsnt ) { + ntn[new].aplus= ntn[new].dplus= 0; + } else { + ntn[new].aplus= ntn[target].aplus - 10; + ntn[new].dplus= ntn[target].dplus - 10; + } + ntn[new].location= ntn[target].location; + ntn[new].powers= ntn[target].powers; + ntn[new].tships= 0; + ntn[new].tsctrs = split; + ntn[new].tax_rate = 10; + + /* first check first letter of name */ + if( markok(toupper(ntn[new].name[0]),FALSE) ) + ntn[new].mark = toupper(ntn[new].name[0]); + else + ntn[new].mark = getnewmark(); + + for ( dist=1 ; dist < 10; dist++) if (split > 0) + for (i=realx-dist; i0 ) + &&( sct[i][j].designation != DCAPITOL ) + &&( sct[i][j].owner == target)){ + split--; + if( sct[i][j].people > 0 ) + sct[i][j].owner=new; + } + } + + narmynum=1; + for (armynum=0;armynum0) + &&(sct[ntn[target].arm[armynum].xloc][ntn[target].arm[armynum].yloc].owner==new)){ + ntn[new].arm[narmynum].sold + =ntn[target].arm[armynum].sold; + ntn[new].arm[narmynum].unittyp + =ntn[target].arm[armynum].unittyp; + ntn[new].arm[narmynum].xloc + =ntn[target].arm[armynum].xloc; + ntn[new].arm[narmynum].yloc + =ntn[target].arm[armynum].yloc; + ntn[new].arm[narmynum].stat + =ntn[target].arm[armynum].stat; + ntn[new].arm[narmynum].smove + =ntn[target].arm[armynum].smove; + ntn[target].arm[armynum].sold = 0; + narmynum++; + } + } + if( !ispsnt ) { + armynum=0; + ntn[new].arm[0].sold = 300; + ntn[new].arm[0].unittyp = A_INFANTRY; + ntn[new].arm[0].xloc = realx; + ntn[new].arm[0].yloc = realy; + ntn[new].arm[0].stat = GARRISON; + ntn[new].arm[0].smove = 0; + } + for(dist=0;dist 1;i++ ){ + for(count=0;countactive)) + ||(curntn->score<=20L) + ||(curntn->tsctrs<=20)) + continue; + + /* clear the event string */ + strcpy(eventstr,""); + + x = 10*curntn->tax_rate - curntn->popularity- curntn->terror - 3*curntn->charity; +#ifdef DEBUG +printf("TEMP: %s chance of peasant revolt is %d (tax=%d pop=%d terror=%d)\n", + curntn->name, x, curntn->tax_rate, curntn->popularity, + curntn->terror ); +#endif /* DEBUG */ + + if((rand()%100)name,eventstr); + } + } + + x = 5 * curntn->tax_rate - curntn->prestige; +#ifdef DEBUG +printf("TEMP: %s chance of revolt is %d (tax=%d prest=%d)\n", + curntn->name, x, curntn->tax_rate, curntn->prestige ); +#endif /* DEBUG */ + + if(( rand()%100)< x ){ + if(rand()%100name,eventstr); + } + } + + if( (rand()%100) < PWEATHER ) weather(); + + /* clear the event string for other random events */ + strcpy(eventstr,""); + + /* do truely random events */ + if((rand()%100)* WORLDSCORE < RANEVENT * WORLDNTN * curntn->score){ + + percent=0; + event = rand()%(MAXRANEVENT-9) + 9; + done=TRUE; + xpos = ypos = -1; + /* do the event */ + switch(event) { + case 9: /*dragon raid -- lose 30% of food*/ + strcpy(eventstr,"lose 30% of food"); + curntn->tfood *= 7L; + curntn->tfood /= 10L; + break; + case 10: /*famine -- food=0 10% starve*/ + curntn->tfood /= 4L; + strcpy(eventstr,"lose 3/4ths of food & 10% starve"); + for (i=0; idesignation )) + && (sptr->designation != DRUIN)) + sptr->designation = DNODESIG; + if (sptr->fortress>=1) sptr->fortress--; + reduce(x, y, percent); + } + break; + case 12: + /*tornado*/ + sptr = rand_sector(); + if( !(ISCITY( sptr->designation )) + && (sptr->designation != DRUIN)) + sptr->designation = DNODESIG; + else { + if (sptr->fortress < 2) sptr->fortress = 0; + else sptr->fortress -= 2; + } + percent = 10 + rand()%25; + reduce(xpos, ypos, percent); + break; + case 13: + /*volcano -- all flee around one mountain -- 30% die*/ + holdval=0; /* holdval is # of mountains */ + for (i=0; i 0) count = (rand()%holdval) + 1; + else { + done = FALSE; + break; + } + + sprintf(eventstr,"all flee, 30%% die in 1 sector range"); + for (xpos=0; count && (xpospowers|=WARRIOR; + exenewmgk(WARRIOR); + strcpy(eventstr,"gives WARRIOR power"); + } + else if(magic(country,CAPTAIN)!=1){ + curntn->powers|=CAPTAIN; + exenewmgk(CAPTAIN); + strcpy(eventstr,"gives CAPTAIN power"); + } + else if(magic(country,WARLORD)!=1){ + curntn->powers|=WARLORD; + exenewmgk(WARLORD); + strcpy(eventstr,"gives WARLORD power"); + } + else { /* have all three powers... oh well */ + done=FALSE; + } + break; + case 16: + /*royal advisor is spy -- lose power*/ + /* sprintf(eventstr,"nation loses power %s");*/ + done=FALSE; + break; + case 17: + case 18: + /*gold/jewel strike one sector */ + holdval = 0; + for (i=0; i 0) count = (rand()%holdval) + 1; + else { + done = FALSE; + break; + } + for (xpos=0; count && (xpos 0) count = (rand()%holdval) + 1; + else count = done = FALSE; + if (count == FALSE ) break; + for (xpos=0; count && (xposfortress < 2) sptr->fortress = 0; + else sptr->fortress -= 2; + reduce(xpos, ypos, (percent*3)/5); /* ADDITIONAL % */ + break; + case 23: + /*frost -- crops ruined*/ + done=FALSE; + break; + case 24: + /*dragon killed + 50000 jewels*/ + longval = rand()%10 * 10000; + sprintf(eventstr,"you gain %ld jewels",longval); + curntn->jewels+=longval; + break; + case 25: +#ifdef MONSTER + /*nomad raid -- put large nomad army in area*/ + for( holdval=1;holdvaltmil > 10000) /* 800-4800 */ + ntn[holdval].arm[armynum].sold =800+50*(rand()%80); + else if(curntn->tmil > 5000) /* 500-2500 */ + ntn[holdval].arm[armynum].sold =500+50*(rand()%40); + else if(curntn->tmil > 1000) /* 400-1400 */ + ntn[holdval].arm[armynum].sold =400+20*(rand()%50); + else /* 200-600 */ + ntn[holdval].arm[armynum].sold =200+20*(rand()%20); + ntn[holdval].arm[armynum].unittyp = A_LT_CAV; + ntn[holdval].arm[armynum].stat =ATTACK; + done++; + } + } + done=TRUE; + break; +#endif /* MONSTER */ + case 26: + /*town burns -- reduce fort and redesignate*/ + holdval=0; + for (xpos=0; xpos 0) count = (rand()%holdval) + 1; + else break; + + percent = 25 + rand()%50; + for (xpos=0; count && (xposdesignation )){ + sct[i][j].people *= 6; + sct[i][j].people /= 10; + } + } + for (armynum=0; armynum 0)&&(P_ATYPEdesignation )){ + P_ASOLD *= (6); + P_ASOLD /= (10); + } + } + break; + case 28: /*pirate raid on harbor*/ + done=FALSE; + break; + case 29: /*savages raid*/ + done=FALSE; + break; + case 30: /*new magician + RANDOM POWER*/ + /*buy new powers and/or new weapons*/ + if((newpower=getmagic(M_CIV))!=0L){ + for(i=S_CIV;iname,pwrname[i]); + } + exenewmgk(newpower); + } + else done=FALSE; + break; + case 31: /*new magic item + RANDOM POWER*/ + /*buy new powers and/or new weapons*/ + if((newpower=getmagic(M_MIL))!=0){ + for(i=S_MIL;iname,pwrname[i]); + exenewmgk(newpower); + } + else done=FALSE; + break; + case 32: + /* ores run out */ + holdval=0; + for (i=0; i 0) count = (rand()%holdval) + 1; + else break; + + for (xpos=0; count && (xposdesignation )) + sct[i][j].fortress += 2; + } + break; + case 34: /* new ores discovered */ + holdval=0; + for (i=0; i 0) count = (rand()%holdval)+1; + else break; + + for (xpos=0; count && (xposNEUTRAL )){ + ntn[newnation].dstatus[country]=NEUTRAL; + curntn->dstatus[newnation]=NEUTRAL; + } + break; + case 36: + /*powerful magi curses nation; lose a power*/ + done=TRUE; + i=holdval=0; + while( powers[i] != 0 ){ + if(magic(country,powers[i])==TRUE) holdval++; + i++; + } + if (holdval!=0) holdval = rand()%holdval+1; + newpower=0L; + for(i=0;powers[i]!=0 && holdval>0;i++) { + if (magic(country,powers[i])==TRUE) holdval--; + if (holdval==0) { + newpower=powers[i]; + break; + } + } + if(newpower==0L) { + done=FALSE; + break; + } + /* upgrade powers */ + switch(newpower) { + case MI_MONST: + if(magic(country,AV_MONST)==TRUE) { + newpower=AV_MONST; + i++; + } + case AV_MONST: + if(magic(country,MA_MONST)==TRUE) { + newpower=MA_MONST; + i++; + } + break; + case WARRIOR: + if(magic(country,CAPTAIN)==TRUE) { + newpower=CAPTAIN; + i++; + } + case CAPTAIN: + if(magic(country,WARLORD)==TRUE) { + newpower=WARLORD; + i++; + } + break; + case SUMMON: + if(magic(country,WYZARD)==TRUE) { + newpower=WYZARD; + i++; + } + case WYZARD: + if(magic(country,SORCERER)==TRUE) { + newpower=SORCERER; + i++; + } + break; + default: + break; + } + /* may not remove racial magics */ + switch(curntn->race) { + case ORC: + if(newpower==MI_MONST) done=FALSE; + break; + case ELF: + if(newpower==THE_VOID) done=FALSE; + break; + case DWARF: + if(newpower==MINER) done=FALSE; + break; + case HUMAN: + if(newpower==WARRIOR) done=FALSE; + break; + } + switch(curntn->class) { + case C_WIZARD: + if(newpower==SUMMON) done=FALSE; + if(newpower==WYZARD) done=FALSE; + break; + case C_PRIEST: + if(newpower==RELIGION) done=FALSE; + break; + case C_PIRATE: + if(newpower==SAILOR) done=FALSE; + break; + case C_TRADER: + if(newpower==URBAN) done=FALSE; + break; + case C_WARLORD: + if(newpower==WARLORD) done=FALSE; + break; + case C_DEMON: + if(newpower==DESTROYER) done=FALSE; + break; + case C_DRAGON: + if(newpower==MA_MONST) done=FALSE; + break; + case C_SHADOW: + if(newpower==THE_VOID) done=FALSE; + break; + default: + break; + } + /* remove the magic */ + if(done==TRUE) { + if(magic(country,newpower)==TRUE) { + curntn->powers ^= newpower; + removemgk(newpower); + sprintf(eventstr,"nation %s loses %s power",curntn->name,pwrname[i]); + } else { + done=FALSE; + fprintf(stderr,"ERROR: removing no-magic\n"); + } + } + break; + case 37: + /*severe winter*/ + done=FALSE; + break; + case 38: + /*tidal wave -- abandon all coastlands */ + done=FALSE; + break; + case 39: /*ninja attack paralyzes half your armys P_AMOVE=0*/ + case 40: /*general found to be spy P_AMOVE=0*/ + strcpy(eventstr,"1/2 nations armies are paralyzed"); + for(armynum=0;armynumtgold > 0l) { + curntn->tgold += curntn->tgold / 5; + } + else + curntn->tgold += 50000L; + break; + case 42: + case 43: + /*kill 20% of armies*/ + for (armynum=0; armynum 0) && (P_ATYPE0) { + fprintf(fm,"Damage was estimated at about %d%% in severity.\n",prcnt); + } + } + } + + if(strlen(eventstr)>5) { +#ifdef HIDELOC + /* make sure that volcano locations are not revealed */ + if(strcmp(eventstr,"all flee, 30%% die in 1 sector range")!=0) +#endif /* HIDELOC */ + fprintf(fnews,"1. \tevent in %s -->%s\n",ntn[cntry].name,eventstr); +#ifndef HIDELOC + if(xloc != -1) + fprintf(fnews,"1. \tevent in %s -->centered around location %d, %d.\n",ntn[cntry].name,xloc,yloc); +#endif /* HIDELOC */ + printf("\t\t->%s\n",eventstr); + if(ispc(ntn[cntry].active)) + fprintf(fm,"\t%s\n",eventstr); + } + if(ispc(ntn[cntry].active)) mailclose(cntry); +} + +int +peasant_revolt(newnation) /* peasant revolt */ +int *newnation; /* return nation id */ +{ + register int i,j; + int armynum; + + /* a little cheating for now */ + if(isnpc( ntn[country].active ) && (rand()%2==0)) { + strcpy(eventstr,"npc cheating"); + return; + } + if((*newnation=disolve(10, country, TRUE)) == 0 ) return; + + curntn = &ntn[*newnation]; /* beware - curntn & country not same */ + curntn->active = NPC_PEASANT; + curntn->class = 0; + + for (i=0; i 0 ) + &&( solds_in_sector(i,j,country)==0)){ + sct[i][j].owner = *newnation; + for(armynum=0;armynumpopularity=99; /* so it dont happen too often */ + curntn = &ntn[country]; /* fix above beware comment */ + return; +} +int +other_revolt( new ) /* return reason and new nation number*/ +int *new; +{ + short reason = rand()%8; + switch( reason ) { + case 0: /* general */ + if((*new=disolve(10, country, FALSE))!=0) return(reason); + break; + case 1: /* cult */ + if((*new=disolve(10, country, FALSE))!=0) return(reason); + break; + case 2: /* general/province defects*/ + if((*new=disolve(10, country, FALSE))!=0) return(reason); + break; + case 3: /* evil wizard sets up */ + if((*new=disolve(10, country, FALSE))!=0) return(reason); + break; + case 4: /* tax revolt */ + if((*new=disolve(20, country, FALSE))!=0) return(reason); + break; + case 5: /* open rebellion */ + if((*new=disolve(30, country, FALSE))!=0) return(reason); + break; + case 6: /* general takes over province*/ + if((*new=disolve(30, country, FALSE))!=0) return(reason); + break; + case 7: /*religious schism*/ + if((*new=disolve(30, country, FALSE))!=0) return(reason); + break; + } + return(-1); +} + +#ifdef VULCANIZE +/*volcano erupts --- causes devastation in surrounding sectors */ +void +erupt() +{ + int i, j, nvolcanos=0, volhold; + + printf("checking for volcanic eruptions\n"); + /* count all of the volcanos */ + for (i=0; ivolcanic eruption causes devastation\n",i,j); + sct[i][j].vegetation = VOLCANO; + sct[i][j].jewels = 0; + sct[i][j].metal = 0; + reduce(i,j,100); + DEVASTATE(i,j); + sct[i][j].fortress = 0; + /* decrease neighboring population and armies 30% */ + for(x=i-1; x<=i+1; x++) for(y=j-1; y<=j+1; y++) + if((ONMAP(x,y))&&(sct[x][y].altitude != WATER)) { + reduce(x,y,30); + DEVASTATE(i,j); + sct[x][y].fortress = 0; + } +} + +/** reduce will drop armies & and civilians in sector by percent **/ +void +reduce(x,y,percent) +int x,y,percent; +{ + long temp; /* used to avoid overflow problems */ + int armynum,ctry; + + percent = 100 - percent; /* invert percent so math works */ + + /* work on people */ + temp = sct[x][y].people; + temp *= percent; + temp /= 100; + sct[x][y].people = temp; + + /* work on armies */ + for(ctry=1;ctry +#include +#include +#include +#include +#include "header.h" +#include "data.h" + +extern FILE *fexe; +extern short country; +extern long startgold; +extern short xcurs,ycurs; +extern short xoffset,yoffset; +extern short redraw; + +#define RPT_LINES 11 +#define RPT_COLS 10 +#define BUF_LINES 10 +#define BUF_COLS 15 +#define MAXINROW ((COLS-BUF_COLS)/RPT_COLS) +#define MAXINSCR (((LINES-BUF_LINES)/RPT_LINES)*MAXINROW) +/*report on armies and allow changes*/ +void +armyrpt(repnum) + int repnum; + /* 0 is for full report 'a' and 1 is for group report 'g' */ +{ + int i,j; + char inpkey; + int men,attset,defset,bemerc; + short oldarmy; + int done=FALSE; + int xpos,ypos; + int isgod=FALSE; + int count,count2; /*number of armies on current screen */ + short armynum=0; + + if(country==0) { + isgod=TRUE; + if (get_god()) return; + } else { + /* if not god, check there are armies to display */ + men=FALSE; + for(armynum=0;men==FALSE && armynum0 && (!repnum || + (P_AXLOC==XREAL && P_AYLOC==YREAL))) + men=TRUE; + if (!men) { + redraw=DONE; + clear_bottom(0); + errormsg("no armies to display"); + makebottom(); + return; + } + } + /*new army screen*/ + clear(); + count2=0; + while(done==FALSE) { + move(0,0); + clrtobot(); + armynum=count2; + xpos=BUF_COLS; + ypos=2; + count=0; + while((armynum0 && (!repnum || (P_AXLOC==XREAL && P_AYLOC==YREAL))) { + if (count%MAXINROW==0) { + /* diplay header information */ + mvaddstr(ypos+1,0,"soldiers :"); + mvaddstr(ypos+2,0,"x location:"); + mvaddstr(ypos+3,0,"y location:"); + mvaddstr(ypos+4,0,"movement :"); + mvaddstr(ypos+5,0,"status :"); + mvaddstr(ypos+6,0,"unit type :"); + mvaddstr(ypos+7,0,"cost/turn :"); + mvaddstr(ypos+8,0,"enlist :"); + } + standout(); + mvprintw(ypos,xpos,"%d:",armynum); + standend(); + mvprintw(ypos+1,xpos,"%ld",P_ASOLD); + mvprintw(ypos+2,xpos,"%d",(int)P_AXLOC); + mvprintw(ypos+3,xpos,"%d",(int)P_AYLOC); + mvprintw(ypos+4,xpos,"%d",P_AMOVE); + if(P_ASTAT>=NUMSTATUS) + mvprintw(ypos+5,xpos,"group %d",P_ASTAT-NUMSTATUS); + else + mvprintw(ypos+5,xpos,"%s",*(soldname+P_ASTAT)); + mvprintw(ypos+6,xpos,"%s",*(unittype+(P_ATYPE%UTYPE))); + if (P_ATYPEname)/2,"ARMY STATS SUMMARY FOR %s",curntn->name); + + ypos+=10; + mvaddstr(ypos++,(COLS/2)-14,"HIT SPACE KEY IF DONE"); + mvaddstr(ypos++,(COLS/2)-25,"HIT RETURN TO CHANGE ANY ARMY STATISTICS"); + mvaddstr(ypos++,(COLS/2)-17,"HIT ANY OTHER KEY FOR MORE"); + standend(); + refresh(); + + ypos++; + if ((inpkey = getch())==' ') done=TRUE; + else if((inpkey=='\n')||(inpkey=='\r')) { + done=0; + mvaddstr(ypos++,0,"WHAT ARMY DO YOU WANT TO CHANGE:"); + ypos++; + clrtoeol(); + refresh(); + armynum = get_number(); + if((armynum<0)||(armynum>MAXARM)) { + continue; + } +#ifdef TRADE + if(isgod==FALSE && P_ASTAT==TRADED) { + errormsg("May not change traded army"); + continue; + } +#endif /* TRADE */ + mvaddstr(ypos,0,"OPTIONS: 1) COMMAND 2) DISBAND 3) CHANGE GROUP"); + if(P_ATYPE=MINLEADER){ + errormsg("SORRY -- army is monster"); + break; + } + oldarmy=armynum; + mvaddstr(ypos++,0,"TO WHAT ARMY: "); + refresh(); + armynum = get_number(); + if (armynum < 0) break; + combinearmies(armynum,oldarmy); + break; + case '5': + splitarmy(armynum); + break; + case '2': /* disband army */ + clear_bottom(0); + if(P_ATYPEtgold -= *(u_encost+(P_ATYPE%UTYPE)) * 2; + P_ASOLD=0; + AADJMEN; + } + } else if(P_ATYPE==A_MERCENARY){ + /*mercs must be payed off*/ + mvprintw(LINES-4,0,"Your mercenaries demand %ld talons to disband", + *(u_encost+(P_ATYPE%UTYPE)) * P_ASOLD); + + mvaddstr(LINES-3,0,"Give them severance pay? (y or n)"); + clrtoeol(); + refresh(); + if(getch()=='y'){ + curntn->tgold -= *(u_encost+(P_ATYPE%UTYPE)) * P_ASOLD; + /*mercs do not add to local populace*/ + attset = MERCATT; + defset = MERCDEF; + bemerc = P_ASOLD; + P_ASOLD=0; + AADJMEN; + AADJDISB; + } + } else if(P_ATYPE==A_ZOMBIE){ + errormsg("Zombie units cannot disband"); + break; + } else { + if (P_ATYPE < MINLEADER) { + bemerc = (P_ASOLD*15)/100; + /*15% become mercs*/ + attset = curntn->aplus + + *(unitattack+(P_ATYPE%UTYPE)); + defset = curntn->dplus + + *(unitdefend+(P_ATYPE%UTYPE)); + P_ASOLD -= bemerc; + sct[P_AXLOC][P_AYLOC].people+=P_ASOLD; + AADJDISB; + } + P_ASOLD=0; + AADJMEN; + i=P_AXLOC; + j=P_AYLOC; + SADJCIV2; + } + break; + case '3': + addgroup(armynum); + break; +#ifdef OGOD + case '6': + if(isgod==TRUE){ + /*X LOCATION*/ + mvaddstr(ypos++,0,"What is the New X Loc: "); + refresh(); + men = get_number(); + if (men>=0 && men=0 && men=0) { + P_ASOLD=men; + AADJMEN; + } + } + break; + case '8': + if (isgod == TRUE) { + mvaddstr(ypos, 0, "What is the new movement value?"); + refresh(); + men = get_number(); + + if (men >=0 && men <= 100) { + P_AMOVE = men; + } + } + break; + case '9': + if (isgod == TRUE) { + mvaddstr(ypos++, 0, "Change unit type; Normal 0-26, Leader 27-44, Monster 45-59"); + mvaddstr(ypos++, 0, "[MajorHackEH?] New Type is? "); + refresh(); + men = get_number(); + + if (men < 0 || men > MAXMONSTER) break; + if (men > 44) men += TWOUTYPE; + else if (men > NOUNITTYPES) men += UTYPE; + + P_ATYPE = men; + } + break; + case '0': + if (isgod == TRUE) { + mvprintw(ypos++, 0, "1) Mar 2) Sct 3) Garr 4) Trade 5) Mil 6) Fly 7) Def 8) MDef 9) Att 10) MAtt"); + mvprintw(ypos++, 0, "11) Genrl 12) Sort 13) Sieg 14) Sgd 15) Onb 16) Rule 17+) Group (leader-=17)"); + mvaddstr(ypos++, 0, "Set what status? "); + refresh(); + men = get_number(); + + if (men < 0 || men > NUMSTATUS+MAXARM) + break; + if (men >= NUMSTATUS) { + i = curntn->arm[men-NUMSTATUS].unittyp; + if (i < MINLEADER || i >= MINMONSTER) { + errormsg("There is no such leader to group under"); + break; + } + } + P_ASTAT = men; + } + break; +#endif /* OGOD */ + default: + errormsg("Invalid Input"); + } + armynum=0; + } else { + /* go to start of next page in army list */ + while(armynumtgold; + } + + clear(); + standout(); + mvaddstr(0,(COLS/2)-15,"NEXT SEASON'S BUDGET ESTIMATES"); + standend(); + spreadsheet(country); + + for(armynum=0;armynum0) { + if(P_ATYPE=MINMONSTER) { + nummonst++; + costmonst += 5L * ((long) *(unitmaint+(P_ATYPE%UTYPE))); + } + } + for(nvynum=0;nvynumname); + standend(); + mvprintw(3,0, "starting treasury..$%ld",startgold); + mvprintw(4,0, "number of sectors...%d",spread.sectors); + if(curntn->tfood<2*curntn->tciv) standout(); + mvprintw(6,0, "granary holds.....%8ld",curntn->tfood); + standend(); + mvprintw(7,0, "jewels owned......%8ld",curntn->jewels); + mvprintw(8,0, "metal ore owned...%8ld",curntn->metals); + mvprintw(2,COLS-50, "%8ld people in gold mines.%8ld",spread.ingold,spread.revjewels); + mvprintw(3,COLS-50, "%8ld people in mines......%8ld",spread.inmetal,spread.revmetal); + mvprintw(4,COLS-50, "%8ld people in farms......%8ld",spread.infarm,spread.revfood); + mvprintw(5,COLS-50,"%8ld people in cities.....%8ld",spread.incap,spread.revcap); + mvprintw(6,COLS-50,"%8ld people in towns......%8ld",spread.incity,spread.revcity); + mvprintw(7,COLS-50, "%8ld people elsewhere.....%8ld",spread.inothr,spread.revothr); + standout(); + mvprintw(8,COLS-50,"%8ld people INCOME........%8ld",spread.civilians,spread.gold - curntn->tgold); + standend(); + mvprintw(10,COLS-50,"%8ld troops...............%8ld",numsold,costsold); + mvprintw(11,COLS-50,"%8ld monsters.............%8ld",nummonst,costmonst); + + mvprintw(12,COLS-50,"%8ld ship holds @ %4d....%8ld",numship,SHIPMAINT,numship*SHIPMAINT); + mvprintw(13,COLS-50,"other expenses this turn......%8ld",startgold-curntn->tgold); + standout(); + money=costmonst+costsold+(numship*SHIPMAINT)+startgold-curntn->tgold; + mvprintw(14,COLS-50,"TOTAL EXPENSES................%8ld",money); + standend(); + money=spread.gold - curntn->tgold - money; /* net income */ + chty = max((money*(long)curntn->charity)/100L,0L); + mvprintw(15,COLS-50,"CHARITY.......................%8ld",chty); + mvprintw(16,COLS-50,"NET INCOME....................%8ld",money); + + infmoney = startgold + money - chty; + if (infmoney > 1000000L) { + infmoney = (infmoney / (400L + curntn->inflation)) * 400L; + } else { + infmoney = (infmoney * 400L) / (400L + curntn->inflation); + } + + mvprintw(17,COLS-50,"LOSS DUE TO INFLATION.........%8ld",(startgold + money-chty)-infmoney); + standout(); + mvprintw(18,COLS-50,"NEXT SEASON'S TREASURY........%8ld",infmoney); + + mvaddstr(LINES-3,(COLS/2)-15,"HIT 'P' TO SEE PRODUCTION SCREEN"); + mvaddstr(LINES-2,(COLS/2)-15,"HIT 'C' FOR CHANGE NATION SCREEN"); + mvaddstr(LINES-1,(COLS/2)-14,"HIT ANY OTHER KEY TO CONTINUE"); + standend(); + refresh(); + switch( getch() ) { + case 'p': + case 'P': produce(); break; + case 'c': + case 'C': change(); break; + } + if(isgod==TRUE) reset_god(); +} + +void +produce() +{ + FILE *fp; + short armynum; + long military=0; + long nummonst=0L,costmonst=0L; + int isgod=FALSE; + + if(country==0) { + isgod=TRUE; + if (get_god()) return; + } + fp=fopen("temp","w"); + clear(); + standout(); + mvaddstr(0,(COLS/2)-17,"NEXT SEASON'S PRODUCTION ESTIMATES"); + standend(); + + spreadsheet(country); + fprintf(fp,"LINE %d FILE %s\n",__LINE__,__FILE__); + for(armynum=0;armynum0) + { + if (P_ATYPE=MINMONSTER) { + nummonst++; + costmonst += (long) *(unitmaint+(P_ATYPE%UTYPE)); + } + } + + standout(); + mvprintw(4,0, "nation name is....%s",curntn->name); + standend(); + mvprintw(5,0, "talons in treasury..$%ld",curntn->tgold); + mvaddstr(7,0, "FOOD PRODUCTION"); + mvprintw(9,0, "granary now holds.........%8ld tons",curntn->tfood); + mvprintw(10,0, "%8ld people in farms..%8ld tons",spread.infarm,spread.food - curntn->tfood); + fprintf(fp,"LINE %d FILE %s\n",__LINE__,__FILE__); + mvprintw(12,0, "%8ld people @ %3.1f eat.%8.0ld tons",spread.civilians,P_EATRATE,(long)(P_EATRATE*(float)spread.civilians)); + fprintf(fp,"LINE %d FILE %s\n",__LINE__,__FILE__); + mvprintw(13,0, "%8ld soldiers eat.....%8.0ld tons",military,(long)(military*2*P_EATRATE)); + military+= military+spread.civilians; /* military is amount eaten */ + fprintf(fp,"LINE %d FILE %s\n",__LINE__,__FILE__); + standout(); + mvprintw(15,0, "ESTIMATE NET FOOD.........%8.0f tons",spread.food-curntn->tfood-P_EATRATE*military); + mvprintw(16,0, "ESTIMATE FOOD SUPPLY......%8.0f tons",spread.food-P_EATRATE*military); + standend(); + fprintf(fp,"LINE %d FILE %s\n",__LINE__,__FILE__); + + mvaddstr(7,COLS/2+1, "OTHER PRODUCTION"); + mvprintw(9,COLS/2+1, "jewels owned is...............%8ld",curntn->jewels); + mvprintw(10,COLS/2+1, "%8ld people in goldmines..%8ld",spread.ingold,spread.jewels-curntn->jewels); + mvprintw(11,COLS/2+1, "%8ld monsters.............%8ld",nummonst,-costmonst); + standout(); + mvprintw(12,COLS/2+1, "ESTIMATE JEWEL SUPPLY.........%8ld",spread.jewels-costmonst); + standend(); + + mvprintw(14,COLS/2+1, "metal ore owned is............%8ld",curntn->metals); + mvprintw(15,COLS/2+1, "%8ld people in mines......%8ld",spread.inmetal,spread.metal-curntn->metals); + standout(); + mvprintw(16,COLS/2+1, "ESTIMATE METAL SUPPLY.........%8ld",spread.metal); + standend(); + + standout(); + mvaddstr(LINES-3,(COLS/2)-15,"HIT 'B' TO SEE BUDGET SCREEN"); + mvaddstr(LINES-2,(COLS/2)-17,"HIT 'C' FOR CHANGE NATION SCREEN"); + mvaddstr(LINES-1,(COLS/2)-15,"HIT ANY OTHER KEY TO CONTINUE"); + standend(); + refresh(); + switch( getch() ) { + case 'b': + case 'B': budget(); break; + case 'c': + case 'C': change(); break; + } + + if(isgod==TRUE) reset_god(); + fclose(fp); +} + +#undef RPT_LINES +#undef RPT_COLS +#undef BUF_LINES +#undef BUF_COLS +#define RPT_LINES 13 +#define RPT_COLS 11 +#define BUF_LINES 10 +#define BUF_COLS 15 +char *fltstr[]= {"Light", "Medium", "Heavy"}; +/*report on ships and allow changes */ +void +fleetrpt() +{ + short navy,armynum; + short newx,newy,newnavy; + short done=FALSE; + int i,j; + int xpos,ypos,crew,people; + int count,count2; /*screen number */ + short nvynum=0; /*current ship id */ + short shipsize; + int isgod=FALSE; + if(country==0) { + isgod=TRUE; + if (get_god()) return; + } + else { + /* if not god, check if there are navies to display */ + for(count=nvynum=0;count==0 && nvynumname)/2,"NAVY STATS SUMMARY FOR %s",curntn->name); + + ypos+=12; + mvaddstr(ypos++,(COLS/2)-14,"HIT SPACE KEY IF DONE"); + mvaddstr(ypos++,(COLS/2)-18,"HIT RETURN TO CHANGE A NAVY"); + mvaddstr(ypos++,(COLS/2)-17,"HIT ANY OTHER KEY FOR MORE"); + ypos++; + standend(); + refresh(); + + if ((navy=getch())==' ') done=TRUE; + else if ((navy=='\n')||(navy=='\r')){ + mvaddstr(ypos++,0,"WHAT NAVY DO YOU WANT TO CHANGE:"); + clrtoeol(); + refresh(); + nvynum = get_number(); + if(nvynum<0) continue; +#ifdef TRADE + if (isgod == FALSE && curntn->nvy[nvynum].commodity==TRADED) { + errormsg("Sorry - That Navy is up for trade"); + continue; + } +#endif /* TRADE */ + if((nvynum<0)||(nvynum>=MAXNAVY)) { + errormsg("Invalid Naval unit"); + continue; + } + mvaddstr(ypos++,0,"OPTIONS: 1) TRANSFER / MERGE, 2) SPLIT NAVY, 3) DISBAND NAVY"); + clrtoeol(); +#ifdef OGOD + if(isgod==TRUE) mvaddstr(ypos++,0,"GOD OPTIONS: 4) ADJUST SHIPS, 5) LOCATION, 6) CREW 7) MOVE"); + ypos++; + clrtoeol(); +#endif /* OGOD */ + refresh(); + switch(getch()){ + case '1': + mvaddstr(ypos++,0,"TO WHAT NAVY: "); + clrtoeol(); + refresh(); + newnavy = get_number(); + if(newnavy < 0) break; + if(newnavy >= MAXNAVY) { + errormsg("Sorry - Invalid Navy unit"); + break; + } + newx = curntn->nvy[newnavy].xloc; + newy = curntn->nvy[newnavy].yloc; +#ifdef TRADE + if (curntn->nvy[newnavy].commodity==TRADED) { + errormsg("Sorry - That Navy is up for trade"); + } else +#endif /* TRADE */ + if(nvynum==newnavy) { + errormsg("Sorry -- That is the same Navy"); + } + else if((P_NARMY!=MAXARM) + &&(curntn->nvy[newnavy].armynum!=MAXARM)) { + errormsg("Sorry -- One of the two Armies must be unloaded"); + } + else if((newx==P_NXLOC)&&(newy==P_NYLOC)) { + /* first check sizes */ + for(i=N_LIGHT;i<=N_HEAVY;i++) { + if (P_NGAL(i) + SHIPS(curntn->nvy[newnavy].galleys,i) > N_MASK) { + i = (-1); + break; + } + if (P_NMER(i) + SHIPS(curntn->nvy[newnavy].merchant,i) > N_MASK) { + i = (-1); + break; + } + if (P_NWAR(i) + SHIPS(curntn->nvy[newnavy].warships,i) > N_MASK) { + i = (-1); + break; + } + } + if (i == (-1)) { + errormsg("That would cause you to have too many ships of one type"); + break; + } + crew = flthold(nvynum)*P_NCREW; + people = fltmhold(nvynum)*P_NPEOP; + crew += flthold(newnavy)*curntn->nvy[newnavy].crew; + people += fltmhold(newnavy)*curntn->nvy[newnavy].people; + for(i=N_LIGHT;i<=N_HEAVY;i++) { + (void) addwships(newnavy,i,P_NWAR(i)); + (void) addmships(newnavy,i,P_NMER(i)); + (void) addgships(newnavy,i,P_NGAL(i)); + } + P_NCREW=0; + P_NWSHP=0; + P_NMSHP=0; + P_NGSHP=0; + if (P_NARMY!=MAXARM) { + curntn->nvy[newnavy].armynum=P_NARMY; + P_NARMY=MAXARM; + } + P_NPEOP=0; + NADJWAR; + NADJMER; + NADJGAL; + NADJCRW; + NADJHLD; + if(P_NMOVEnvy[newnavy].smove) + curntn->nvy[newnavy].smove=P_NMOVE; + P_NMOVE=0; + NADJMOV; + nvynum=newnavy; + if (flthold(nvynum)>0) + P_NCREW=(unsigned char)(crew/flthold(nvynum)); + if (fltmhold(nvynum)>0) + P_NPEOP=(unsigned char)(people/fltmhold(nvynum)); + NADJMOV; + NADJWAR; + NADJMER; + NADJGAL; + NADJCRW; + NADJHLD; + } + else { + errormsg("Navies not together"); + } + break; + case '2': + newnavy=nvynum; + navy=(-1); + for(nvynum=0;nvynumnvy[navy].xloc=P_NXLOC; + curntn->nvy[navy].yloc=P_NYLOC; + curntn->nvy[navy].crew=P_NCREW; + curntn->nvy[navy].people=P_NPEOP; + curntn->nvy[navy].smove=P_NMOVE; + + if (P_NWSHP != 0) + mvaddstr(LINES-2,0,"Do you wish to separate warships from remainder of fleet?"); + refresh(); + if(P_NWSHP!=0 && getch()=='y') { + curntn->nvy[navy].warships=P_NWSHP; + P_NWSHP=0; + NADJWAR; + nvynum=navy; + P_NMSHP=0; + P_NGSHP=0; + P_NARMY=MAXARM; + P_NPEOP=0; + NADJMOV; + NADJCRW; + NADJWAR; + NADJMER; + NADJGAL; + NADJHLD; + NADJLOC; + break; + } else if(P_NARMY!=MAXARM) { + errormsg("Army must be unloaded before Navy is divided"); + break; + } + for(shipsize=N_LIGHT;shipsize<=N_HEAVY;shipsize++) { + if (P_NWAR(shipsize) == 0) continue; + mvprintw(ypos,0,"How Many %s Warships To Split?",fltstr[shipsize]); + clrtoeol(); + refresh(); + newnavy = get_number(); + if(newnavy>P_NWAR(shipsize)||newnavy<0) newnavy=0; + NSUB_WAR(newnavy); + (void) addwships(navy,shipsize,newnavy); + } + for(shipsize=N_LIGHT;shipsize<=N_HEAVY;shipsize++) { + if (P_NMER(shipsize) == 0) continue; + mvprintw(ypos,0,"How Many %s Merchants To Split?",fltstr[shipsize]); + clrtoeol(); + refresh(); + newnavy = get_number(); + if(newnavy>P_NMER(shipsize)||newnavy<0) newnavy=0; + NSUB_MER(newnavy); + (void) addmships(navy,shipsize,newnavy); + } + for(shipsize=N_LIGHT;shipsize<=N_HEAVY;shipsize++) { + if (P_NGAL(shipsize) == 0) continue; + mvprintw(ypos,0,"How Many %s Galleys To Split?",fltstr[shipsize]); + clrtoeol(); + refresh(); + newnavy = get_number(); + if(newnavy>P_NGAL(shipsize)||newnavy<0) newnavy=0; + NSUB_GAL(newnavy); + (void) addgships(navy,shipsize,newnavy); + } + + NADJWAR; + NADJMER; + NADJGAL; + nvynum=navy; + P_NARMY=MAXARM; + NADJMOV; + NADJCRW; + NADJWAR; + NADJMER; + NADJGAL; + NADJHLD; + NADJLOC; + break; + case '3': + /* DISBAND NAVY */ + i=P_NXLOC; + j=P_NYLOC; + if(sct[i][j].altitude == WATER && isgod==FALSE) { + errormsg("Ships need to be on land or in harbor"); + break; + } + if(sct[i][j].owner != country && isgod==FALSE) { + errormsg("You don't own the land"); + break; + } + sct[i][j].people+=P_NCREW*flthold(nvynum); + sct[i][j].people+=P_NPEOP*fltmhold(nvynum); + if(P_NARMY!=MAXARM) { + armynum=P_NARMY; + P_NARMY=MAXARM; + P_ASTAT=DEFEND; + AADJSTAT; + } + P_NWSHP=0; + P_NMSHP=0; + P_NGSHP=0; + P_NCREW=0; + P_NPEOP=0; + SADJCIV2; + NADJCRW; + NADJWAR; + NADJGAL; + NADJMER; + NADJHLD; + break; +#ifdef OGOD + case '4': + if (isgod==TRUE) { + /* ADJUST SHIPS */ + for(shipsize=N_LIGHT;shipsize<=N_HEAVY;shipsize++) { + mvprintw(ypos,0,"How Many %s Warships? [%d] ", + fltstr[shipsize],P_NWAR(shipsize)); + clrtoeol(); + refresh(); + newnavy = get_number(); + if (newnavy < 0 || newnavy > N_MASK) continue; + newnavy -= P_NWAR(shipsize); + if (newnavy > 0) { + (void) NADD_WAR(newnavy); + } else if (newnavy < 0) { + newnavy = -newnavy; + (void) NSUB_WAR(newnavy); + } + } + for(shipsize=N_LIGHT;shipsize<=N_HEAVY;shipsize++) { + mvprintw(ypos,0,"How Many %s Merchants? [%d] ", + fltstr[shipsize], P_NMER(shipsize)); + clrtoeol(); + refresh(); + newnavy = get_number(); + if(newnavy>N_MASK||newnavy<0) continue; + newnavy -= P_NMER(shipsize); + if (newnavy > 0) { + (void) NADD_MER(newnavy); + } else if (newnavy < 0) { + newnavy = -newnavy; + (void) NSUB_MER(newnavy); + } + } + for(shipsize=N_LIGHT;shipsize<=N_HEAVY;shipsize++) { + mvprintw(ypos,0,"How Many %s Galleys? [%d]", + fltstr[shipsize], P_NGAL(shipsize)); + clrtoeol(); + refresh(); + newnavy = get_number(); + if(newnavy>N_MASK||newnavy<0) continue; + newnavy -= P_NGAL(shipsize); + if (newnavy > 0) { + (void) NADD_GAL(newnavy); + } else if (newnavy < 0) { + newnavy = -newnavy; + (void) NSUB_GAL(newnavy); + } + } + NADJWAR; + NADJMER; + NADJGAL; + } + break; + case '5': + if (isgod==TRUE) { + /*X LOCATION*/ + mvaddstr(ypos++,0,"What Is The New X Loc: "); + refresh(); + crew = get_number(); + if (crew>=0 && crew=0 && crew=0 && crew<=SHIPCREW) { + P_NCREW = crew; + NADJCRW; + } + } + break; + case '7': + if (isgod == TRUE) { + mvaddstr(ypos, 0, "Set what move value? "); + refresh(); + newnavy = get_number(); + if (newnavy <= 100 && newnavy >= 0) { + P_NMOVE = newnavy; + } + } + break; +#endif /* OGOD */ + default: + errormsg("Invalid Input"); + } + noecho(); + nvynum=0; + } else { + /* go to start of next page in navy list */ + while((nvynum" to remove existing at jobs +######################################################### +TIME1=1000 +TIME1H=10 +TIME2=1700 +TIME2H=17 +TIME3=2300 +#Below is the full command to update a game of conquer +PATHTOCONQ="/d7/c7913/smile/oldgame/conquer -x -d/d7/c7913/smile/oldgame/temp" +#Path to this file +PATHTORUN=/d7/c7913/smile/oldgame/run +#LOG is full path name of log file +LOG=/d7/c7913/smile/oldgame/runlog + +/bin/date >> $LOG +$PATHTOCONQ >> $LOG + +DAY=`/bin/date | /usr/bin/awk '{ print $1 }'` +echo "day is $DAY" >> $LOG +HOUR=`/bin/date|/usr/bin/awk '{ print $4 }'|/usr/bin/awk -F: '{ print $1 }'` +echo "hour is $HOUR" >> $LOG +#BELOW IS AN EXAMPLE OF A BSD SCRIPT +#switch $DAY +# case Sat: +# set nextday=mon +# breaksw +# default: +# set nextday = +# breaksw +#endsw +case $DAY in + Sat) + nextday=mon + ;; + *) + nextday="" + ;; +esac +#switch $HOUR +# case 00: +# set nexthour=$TIME1 +# breaksw +# default: +# set nexthour=$TIME2 +# breaksw +#endsw +case $HOUR in +$TIME1H) + nexthour=$TIME2 + echo "nexthour is $nexthour" >> $LOG + ;; +$TIME2H) + nexthour=$TIME3 + echo "nexthour is $nexthour" >> $LOG + ;; +*) + nexthour=$TIME1 + echo "nexthour is $nexthour" >> $LOG + ;; +esac +#below for bsd (i think) +#/usr/bin/at $nexthour $nextday $PATHTORUN +#below for SYSV +echo "/usr/bin/at $nexthour $nextday < $PATHTORUN" >> $LOG +echo "XXX" >> $LOG +/usr/bin/at $nexthour $nextday < $PATHTORUN diff --git a/original/sort.c b/original/sort.c new file mode 100644 index 0000000..1c95a66 --- /dev/null +++ b/original/sort.c @@ -0,0 +1,322 @@ +/* + * sort.c + * + * Written by Adam Bryant as a replacement for 'sort' + * for use with the conquer program. Note that it + * is initially written with this program in mind and + * will not have many features useful elsewhere. + * + * INITIAL FORMAT USES [YIELDS SAME RESULTS]: + * + * standard in to standard out: + * 'cat foo | conqsort > foonew' + * file input to standard output: + * 'conqsort foo > foonew' + * file input to file output: + * 'conqsort foo foonew' + * + * OR MAY EVEN OVERWRITE INITIAL FILE VIA: + * + * 'conqsort infoo infoo' + * + * Design Notes: + * - all of the file will have to be placed into memory; + * - to allow for any line length, space will be malloced() + * as it comes in. + * + * Initial Revision: (adb@bucsf.bu.edu) + * Tuesday March 21th, 1989 - Began the program at 23:26 EST + * Wednesday March 22nd, 1989 - Finished the initial version 11:29 EST + * Wednesday July 5th, 1989 - Stopped use of sysexits.h 7:22 EST + */ + +#include +#include +#include +#include + +/* system definitions just in case */ +#ifndef FALSE +#define FALSE (0) +#define TRUE (1) +#endif /* FALSE */ + +/* system exit definitions from sysexits.h on BSD machines */ +#ifndef EX_OK +#define EX_OK 0 /* successful termination */ +#define EX_USAGE 64 /* invalid command line format */ +#define EX_NOINPUT 66 /* could not open input file */ +#define EX_SOFTWARE 70 /* software error; couldn't malloc */ +#define EX_CANTCREAT 73 /* could not create output file */ +#endif /* EX_OK */ + +/* number of characters to compare by default */ +#define DEFAULT_COMP 2 +#define MAX_STR 200 + +/* structure for holding a line of information */ +typedef struct holder { + char *line; + struct holder *next; +} L_DATA, *L_PTR; + +/* pointer to head of list of lines */ +L_PTR head; + +/* usage string */ +static char usage[]="Usage: %s [-num -h] [infile] [outfile]\n\ + -h display this screen\n\ + -i treat upper and lower case characters as equivalent\n\ + -num Sort on first num characters\n"; + +/* number of characters for comparison */ +int compnum=DEFAULT_COMP; + +/* flag for folding upper and lowercase characters */ +int iflag=FALSE; + +/* file pointers to infile and outfile */ +FILE *infile, *outfile; + +/* macros */ +#define UPPER(x) ((islower(x))?(toupper(x)):(x)) + +int +main(argc, argv) + int argc; + char *argv[]; +{ + /* declare temporary variables and functions */ + int i,j,num_args=0,l,innum=0,outnum=0; + FILE *fopen(); + int get_line(); + void place(), send_out(); + + /* This needs to be done at run-time now */ + infile=stdin; + outfile=stdout; + + /* input string */ + char data[MAX_STR]; + + /* parse command line arguments */ + for (i=1; i='0' && argv[i][j]<='9';j++) + { + compnum *= 10; + compnum += argv[i][j]-'0'; + } + /* compensate for increment on exit */ + j--; + break; + default: + fprintf(stderr,"%s: invalid option '%c' in <%s>\n", + argv[0],argv[i][j],argv[i]); + fprintf(stderr,usage,argv[0]); + exit(EX_USAGE); + break; + } + } + } + + /* open input file now */ + if(innum!=0) { + if((infile=fopen(argv[innum],"r"))==(FILE *)NULL) { + fprintf(stderr,"%s: can't open file <%s> for input\n", + argv[0],argv[innum]); + exit(EX_NOINPUT); + } + } + + /* ======= main processing loop ======== */ + + while(!feof(infile)) { + + /* remove any lines less than sort characters */ + if (get_line(data)>compnum) { + place(data); + } + + } + + /* ==== end of main processing loop ==== */ + + /* close input file if not stdin */ + if (infile!=stdin) { + (void) fclose(infile); + } + + /* open output file now */ + if(outnum!=0) { + if ((outfile=fopen(argv[outnum],"w"))==(FILE *)NULL) { + fprintf(stderr,"%s: cannot open file <%s> for output\n", + argv[0],argv[outnum]); + exit(EX_CANTCREAT); + } + } + + send_out(); + + /* close output file if not stdout */ + if (outfile!=stdout) { + (void) fclose(outfile); + } + + exit(EX_OK); +} + +/* routine to read all characters in until carriage returns */ +int +get_line(data) + char data[]; +{ + int in,ch; + + /* discard exceptionally long lines */ + for(in=0;!feof(infile)&&(in=' ')&&(ch<='~'))) { + data[in]=ch; + in++; + } + } + /* end string */ + data[in]='\0'; + + return(in); +} + +/* routine to output entire sorted file to outfile */ +void +send_out() +{ + L_PTR temp=head; + + while (temp!=(L_PTR)NULL) { + fprintf(outfile,"%s\n",temp->line); + temp = temp->next; + } +} + +/* routine to sort list as it comes in */ +void +place(data) + char data[]; +{ + L_PTR temp, build_node(); + int comp_line(); + + /* find location for placing input */ + if(head==(L_PTR)NULL) { + /* begin list properly */ + head = build_node(data,(L_PTR)NULL); + } else if (comp_line(head->line,data)==1) { + /* add to beginning of list */ + head = build_node(data,head); + } else { + /* otherwise add in proper position */ + temp=head; + while ((temp->next!=(L_PTR)NULL) + &&(comp_line(temp->next->line,data)!=1)) { + temp=temp->next; + } + temp->next = build_node(data,temp->next); + } +} + +/* routine to compare two lines through N characters */ +/* where N is given by the variable compnum */ +/* returns: 0 on equal */ +/* -1 on a preceding b */ +/* 1 on a following b */ +int +comp_line(a,b) + char *a,*b; +{ + int i; + + for(i=0;iline=(char *)malloc((strlen(data)+1)*sizeof(char)))==NULL) { + fprintf(stderr,"Error in creating data memory!\n"); + exit(EX_SOFTWARE); + } + + /* assign the values */ + (void) strcpy(temp->line,data); + temp->next = nptr; + return(temp); +} diff --git a/original/spew.c b/original/spew.c new file mode 100644 index 0000000..ba78ef5 --- /dev/null +++ b/original/spew.c @@ -0,0 +1,505 @@ +/* + * SPEW.C + */ +#ifndef lint +static char *cpr[]={ +" Copyright 1987 Greg Smith", +" Permission is granted to freely use and distribute this software", +"provided this notice is left attached and no monetary gain is made." +}; +#endif + +/* This file has been adapted from the "spew" program by Paul Davison, + pd@cs.qmc.ac.uk, on 1st March 1989. It is part of the conquer game + and is subject to the same conditions of use as that game. */ + +/* This in no way supersceedes the copyright notice noted above */ + +#include +#include +#include +#include +#include "header.h" +#include "data.h" +#ifdef SPEW +#include +#include + +char *my_alloc(); +char *save(); + +#if 0 +#ifdef BSD +extern char *index(); /* This may be strchr */ +extern char *rindex(); /* This may be strrchr */ +#else +#define index(s,c) strchr(s,c) +#define rindex(s,c) strrchr(s,c) +extern char *strchr(); /* This may be index */ +extern char *strrchr(); /* This may be rindex */ +#endif +#endif + +/*--------------- system configuration ------------------*/ + +/* define some parameters */ + +#define MAXCLASS 300 /* max # of classes */ +#define MAXLINE 256 /* max size of input line */ +#define MAXDEF 1000 /* max # bytes in a definition */ + +/* Define the default rulesfile */ + +#ifndef DEFFILE +# define DEFFILE "rules" +#endif + +/* Define the random number generator */ + +extern long getpid(); + /* ROLL(n) returns integer 0..n-1 */ +#define ROLL(n) ((((long)rand()&0x7ffffff)>>5)%(n)) + +/*---------------------------------------------------*/ + +FILE *InFile; + +typedef struct def_struct{ + int cumul; /* cumulative weights */ + char *string; /* string which defines it */ + struct def_struct *next; /* link to next */ +} defn; +defn *process(); +/* + * within a definition, names of subdefinitions are bracketed in BSLASH + * and SLASH chars. The whole definition ends with a '\0'. + * The SLASH character is always follwed by a variant tag - default is ' '. + */ +#define BSLASH '\\' +#define SLASH '/' +#define VBAR '|' + +typedef struct{ + int weight; /* total weight of definitions in class */ + defn *list; /* list of them */ + char *name; /* name of this class */ + char *tags; /* pointer to list of tags */ +} classrec; + +classrec * Classptr; /* pointer to array of class records */ +char *NullTags = " "; /* default tags ( shared ) */ +int Classes; /* number of them */ +int HowMany = 1; +int CompIn = FALSE; /* is input file in compressed format? */ +int CompMain; /* class # of MAIN class when compressed */ + +char InLine[MAXLINE]; + +makemess(n,fp) +int n; +FILE *fp; +{ + char fname[BIGLTH]; + char main_class[20]; + int i; + HowMany = n; + + /* read in only the rules file in defaultdir */ + sprintf(fname, "%s/%s", DEFAULTDIR, DEFFILE); + InFile = fopen( fname, "r" ); + if( InFile == NULL ){ + fprintf( stderr, "Can\'t open: %s\n", fname ); + exit(1); + } + init(); + if( CompIn ) sprintf( main_class, "%d/ ", CompMain); + else strcpy( main_class, "MAIN/ "); + for(i=0; ilist); /* update pointer */ + do{ + dp = process(); + *update = dp; + cp->weight += dp->cumul; /* add new stuff */ + dp->cumul = cp->weight; /* set breakpoint */ + update = &(dp->next); + }while( readline(), InLine[0]!= '%' ); + ++Classes; /* count them */ + ++cp; + *update = NULL; + } + qsort( (char*)Classptr, Classes, sizeof( classrec ), clcomp); +} +/* + * display is given a class name ( delimited by SLASH, not '\0' ), + * and will (1) find its class descriptor, by calling lookup + * (2) pick a definition (3) output that definition, and + * recursively display any definitions in it, and convert any escapes. + * The variant tag after the SLASH is used to pick out the appropriate + * variants. If that variant tag is '&', the tag 'deftag' is used, which + * is the active variant of the containing activation. + */ +display(s,deftag,fp) +char *s; +int deftag; +FILE *fp; +{ + register classrec *cp; + register defn *dp; + register char *p; + classrec *lookup(); + int i,variant,incurly; + register int c,writing; + + if( CompIn ){ /* input is compressed */ + cp = &Classptr[ atoi(s) ]; /* explicit class # */ + }else{ + cp = lookup(s); + if( cp == NULL ) { /* none found */ + fprintf(fp,"???"); + while( *s != SLASH ) putc( *s++,fp ); + fprintf(fp,"???"); + return; + } + } + c = index(s,SLASH)[1]; /* get variant tag */ + if( c != '&' ) deftag=c; /* use given tag */ + p = index(cp->tags, deftag); /* look it up */ + if(p == NULL ){ + variant = 0; + fprintf(fp,"\?\?/%c\?\?", deftag ); + deftag = ' '; /* for passing as deftag */ + }else variant = p - cp->tags; + + i = ROLL( cp->weight ); + dp = cp->list; + while(dp->cumul <= i){ /* pick one based on cumul. weights */ + dp = dp->next; + } + + incurly = 0; /* not in curlies */ + writing = 1; /* writing */ + p = dp->string; /* this is the string */ + for(;;)switch(c = *p++){ + case '\0': return; + case BSLASH: + if(( c = *p++) == '\0' ) return; /* ?? */ + else if( c == '!' ){ + if(writing)putc('\n',fp); /* \! = newline */ + }else if( isalnum(c) ){ /* reference */ + if(writing)display(p-1,deftag,fp); /* recurse */ + while( *p!=SLASH )++p; + p += 2; /* skip variant tag */ + }else{ + if(writing) putc(c,fp); + } + break; + case '{': + if( !incurly ){ + incurly = 1; + writing = (variant == 0 ); + }else{ + if( writing )putc('{',fp); + } + break; + case VBAR: + if( incurly ){ + writing = ( variant == incurly++ ); + }else{ + putc(VBAR,fp); + } + break; + case '}': + if( incurly ){ + writing = 1; + incurly = 0; + }else putc('}',fp); + break; + default: + if( writing) putc(c,fp); + } +} +classrec * +lookup( str ) /* delimited by SLASH, not '\0' */ +char *str; +{ + int first, last, try, comp; + int namecomp(); + + first = 0; + last = Classes-1; + while( first <= last ){ + try = (first+last)>>1; + comp = namecomp( str, Classptr[try].name ); + if( comp == 0 ) return &Classptr[try]; + if( comp > 0 ) first = try+1; + else last = try-1; + } + return NULL; +} +int namecomp(a,b) /* 'a' is delim. by SLASH, 'b' by NULL */ +register char *a,*b; +{ + register int ac; + for(;;){ + ac = *a++; + if(ac == SLASH ) ac = '\0'; + if( ac < *b ) return -1; + if( ac > *b++ ) return 1; + if( ac == '\0' ) return 0; + } +} +readline(){ + register char *p; + do{ + if( fgets( InLine, MAXLINE, InFile ) == NULL ){ + InLine[0] = InLine[1] = '%'; + InLine[2] = '\0'; /* create EOF */ + }else if( (p=rindex( InLine, '\n'))!= NULL ) *p = '\0'; + p = InLine; + while( (p = index( p, BSLASH )) != NULL ){ + if(p[1] == '*' ){ + *p = 0; /* kill comment */ + break; + }else ++p; + } + }while( InLine[0] == '\0' ); +} + +int clcomp(a,b) +register classrec *a,*b; +{ + if( a==b) return 0; + return strcmp( a->name, b->name ); +} +char *save(str) +char *str; +{ + register char *p; + p = (char *) my_alloc( (unsigned)((strlen(str)+1)*sizeof(char))); + return strcpy(p,str); +} +/* + * setup a class record. The 'class' line is in InLine. + */ +setup(cp) +register classrec *cp; +{ + char temp[100]; + register char *p,*p2; + + p = &InLine[1]; /* point after the % */ + while( *p == ' ' )++p; + if( !isalnum(*p) ) goto baddec; + p2 = temp; + do *p2++ = *p++; while( isalnum(*p)); + *p2 = '\0'; + cp->weight = 0; /* save the name of it */ + cp->name = save( temp ); + cp->list = NULL; + cp->tags = NullTags; /* by default */ + for(;;)switch(*p++){ + case '\0': + return; /* all done; */ + case ' ': + break; /* allowed those */ + case '{': /* tags list */ + if( cp->tags != NullTags ) goto baddec; /* already */ + p2 = temp; + *p2++ = ' '; /* provide null tag */ + while(*p!='}'){ + if( !isalnum(*p)) goto baddec; + *p2++ = *p++; + } + ++p; /* junk rh brace */ + *p2 = 0; + cp->tags = save(temp); + break; + default: goto baddec; + } + baddec: + fprintf(stderr,"Bad class header: %s\n", InLine ); + exit(1); +} +/* + * create a 'processed' version of the InLine, and return a pointer to + * the definition. The 'cumul' field is temporarily used to hold the + * assigned weight of the line. + */ +defn *process(){ + static char stuff[ MAXDEF ]; + register char *p,*pout; + register defn *dp; + register int c; + + dp = (defn *) my_alloc( (unsigned) sizeof( defn )); + + p = InLine; + pout = stuff; + if( *p == '(' ){ /* get a weight */ + while(*++p ==' '); /* scan */ + if(!isdigit(*p)) goto badweight; + c = *p - '0'; + while(isdigit(*++p)) c = c*10 + (*p - '0' ); + while( *p == ' ')++p; + if( *p != ')') goto badweight; + ++p; + dp->cumul = c; + }else{ + dp->cumul = 1; /* default weight */ + } + while((c = *p++)!='\0')switch(c){ + case BSLASH: + *pout++ = BSLASH; + if( isalnum(*p)){ /* is a ref */ + do{ *pout++ = *p++; + }while( isalnum(*p)); + *pout++ = SLASH; /* delimit */ + if( *p == SLASH ){ /* get variant char */ + ++p; + if( !isalnum(*p)&& *p!= ' ' && *p!= '&' ){ + *pout++ = ' '; + }else *pout++ = *p++; + }else *pout++ = ' '; + }else{ + *pout++ = *p; + if( *p!= '\0'){ + ++p; + }else{ + --pout; /* delete spurious '\' */ + readline(); /* get new line */ + p = InLine; /* point to it */ + } + } + break; + default: + *pout++ = c; + } + *pout = '\0'; + dp->string = save( stuff ); + return dp; + + badweight: + fprintf(stderr, "Bad line weight: %s\n", InLine ); + exit(1); + /*NOTREACHED*/ +} + +char *my_alloc(n) +unsigned n; +{ + register char *p; + p = (char *) malloc( n ); + if( p==NULL ){ + fprintf(stderr, "Out Of Memory\n"); + exit(1); + } + return p; +} + + +compdef(dp) +register defn *dp; +{ + register char *p; + register int c; + putw( dp-> cumul , stdout ); /* write its cumul weight */ + p = dp->string; + while( (c = *p++) != '\0' ){ + if( c==BSLASH){ + if(!CompIn && isalnum(*p) ){ /* a ref */ + classrec *cp; + cp = lookup(p); /* find it */ + if( cp == NULL ){ + fprintf( stderr, "Undefined class: "); + while( *p != SLASH ) fputc( *p++, stderr); + fputc('\n', stderr ); + exit(1); + }else{ + printf("%c%d", BSLASH, cp-Classptr ); + while( *p != SLASH ) ++p; + } + }else{ /* is escape seq */ + putchar( BSLASH ); + putchar( *p++ ); + } + }else{ + putchar(c); + } + } + putchar(0); +} + +readcclass(cp) +register classrec *cp; +{ + register int n; + register defn *dp; + defn **dput; + + char store[MAXDEF]; /* for tags */ + cp->weight = getw( InFile ); + instring(store,MAXDEF); + cp->tags = ( store[0] == '\0' )? NullTags: save( store ); + n = getw( InFile ); + if( n<=0 ) badfile(); + dput = &(cp->list); /* link on here */ + while(n--){ + dp = (defn *)my_alloc( (unsigned) sizeof( defn)); + *dput = dp; + dp->cumul = getw( InFile ); + instring(store, MAXDEF ); + dp->string = save( store ); + dput = &(dp->next); + } + *dput = NULL; /* last one */ +} + +instring( where, how_many ) +register char *where; +register int how_many; +{ + register int c; + do{ + c = getc( InFile ); + if( c == EOF ) badfile(); + *where++ = c; + if( c== '\0' ) return; + }while(--how_many); + badfile(); +} +badfile(){ + fprintf(stderr,"Bad file format\n"); + exit(1); +} +#endif /* SPEW */ diff --git a/original/trade.c b/original/trade.c new file mode 100644 index 0000000..0435542 --- /dev/null +++ b/original/trade.c @@ -0,0 +1,1116 @@ +/*conquer : Copyright (c) 1988 by Ed Barlow. + * I spent a long time writing this code & I hope that you respect this. + * I give permission to alter the code, but not to copy or redistribute + * it without my explicit permission. If you alter the code, + * please document changes and send me a copy, so all can have it. + * This code, to the best of my knowledge works well, but it is my first + * 'C' program and should be treated as such. I disclaim any + * responsibility for the codes actions (use at your own risk). I guess + * I am saying "Happy gaming", and am trying not to get sued in the process. + * Ed + */ + +/* + * The following file "trade.c" was written by Adam Bryant who + * gives all rights to this code to Ed Barlow provided that this + * message remains intact. + */ + +/* thanks adam -- Ed */ + +/* trade.c */ + +/*include files*/ +#include +#include +#include +#include +#include "header.h" +#include "data.h" + +#ifdef TRADE + +/* possible commodities */ +#define TDGOLD 0 +#define TDFOOD 1 +#define TDMETAL 2 +#define TDJEWL 3 +#define TDLAND 4 +#define TDARMY 5 +#define TDSHIP 6 + +/* constants and indicators */ +#define NUMPRODUCTS 7 +#define MAXITM 30 +#define SELL 0 +#define BUY 1 +#define NODEAL 2 +#define NOSALE 3 +#define TRADECOST(cost) (100-cost)/100 /* twenty percent cost is normal*/ + +extern short country; + +char *commodities[NUMPRODUCTS] = { "Gold", "Food", "Metal", "Jewels", + "Land", "Soldiers", "Ships"}; +#ifdef ADMIN +char *tradefail[NUMPRODUCTS] = { "lack of gold", "lack of food", + "lack of metal", "lack of jewels", "land not owned", + "unavailable or destroyed armies", + "unavailable or destoryed navies"}; +#endif /* ADMIN */ +#ifdef CONQUER +/* Use this when you wish to bid something */ +char *buylist[NUMPRODUCTS] = { "Bid how much gold? ", "Bid how much food? ", + "Bid how much metal? ", "Bid how many jewels? ", "What X location? ", + "Bid what army? ", "Bid what navy? "}; + +void +trade() +{ + FILE *tfile; + int count, done=FALSE, notopen=FALSE; + int buysell, holdint, holdint2, extint, inloop; + int type1[MAXITM], type2[MAXITM], deal[MAXITM], extra[MAXITM]; + int natn[MAXITM], itemnum, getland(), gettrade(), checkland(); + int tradable(); + long lvar1[MAXITM], lvar2[MAXITM], holdlong, holdlong2, armyvalue(); + void tradeerr(), setaside(), takeback(); + + clear(); + while (done==FALSE) { + itemnum=0; + done=TRUE; + /* open trading file */ + if ((tfile=fopen(tradefile,"r")) == NULL ) { + notopen=TRUE; + } + /* read in all of the data */ + while (notopen==FALSE && !feof(tfile)) { + holdint = fscanf(tfile,"%d %d %d %d %ld %ld %d\n", + &deal[itemnum],&natn[itemnum],&type1[itemnum], + &type2[itemnum],&lvar1[itemnum], + &lvar2[itemnum],&extra[itemnum]); + if (holdint == 7) { + if (deal[itemnum]==NOSALE) { + /* remove item from sales list */ + deal[type1[itemnum]]=NOSALE; + } else if (deal[itemnum]==SELL) { + itemnum++; + } + } + } + if (notopen==FALSE) fclose(tfile); + move(0,0); + clrtobot(); + /* display header */ + standout(); + mvaddstr(0,27,"COMMODITIES EXCHANGE"); + mvaddstr(1,20,"No Guarantees... All Trades Final"); + standend(); + count=3; + mvaddstr(count,0," Nation Item Price"); + /* give some minor items for purchase */ + mvprintw(++count,0,"%2d) %-20s",GETFOOD,"Merchants Guild"); + mvprintw(count,30,"%9ld %s",GODFOOD,commodities[TDFOOD]); + mvprintw(count,50,"%9ld %s",GODPRICE,commodities[TDGOLD]); + mvprintw(++count,0,"%2d) %-20s",GETMETAL,"Merchants Guild"); + mvprintw(count,30,"%9ld %s",GODMETAL,commodities[TDMETAL]); + mvprintw(count,50,"%9ld %s",GODPRICE,commodities[TDGOLD]); + mvprintw(++count,0,"%2d) %-20s",GETJEWL,"Merchants Guild"); + mvprintw(count,30,"%9ld %s",GODJEWL,commodities[TDJEWL]); + mvprintw(count,50,"%9ld %s",GODPRICE,commodities[TDGOLD]); + + /* go through list of commodities */ + for (holdint=0;holdintLINES-8) { + standout(); + mvaddstr(LINES-2,30,"Hit Any Key to Continue"); + standend(); + refresh(); + getch(); + clear(); + standout(); + mvaddstr(0,27,"COMMODITIES EXCHANGE"); + standend(); + mvaddstr(2,0," Nation Item Minimum Price"); + count=2; + } + } + } + standout(); + count++; + count++; + mvaddstr(count++,0,"Do you wish to (B)uy, (S)ell, or (U)nsell?"); + standend(); + refresh(); + inloop=TRUE; + while (inloop==TRUE) switch(getch()) { + case 'b': + case 'B': + buysell=BUY; + mvaddstr(count++,0,"What item number do you want to purchase? "); + refresh(); + holdint = get_number(); + if (holdint<0) break; + /* check for minor sales */ + if (holdint==GETFOOD || holdint==GETMETAL || holdint==GETJEWL) { + /* strange flow but less control needed */ + mvaddstr(count++,0,"Spend how much gold? "); + refresh(); + holdlong = get_number(); + curntn->tgold-=holdlong; + if (curntn->tgold<0L) { + curntn->tgold+=holdlong; + tradeerr("You do not have enough gold"); + } + else switch (holdint) { + case GETFOOD: + curntn->tfood+= (long)(GODFOOD * ((double)holdlong / GODPRICE)); + if ( (tfile = fopen(tradefile,"a+"))==NULL) { + tradeerr("Error opening file for trading"); + abrt(); + } + fprintf(tfile, "%d %d %d %d %ld %ld %d\n",BUY, country, GETFOOD, 0, curntn->tfood, 0, 0); + fclose(tfile); + break; + case GETMETAL: + curntn->metals+=(long)(GODMETAL * ((double)holdlong / GODPRICE)); + break; + case GETJEWL: + curntn->jewels+=(long)(GODMETAL * ((double)holdlong / GODPRICE)); + break; + } + inloop=FALSE; + done=FALSE; + break; + } else if (holdint<1 || holdint>itemnum + || ntn[natn[holdint - 1]].dstatus[country]==UNMET) { + tradeerr("Invalid Item Number"); + return; + } + holdint--; + if (deal[holdint]!=SELL) { + tradeerr("Sorry, that item is not on the market."); + return; + } + if (ntn[natn[holdint]].dstatus[country]==UNMET) { + tradeerr("That nation has not been met by you"); + return; + } + if (ntn[natn[holdint]].dstatus[country]>HOSTILE) { + tradeerr("That nation is not doing business with you"); + return; + } + /* obtain bid */ + mvprintw(count++,0,"%s",buylist[type2[holdint]]); + refresh(); + holdlong2 = 0L; + holdlong = (long) get_number(); + if (holdlong< 0L) break; + /* check for valid bid */ + switch(type2[holdint]) { + case TDGOLD: + if (holdlong < lvar2[holdint]) { + tradeerr("You underbid the minimum."); + buysell=NODEAL; + } else if (holdlong > curntn->tgold) { + tradeerr("Not Enough Gold"); + buysell=NODEAL; + } + break; + case TDFOOD: + if (holdlong < lvar2[holdint]) { + tradeerr("You underbid the minimum."); + buysell=NODEAL; + } else if (holdlong > curntn->tfood) { + tradeerr("Not Enough Food"); + buysell=NODEAL; + } + break; + case TDMETAL: + if (holdlong < lvar2[holdint]) { + tradeerr("You underbid the minimum."); + buysell=NODEAL; + } else if (holdlong > curntn->metals) { + tradeerr("Not Enough Iron"); + buysell=NODEAL; + } + break; + case TDJEWL: + if (holdlong < lvar2[holdint]) { + tradeerr("You underbid the minimum."); + buysell=NODEAL; + } else if (holdlong > curntn->jewels) { + tradeerr("Not Enough Jewels"); + buysell=NODEAL; + } + break; + case TDLAND: + mvaddstr(count++,0,"What Y position? "); + refresh(); + holdlong2 = (long) get_number(); + if (holdlong2 < 0L) break; + if (checkland(BUY,(int)(holdlong),(int)(holdlong2))==NODEAL) { + buysell=NODEAL; + } else if (tofood( &sct[(int)holdlong][(int)holdlong2],natn[holdint]) < lvar2[holdint]) { + tradeerr("You underbid the minimum"); + buysell=NODEAL; + } + break; + case TDARMY: + if ((int)holdlong > MAXARM) { + tradeerr("Invalid Unit"); + buysell=NODEAL; + } else if (tradable(country,(int)holdlong)==FALSE) { + tradeerr("That unit type is non-tradable."); + buysell=NODEAL; + } else if (armyvalue(country,(int)holdlong) < lvar2[holdint]) { + tradeerr("You underbid the minimum."); + buysell=NODEAL; + } + holdlong2=holdlong; + break; + case TDSHIP: + if ((int)holdlong >= MAXNAVY) { + tradeerr("Invalid Navy"); + buysell=NODEAL; + } else if (flthold((int)holdlong) < (int)lvar2[holdint]) { + tradeerr("You underbid the minimum."); + buysell=NODEAL; + } else if((curntn->nvy[(int)holdlong].armynum!=MAXARM)||(curntn->nvy[(int)holdlong].people!=0)) { + tradeerr("Navy must be unloaded first."); + buysell=NODEAL; + } + holdlong2=holdlong; + break; + default: + tradeerr("Invalid Commodity"); + buysell=NODEAL; + break; + } + if (buysell==BUY) { + if ( (tfile = fopen(tradefile,"a+"))==NULL) { + tradeerr("Error opening file for trading"); + abrt(); + } + setaside(country,type2[holdint],holdlong,(int)holdlong,FALSE); + fprintf(tfile, "%d %d %d %d %ld %ld %d\n",BUY, country, holdint, 0, holdlong, holdlong2, 0); + fclose(tfile); + } + return; + case 's': + case 'S': + /* sell an item */ + /* only allow MAXITM on market */ + if (itemnum>=MAXITM) { + standout(); + if (itemnum==0) mvaddstr(count++,0,"Market Congested. Hit any key to continue"); + else mvaddstr(count++,0,"Market Congested. (B)uy or any key to continue"); + standend(); + refresh(); + break; + } + buysell=SELL; + holdint = gettrade("Selling",&count); + if (holdint==(-1)) { + tradeerr("Invalid Option"); + return; + } + + mvprintw(count++,0,"%s",buylist[holdint]); + refresh(); + /* find out how much commodities */ + holdlong = (long) get_number(); + if (holdlong < 0) return; + extint = 0; + if (holdint< TDLAND && holdlong==0L) + return; + + /* check for valid items */ + switch(holdint) { + case TDGOLD: + if (holdlong > curntn->tgold) { + tradeerr("Not Enough Gold"); + buysell=NODEAL; + } + break; + case TDFOOD: + if (holdlong > curntn->tfood) { + tradeerr("Not Enough Food"); + buysell=NODEAL; + } + break; + case TDMETAL: + if (holdlong > curntn->metals) { + tradeerr("Not Enough Iron"); + buysell=NODEAL; + } + break; + case TDJEWL: + if (holdlong > curntn->jewels) { + tradeerr("Not Enough Jewels"); + buysell=NODEAL; + } + break; + case TDLAND: + mvaddstr(count++,0,"What Y position? "); + refresh(); + extint = get_number(); + if (extint < 0) { + buysell=NODEAL; + break; + } + buysell = checkland(SELL,(int)holdlong,extint); + break; + case TDARMY: + if (holdlong>=MAXARM || curntn->arm[(int)holdlong].sold <= 0) { + tradeerr("Invalid Army"); + buysell=NODEAL; + } else if (tradable(country,(int)holdlong)==FALSE) { + tradeerr("That unit is non-tradable."); + buysell=NODEAL; + } + break; + case TDSHIP: + if (holdlong>=MAXNAVY || flthold((int)holdlong) <= 0) { + tradeerr("Invalid Navy"); + buysell=NODEAL; + } else if((curntn->nvy[(int)holdlong].armynum!=MAXARM)||(curntn->nvy[(int)holdlong].people!=0)) { + tradeerr("Navy must be unloaded first."); + buysell=NODEAL; + } + break; + default: + tradeerr("Invalid Commodity"); + buysell=NODEAL; + break; + } + /* invalid commodity */ + if (buysell==NODEAL) return; + + /* find out what they want in trade */ + holdint2 = gettrade("In Trade For",&count); + if (holdint2==(-1)) { + tradeerr("Invalid Option"); + return; + } + if (holdint2==TDLAND) { + holdlong2 = (long) getland(&count); + if (holdlong2==(-1L)) { + tradeerr("Invalid Vegetation"); + return; + } + } else { + /* find out for what value */ + mvprintw(count++,0,"Minimum Amount of %s? " + ,commodities[holdint2]); + refresh(); + holdlong2 = (long) get_number(); + if (holdlong2 <= 0L) return; + } + + /* make sure what was bid is unusable */ + setaside(country,holdint,holdlong,(int)holdlong,FALSE); + + /* set up output properly */ + if (holdint==TDARMY) { + extint = (int) holdlong; + holdlong = armyvalue(country,(int)holdlong); + } + else if (holdint==TDSHIP) { + extint = (int)holdlong; + holdlong = (long)flthold(extint); + } + + /* send it out */ + if ( (tfile = fopen(tradefile,"a+"))==NULL) { + tradeerr("Error opening file for trading"); + abrt(); + } + fprintf(tfile, "%d %d %d %d %ld %ld %d\n", SELL, country, holdint, holdint2, holdlong, holdlong2, extint); + fclose(tfile); + inloop=FALSE; + done=FALSE; + break; + case 'u': + case 'U': + /* unsell an item */ + if (itemnum==0) break; + mvaddstr(count++,0,"What item number to remove? "); + refresh(); + holdint = get_number(); + if (holdint < 0) return; + if (holdint==0 || holdint>itemnum) { + tradeerr("Invalid Item Number"); + return; + } + holdint--; +#ifdef OGOD + /* allow god to remove commodities */ + if (country!=0 && country!=natn[holdint]) +#else + if (country != natn[holdint]) +#endif /* OGOD */ + { + tradeerr("That is not your item"); + return; + } + + if (deal[holdint]!=SELL) { + tradeerr("That item is not up for sale"); + return; + } + + /* remove it from market */ + if ( (tfile = fopen(tradefile,"a+"))==NULL) { + tradeerr("Error opening file for trading"); + abrt(); + } + fprintf(tfile, "%d %d %d %d %ld %ld %d\n", NOSALE, natn[holdint], holdint, 0, 0L, 0L, 0); + fclose(tfile); + takeback(natn[holdint],type1[holdint],lvar1[holdint],extra[holdint],FALSE); + /*redraw the commodities board so removal is seen*/ + inloop=FALSE; + done=FALSE; + break; + default: + /* return on no choice */ + return; + } + } +} + +void +tradeerr(mesg) +char *mesg; +{ + clear_bottom(0); + standout(); + mvaddstr(21,0,mesg); + standend(); + mvaddstr(22,0,"Hit any key to continue"); + refresh(); + getch(); +} + +int +checkland(tradestat,xspot,yspot) +int tradestat,xspot,yspot; +{ + int newstat=tradestat; + if (!ONMAP(xspot,yspot)) { + tradeerr("That is off the map"); + newstat=NODEAL; + } + else if (sct[xspot][yspot].owner != country) { + tradeerr("You don't own it"); + newstat=NODEAL; + } + else if (curntn->capx==xspot && curntn->capy==yspot) { + tradeerr("That is your capitol"); + newstat=NODEAL; + } + else if (sct[xspot][yspot].designation == DTOWN) { + tradeerr("Towns may not be sold"); + newstat=NODEAL; + } + else if (sct[xspot][yspot].designation == DCITY) { + tradeerr("Cities may not be sold"); + newstat=NODEAL; + } + return(newstat); +} + +/* get minimum foodvalue for land */ +int +getland(count) +int *count; +{ + int temp; + int i,j; + char entered; + + mvprintw((*count)++,0,"MINIMUM VEGETATION: %c, %c, %c, %c, %c, %c, %c, %c, %c, %c, %c or %c: ", + VOLCANO,DESERT,TUNDRA,BARREN,LT_VEG, + GOOD,WOOD,FOREST,JUNGLE,SWAMP,ICE,NONE); + + refresh(); + entered=getch(); + if(entered!=VOLCANO &&entered!=JUNGLE + &&entered!=DESERT &&entered!=TUNDRA + &&entered!=BARREN &&entered!=LT_VEG + &&entered!=NONE &&entered!=GOOD + &&entered!=WOOD &&entered!=FOREST + &&entered!=SWAMP &&entered!=ICE) temp=(-1); + else { + for(i=0;i0) + returnval=armyvalue(cntry2,extint); + break; + case TDSHIP: + curntn = &ntn[cntry2]; + if (flthold(extint)>0) + returnval = (long)flthold(extint); + break; + } + return(returnval); +} + +/* this function sends detailed message to players */ +/* upon completion of a trade */ +void +trademail(cntry1,cntry2,item1,item2,lvar1,lvar2,lvar3,lvar4) +int cntry1,cntry2,item1,item2; +long lvar1,lvar2,lvar3,lvar4; +{ + FILE *fp[2]; + int count; + char cname[2][NAMELTH+1],filename[2][FILELTH]; + + sprintf(filename[0],"%s%d",msgfile,cntry1); + sprintf(filename[1],"%s%d",msgfile,cntry2); + strcpy(cname[0],ntn[cntry1].name); + strcpy(cname[1],ntn[cntry2].name); + + if ((fp[0]=fopen(filename[0],"a+"))==NULL) { + printf("error opening <%s>\n",filename[0]); + abrt(); + } + if ((fp[1]=fopen(filename[1],"a+"))==NULL) { + printf("error opening <%s>\n",filename[1]); + abrt(); + } + + for (count=0;count<2;count++) { + fprintf(fp[count],"Message to %s from Conquer Commerce Commision\n",cname[count]); + fprintf(fp[count],"Dated: %s of Year %d\n",PSEASON(TURN),YEAR(TURN)); + fprintf(fp[count],"\n"); + fprintf(fp[count]," Trade transaction between %s and %s completed.\n",cname[1],cname[0]); + if (item1<=TDJEWL) + fprintf(fp[count]," Nation %s receives %ld %s\n",cname[1],lvar1,commodities[item1]); + else if (item1==TDLAND) + fprintf(fp[count]," Nation %s receives sector %ld, %ld\n",cname[1],lvar1,lvar2); + else if (item1==TDARMY) + fprintf(fp[count]," Nation %s receives army #%ld\n",cname[1],lvar1); + else if (item1==TDSHIP) + fprintf(fp[count]," Nation %s receives navy #%ld\n",cname[1],lvar1); + if (item2<=TDJEWL) + fprintf(fp[count]," Nation %s receives %ld %s\n",cname[0],lvar3,commodities[item2]); + else if (item2==TDLAND) + fprintf(fp[count]," Nation %s receives sector %ld, %ld\n",cname[0],lvar3,lvar4); + else if (item2==TDARMY) + fprintf(fp[count]," Nation %s receives army #%ld\n",cname[0],lvar3); + else if (item2==TDSHIP) + fprintf(fp[count]," Nation %s receives navy #%ld\n",cname[0],lvar3); + fprintf(fp[count],"END\n"); + fclose(fp[count]); + } +} +#endif /* ADMIN */ + +#ifdef CONQUER +/* routine to determine whether or not an army type is tradable */ +int +tradable(cntry,armynum) +int cntry,armynum; +{ + int oldcntry=country,returnval=FALSE; + country=cntry; + if ( (ASTAT!=TRADED) && (ASTAT!=ONBOARD) && (ATYPE==A_MERCENARY + || ATYPE==A_SIEGE || ATYPE==A_CATAPULT + || ATYPE==A_ELEPHANT || ATYPE>=MINMONSTER) ) returnval=TRUE; + country=oldcntry; + return(returnval); +} +#endif /* CONQUER */ + +/* routine to determine commercial value of army */ +long armyvalue(cntry,unit) +int cntry,unit; +{ + long returnval; + + returnval = ntn[cntry].arm[unit].sold*100 + + ntn[cntry].arm[unit].sold * unitattack[ntn[cntry].arm[unit].unittyp%UTYPE]; + if (ntn[cntry].arm[unit].unittyp >= MINMONSTER) returnval+=ntn[cntry].arm[unit].sold*10; + returnval/=100; + return(returnval); +} + +void +checktrade() +{ + FILE *tfile; + int count, itemnum=0, natn[MAXITM]; + int type1[MAXITM], type2[MAXITM], deal[MAXITM], extra[MAXITM]; + long lvar1[MAXITM], lvar2[MAXITM]; + void takeback(); + void setaside(); + /* initialize purchase list */ + for (count=0; count for trade update\n",tradefile); + abrt(); + } + + /* compute the trading */ + for (count=0;count=0) fprintf(tfile,"%d %d %d %d %ld %ld %d\n", deal[count], natn[count],type1[count],type2[count],lvar1[count],lvar2[count],extra[count]); + } else if (deal[count]==BUY) { + /* do the trading */ + longval1 = tradeit(natn[count],whobuy[count],type1[count],lvar1[count],extra[count]); + if (longval1!=(-1)) longval2 = tradeit(whobuy[count],natn[count],type2[count],buy1[count],(int)buy2[count]); + if (longval1==(-1)) { + /* abort due to seller */ + fprintf(fnews,"2.\tTrade between %s and %s breaks down due to %s.\n", + ntn[natn[count]].name,ntn[whobuy[count]].name,tradefail[type1[count]]); + } else if (longval2==(-1)) { + /* abort due to buyer */ + tradeit(whobuy[count],natn[count],type1[count],longval1,extra[count]); + fprintf(fnews,"2.\tTrade between %s and %s breaks down due to %s.\n", + ntn[whobuy[count]].name,ntn[natn[count]].name,tradefail[type2[count]]); + /* place it on the list for next turn */ + /* adjust the displayed value */ + /* let land fail during trade */ + if (type1[count] != TDLAND) + lvar1[count]=gettval(0,natn[count],type1[count],lvar1[count],extra[count]); + if(lvar1[count]>=0) fprintf(tfile,"%d %d %d %d %ld %ld %d\n", SELL, natn[count],type1[count],type2[count],lvar1[count],lvar2[count],extra[count]); + } else { + /* trade completed send mail */ + fprintf(fnews,"2.\tNation %s sells %s to %s for %s\n" + ,ntn[natn[count]].name,commodities[type1[count]],ntn[whobuy[count]].name,commodities[type2[count]]); + trademail(natn[count],whobuy[count],type1[count], + type2[count],longval1,(long)extra[count], + longval2,buy2[count]); + } + } + } + fclose(tfile); +} + +/* remove a nations items from the trading board */ +void +fixtrade (cntry) +int cntry; +{ + FILE *tfile; + int holdint, notopen=FALSE; + int type1[MAXITM], type2[MAXITM], deal[MAXITM], extra[MAXITM]; + int natn[MAXITM], itemnum, getland(), gettrade(), checkland(); + long lvar1[MAXITM], lvar2[MAXITM], armyvalue(); + void setaside(), takeback(); + + /* open trading file */ + if ((tfile=fopen(tradefile,"r")) == NULL ) { + notopen=TRUE; + } + itemnum = 0; + + /* read in all of the data */ + while (notopen==FALSE && !feof(tfile)) + { + if (fscanf(tfile,"%d %d %d %d %ld %ld %d\n",&deal[itemnum], + &natn[itemnum],&type1[itemnum],&type2[itemnum], + &lvar1[itemnum],&lvar2[itemnum],&extra[itemnum]) == 7){ + if (deal[itemnum]==NOSALE) { + /* remove item from sales list */ + deal[type1[itemnum]]=NOSALE; + } else if (deal[itemnum]==SELL) { + itemnum++; + } + } + } + if (notopen==FALSE) fclose(tfile); + + /* go through list of commodities */ + + for ( holdint=0; holdint-L will redraw the screen +END + CONQUER EXTENDED COMMANDS + + All of the extended commands are accessed by typing the ESC key and +then one of the following extended command keys. + + Each of the commands takes action on the currently selected army unit. + + 'a': set army status to ATTACK + 'd': set army status to DEFEND + 's': set army status to SCOUT + 'm': set army status to MARCH + 'g': set army status to GARRISON + 'G': place army in a group with other armies + 'S': set army status to SEIGE or SORTIE + 'R': set army leader status to RULE + '+': combine selected and next army + '-': separate army into two units + '/': separate army into two equal units +END + Welcome to Conquer XVERSION + +CONQUER is a multi player computer game designed to run under the UNIX +operating system. In CONQUER, each player is the leader of a nation, +composed of people (humans, orcs, elves, dwarves), resources, and land. +Rulers customize their nation at creation by chosing their race and by giving +their nation special powers (magic, combat factor, location, speed...) +and resources (civilians, troops, metal, gold...). Play involves building, +moving, and controlling armies and navies, diplomacy with other players, +and adjusting economic activity, which is primarily geared to the production +of gold for your treasury. Also, metals are needed to build ships & armies, +and food is needed to prevent revolts and keep people alive. + +Command format: conquer [-Ghs -nNAT -dDIR] + -G highlight name in news (gaudy!) + -h print this help text + -s print out scores + -n NTN run as nation NTN + -d DIR run on data in directory DIR + +The game administrator should read documentation on using the conqrun command. +END + CONQUER ENVIRONMENT VARIABLES + + To facilitate the use of conquer, the environment variable +XCONQENV has been added to conquer to allow settings of default options +to conquer. Just add a line to your .cshrc or .login (BSD) or .profile (SYSV) +file with the following format: + +setenv XCONQENV "G,nation=MyLand,datadir=this_game" (BSD) +XCONQENV="G,nation=MyLand,datadir=this_game" (SYSV) + + If you then type just 'conquer' to enter conquer, it will be +equivalent to typing 'conquer -G -n MyLand -d this_game'. + + The data directory and nation settings through the environment +are just defaults and maybe overridden by actually entering a different +option using '-d' or '-n'. [Note: to specify the default directory, +you may simply specify '-d ""'.] + + The XCONQENV environment variable combined with the use of shell +aliases should allow quick access for players in multiple campaigns. +END + CONQUER DEMI-GODS + + Since god is often a busy fellow, it is within his power to +assign worlds to his loyal followers. When creating a world god simply +indicates a mortal who may administrate that world, and that player is +promoted to demi-god status. + + The demi-god may perform all of the godly functions for his world, +including updates and nation alterations. He may even rebuild the current +world from the beginning, if god grants him that power. The only definite +restrictions are that he may not create a completely new world or effect any +world, other than his own. The demi-god for each world is indicated +in the campaign information display ('I'). + + Perhaps god is looking for people to run his worlds. Send mail +to XLOGIN and you may find out. +END + CONQUER COMMANDS -- lower case commands + +'a': army report: Gives an army's details & permits changing army status, + merging armies, splitting armies, and disbanding armies +'c': administration: Report on nation status and then change name, password, + add to combat bonus, or (if god) destroy a nation. +'d': change display: Change display mode. metal/jewel screens #'s are sector + value. Pop. is by 100's in Arabic, and 1000's in Roman. +'f': fleet report: Report on the status of your fleets. +'g': group report: As army report, but only show armies in current sector. +'m': move unit: Move selected unit. The unit will stop when it runs out + of move points or runs into an army larger than it. +'o': pick previous: Allow you to select the next/previous army or navy in the +'p': pick next: sector. Other commands will operate on that unit. +'r': redesignate: You can change habitable sectors you own to other + designations. Towns require 500+ people & Capitols + require Towns. God can redesignate anything. +'s': score: Print out a screen showing the scores +'t': transport: Load/unload soldiers or civilians onto selected fleet. +'w': wizardry: Cast spells if you have the ability +'?': help screen: Display this help text +END + CONQUER COMMANDS -- upper case commands pg. 1. + +'B': budget: ESTIMATE your nations budget statistics +'C': construct: If you have cash, you can build fortifications and + ships in your Towns. Ships can only be built in Towns + located on the water. +'D': draft: You may draft a 1/4 of the starting sector population if it + was a Town/City/Cap and if you have the gold & metal. You + must draft soldiers in multiples of 10 men. +'F': next fleet: Move cursor to your next fleet. +'G': next army: Move cursor to your next army. +'I': information: Display a screen containing general conquer statistics. +'M': magic: Prints your magic powers & offers you the option to + purchase more (cost increase with each power). Monster + Power gives you the chance to take over NPC nations. +END + CONQUER COMMANDS -- upper case commands pg. 2. + +'N': newspaper: Briefs you on world happenings. Note: News has 4 pages. +'P': production: ESTIMATE your nations production statistics +'S': diplomacy: Allow you to see and alter your diplomatic status. +'T': commerce: Allow you to trade with other nations. +'Q': quit: Save your move and quit the game. Note there is no + means supported to quit without saving your moves. +'R': read mail: Read mail messages +'W': write mail: Write mail messages. You can write to the administrator + and can post articles to the news board with this command. +'Z': move people: Civilians can move between two of your sectors at a cost + of 50 per civilian. Civilians naturally move in the update. +END + A TYPICAL FIRST TURN + +This section is offered to help beginning players understand the first +turns of the game. The objective at this point is to take land and to +make enough farms that your people don't starve. The first thing to do is +to look at sectors you can see (using the cursor keys). You +are looking for sectors with high (4+) food/metal/jewel values. You should +now assign soldiers to army groups (via. the Escape / G sequence). An army +group id is the same as a leader id. Then, pick an army or army group with +the 'p'ick command and 'm'ove it to a target sectors. When you stop the +army, it should take the sector, and you should be able to see a little bit +more of the world. Every army should try to take a different sector each +of the first few turns. 'r'edesignate sectors to farms (f),mines (m), or +goldmines ($). Now browse the other reports and forms to get a feel of the +game. When done, quit via the 'q'uit command. After the update, +civilians will have moved into your sectors, and will start producing. +Watch that food consumption early on!!! +END + FINAL COMMENTS + +To my knowledge Conquer runs well on UNIX (SYS V or BSD 4.3) systems. The +game treats turns like a hidden move wargame would... you enter all your +moves into the program and conquer tells you what happens. Like wargames, +there is no turning back. Every move you make will be saved when you quit. +If you goof up real bad, you need to go to the administrator, and have him +log in (as god) and fix whatever you did. Of course, bribery will probably +work well in such a situation. ;-) + +Have Fun + +The Ed +END +DONE diff --git a/original/txt1 b/original/txt1 new file mode 100644 index 0000000..f98eaf2 --- /dev/null +++ b/original/txt1 @@ -0,0 +1,340 @@ + THE WORLD OF CONQUER + +The Conquer world is very bloody, and a player needs skills at war gaming, +diplomacy, and building an economy to succeed. Rival races are constantly +at war, and the world starts filled with player nations, random peoples +(lizard men in their cities of gold, savages, nomads, pirates, brigands), +and both hostile and friendly computer controlled non player countries. +Conquer can be played solitaire. The computer uses a highly intelligent +movement algorithm to run the armies and navies of these non player +countries (NPC), and has intelligent algorithms built in that control these +nations diplomacy, construction, and economies. You can find NPCs allied with +you against a common enemy, but can also suddenly be stabbed in the +back and find hostile NPC armies at your doorstep. +END + WHAT IS WHAT IN THE WORLD + +The world is composed of a 2 dimensional map of sectors, created by the +computer at the beginning of the game. Each sector has about 10 unique +characteristics (altitude, gold, vegetation...). + +SECTOR ELEVATIONS include: + ZMOUNTAIN ZHILL ZCLEAR + ZWATER ZPEAK +SECTOR VEGETATION +Uninhabitable Areas (do not produce food and people simply do not like) + ZVOLCANO ZDESERT ZJUNGLE + ZTUNDRA ZICE ZSWAMP +Inhabitable (people like, number is relative value of food production) + ZGOOD...9 ZFOREST...3 (4 ELF) ZLIGHT...6 + ZWOOD...7 ZBARREN...4 (3 ELF) + +CONQUER is designed so each race likes their appropriate terrain. Elves like +woods & forests, Humans like good & light vegetation, and Orcs and Dwarves +like hills and mountains. You can only redesignate inhabitable sector types. +END + RACES OF THE WORLD + +ORC 'O' See next page. +ELF 'E' Great at defense and quick, but few in numbers. They start + with VOID power, which is perhaps the most potent power in the + game, but which costs them an extra distribution point. +DWARF 'D' Dwarves are good at combat, but slow and few in numbers. They + start with MINER power, which allows them to quickly mine + metal/jewels, and thus improve their combat skills and powers. +HUMAN 'H' Humans start average at everything -- with reasonable numbers, + of people, and WARRIOR power, which gives them +10% in combat. + They have OK reproduction and good movement. +LIZARD 'L' (NPC only) An ancient race bound to their cities of gold +PIRATE 'P' (NPC only) Wandering pirates/brigands intent on plunder +NOMAD 'N' (NPC only) Will the wandering nomads tribes leave you alone? +SAVAGES 'S' (NPC only) Indigenous natives and monsters +END + ORC NATIONS IN CONQUER + +Orc nations are very special in Conquer. The only thing an orc is good at is +making other orcs. They are slow, poor at combat, & bad in special abilities. +They can get reproduction of up to 14% per year (the normal limit is 10%) & +can start with a large number of people as initial reproduction costs are less +than normal. Orcs are led by monsters (they start with MINOR MONSTER power), +and are always evil (the only good orc is a dead orc...). They are so nasty, +EVERYBODY they meet start out hostile (50%) or at war (50%) with them. +Player nations get an option here, but they usually start out hostile to you. + +In combat, orc & goblin units types flee just like mercenaries (a random +chance, modified by odds...), and orcs are charged 2x normal cost for raising +their combat bonus at game start and 3x during play, so they usually need +2:1 odds or better to win (expect heavy losses). + +Finally, Orcs are slow, as they require tremendous leader incentive to move +and not kill each other. Large orc nations do have the ability to take over +other Orc nations (The Sauron Syndrome). There is no Orc CAVALRY. +END + POSSIBLE NATION ALIGNMENTS + +Nations in conquer can be good, neutral, or evil. Alignment impacts how +non player nations will react to your nation ( good nations like good +nations, but hate evil nations. Nobody is mean to neutral nations, +but nobody likes them either ). Player nations choose an alignment +when they get created (no limitations) which can not change. Players +actions are not restricted by their alignments, but players should +play "in character". There are more evil non player nations than there +are good non player nations, so it is more fun/challenging to play the +good guys. +END + SECTOR DESIGNATIONS + +The following is the list of possible sector designations: + + ZTOWN ZFORT ZMILL + ZCITY ZSTOCKADE ZGRANARY + ZCAPITOL ZUNIVERSITY ZCHURCH + ZMINE ZLUMBERYARD ZSPECIAL + ZGOLD ZBLACKSMITH ZRUIN + ZFARM ZROAD ZDEVASTATED + +For more information on each, see the helpfile on 'Designations' +END + METAL, FOOD, AND GOLD + +FOOD: You MUST have enough food to feed your people... One civilian eats + your national eatrate units of food. Soldiers eat double. If you + run out of food, you run the risk of famine. Food will spoil based + on the spoilrate percentage for each nation. +METAL: You need to have metal to draft new military, as per the unit types + section. One person produces one metal per point of mineral in + the sector per turn. An amount of Metal (based on how many troops + you have) can be used to buy +1% in your nations attack or defense. +JEWELS: You can have a maximum of 10 talons debt for every jewel + point that you mined. After that point, you undergo a TAX REVOLT, + which has not yet been implemented. Thus gold can be negative to + a certain level. Jewels are also useful to obtain magic, spending + Jewels will buy you one random new power (command M). The cost for + the magic power is dependent on your race and how many other powers + you have. See the helpfile on magic for more information. You can + have 10 talons in the treasury for each jewel (gold based economy). + After that, your gold talons will be converted to jewels at a 10:1 + ratio. +END + CIVILIAN MOVEMENT + +The game offers users the capability to forcibly move civilians around +the map (via the 'Z' command). Civilians will, however, move of their +own volition. Below are how civilians of different races think about "good" +sectors of various types. The program is intelligent enough to appropriately +handle poor or low value sectors. Sum the numbers found below. The result +is the relative "attractiveness" of a sector. + +General Modifiers: Goldmine: XGOLDATTR * jewels Farm: XFARMATTR * food value Other: XOTHRATTR + Trade Good: XTGATTR Mine: XMINEATTR * metals Town: XTOWNATTR City: XCAPATTR + + Racial Modifiers +Race Mtn Hill Clear Forest Wood City Mine Gldmine +Dwarf XDMNTNATTR XDHILLATTR XDCLERATTR XDFOREATTR XDWOODATTR XDCITYATTR XDMINEATTR XDGOLDATTR +Elf XEMNTNATTR XEHILLATTR XECLERATTR XEFOREATTR XEWOODATTR XECITYATTR XEMINEATTR XEGOLDATTR +Human XHMNTNATTR XHHILLATTR XHCLERATTR XHFOREATTR XHWOODATTR XHCITYATTR XHMINEATTR XHGOLDATTR +Orc XOMNTNATTR XOHILLATTR XOCLERATTR XOFOREATTR XOWOODATTR XOCITYATTR XOMINEATTR XOGOLDATTR +END + VIEWING THE WORLD + +When you first log in, you will notice that you can only see a portion of the +entire world. Your range of vision is determined by the magic powers you +possess and the location of your sectors and armies. Scouts are useful to +expand the amount of land you can view. + +The 'd' command allows you to change what you see on the map. You can +alter the information in the sector and can change the type of sectors that +are highlighted. See the next two sections for the list of possible display +and hightlight options. + +Normally, the conquer display shows your chosen display option with blank +spaces to the right to space out the map nicely. But, you may also use the +area thus provided to show a secondary display. This secondary display may +be turned on and off using the '/' display selection. Also, you may +distinguish between what to display in the primary or secondary display by +prefacing your selection with either a '1' or '2'. If neither is chosen, +then the primary display is set to the selected option, while the secondary +display is turned off. +END + DISPLAY OPTIONS + +This section describes the possible display options proceeded by their +associated keystroke: + + (d) designation: show your designations and other nation's marks. + (r) race: show race of owned sectors (Human, Orc, Elf, Dwarf, Lizard, etc.) + (M) move cost: show the cost in movement points to move into a sector. + (p) people: show how many people live in a sector; arabic numbers indicate + the amount in hundreds, while 'I', 'V' and 'X' are used to indicate + at least one thousand, five thousand, and ten thousand respectively. + (D) defense: show the relative defensive strength of a sector. Both sector + terrain and sector fortifications are taken into account. + (f) food: display relative food production ability of a sector. + (c) contour: display the elevation symbol of each sector. + (v) vegetation: display the vegetation symbol of each sector. + (m) metal: show the relative metal production ability of a sector. + (n) nation mark: display the national mark for all owned sectors. + (j) jewels: show the relative jewel production ability of a sector. + (i) items: display the designation neccesary to take advantage of the + special item in a sector. +END + HIGHLIGHT OPTIONS + +This section describes the possible modes of highlighting proceeded by the +keystroke used to select each: + + (o) owned: highlight all sectors owned by your country. + (a) army: highlight all sectors containing army units. + (y) your army: hightlight all sectors containing at least on of your + army units. + (l) moves left: hightlight any sectors containing one of your armies with + movement points remaining. + (s) special: highlight any sector containing a special item visable to + your nation. + (x) none: do not highlight any sectors. + + In general, the most useful displays are the production displays (food, +metal, and jewels), and the most useful highlights are the army highlight +(to show where your enemies are), and the moves left highlight (to indicate +those units which may still be moved onto your enemies). +END + COMMERCE AND TRADING + +Trading makes it be possible to exchange items between nations. + +There are seven types of items available for trade: gold, food, metal, +jewels, land, soldiers, and ships. To place an item up for trade, +the player need only select the sell option on the commerce board. The +player will then enter the type and amount of his product followed by the +type and minimum amount of what he wants in return. The product will +remain on the commerce board until it is purchased or removed by the +owner of the product. To purchase an item, a player can just select the +item number to purchase and then enter a bid amount. You may only trade +mercenary, siege engine, catapult, (summoned) monster, or elephant units. +Certain Items will be available for "instant purchase" from the game +itself, these are indicated by the nation name of "Conquer". + +During every update, bids will be resolved and the highest bid for a +product will receive the product. There is a 20% administration fee +for a trade (i.e. 20% of the traded goods on each side disappear) +NOTE: the trading code is buggy and trading should be used with caution. +END + DIPLOMACY IN CONQUER + +Diplomacy is very important in conquer. You maintain a diplomatic status with +each nation in the game. This is adjusted via the 'S' (diplomacy) command. +Possible status' are TREATY, ALLIED, FRIENDLY, NEUTRAL, HOSTILE, +WAR, and JIHAD. Be very careful with TREATY and JIHAD. Once chosen, +it will take XBREAKJIHAD gold talons to change your mind (and might ruin +your reputation). You can only take land from a nation that you are at +WAR or JIHAD with. TREATY implies that you AUTOMATICALLY declare war on +nations who ATTACK your ally - but not on nations whom they attack. + +Diplomacy with non player nations is important as it determines if you get +attacked or not. +END + BRIBING NPC NATIONS + +Conquer allows you a chance to bribe non player nations for the paltry sum +of XBRIBE per 1000 troops in the bribee's nation. A nation with 10000 troops +can be bribed for only 10xXBRIBE gold talons (a bargain). This has a +percentage chance of working, but you wont know if it worked until the update. + + same allignment: 50% + 1 level allignment difference: 30% + 2 level allignment difference: 20% + They are isolationist: 15% + same race: +20% + +Bribing NPCs is a good way to get some breathing room. +You waste your money if you are at war with them that turn. +You can not bribe player nations, savages, nomads, lizards, or pirates. +END + SEASONS + (only food production is implemented) + +winter: army units must end turn in town or suffer 10% attrition. + farms produce no food. movement is at half ability. +spring: produce 1/2x food. +summer: produce 1x food. units get 50% movement bonus. +fall: produce 2.5x food. + +you must have a sector spring,summer,and fall or it will produce no food +global events should be good too; typhoon season, famine times, etc. +Perhaps the climate of a region should also effect the events. ie, +more typhoons in the equatorial belt. Typhoon should be calculated +with a starting point and an ending point and then it walks in +between causing devastation. +END + FINAL HINTS & OTHER COSTS + +It is important to initially have a reproduction of 9-10% and a move of ~8-9. +You need about 1000 military to start - to take enough new land. +Take as much land as possible in the beginning. +Make sure your combat bonus stays respectable. + + OTHER COSTS + + Designation Costs: $XDESCOST + Designation to Fort or Town: 10x$XDESCOST+$XDESCOST METAL + Designation to City: 20x$XDESCOST+5*$XDESCOST METAL + Fortification: $XFORTCOST*(2**Fort Level) + Bribe Nation: $XBRIBE/level + Move Civilians: $50/civilian +END + OTHER NOTES + + The computer can move for players if they don't enter a turn and the +CMOVE variable is set before the program is compiled. This works well... +for a time. The Computer will NOT redesignate captured sectors for you. + +Mercenaries must be paid a fee equal to enlistment fee when disbanded. + +If you have too many people in a given non Town, non capitol sector, +reproduction and production is halved for them. If you have a large +number of people in a sector, they will not reproduce. + +WARNING: The Naval and Trade Code has been known to be buggy. Please +pay attention and send the author notes on discrepancies in the code. +END + OPTIONS OF YOUR VERSION + + Maximum Number of Armies Per Nation....XMAXARM + Maximum Number of Navies Per Nation....XMAXNAVY + Absolute Maximum Number of Nations.....XNTOTAL + Starting Points to buy your nation.....XMAXPTS + Percentage of land that is mountains...XPMOUNT + Storm Percentage.......................XPSTORM + Cost for Orc Npc Takeover..............XTAKEPRICE + Average Number of Random Events........XNORANDEVENTS + Chance of Volcano Eruption.............XPVULCAN + + Mail Checker XSYSMAIL System V XSYSV + Monsters XMONSTER Npc Cheat XCHEAT + Storms XSTORMS Volcanos XVULCANIZE + Npc Nations XNPC PC Automove XCMOVE + Random Events XRANEVENT Orc Takeovers XORCTAKE + Super God XOGOD Hidden News XHIDELOC + Trading XTRADE +END + ADDITIONAL OPTIONS + + Land Vision Range is..................XLANDSEE + Navy Vision Range is..................XNAVYSEE + Army Vision Range is..................XARMYSEE + + Taxation Rates: + Food tax per value point per person...XTAXFOOD + Jewel tax per jewel point per person..XTAXGOLD + Metal tax per metal point per person..XTAXMETAL + Town tax per person...................XTAXTOWN + City tax per person...................XTAXCITY + + 100% chance per XTOMUCHMINED metal mined of deplete metal mines. + 100% chance per XTOMUCHMINED jewels mined of deplete gold mines. + XFINDPERCENT% chance that new materials are found in a sector. + Sector overpopulation occurs with XTOMANYPEOPLE people. + Maximum Sector Population is XABSMAXPEOPLE people. + Ships may carry XSHIPHOLD items per holding unit. +END +DONE diff --git a/original/txt2 b/original/txt2 new file mode 100644 index 0000000..9cb1be2 --- /dev/null +++ b/original/txt2 @@ -0,0 +1,333 @@ + MILITARY AND WAR IN CONQUER + +Conquer permits both players and the computer to draft a variety +of unit types via the 'D'raft command. Ships can be created via +the 'C'onstruct command. Units differ in combat ability, movement +rate, and costs. Some unit types have prerequisite powers. For +example, as detailed on the next two tables, a archer unit requires +the drafting nation to have ARCHER power, and costs 100 talons and +100 metal points per soldier to draft. Archer units move at 1 times +the nations default movement rate, and fight at +10% if they are +defending. The special list shows that archers gain special combat +advantages in certain circumstances. In other words, archers cost the +same as infantry, but fight slightly better (so if you have ARCHER power, +you will draft Archers, not Infantry). +END + UNIT TYPES + + costs combat power + enlist maintain attack defend move metal prerequisites + +MILITIA $50 $20 -40 -25 0 0 +GOBLIN $70 $20 -15 -15 x1 80 MI_MONST +ORC $85 $50 +0 +0 x1 80 MI_MONST +INFANTRY $100 $50 +0 +0 x1 100 +SAILOR $100 $50 +0 +0 0 100 +MARINES $100 $50 +5 +0 0 100 SAILOR +ARCHER $100 $50 +0 +10 x1 100 ARCHER +ZOMBIE $100 $0 -15 -15 x1 100 VAMPIRE +URUK-HAI $125 $50 +5 +5 x1 150 AV_MONST +NINJA $125 $50 +20 +0 x1 150 NINJA +PHALANX $150 $50 +10 +10 x1 150 CAPTAIN +OLOG-HAI $180 $75 +15 +15 x1 150 BREEDER+AV_MONST +LEGION $180 $75 +20 +20 x1 150 WARLORD +DRAGOON $300 $200 +10 +10 x1.5 100 +MERCENARY $225 $100 * * x1 0 +TROLL $225 $100 +25 +15 x1 200 MA_MONST +END + UNIT TYPES - CONTINUED + + costs combat power + enlist maintain attack defend move metal prerequisites + +ELITE $225 $100 +20 +20 x1.3 200 ARMOR +LT_CAVALRY $275 $175 +20 +20 x1.5 100 CAVALRY +HV_CAVALRY $450 $225 +30 +30 x2 300 CAVALRY +CATAPULT $600 $250 -20 -20 x.5 1000 +SIEGE $600 $250 -20 -20 x.5 1000 +ROC $600 $250 +20 +30 x1 300 AVIAN +KNIGHT $600 $250 +40 +40 x2 600 ARMOR & CAVALRY +ELEPHANT $600 $250 +50 +50 x.5 600 DERVISH +GRIFFON $800 $250 +40 +50 x1.5 400 AVIAN +SPY $10000 $2000 -30 -30 x1 0 +SCOUT $100 $100 -30 -30 x2 0 +END + ADDITIONAL NOTES ON UNITS + +INFANTRY are the default units. You can't get them if you have any powers + (ARCHER, VAMPIRE, or any MONSTER) which change your default unit. +DRAGOONS are cavalry that fight on foot as regular infantry. They move + as cavalry but fight as infantry. +ARCHERS gain bonuses when fighting cavalry or near fortifcations. They + get an additional +15%*(percent of cavalry/knight opponents) + and gain +15% defending & +5% attacking forts/cities... They + don't get the bonus vs cavalry if they are in a fort. +MERCENARIES are drafted from the world mercenary pool and thus don't deplete + your nations population when hired. Only 1/2 your troops can + be mercenaries. They must be paid their enlistment cost to + disband them. They have a tendency to run away from combats if + outnumbered. Mercenary combat bonuses are independent of the + drafting nations bonus, and are based on an average worldwide + mercenary combat bonus. +CAVALRY/KNIGHTS get -20% attacking or defending fortress. + +note. you can purchase non catapult/seige/knight/elephant units even if +you have inadequate iron reserves if you pay triple their enlistment cost. +END + ADDITIONAL NOTES ON UNITS p.2 + +SIEGE_ENGINES add +1%/20 men *TO WHOLE COMBAT* attacking fortress (max +30%) + siege engines can damage any fortifications they attack. +CATAPULTS add +1%/40 men *TO WHOLE COMBAT* in normal combat (max +10%) + add +1%/20 men *TO WHOLE COMBAT* when defending castle (max +10%) + catapults can damage any fortifications they attack. +PHALANX & Phalanx and Legionaries get an additional +10 combat bonus if in +LEGIONARY 500+ men units +20 combat bonus if in 1000+ men units +ROC/GRIFFON units have the ability of flight. +NINJA units ignore enemy zones of control +SAILOR units may disembark from ships into unowned sectors. +MARINE units are the only units that can disembark from ships in another + nation's territory. + marines also have excellent combat ability while aboard ships. +ZOMBIE units are just plain dumb. They don't know how to MARCH, only + use half of a forts defenses and cannot even play follow the + leader. But, to the horror of their enemies, they obsorb 33% of + the enemy dead into their ranks. +SPY units are never captured and start in another nations capitol +SCOUT scouts can ignore enemy zones of control. +END + POSSIBLE ARMY STATUS + +The following is the list of normally selectable army statuses: + +MARCH :Marching doubles army movement at the expense of combat strength. + : One fifth of national moverate is required to stop marching. +SCOUT :Scout and spy units can have scout status, and will, if possible, + : avoid any enemy. They can move through hostile armies but are + : not able to take unowned land. They are useful to check out + : the map and to determine the enemy combat strength. +ATTACK :Armies in this mode can take owned sectors, initiate + : combat, and have they reasonable movement rates. +DEFEND :In this mode, can take owned sectors and have good defense + : and movement, but can not initiate combat. +GARRISON :This mode offers the strongest defense but is used only in YOUR + : Towns, Capitol, and castles. Garrisons may not move. +RULE :This mode is available to leaders within cities. It means that + : the leader will not participate in battle and may only be + : killed if surrounding troops receive more than 80% of damage. +SORTIE :A quick attack from a fortification. See page on CITY COMBAT. +SIEGE :An encampment to pin armies in a sector. See page on CITY COMBAT. +END + POSSIBLE ARMY STATUS (page 2) + +The following is the list of specialized statuses: + +MILITIA :Militia units have this status, which indicates that they are + : unable to move but DO get the bonuses of GARRISON troops. + : Militia units are not full time troops, and are intrinsically + : weak in combat. +FLIGHT :Flying units ignore normal movement costs while moving, and can + : cross water. See the FLIGHT section below. +MAGDEF :Magically enhanced DEFEND is normal DEFEND mode with a +30% bonus. + : You get this status by spending spell points via 'w'izardry +MAGATT :Magically enhanced ATTACK is normal ATTACK mode with a +30% bonus. + : You get this status by spending spell points via 'w'izardry +GROUP :Members of army groups move at the rate of the slowest unit in + : the group. They gain leader bonuses and have the same + : properties in combat as would an army in attack mode. +BESIEGED :A troop which is under siege. See page on CITY COMBAT. + +Due to unit reorganization, switching from one status to another consumes +one point of movement. (Only march is unchangable with zero movement.) +END + CAPTURING SECTORS AND TAKING COUNTRIES + +It takes armies greater than 75 AND greater than your total civilians/350 to +take a sector. You MUST be either at WAR or in JIHAD with the nation you want +to take the sector from. Because leader and monster units are really just a +single entity per unit, they do not possess enough men to take sectors. + +If one nation captures another nation's Capitol, that Capitol is sacked and +all items kept there are transfered to the conquerer: metal, gold, jewels and +a fifth of the food supply. In addition, the nation will be depleted because +it will now lack a Capitol. That will result in the loss of all monster and +mercenary troops and XDEPLETE% of it's regular armies and sectors. If a nation +loses all of it's population and army units, that nation is destroyed. + +Mercenaries are not drafted from your populace. 15% of all troops +disbanded become mercenaries and are added to the mercenary soldier pool +for potential drafting by any nation. +END + FLIGHT + +Some avian units have the ability of flight, these units will have a +status of FLYING automatically set after each update. Also, magicians +will have the ability to grant flight to individual units. Flying +units may not be combined with other units, but may be separated as +per normal units. + +Flying allows a unit to pass over land and water without being stopped +by enemy troops. It also allows allows cheaper travel over most +sectors. The major difference between flying and normal movement is that, +when a flying unit stops its movement, it will have landed, and its +status will become DEFEND, prohibiting any further flight. + +NOTE: if a FLYING unit runs out of movement over water, it will drown. +END + SHIPS AND SHIP COSTS + +There are three types of ships available: + + ship type cargo/hold base move base cost + +Warships combat ships XWARSPD XWARSHPCOST +Galleys XSHIPHOLD soldiers XGALSPD XGALSHPCOST +Merchants XSHIPHOLD civilians XMERSPD XMERSHPCOST + +Of each type, there are three classes of ships: + + ship class holds move bonus cost rate + +Light One +(2*XSIZESPD) 1 x Base +Medium Two +XSIZESPD 2 x Base +Heavy Three +0 3 x Base + +Ship maintenance will cost XSHIPMAINT per holding space on each update. +(Un)loading costs XNCITYCOST movement in cities, full movement elsewhere. +END + SHIP INFORMATION + + Ships travel in fleets which may contain up to XNMASK ships of each type +and class. The movement ability of the fleet is determined by the movement +ability of the slowest member. It is important to note that it costs 4 move +points to land a fleet and fleets with light ships may not enter deep water. + + Each ship also has a maximum crew of XSHIPCREW/hold. If the crew is +below the maximum, movement will be reduced by the percentage of crew missing +is until the ship is repaired in harbor. (via the 'C'onstruct command) + + Also, ships may be loaded (or unloaded) with armies and civilians via +the 't'ransport command. Only sailors or marines may be unloaded in +unowned sectors and only marines may be unloaded in someone else's land. +The maximum transport capability of a fleet is determined by how many +holds are in the fleet of the proper type. So, a fleet with 2 medium +merchants and 1 light galley may carry up to XSHIPHOLD soldiers and 4 +* XSHIPHOLD civilians. Loading or unloading of a fleet means the +fleet loses all remaining movement. NOTE: Due to the hazards of the +sea, some of the civilians will not survive the trip. +END + NOTES ON COMBAT + +Towns / Cities / Forts / Capitols result in bloodier battles than normal. +Battles in these sectors result in 20% more casualties on both sides (so +if there would be 30% casualties, the result is 36% casualties). Also, +special tactics may be needed in such sectors. See following page. + +You can expect to take several turns to reduce a large army, especially +in a Town or Capitol. NPC defenders will draft new troops each turn. + +Combats calculations are based on an even 1:1 battle, and then the results +are adjusted based on the calculated odds of the battle. First, an initial +roll from 0 to 100 is made with probabilities being an even gaussian +distribution. Then odds are calculated based on the number of men and their +combat strength, with better soldiers having the same weight as more men of +poorer quality. The losses given by the initial combat roll are then +adjusted by removing from the percent loss of the side the with the better +odds and adding to the percent losses of the side with unfavorable odds. +END + CITY COMBAT + +In fortified sectors, such as cities, towns, forts and capitols, armies may +perform SORTIES and SIEGES, and may RULE or be BESIEGED. + +Cities may issue special SORTIE attacks. These attacks occur as if 20% +more men are in the unit and they are also given an increase of 10% to attack +bonus. If a SORTIE unit is caught by an enemy attack it will fight at a -30% +defensive bonus. Note: once a SORTIE is sent out, it may not be recalled. + +Special SORTIE considerations and extra bonuses: + ARCHERS and CATAPULTS take only half damage due to attacking from walls. + DRAGOONS, LEGIONS and PHALANX gain +5% to attack. + LT_CAVALRY and CAVALRY gain +10% to attack. + KNIGHTS, ELEPHANTS, and AVIAN units gain +15% to attack. + Summoned MONSTERS gain an additional 5% due to shock. + +A leader unit within a fortification may decide to RULE. This unit +will not participate in any combat and may only be damaged if the +surrounding troops suffer 80% casualties. This is a good way to protect +national leaders from harm within the Capitol. +END + CITY COMBAT (page 2) + +If a unit is placed on SIEGE status and there are twice as many units on +siege as there are of the sector owners', any non flying troops will be set +to a status of BESIEGED. BESIEGED units have a movement of zero and may +only have their status changed to SORTIE. In addition, defensive bonus +for BESIEGED troops is at -20% after addition of fortification bonuses. + +An ideal method of taking a city would be to have four times the troops +inside and set half of your troops on SIEGE and half on ATTACK. + +Special Considerations for SIEGES: + SIEGE engines count triple for calculations of sieging troops. + MILITIA troops count half for calculations of besieged troops. + +The only method to take an occupied City or Capitol is to be the the only army +in the sector when the combat is *over*. This is VERY difficult, as it should +be. Fortifications can be damaged in combat by SIEGE ENGINES and CATAPULTS. +END + AN EXAMPLE OF COMBAT + +A battle occurs in 22,29 (a "good" farm) between your nation "uru" (defender) +and "edland". They have 339 infantry vs. 100 of your infantry. Your defensive +bonus is +70, their attack bonus is +40. Infantry are +0/+0. A movement bonus +goes to both sides = 5*(9-movecost)=+40. Their total bonus is 40+40+=+80. +Yours is 70+40=110. This leads to dice modifier of 30 in your favor. +The roll is 91 which becomes +91-30=61; the defenders base loss is then: +(61+30)/160*60 = 40% and the attackers base loss is then: (160-(61+30)) +/160*60 = 20%. Since the odds favor the attacker, there is a (339/10)-10 +adjustment to the defenders losses, bringing their losses to 63%. +The actual loss to each unit is troops * Percent * random / 100, where the +random is a random value between 0 and 2. For you this leads +to 84*63*(~1) / 100 = 45 men. for them it leads to 56 men. +Despite your awful luck at the dice, you still came out quite well. + +However, because they did cream you, there was a chance that you were + forced to retreat, which you did to 21 28. +END + MAIL MESSAGE FROM COMBAT + +The following is a mail message you might receive after the combat described +on the last page. + +BATTLE SUMMARY for sector 22, 29 +You are on the Defending Side + edland is attacking with army 17 (type Infantry, men 125, bonus=80) + edland is attacking with army 23 (type Infantry, men 160, bonus=80) + uru is defending with army 9 (type Infantry, men 84, bonus=110) +attacking soldiers=285 -> attackers percent loss 20% +defending soldiers=84 -> defenders percent loss 63% +ODDS are 339 to 100; ADJUSTED ROLL is 61 +RESULT: Attackers lose 56 men, Defenders lose 45 men +Additionally, All defenders retreat to 21 28 +END + NAVAL COMBAT + + Naval Combat is very similar to army combat, except that capturing +of ships is taken into account and fleets within two sectors may +participate in battle. Odds are calculated based on the amount of crews +for each ships. Warship crew is added in on a 1 to 1 basis, while Galleys +are at half that, and Merchants are halved again. Then, any soldiers on +board are added in at half strength except for ARCHERS and SAILORS which +are full strength and MARINES which are twice strength. If a nation has +SAILOR power, his crews are given a 20% bonus in strength due to better +ability. + + Finally, if a ship is damaged in combat there is a percent +chance based on the odds of combat that that ship will be captured. +At 1:1 odds, only a 15% capture chance exists; At 10:1 odds there is a +60% chance; At >60:1 odds there is a 100% chance; And then if the odds +are against the player, 1:10 has only a 1% chance of capturing, and +below that it drops to 0%. +END +DONE diff --git a/original/txt3 b/original/txt3 new file mode 100644 index 0000000..95fd055 --- /dev/null +++ b/original/txt3 @@ -0,0 +1,162 @@ + MAGIC POWERS + +Magic powers differentiate your nation from all the other nations in the +world. There are three types of powers - truly MAGICAL powers, which usually +involve summoning or spell use, CIVILIAN powers, which are related to civili- +zation and trade, and MILITARY powers, which measure your ability to make +war. + +All nations start with at least one power (based on race or class) and can +purchase additional powers by expending jewels. On the Magic Screen ('M'), +if you have enough jewels, you will be asked if you wish to buy a magic +power. + +The magic screen also permits you to see what powers you have, and to take- +over ORC nations if you are an ORC nation with the appropriate powers. +END + HOW TO GET MAGIC + +Magic powers cost jewels to obtain; the cost to obtain a power is based on +your nations magic ability. The formulae for this is to take two to the +power of the sum of the number of powers you have from that type and half the +number of other powers times your base value: + +jewel cost for civilian power = Base * 2**( #mgk/2 + #civ + #mil/2 ) + + type of power desired + race magical civilian military + elves - XEMMAG XECMAG XEWMAG + dwarves - XDMMAG XDCMAG XDWMAG + humans - XHMMAG XHCMAG XHWMAG + orcs - XOMMAG XOCMAG XOWMAG + +for example a human with 1 of each power wanting a magic power would pay + XHMMAG * 2**(1+1/2+1/2) = 4 *XHMMAG jewels +END + COMBAT TYPE POWERS + +WARRIOR +10% in combat. 1/2 Enlistment cost. +CAPTAIN +10% in combat. Can have PHALANX Units. Need WARRIOR power. +WARLORD +10% in combat. Can have LEGIONARY Units. Need CAPTAIN power. +ARCHER Can get ARCHER units. +CAVALRY Can get LIGHT & HEAVY CAVALRY units. +SAPPER CATAPULT/SIEGE @ 1/2 price & 1/2 metal. 1/2 maint. + +10% against cities/forts/capitols. +ARMOR With CAVALRY, can get KNIGHTS; Can Get ELITE Units, + -3 Move (4 Min), +20 Defense +AVIAN Use ROC and GRIFFON units. + +MONSTER POWERS The three powers below are monster powers for orc nations. + If using the Orc Takeover option, monster nations have a + chance to takeover ORC NPCs for jewels. +MINOR MONST 1 minor monster unit/spring. Can get ORCs. 1/2 spell point/turn +AVERAGE MONST 1 avg monster unit/spring. Can get URUK HAI. 1 spell point/turn +MAJOR MONST 1 major monster unit/spring. Can get TROLLs. 2 spell point/turn +END + CIVILIAN TYPE POWERS + +DERVISH Desert/ICE sectors => 1 move point, vegetation 6, +30% combat in + XDERVDESG redesignate desert/ice sectors. +HIDDEN Nobody can count troops in your armies on map. +ARCHITECT Double strength forts, Double Town revenue. +RELIGION +2 repro to 10% limit. excess adds +5% to defense. (Not ORCS). +MINER 2x metal and jewel production. Elves cant get. +URBAN +3% Birth Rate to 12% limit. remainder gives + to move (roads) +BREEDER +3% Birth Rate (ORCS ONLY) (to 14% limit). -10% combat. (no urban) + remainder adds to movement. +STEEL Additional 2x Metal Production for MINERS. +NINJA Can have Ninja units. Spys show enemy troop/civilian strength + exactly (even voids). +SAILOR 1/2 price naval units. Can use marines. Double ship speed. + sailor nations ships are immune to storms at sea. +DEMOCRACY +10% in combat (moralle) +1 Move +1 repro. +1 eatrate. Also if you + don't watch your charity level, you will give too much to the poor. +ROADS +4 to move if unit starts in your nation. +SLAVER you gain 25% of the populace of *any* sector you take over. +END + MAGICAL TYPE POWERS + +THE_VOID Nobody can see your sectors/armies (they appear blank). +KNOWALL Know all troop strengths and see the whole map (except voids). +DESTROYER Vegetation in 3 sectors of Capitol = Desert. Act as Dervish. + Note: you cant have both DESTROYER and DERVISH power. +VAMPIRE 35% of troops killed become your zombies, -35% in all combat, + All infantry/militia become zombies. Can't add to combat bonus. + Vampire Power causes all nations to go to jihad with you. +SUMMON gives 4 spell pts per turn... can summon monsters with them + Can also do spell casting. 100K Jewels and 1M gold gives + a 20% chance of gaining +1 spell point per turn. Not Dwarves. +WYZARD Gives +3 spell points. Must have SUMMON Power. +SORCERER Gives +3 spell points. Must have SUMMON Power. +END + SPELL CASTING + +If a nation has magical spell points, that nation may cast a number of +useful spells. + +The current list of spells and their costs: + +Summon -- must have SUMMON to cast this spell; cost is dependent + on the monster summoned. (see next page) +Flight -- give flight to a unit at a cost of 1 spell pt / 100 men +Enhance Attack -- 30% increase in attack at a cost of 1 spell pt / 300 men +Enhance Defense -- 30% increase in defense at a cost of 1 spell pt / 300 men + +All of the above spells except summoning have an effect area of one army unit +and a duration of one turn. Flight and the Combat Enhancements each cause +the unit to lose one movement point due to the change in status. +END + SUMMONED MONSTERS + +A monster unit represents one monster, but is the equivalent in combat of an +army of the given number of men. When summoned, they appear in your Capitol, +and are yours to command until you disband them or can not afford to pay +their per/turn jewel cost *and* 5x that cost in gold. Monsters may be +wounded in combat as can normal army units. Wounded monsters have a percent +chance of dying based on the percent damage taken (a dragon (1000 men) taking +200 equivalent men of damage has a 20% chance of dying). Next turn, however +its strength will be fully restored (1000 men again). A number of the mon- +sters will also have the ability of flight. + +Spell points can accumulate from turn to turn, but there is a 25% chance that +half your unused spell points disappear each turn.... This gives you some +incentive to use them. +END + SUMMONED MONSTER TYPES + + spell combat jewels power + points bonus move men turn prerequisites +Spirit 2 +0 x1 50 1000 +Assasin 2 +20 x1 50 400 NINJA +Efreet 2 +10 x1.5 50 400 DERVISH +Gargoyl 2 +10 x1 75 450 MI_MONST +Wraith 2 +10 x1 75 450 VAMPIRE +Hero 2 +0 x1 75 200 WARRIOR +Centaur 2 +10 x1.5 50 200 CAVALRY +Giant 5 +0 x1 150 2100 +Suphero 5 +15 x1 150 450 WARLORD +Mummy 5 +15 x1 150 1000 VAMPIRE +Elmentl 5 +5 x1.5 175 1900 SORCERER +Mintaur 5 +20 x1 150 2100 DESTROYER +Daemon 10 +50 x1 500 6000 DESTROYER +Balrog 10 +40 x1.5 500 6000 WIZARD & VAMPIRE +Dragon 15 +50 x2 1000 10000 MA_MONST & WIZARD +END + FURTHER RESTRICTIONS ON ACQUIRING MAGIC + +Note: This applies only to powers acquired during the course of the game and +not to innate powers of nations. Further, extra random powers bought by new +nations are considered to be bought on their first turn as their first +action. + +God only: KNOWALL +Orc only: MI_MONST, AV_MONST, MA_MONST, BREEDER +PC only: ARMOR, AVIAN, SAPPER, + DEMOCRACY, NINJA, ROADS, SAILOR, SLAVER, + SUMMON, WYZARD, SORCEROR +Forbidden to Dwarves: SUMMON, WYZARD, SORCEROR +Forbidden to Elves: DESTROYER, VAMPIRE, MINER +Forbidden to Orcs: RELIGION, CAVALRY +Forbidden to NPC's: CAVALRY +END +DONE diff --git a/original/txt4 b/original/txt4 new file mode 100644 index 0000000..5d8bff2 --- /dev/null +++ b/original/txt4 @@ -0,0 +1,122 @@ + SECTOR DESIGNATIONS + +For nations to make use of the sectors that they own, they +must indicate what each sector should be used for. The following +table lists sector designations and the cost for their designation: + + name symbol gold cost iron cost + ---------------- --------- --------- + ZCITY 20 * XDESCOST 5 * XDESCOST + ZCAPITOL 20 * XDESCOST 5 * XDESCOST + ZTOWN 10 * XDESCOST XDESCOST + ZFORT 10 * XDESCOST XDESCOST + ZSTOCKADE ZSTOCKCOST ---- + +All of the following designations only cost XDESCOST gold: + + ZMILL ZUNIVERSITY ZCHURCH + ZMINE ZLUMBERYARD ZSPECIAL + ZGOLD ZBLACKSMITH ZGRANARY + ZFARM ZROAD ZRUIN + ZDEVASTATED +END + DESIGNATION DESCRIPTIONS pg.1 + +ZTOWN Towns, Cities, & Capitols are your power bases. You can draft +ZCITY troops (if population > civilians / 16+(number of sectors)/2) +ZCAPITOL and can build ships here. Town tax=rate*XTAXTOWN talons/person and + City tax=rate*XTAXCITY talons/person. Both cost a lot to redesignate + AND take metal to create. They are captured only if you are the ONLY + occupant of the sector when the world is updated. Nations become + depleted if they lose their capitol. Cities, Towns, and Capitols + add to many of a nations characteristics. +ZMINE Mine: Produce (tax/100)*XTAXMETAL*Metal*People Talons & Produces + Metal Ores. Each mine you own adds to your nations mine_ability. +ZFARM Produces (tax/100)*XTAXFOOD*Vegetation*People Talons & Produces Food + Each farm you own adds to your nations farm_ability. +ZGOLD Produces (tax/100)*XTAXGOLD*Gold*People Talons & Produces Jewels +ZDEVASTATED Devastated sector. People dont like to live where devastated. +ZRUIN Ruins are devastated Cities. They may be rebuilt to cities at + half cost or for XREBUILDCOST talons may be redesignated otherwise. +END + DESIGNATION DESCRIPTIONS pg.2 + +ZFORT Expensive fortress. Cost same as town cost. Only for defense. +ZSPECIAL Produces Exotic Trade Goods - see next page. +ZSTOCKADE Stockades are minor (+10%) fortresses. They cost ZSTOCKCOST. +ZUNIVERSITY produce knowledge points (see nation attributes) +ZLUMBERYARD UNUSED +ZBLACKSMITH adds to nations mine ability +ZROAD Roads add 0.1 to communication ability. 1/2 cost to movement, + but they cost gold to maintain. You may only build 2 each turn. + You must have 100 civilians in a sector to build a road. +ZMILL 1.2x food production in one sector range if there are adequate + people in the sector. It does not produce food on its own. +ZGRANARY these "warehouses" serve as a point to store any food for the + winter. They decrease national spoilrate. +ZCHURCH add to your nations popularity and patriotism + +sector redesignation requires food ability of XDESFOOD (not forts/stockades). +Stockade, City, Town, & Fort defenses work for defenders with garrison status. +END + MINE ABILITY & WEALTH + +Mine ability impacts your nations ability to mine ores (see below), and +wealth impacts your nations ability to use specialty luxury items that +can be produced in your nation. As such, these are the most important +attributes your nation has. It is difficult to get these attibutes to +OK levels at the beginning of the game - you must work at it. + +mine ability = (people in cities,capitols,&towns)/333 + blacksmiths/167 + + (number of metal points being mined)/3 +add 15 if the nation has MINER power +add 15 if the nation has STEEL power (in addition to miner bonus) + +wealth = % of worlds gold + % of worlds jewels + % of worlds metal + + cityfolk/1000 + townfolk/2000 + +add 30 to wealth if the nation is either a trader or empire class + +The maximum wealth and mine ability is 100. +END + METAL + +Many sectors have metal ores. Nations can use these ores if they have the +appropriate mine ability. The following table details the metal type, +required mine ability, metal production value, and percentage of the world +metal sectors containing that type of metal. + + required metal world + type mine_ability value percent + copper 0 1-2 10% + lead 8 1-4 10% + tin 11 2-5 15% + bronze 15 2-5 20% + iron 25 2-8 25% + steel 30 3-10 15% + mithral 30 5-15 4% + adamantine 40 8-20 1% +END + WEALTH & JEWELS + +Jewels is the "generic" name given to any luxury items you can make in +your nation. Like iron, certain sectors have an inate ability to produce +these luxury goods, which can be used only if the nation has a high enough +wealth. The following table details the luxury good type, required wealth, +jewel value, and percentage of the world jewel sectors containing that type +of good. + + required jewel world + type wealth value percent + spice 0 1-2 20 + silver 0 1-3 20 + pearls 0 1-3 8 + dye 5 1-5 8 + silk 5 1-5 8 + gold 8 1-6 20 + rubys 8 1-6 7 + ivory 15 2-8 5 + diamonds 20 2-12 3 + platinum 25 4-20 1 +END +DONE diff --git a/original/txt5 b/original/txt5 new file mode 100644 index 0000000..a468d73 --- /dev/null +++ b/original/txt5 @@ -0,0 +1,249 @@ + SCORING & CHARACTER CLASSES + +Each nation has a types (class), which is chosen when it it is created, and +which determines how Victory points are received. Some classes start with +powers and have a starting cost. Warlord/Monster powers get all prerequisite +powers, and thus starting cost can varies. + + Per 1000 1000 100K 100K 100K Magic 10 Start + Sector People Troops Gold Jewels Metal Power Ship Cost Races Powers +king 1 1 2 3 0 0 0 0 0 HDE None +empire 1.5 0 0 1 1 0 0 0 0 HDE None +wizard 0 2 1 0 3 5 7 0 4 HE SUMMON +priest 1 1 0 0 3 0 3 0 2 H RELIGION +pirate 0 0 5 0 10 10 1 5 2 HOD SAILOR +trader 1 1 0 0 1 1 1 8 2 HE URBAN +warlord 1 1 2 0 1 1 1 0 * HOD WARLORD +demon 1 0 1 0 1 0 5 0 4 O DESTROYER +dragon 0 0 0 10 20 0 0 0 4 O MA_MONST +shadow 1 0 0 0 0 5 0 0 2 O VOID +monster 1 1 0 0 1 1 1 0 0 HDEO None +END + ADDITIONAL SCORING + +Nations can get points by having large values in their important national +attributes. This bonus to scoring is calculated as follows. + +king ( Popularity + Prestige - Poverty ) / 10 +empire ( Power + Prestige - Poverty ) / 10 +wizard ( Knowledge + Power - 50 ) / 10 +priest ( Wealth + Terror - Poverty ) / 10 +pirate ( Reputation + Wealth - 50 ) / 10 +trader ( Wealth + Prestige - Tax Rate * 5 ) / 10 +warlord ( Reputation + Prestige - 50 ) / 10 +demon ( Knowledge + Terror - 50 ) / 10 +dragon ( Wealth + Terror - 50 ) / 10 +shadow ( Power + Terror - 50 ) / 10 +END + LEADERS + +Leader units represent individual leaders and may not be merged or joined +with other leader units. + +Leaders are born (randomly created), not summoned or drafted. A new +leader will be placed in the owning players capitol. Leader types +are created based on a nations class based on the table on the next page. +They can move at double speed and ignore enemy zones of control. They +can not, however, capture land. They work by the same rules that magic +monsters do... if they take damage in combat, there is a percent chance +that they will be killed. A leader is required to be in the same sector +for an army to move at full movement rate (if no leader is present, the +unit can move only half as far). Leaders are the foundations of army +groups, and armies in a group move at +2 sectors per turn, and fight +at +20% in all combats. +END + LEADERS STATS + +Nation # Start % Born Nation combat combat Minor combat combat +Class Leaders Year Leader bonus strength Leader bonus strength + Name Name + +trader 1/4 50 KING +30 100 BARON +20 50 +king 1/4 50 KING +30 100 BARON +20 50 +empire 1/4 50 EMPEROR +30 100 PRINCE +20 50 +wizard 1/4 25 WIZARD +30 250 MAGI +20 50 +priest 1/6 25 APOSTLE +30 100 BISHOP +20 50 +pirate 1/6 25 ADMIRAL +30 100 CAPTAIN +20 50 +warlord 1/6 25 WARLORD +30 250 LORD +20 100 +demon 1/6 25 DEMON +50 250 DEVIL +20 50 +dragon 1/6 2 DRAGON +50 500 WYRM +40 100 +shadow 1/6 2 SHADOW +50 250 NAZGUL +40 120 +NPC 1/4 50 KING +30 100 BARON +20 50 +END + LOSING YOUR NATIONAL LEADER + +If you lose your nations leader, your nation is thrown into chaos. None of +your armies can move for the turn (this works for npcs too). There is a +30% chance per turn that your nation is restored to normalcy (a new leader +ascends to the throne... and you get your nations leader back). This +is a disaster to your country and is designed to knock you out of the +game for a few turns (after all - losing your king is a BIG deal). Minor +leaders are reborn at a good clip, but you should guard them because they +are important to your ability to wage war. + +Note that birth rates given on the last table are per year (not per turn). +END + EXOTIC TRADE GOODS + +Special products, or exotic trade goods, are another way to customize +your nation. Many sectors have the ability to produce these goods... +it is your choice to redesignate these sectors so as to be able to use +them. The goods in a sector are listed as "special: ?????" on the +right hand side of the screen. There are 5 levels of exotic trade +goods. Each requires prerequisite values in the nation attribute they +shall effect. If you don't have the prerequisite, you don't even know +that the good exists (surprise). + +Exotic Trade Goods are distributed to sectors at the beginning of the +game, and don't change. Each sector has XTRADEPCT% chance of having an +exotic trade good. Goods are random distributed based on the goods +value (a value 5 good occurs 1/5th as often as value 1 good). Any +sector can have any good except: + +corn,fruit - food value > 6 fish - next to water +timber,pine,oak - wood/forest + +They add ( value * sect_pop / 1000) to your nations attributes as follows: +END + WHAT GOODS EXIST pg. 1 + +There are approximately 60 different trade goods. They affects specific +national attributes WHEN the sector they are in has the correct designation. +The following lists the value, designation needed, and nation attribute +changed for each trade good. Thus, an wool sector designated as a farm +produces 3 points of popularity. Special display and redesignation options +will help you redesignate sectors to use the tradegood you desire. + +popularity fur(2,any),wool(5,farm),beer(6,farm),cloth(6,farm),wine(9,farm) +communications mules(1,town),horses(5,town),pigeons(7,town),griffons(9,town) +spoilrate pottery(1,town),salt(3,mine),timber(1,lumberyard), + granite(1,mine),pine(3,lumberyd),oak(5,lumberyd),nails(7,town) +knowledge papyrus(3,town),math(4,university),library(5,university), + drama(6,city),paper(7,town),literature(7,city), + law(8,city),philosophy(9,city) +END + WHAT GOODS EXIST pg. 2 + +farm irrigation(1,farm),oxen(2,farm),plows(3,farm) +magic mercury(5,mine),guild(7,town) +spell points magic stones(9,special) +health herbs(3,any),medicine(7,town) +terror torture(5,city),prison(7,city) + +The following trade goods add directly to a sectors food value: + corn(1,farm),fish(1,farm),sugar(3,farm),honey(3,farm),fruit(3,farm) +END + NATION ATTRIBUTES pg. 1 + +All nation attributes range from 0 to 100 except for eatrate, spoilrate, +and communications. The base figures stated below are just that. These +values may be modified by random events and by trade goods. + +tax rate Each player can control their tax rate. This number directly + impacts your revenue, but lowers your governments popularity + and increases the chances of a revolt. Anything over + 15% pretty much lose you the game when your nation revolts. +prestige National prestige. Lowers chance of military revolts. +popularity Modifies the chance of peasant revolts. You get one added + point of popularity for each sector you take. +power Relative power of your nation. +END + NATION ATTRIBUTES pg. 2 + +communications Effects leader range ( to keep units at full movement ). +wealth How wealthy is your nation +eatrate How much food each civilian can eat each turn. This is + a value in terms of food per civilian person. +storerate How much food per civilian you can store each turn. +knowledge Knowledge of the arts and sciences in your nation. +farm ability How good are you at farming. +mine ability How good are you at mining. +poverty Percent of the nation that cant eat, live, or be merry. +terror How scared people are of you. Lowers chance of revolts. +reputation How well liked is your nation. +END + FORMULAE USED FOR NATION ATTRIBUTES pg. 1 + +The formulae used to compute national attributes are listed on the next +page. Values are stored in an unsigned character (0 to 256). One real +point of communications range is gained for each 50 points of +communications, and one point of eatrate and store rate are gained per 25 +points. Other variables are normal. Aggressiveness (see below) is gained +when you change diplomatic status, and become more hostile to a nation than +they are with you. Thus, if you are neutral with phonos, and they are +hostile to you, you lose nothing by going hostile with them, but accrue 1 +point of aggressiveness by going to war with them, and 2 by going on a +jihad. Aggressiveness points accrue doubled when against a nation of the +same race as you. + +# STARTING VALUES +reputation = prestige = 50 knowledge = mine ability = farm ability = 10 +eatrate = 1.00 tax rate=10% poverty = 95% +END + FORMULAE USED FOR NATION ATTRIBUTES pg. 2 + +terror = 200*military/civilians + 200*mercenaries/military max=100 +power = 2*( % of worlds score + % of worlds military ) max=100 +reputation = reputation + rand(8) - 2 per point of aggressiveness max=100 +prestige = ( old prestige + power + wealth ) / 3 + tradegoods max=100 +tax_rate = user definable parameter +communicate = (townfolk/1000 + cityfolk/333 + tradegoods/50 + + MONEY/(5000*sctrs))/50 max=4 +farm ability= sum (sector people*foodvalue)*10/civilians + tradegoods max=100 +mine ability= see special section below +eat rate = eatrate + food remaining/(5*population) + tradegoods/25 min=1 +spoil rate = 30-(grainaries+cities+3*capitols)/sectors-tradegoods/25 min=1 +popularity = (old popularity + charity modifier + wealth + 10*eatrate + + tradegoods +2*clerics ) /2 max=100 +knowledge = cityfolk/333 + scholars/333 + townfolk/1000 + tradegoods max=100 +END + FORMULAE USED FOR NATION ATTRIBUTES pg. 3 + +charity = Is the percent of net gold given directly to the general + population. This has a direct effect of reducing poverty + by 1% for every two talons given to each person. +poverty = Poverty is a relative value of the number of talons you have + per each civilian. The inital value is determined as: + talons/civilian poverty talons/civilian poverty + < 0 95% 80-120 40%-30% + 0-30 95%-65% 120-200 30%-20% + 30-80 65%-40% > 200 20% + Poverty is then modified directly by the amount of talons given + directly to the people through charity. +inflation = inflation is an indicator as to the actual value of the national + talon. If inflation is zero percent, then it is 1:1. + Inflation is calculated as: + between 25%-125% of the tax rate [randomly determined] + plus (poverty - 50)/2 and is then adjusted by the ratio of + military to civilians. + Money lost due to inflation will be indicated in the budget. +wealth = see elsewhere. +END + ADDITIONAL MODIFIERS TO NATIONAL ATTRIBUTES + +MAGIC POWERS ADD OR SUBTRACT 10 FROM POWERS AS FOLLOWS: + SLAVER.....terror ARCHITECT..storerate + RELIGION...popularity URBAN......-popularity + DEMOCRACY..-terror ROADS......communication + KNOWALL....knowledge DESTROYER..terror + VAMPIRE....terror + +CLASSES ADD 30 TO POWERS AS FOLLOWS: + kingdom....popularity dragon.....terror + wizard.....knowledge priest.....popularity + pirate.....terror shadow.....terror + warlord....prestige demon......terror +END + REVOLTS + +Revolts are the worst thing that can happen to your nation. Revolts +occur based on the following formulae: + +probability of peasant revolt = 10*tax_rate - popularity - terror - 3*charity +probability of military revolt = 5*tax_rate - prestige + +Revolts only occur when a nation has more than 20 sectors and a +score > 20. To prevent abuse of this "charity" the maximum tax_rate +before this time is 10%. +END +DONE diff --git a/original/update.c b/original/update.c new file mode 100644 index 0000000..191a932 --- /dev/null +++ b/original/update.c @@ -0,0 +1,1622 @@ +/* Conquer: Copyright (c) 1988 by Edward M Barlow + * I spent a long time writing this code & I hope that you respect this. + * I give permission to alter the code, but not to copy or redistribute + * it without my explicit permission. If you alter the code, + * please document changes and send me a copy, so all can have it. + * This code, to the best of my knowledge works well, but it is my first + * 'C' program and should be treated as such. I disclaim any + * responsibility for the codes actions (use at your own risk). I guess + * I am saying "Happy gaming", and am trying not to get sued in the process. + * Ed + */ + +#include +#include +#include +#include +#include +#ifndef XENIX +#include +#include +#else +#include +#endif +#include "header.h" +#include "data.h" + +extern FILE *fnews; + +extern short country; +int disarray; /* TRUE if nation in disarray */ +int **attr; /* sector attractiveness */ +long **newpop; /* storage for old population */ + +long +dtol(d) double d; +{ + char tempstr[BIGLTH]; + long l; + sprintf(tempstr,"%-60.0lf",d); + sscanf(tempstr,"%ld",&l); + return(l); +} + +/****************************************************************/ +/* UPDATE() - updates the whole world */ +/****************************************************************/ +void +update() +{ + char command[BIGLTH],filename[FILELTH]; + + sprintf(filename,"%s%d",newsfile,TURN); + if ((fnews=fopen(filename,"w"))==NULL) { + printf("error opening news file\n"); + exit(FAIL); + } + check(); + + updexecs(); /*run each nation in a random order*/ + check(); + +#ifdef MONSTER + check(); + monster(); /* update monster nations */ + check(); +#endif + + check(); + combat(); /* run combat */ + check(); + updcapture(); /* capture unoccupied sectors */ + +#ifdef TRADE + uptrade(); /* update trade */ +#endif + + updmil(); /* reset military stuff for whole world */ + +#ifdef RANEVENT + randomevent(); /*run random events after setting movements */ +#endif /* RANEVENT */ + + updsectors(); /* for whole map, update one sector at a time*/ + updcomodities();/* commodities & food, metal, jewels */ + updleader(); /* new leaders are born, old leaders become wiser */ + + /* check for destroyed nations */ + for(country=1;countryMAXNEWS) { + sprintf(filename,"%s%d",newsfile,TURN-MAXNEWS); + unlink(filename); + } + + /* increase turn number by one */ + TURN++; + att_base(); /* calculate base for nation attributes */ + att_bonus(); /* calculate tradegood bonus for nation attributes */ +} + +/****************************************************************/ +/* ATTRACT() - how attractive is sector to civilians */ +/* returns attractiveness */ +/****************************************************************/ +int +attract(x,y,race) +{ + register struct s_sector *sptr = &sct[x][y]; + int designation; + int Attr = 0; + + designation=sptr->designation; + if(sptr->tradegood != TG_none + && *(tg_stype+sptr->tradegood)==designation ) { + if((designation!=DMINE) + && (designation!=DGOLDMINE)) + Attr += ( tg_value[sptr->tradegood] - '0' )*TGATTR; + } + + if(designation==DGOLDMINE){ + if(sptr->jewels>=6) Attr+=GOLDATTR*sptr->jewels*2; + else Attr+=GOLDATTR*sptr->jewels; + } else if(designation==DFARM){ + if(ntn[sptr->owner].tfood*250 <= ntn[sptr->owner].eatrate*(ntn[sptr->owner].tciv*11)) + Attr+=50*FARMATTR; + else Attr+=tofood(sptr,sptr->owner)*FARMATTR; + } + else if(designation==DCITY) Attr+=CITYATTR; + else if(designation==DCAPITOL) Attr+=CITYATTR; + else if(designation==DTOWN) Attr+=TOWNATTR; + else if(designation==DMINE) { + if(sptr->metal>6) Attr+=MINEATTR*sptr->metal*2; + else Attr+=MINEATTR*sptr->metal; + } else if((designation!=DROAD)&&(designation!=DNODESIG) + &&(designation!=DDEVASTATED)&& is_habitable(x,y) ) Attr+= OTHRATTR; + + switch(race){ + case DWARF: + if((designation==DGOLDMINE)&&(sptr->jewels>3)) + Attr += DGOLDATTR; + else if((designation==DMINE)&&(sptr->metal>3)) + Attr += DMINEATTR; + else if(designation==DTOWN) Attr += DTOWNATTR; + else if(designation==DCITY) Attr += DCITYATTR; + else if(designation==DCAPITOL) Attr += DCITYATTR; + + if(sptr->vegetation==WOOD) Attr += DWOODATTR; + else if(sptr->vegetation==FOREST) Attr += DFOREATTR; + + if(sptr->altitude==MOUNTAIN) Attr += DMNTNATTR; + else if(sptr->altitude==HILL) Attr += DHILLATTR; + else if(sptr->altitude==CLEAR) Attr += DCLERATTR; + else Attr=0; + break; + case ELF: + if((designation==DGOLDMINE)&&(sptr->jewels>3)) + Attr += EGOLDATTR; + else if((designation==DMINE)&&(sptr->metal>3)) + Attr += EMINEATTR; + else if(designation==DTOWN) Attr += ECITYATTR; + else if(designation==DCITY) Attr += ECITYATTR; + else if(designation==DCAPITOL) Attr += ECITYATTR; + + if(sptr->vegetation==WOOD) Attr += EWOODATTR; + else if(sptr->vegetation==FOREST) Attr += EFOREATTR; + + if(sptr->altitude==MOUNTAIN) Attr += EMNTNATTR; + else if(sptr->altitude==HILL) Attr += EHILLATTR; + else if(sptr->altitude==CLEAR) Attr += ECLERATTR; + else Attr=0; + break; + case HUMAN: + if((designation==DGOLDMINE)&&(sptr->jewels>3)) + Attr += HGOLDATTR; + else if((designation==DMINE)&&(sptr->metal>3)) + Attr += HMINEATTR; + else if(designation==DTOWN) Attr += HCITYATTR; + else if(designation==DCITY) Attr += HCITYATTR; + else if(designation==DCAPITOL) Attr += HCITYATTR; + + if(sptr->vegetation==WOOD) Attr += HWOODATTR; + else if(sptr->vegetation==FOREST) Attr += HFOREATTR; + + if(sptr->altitude==MOUNTAIN) Attr += HMNTNATTR; + else if(sptr->altitude==HILL) Attr += HHILLATTR; + else if(sptr->altitude==CLEAR) Attr += HCLERATTR; + else Attr=0; + break; + case ORC: + if((designation==DGOLDMINE)&&(sptr->jewels>3)) + Attr += OGOLDATTR; + else if((designation==DMINE)&&(sptr->metal>3)) + Attr += OMINEATTR; + else if(designation==DTOWN) Attr += OCITYATTR; + else if(designation==DCITY) Attr += OCITYATTR; + else if(designation==DCAPITOL) Attr += OCITYATTR; + + if(sptr->vegetation==WOOD) Attr += OWOODATTR; + else if(sptr->vegetation==FOREST) Attr += OFOREATTR; + + if(sptr->altitude==MOUNTAIN) Attr += OMNTNATTR; + else if(sptr->altitude==HILL) Attr += OHILLATTR; + else if(sptr->altitude==CLEAR) Attr += OCLERATTR; + else Attr=0; + break; + default: + break; + } + if((designation==DDEVASTATED)||(Attr<0)||(movecost[x][y]<0)) Attr=0; + return(Attr); +} +/****************************************************************/ +/* ARMYMOVE() */ +/* armymove moves an army... and returns the # of sectors taken */ +/****************************************************************/ +int +armymove(armynum) +int armynum; +{ + long sum, where; +#ifdef XENIX + register int z; +#endif /*XENIX*/ + register int x, y; + int i; + long menok; /* enough men in the army? */ + int leadflag=FALSE; /* leader w/o group */ + int takesctr=FALSE; /* takesctr is # unowned sctrs*/ + + if(P_ASTAT>=NUMSTATUS || P_AMOVE==0) return(takesctr); + + /* if leader w/o a group, set leadflag */ + if((P_ATYPE>=MINLEADER)&&(P_ATYPEclass)-1 ){ + P_AXLOC=curntn->capx; + P_AYLOC=curntn->capy; + P_ASTAT=RULE; + return(takesctr); + } + } + + sum=0; + if(leadflag) { /* Move based on unattached soldiers */ + for(i=0;iarm[i].unittyparm[i].stat!=MILITIA ) + &&( curntn->arm[i].stat!=ONBOARD ) + &&( curntn->arm[i].stat!=GARRISON ) + &&( curntn->arm[i].stat!=TRADED ) + &&( curntn->arm[i].statarm[i].sold; + } else { /* not leader w/o group */ + /* use menok as a temp vbl now == men in army */ + menok=0; + if((P_ATYPE>=MINLEADER) + &&(P_ATYPEarm[x].stat==(NUMSTATUS+armynum)) + && (curntn->arm[x].unittyp TAKESECTOR ) + ||( P_ATYPE>=MINLEADER)) menok=TRUE; + else menok=FALSE; + /* range of 4 if menok is FALSE else 2 */ + for(x=(int)P_AXLOC-4+menok*2;x<=(int)P_AXLOC+4-menok*2;x++) + for(y=(int)P_AYLOC-4+menok*2;y<=(int)P_AYLOC+4-menok*2;y++) { + if(ONMAP(x,y)) { + if( menok==TRUE || ISCITY(sct[x][y].designation) ) + sum+=attr[x][y]; + } + } + } + + if(sum==0) { /* nowhere to go */ + P_AXLOC=curntn->capx; + P_AYLOC=curntn->capy; + P_ASTAT=DEFEND; + } else if(leadflag) { /* find leader a group! */ + where=rand()%sum; + for(x=0;xarm[x].unittyparm[x].stat!=MILITIA ) + &&( curntn->arm[x].stat!=GARRISON ) + &&( curntn->arm[x].stat!=ONBOARD ) + &&( curntn->arm[x].stat!=TRADED ) + &&( curntn->arm[x].statarm[x].sold) <= 0) { + P_AXLOC=curntn->arm[x].xloc; + P_AYLOC=curntn->arm[x].yloc; + break; + } + } + if(x!=MAXARM) for(x=0;xarm[x].unittyparm[x].statarm[x].sold>=0 ) + &&( curntn->arm[x].stat!=MILITIA ) + &&( curntn->arm[x].stat!=GARRISON ) + &&( curntn->arm[x].stat!=SIEGED ) + &&( curntn->arm[x].stat!=SCOUT ) + &&( curntn->arm[x].stat!=ONBOARD ) + &&( curntn->arm[x].stat!=TRADED ) + &&( curntn->arm[x].unittyp!=A_ZOMBIE ) + &&( P_AXLOC==curntn->arm[x].xloc ) + &&( P_AYLOC==curntn->arm[x].yloc )){ + curntn->arm[x].stat=NUMSTATUS+armynum; + P_ASTAT=GENERAL; + break; + } + } + } else { /* move a normal unit */ + where=rand()%sum; + /* range of 4 if menok is FALSE else 2 */ + for(x=(int)P_AXLOC-4+menok*2;x<=(int)P_AXLOC+4-menok*2;x++) + for(y=(int)P_AYLOC-4+menok*2;y<=(int)P_AYLOC+4-menok*2;y++) + if(ONMAP(x,y)){ + if( menok==TRUE || ISCITY(sct[x][y].designation) ) + where -= attr[x][y]; + if( (where < 0 ) + && movecost[x][y]>=1 + && movecost[x][y]<=P_AMOVE + &&(land_reachp((int)P_AXLOC,(int)P_AYLOC,x,y,P_AMOVE,country))){ + P_AXLOC=x; + P_AYLOC=y; + if(P_ATYPE == getleader(curntn->class)-1 ){ + P_AXLOC=curntn->capx; + P_AYLOC=curntn->capy; + } + + /* ARMIES MOVE PSEUDO INDEPENDANTLY */ + if((sct[x][y].designation != DCITY) + &&(sct[x][y].designation != DCAPITOL) + &&(sct[x][y].designation != DTOWN) + &&(sct[x][y].owner==country)) { +#ifdef XENIX + z = attr[x][y]; + z /= 8; + attr[x][y] = z; +#else + attr[x][y] /= 8; +#endif /*XENIX*/ + } + if(sct[x][y].owner==0){ + sct[x][y].owner=country; + if (curntn->popularitypopularity++; +#ifdef XENIX + z = attr[x][y]; + z /= 8; + attr[x][y] = z; +#else + attr[x][y]/=8; +#endif /*XENIX*/ + takesctr++; + } + + if((P_ATYPE>=MINLEADER)&&(P_ASTAT==GENERAL)) + for(x=0;xarm[x].sold>0 ) + &&( curntn->arm[x].stat==armynum+NUMSTATUS)){ + curntn->arm[x].xloc=P_AXLOC; + curntn->arm[x].yloc=P_AYLOC; + } + return(takesctr); + } /* if */ + } /* for for */ + + /*do again - have this block if lots of bad terrain*/ + /*what could happen is that it won't find a move first time*/ + for(x=(int)P_AXLOC-2;x<=(int)P_AXLOC+2;x++) + for(y=(int)P_AYLOC-2;y<=(int)P_AYLOC+2;y++) { + if(!ONMAP(x,y)) + continue; + + if(leadflag) where -= solds_in_sector(x,y,country); + else where -= attr[x][y]; + if( (where < 0 ) + && movecost[x][y]>=1 + && movecost[x][y]<=P_AMOVE + &&(land_reachp(P_AXLOC,P_AYLOC,x,y,P_AMOVE,country))){ + P_AXLOC=x; + P_AYLOC=y; + if(sct[x][y].owner==0){ + if (curntn->popularitypopularity++; + sct[x][y].owner=country; + attr[x][y] = 1; + takesctr++; + } + if((P_ATYPE>=MINLEADER)&&(P_ASTAT==GENERAL)) + for(i=0;iarm[i].sold>0 ) + &&( curntn->arm[i].stat==armynum+NUMSTATUS)){ + curntn->arm[i].xloc=P_AXLOC; + curntn->arm[i].yloc=P_AYLOC; + } + return(takesctr); + } /* if */ + } /* for for */ + } /* if */ + return(takesctr); +} + +/****************************************************************/ +/* SCORE() */ +/* score updates the scores of all nations */ +/****************************************************************/ +void +score() +{ + int x; + printf("\nUpdating nation's scores\n"); + for(x=1;xntn[x].dplus) ntn[x].dplus+=1; + else ntn[x].aplus+=1; + printf("npc cheat routine - add 1%% to nation %s combat skill\n",ntn[x].name); + } + + /* cheat by making npc's frendlier to each other if they are */ + /* of the same race */ + for(x=1;xactive == INACTIVE) continue; + + printf("updating nation number %d -> %s\n",country,curntn->name); + check(); + + disarray=FALSE; +#ifdef TRADE + if(isntn(curntn->active)) checktrade(); +#endif /* TRADE */ + + /*if execute is 0 and PC nation then they did not move*/ + if((execute(TRUE)==0)&&(ispc(curntn->active))){ + printf("\tnation %s did not move\n",curntn->name); +#ifdef NPC +#ifdef CMOVE + printf("\tthe computer will move for %s\n",curntn->name); + fprintf(fnews,"1.\tthe computer will move for %s\n",curntn->name); + if (mailopen( country )!=(-1)) { + fprintf(fm,"Message to %s from CONQUER\n\n",curntn->name); + fprintf(fm,"The computer moved for you in the %s of Year %d\n",PSEASON(TURN),YEAR(TURN)); + mailclose(country); + } + check(); + nationrun(); + check(); +#endif /*CMOVE*/ + } + /* run npc nations */ + if(isnpc(curntn->active)) { + check(); + nationrun(); + check(); +#ifdef ORCTAKE + /*do npc nation magic*/ + if(magic(country,MA_MONST)==TRUE) { + if((x=takeover(5,0))==1) + printf("SUCCESSFUL TAKEOVER OF %d by %s",x,curntn->name); + } else if(magic(country,AV_MONST)==TRUE) { + if((x=takeover(3,0))==1) + printf("SUCCESSFUL TAKEOVER OF %d by %s",x,curntn->name); + } else if(magic(country,MI_MONST)==TRUE){ + if((x=takeover(1,0))==1) + printf("SUCCESSFUL TAKEOVER OF %d by %s",x,curntn->name); + } +#endif /* ORCTAKE */ +#endif /*NPC*/ + } + + /* is leader killed - put nation into disarray */ + disarray=TRUE; + x = getleader((int)curntn->class) - 1; + for(armynum=0;armynum0) { + disarray=FALSE; + break; + } +#ifdef DEBUG +printf("checking for leader in nation %s: armynum=%d\n",curntn->name,armynum); +#endif /* DEBUG */ + + if(disarray == TRUE) { + if(rand()%100 < 30) { /* new leader takes over */ + x++; + for(armynum=0;armynum 0) break; + if( armynumname); + fprintf(fnews,"1.\tnation %s has a new leader\n",curntn->name); + if(ispc(curntn->active)){ + if (mailopen(country)!=(-1)) { + fprintf(fm,"MESSAGE FROM CONQUER:\n\n"); + fprintf(fm,"YOU HAVE A NEW NATIONAL LEADER.\n"); + fprintf(fm,"YOUR TROOPS MAY NOW MOVE NORMALLY.\n"); + mailclose(country); + } + } + } + } + } + + if( disarray == TRUE) { + fprintf(stderr,"no leader in nation %s\n",curntn->name); + fprintf(fnews,"1.\tnation %s still has no national leader\n",curntn->name); + if(ispc(curntn->active)){ + if (mailopen(country)!=(-1)) { + fprintf(fm,"MESSAGE FROM CONQUER\n\n"); + fprintf(fm,"YOU DON'T HAVE A COUNTRY LEADER;\n"); + fprintf(fm,"YOUR TROOPS MAY NOT MOVE\n"); + fprintf(fm,"THERE IS A 30%% CHANCE/TURN OF GETTING A NEW ONE\n"); + mailclose(country); + } + } + } + + updmove(curntn->race,country); /*update movement array*/ + + /* Recalculate ATTR MATRIX for civilians */ + /*calculate sector attractiveness*/ + for(x=0;xowner==country) + &&(tofood(sptr,sptr->owner)!=0)){ + attr[x][y]=attract(x,y,curntn->race); + } else attr[x][y]=0; + } + + /*if near capitol add to attr*/ + for(x=(int)curntn->capx-2;x<=(int)curntn->capx+2;x++) + for(y=(int)curntn->capy-2;y<=(int)curntn->capy+2;y++) + if((ONMAP(x,y))&&(attr[x][y]>0)) attr[x][y]+=20; + move_people(); + + } /* for */ + + /*zero out all recalculated values; do not clear god */ + for(country=1;country0)) { + P_AMOVE =20; /* just in case god wants to move them */ + /* increase population */ +#ifdef XENIX + x = P_ASOLD * 102; + x /= 100; + P_ASOLD = x; +#else + P_ASOLD*=102; + P_ASOLD/=100; +#endif /*XENIX*/ + if(armynum%2==0) { + if(P_ASTAT!=SIEGED) P_ASTAT=GARRISON; + } else { + if(ntn[country].arm[armynum-1].sold<=0) { + P_ASOLD=0; + continue; + } + P_AXLOC = ntn[country].arm[armynum-1].xloc; + P_AYLOC = ntn[country].arm[armynum-1].yloc; + /* try to relieve sieges */ + if(P_ASTAT!=SIEGED + && ntn[country].arm[armynum-1].stat!=SIEGED) { + for(i=(int)ntn[country].arm[armynum-1].xloc-1;i<=ntn[country].arm[armynum-1].xloc+1;i++) { + for(j=(int)ntn[country].arm[armynum-1].yloc-1;j<=ntn[country].arm[armynum-1].yloc+1;j++) { + if(ONMAP(i,j) + &&(sct[i][j].altitude!=WATER) + &&(sct[i][j].altitude!=PEAK) + &&(sct[i][j].owner != country) + &&(rand()%3==0)){ + P_AXLOC = i; + P_AYLOC = j; + } + } + } + } + /* this cheats by giving garrison bonus with movement */ + if((sct[P_AXLOC][P_AYLOC].designation==DFORT) + &&(sct[P_AXLOC][P_AYLOC].owner==country)) { + if(P_ASTAT!=SIEGED) P_ASTAT=GARRISON; + } else P_ASTAT=ATTACK; + } + } +#ifdef DEBUG + for(armynum=0;armynum0)&&(sct[P_AXLOC][P_AYLOC].altitude==WATER)) + printf("ERROR line %d... %s army %d in water (army %d: x: %d y: %d)\n",__LINE__,ntn[country].name,armynum,armynum-1, ntn[country].arm[armynum-1].xloc, ntn[country].arm[armynum-1].yloc); + } +#endif /* DEBUG */ +} + +/****************************************************************/ +/* UPDCAPTURE() */ +/* capture unoccupied sectors */ +/****************************************************************/ +void +updcapture() +{ + register struct s_sector *sptr; + int armynum, occval; + + fprintf(fnews,"3\tNEWS ON WHAT SECTORS HAVE BEEN CAPTURED\n"); + printf("distributing captured sectors\n"); + + /*look for any areas where armies alone in sector*/ + prep(0,-1); + + for(country=1;countryactive)&&(P_ASOLD>=TAKESECTOR)) + ||((isnotpc(curntn->active))&&(P_ASOLD>75))){ + /* may not capture land while on a fleet */ + if(P_ASTAT==ONBOARD) continue; + /* may not capture water */ + if(sct[P_AXLOC][P_AYLOC].altitude==WATER) { + fprintf(stderr,"Nation %s Army %d in Water\n",curntn->name,armynum); + continue; + } + if(occ[P_AXLOC][P_AYLOC] != country) continue; + sptr = &sct[P_AXLOC][P_AYLOC]; + if(sptr->owner==0){ + sptr->owner=country; + if (curntn->popularitypopularity++; + } else if((sptr->owner!=country) + &&(curntn->dstatus[sptr->owner]>=WAR)) { + if(ntn[sptr->owner].race!=curntn->race) + if(magic(country,SLAVER)==TRUE){ + flee(P_AXLOC,P_AYLOC,1,TRUE); + } else { + flee(P_AXLOC,P_AYLOC,1,FALSE); + } + + if((isntn( curntn->active )) + &&(isntn( ntn[sptr->owner].active))) { +#ifdef HIDELOC + fprintf(fnews,"3.\tarea captured by %s from %s\n",curntn->name,ntn[sptr->owner].name); +#else + fprintf(fnews,"3.\tarea %d,%d captured by %s from %s\n",P_AXLOC,P_AYLOC,curntn->name,ntn[sptr->owner].name); +#endif /* HIDELOC */ + } + sptr->owner=country; + curntn->popularity++; + } + } + } else if(P_ASTAT==A_SCOUT && P_ATYPE!=A_SPY && P_ASOLD>0) { + occval=occ[P_AXLOC][P_AYLOC]; + /* capture situations: + * - alone with a hostile army [PFINDSCOUT% chance] + * - alone in someone else's territory with one of + * their armies (non-allied) [(PFINDSCOUT/5)% chance] + * NOTE: do not remove chance to capture in unmet territory. + */ + if (occval!=0 && occval!=country && occval=HOSTILE) + &&(rand()%100active)) { + if(mailopen(country)!=(-1)) { + fprintf(fm,"Message from Conquer\n\n"); + fprintf(fm,"\tYour Scouting Unit %d was captured\n",armynum); + fprintf(fm,"\t by %s military in sector %d,%d\n", + ntn[occval].name,(int)P_AXLOC,(int)P_AYLOC); + mailclose(country); + } + } + if (ispc(ntn[occval].active)) { + if(mailopen(occval)!=(-1)) { + fprintf(fm,"Message from Conquer\n\n"); + fprintf(fm,"\tA Scout from nation %s was captured\n",curntn->name); + fprintf(fm,"\t in sector %d,%d.\n",(int)P_AXLOC,(int)P_AYLOC); + mailclose(occval); + } + } + } + } + } + } + + /* capture countries */ + for(country=1;countryowner == 0) continue; + nptr = &ntn[sptr->owner]; + + /* add to contents of sector */ + if(rand()%100repro/4; + if ((SEASON(TURN)!=WINTER) && + (SEASON(TURN)<=(nptr->repro%4))) + rephold++; + + /* only one capitol per nation */ + if (sptr->designation==DCAPITOL) { + if (nptr->capx!=x || nptr->capy!=y) { + sptr->designation=DCITY; + } + } + + /* if huge number dont reproduce */ + if(sptr->people >= ABSMAXPEOPLE) { + sptr->people = ABSMAXPEOPLE; + if(sptr->people * sptr->metal > 2*(rand()%100)*TOMUCHMINED) + if(sptr->designation==DMINE) sptr->metal--; + if(sptr->people * sptr->jewels > 2*(rand()%100)*TOMUCHMINED) + if(sptr->designation==DGOLDMINE) sptr->jewels--; + } else if((sptr->people > TOMANYPEOPLE) + &&(sptr->designation!=DTOWN) + &&(sptr->designation!=DCAPITOL) + &&(sptr->designation!=DCITY)){ + sptr->people += (rephold * sptr->people)/200; + if(sptr->people > ABSMAXPEOPLE) + sptr->people = ABSMAXPEOPLE; + if(sptr->people * sptr->metal > 2*(rand()%100)*TOMUCHMINED) + if(sptr->designation==DMINE) sptr->metal--; + if(sptr->people * sptr->jewels > 2*(rand()%100)*TOMUCHMINED) + if(sptr->designation==DGOLDMINE) sptr->jewels--; + } else if(sptr->people<100) { + sptr->people+=sptr->people/10; + } else { + sptr->people += (rephold * sptr->people)/100; + if(sptr->people * sptr->metal > (rand()%100)*TOMUCHMINED) + if(sptr->designation==DMINE) sptr->metal--; + if(sptr->people * sptr->jewels > (rand()%100)*TOMUCHMINED) + if(sptr->designation==DGOLDMINE) sptr->jewels--; + } + /* if no metal/gold left, remove tradegood */ + if(((sptr->designation==DGOLDMINE)&&(sptr->jewels==0)) + ||((sptr->designation==DMINE)&&(sptr->metal==0))){ + sptr->tradegood = TG_none; + sptr->designation = DDEVASTATED; + } + + /*check all adjacent sectors and decide if met */ + for(i=x-MEETNTN;i<=x+MEETNTN;i++) + for(j=y-MEETNTN;j<=y+MEETNTN;j++) + if(ONMAP(i,j)&&(sct[i][j].owner!=0)) { + if(sptr->owner!=sct[i][j].owner) { + if(nptr->dstatus[sct[i][j].owner]==UNMET) + newdip(sptr->owner,sct[i][j].owner); + if(ntn[sct[i][j].owner].dstatus[sptr->owner]==UNMET) + newdip(sct[i][j].owner,sptr->owner); + } + } + + /* if desert sector... reverts to desert */ + if(tofood(sptr,sptr->owner)designation != DSTOCKADE) + &&(sptr->designation != DFORT) + &&(sptr->designation != DROAD)) + sptr->designation=DNODESIG; + } + } + + for(country=1;countryactive)){ + + /* check for depletion of country through */ + /* lack of a capitol */ + if((sct[curntn->capx][curntn->capy].designation!=DCAPITOL) + ||(sct[curntn->capx][curntn->capy].owner!=country)) { + + printf("depleting nation %s\n",curntn->name); + deplete(country); + } + + spreadsheet(country); + if ((int)curntn->popularity-2*curntn->inflation < (int)MAXTGVAL) { + curntn->popularity = max(0,(int)(curntn->popularity-2*curntn->inflation)); + } else curntn->popularity = (char) MAXTGVAL; + curntn->tsctrs = spread.sectors; + curntn->tciv=spread.civilians; + curntn->tfood=spread.food; + + /* take out for charity */ + charity=((spread.gold-curntn->tgold)*curntn->charity)/100; + + if(charity < 0) charity = 0; + curntn->tgold = spread.gold - charity; + + if(curntn->tciv > 0) charity /= curntn->tciv; + else charity = 0; + + /* calculate poverty base */ + if (curntn->tgold < 0L) { + curntn->poverty = 95; + } else if (curntn->tciv < 100L) { + /* give some check on civilians */ + curntn->poverty = (unsigned char)20; + } else if (curntn->tgold/curntn->tciv < 30L) { + curntn->poverty = (unsigned char)(95L - curntn->tgold/curntn->tciv); + } else if (curntn->tgold/curntn->tciv < 80L) { + curntn->poverty = (unsigned char)(65L - (curntn->tgold/curntn->tciv-30L)/2L); + } else if (curntn->tgold/curntn->tciv < 120L) { + curntn->poverty = (unsigned char)(40L - (curntn->tgold/curntn->tciv-80L)/4L); + } else if (curntn->tgold/curntn->tciv < 200L) { + curntn->poverty = (unsigned char)(30L - (curntn->tgold/curntn->tciv-120L)/8L); + } else { + curntn->poverty = (unsigned char)20; + } + + /* charity increase to popularity */ + curntn->popularity = min(curntn->popularity+5*charity,MAXTGVAL); + + /* charity adjustment to poverty; rounding upward */ + if(curntn->poverty < (charity+1)/2 ) + curntn->poverty = 0; + else curntn->poverty -= (charity+1)/2; + + /* Calculate inflation base */ + if(curntn->inflation > 0) + curntn->inflation = rand()%(curntn->inflation/2+1); + else curntn->inflation = 0; + curntn->inflation += (curntn->tax_rate/4 + (rand()%(curntn->tax_rate*3/4+1))); + + /* adjustment for military */ + if (spread.civilians>0) + curntn->inflation += ((curntn->tmil*100/spread.civilians - 15)/5); + /* adjustment for poverty */ + curntn->inflation += (curntn->poverty-50)/2; + + /* plus maybe an adjustment for jewel production as a ratio */ + /* for whatever is produced by the country. */ + + /* now find new total gold talons in nations*/ + if (curntn->tgold > 1000000L) { + curntn->tgold = (curntn->tgold / + (400L + curntn->inflation)) * 400L; + } else { + curntn->tgold = (curntn->tgold * 400L) / + (400L + curntn->inflation); + } + + /* provide goods production */ + curntn->metals=spread.metal; + curntn->jewels=spread.jewels; + } + } +} + +/****************************************************************/ +/* UPDMIL() */ +/* reset military stuff */ +/****************************************************************/ +#define MAXSIEGE (NTOTAL) +void +updmil() +{ + struct army *A; + int AX, AY, AT; /* armies x,y locations, type : for speed */ + int armynum,nvynum,flag,dfltunit; + int army2,asmen,dsmen,nation,sieges=0; + unsigned char siegex[MAXSIEGE],siegey[MAXSIEGE],siegok[MAXSIEGE]; + + fprintf(stderr,"updating armies and navies\n"); + for(country=1;countryclass)-1); + for(armynum=0;armynum0) { + disarray=FALSE; + break; + } + + if(ispc(curntn->active)) { + prep( country, TRUE ); /* occ[][] now >0 if leader near */ + dfltunit = defaultunit(country); + } else dfltunit = A_INFANTRY; + + for(armynum=0;armynum0) { + + A = &curntn->arm[armynum]; + AX = A->xloc; + AY = A->yloc; + if(A->unittyp==A_INFANTRY) + A->unittyp = dfltunit; + AT=A->unittyp; + + if( AT< MINLEADER ) { + curntn->tmil+=A->sold; + if( AT==A_MILITIA ) A->stat=MILITIA; + } + + /* if group does not have a leader anymore */ + if((A->stat >= NUMSTATUS) + &&((curntn->arm[A->stat-NUMSTATUS].unittyparm[A->stat-NUMSTATUS].sold==0))) { + A->stat=ATTACK; + } + flag=TRUE; + + /*add movement to all armies */ + /*unitmove is 10 times movement rate*/ + if(disarray) A->smove=0; + else switch(A->stat) { + case MARCH: + A->smove=(curntn->maxmove * *(unitmove+(AT%UTYPE)))/5; + break; + case MILITIA: + case ONBOARD: + A->smove=0; + break; + case SIEGE: + if((sct[AX][AY].owner!=country) + &&(fort_val(&sct[AX][AY]) > 0)) { + A->smove=0; + flag=FALSE; + for (army2=0;flag==FALSE && army2 2*dsmen) { + siegok[sieges]=TRUE; + sieges++; + /* keep SIEGE status */ + break; + } + } else { + /* keep SIEGE status */ + if (siegok[army2-1]==TRUE) break; + } + } + flag=FALSE; + /* should drop through to defend reset */ + case GARRISON: + if((flag==TRUE) + &&(fort_val(&sct[AX][AY]) > 0) + &&(sct[AX][AY].owner==country)) { + A->smove=0; + P_AMOVE=0; + break; + } + flag=FALSE; + /* reset to defend for improper garrison */ + case RULE: + if((flag==TRUE) + &&(ISCITY(sct[AX][AY].designation)) + &&(AT>=MINLEADER)&&(ATsmove=0; + break; + } + /* reset to defend for improper Rule */ + case SIEGED: + case SORTIE: + /* reset besieged or sortie troops to DEFEND */ + case FLIGHT: + case MAGDEF: + case MAGATT: + /* reset magical stats to DEFEND */ + A->stat=DEFEND; + default: + A->smove=(curntn->maxmove * *(unitmove+(AT%UTYPE)))/10; + break; + } + + /* empower flight */ + if((avian(AT)==TRUE) + &&( A->stat!=ONBOARD ) + &&( A->statstat=FLIGHT; + + if((magic(country,ROADS)==TRUE) + &&(sct[AX][AY].owner!=country)){ + if(A->smove>7) A->smove-=4; + else if (A->smove>4) A->smove=4; + } + + if((magic(country,SAPPER)==1) + &&((AT==A_CATAPULT)||(AT==A_SIEGE))){ + curntn->tgold -= A->sold * (*(unitmaint+(AT))) / 2; + } else if (ATtgold -= A->sold * (*(unitmaint+(AT%UTYPE))); + if((ispc(ntn[country].active)) + &&(occ[AX][AY] == 0)) + A->smove /= 2; + } else if (AT>=MINMONSTER) { + curntn->tgold -= 5L * (*(unitmaint+(AT%UTYPE))); + if(curntn->jewels > (*(unitmaint+(AT%UTYPE)))) + curntn->jewels -= (long) (*(unitmaint+(AT%UTYPE))); + else { + if(ispc(curntn->active)) { + if(mailopen(country)!=(-1)) { + fprintf(fm,"Message to %s from Conquer\n\n",curntn->name); + fprintf(fm,"Your %s (unit %d) leaves due to lack of jewels\n", + *(unittype+(AT%UTYPE)),armynum); + mailclose(country); + A->sold=0; + } + } + } + } + } + /* group moves at rate of slowest +2 */ + for(armynum=0;armynum0)){ + flag=FALSE; + for(nvynum=0;nvynumarm[nvynum].sold>0) + &&(curntn->arm[nvynum].stat==armynum+NUMSTATUS)){ + flag=TRUE; + if(P_AMOVE > curntn->arm[nvynum].smove) + P_AMOVE = curntn->arm[nvynum].smove; + } + } + if(flag==FALSE) P_ASTAT=DEFEND; + else P_AMOVE+=2; + } + /*add to movement of fleets*/ + for(nvynum=0;nvynumname); +#else + fprintf(fnews,"3.\tstorm sinks %s fleet in %d,%d\n",curntn->name,P_NXLOC,P_NYLOC); +#endif /* HIDELOC */ + P_NWSHP=0; + P_NMSHP=0; + P_NGSHP=0; + armynum=P_NARMY; + if(armynum>=0&&armynum=0&&armynumtships += fltships(country,nvynum); + curntn->tgold -= flthold(nvynum)*SHIPMAINT; + } else { + P_NWSHP=0; + P_NMSHP=0; + P_NGSHP=0; + } + } /* for */ + } + fprintf(stderr,"doing sieges\n"); + + /* kill movement on SIEGED troops */ + for(army2=0;army2name); +#else + fprintf(fnews,"2.\tNation %s under siege in sector %d,%d\n", + curntn->name,siegex[army2],siegey[army2]); +#endif /* HIDELOC */ + if(ispc(curntn->active)) { + if (mailopen( country )!=(-1)) { + fprintf(fm, "Message to %s from Conquer\n\n",ntn[nation].name); + fprintf(fm, "\tYou are under siege in sector %d,%d.\n", + siegex[army2],siegey[army2]); + mailclose(country); + } + } + for(armynum=0;armynum0){ + if(P_ASTAT!=FLIGHT&&(P_AXLOC==siegex[army2]) + &&(P_AYLOC==siegey[army2])) { + P_AMOVE=0; + if((P_ASTAT!=ONBOARD)&&(P_ASTAT!=RULE)&&(P_ASTAT!=TRADED)) + P_ASTAT=SIEGED; + } + } + } + printf("done with military\n"); +} + +/****************************************************************/ +/* UPDCOMODITIES() */ +/* update commodities */ +/****************************************************************/ +void +updcomodities() +{ + register struct s_sector *sptr; + register int x,y; + long xx; + float tempflt; + long dead; + + fprintf(fnews,"2\tWORLD ECONOMY & DECLARATIONS OF WAR\n"); + printf("working on world economy\n"); + for(country=1;countrytfood-=curntn->tmil*P_EATRATE*2; + curntn->tfood-=curntn->tciv*P_EATRATE; + + /*starve people*/ + if(curntn->tfood<0) for(x=0;xowner==country) + &&((sptr->designation==DTOWN) + ||(sptr->designation==DCAPITOL) + ||(sptr->designation==DCITY)) + &&(curntn->tfood<0)){ + /*lose one person in city per three food*/ + /*maximum of 1/3 people in city lost*/ + if(sptr->people < curntn->tfood){ + sptr->people+=curntn->tfood/3; + curntn->tfood=0; + } else { + curntn->tfood+=sptr->people; + dead = sptr->people/3; + sptr->people -= dead; + } +#ifdef HIDELOC + fprintf(fnews,"2.\tfamine hits town in %s.\n",curntn->name); +#else + fprintf(fnews,"2.\tfamine hits town at %d,%d in %s.\n",x,y,curntn->name); +#endif /* HIDELOC */ + printf("famine hits town at %d,%d in %s.\n",x,y,curntn->name); + if(ispc(curntn->active)){ + if (mailopen( country )!=(-1)) { + fprintf(fm,"Message to %s from CONQUER\n\n",curntn->name); + fprintf(fm,"During the %s of Year %d,\n",PSEASON(TURN),YEAR(TURN)); + fprintf(fm,"a famine hit your town at %d,%d.\n",x,y); + fprintf(fm,"%d out of %d people died.\n",dead,sptr->people); + mailclose(country); + } + } + } + } + /*this state can occur if few people live in cities*/ + if(curntn->tfood<0) curntn->tfood=0L; + tempflt = (float) curntn->tfood * (100-curntn->spoilrate); + curntn->tfood = (long) (tempflt / 100.0); + + if((0.0+curntn->tgold) - GOLDTHRESH*(0.0+curntn->jewels) > 0.0){ + /* buy jewels off commodities board */ + xx=curntn->tgold-GOLDTHRESH*curntn->jewels; + if (ispc(curntn->active)) { + if (mailopen(country)!=(-1)) { + fprintf(fm,"Message from Conquer\n\n"); + fprintf(fm,"Gold imbalance forced your treasury to purchase\n"); + fprintf(fm,"%ld jewels for %ld gold talons to compensate.\n", + dtol((double)xx*GODJEWL/GODPRICE) + ,xx); + mailclose(country); + } + } + curntn->jewels += dtol((double)xx*GODJEWL/GODPRICE); + curntn->tgold -= xx; + } + + /* fix overflow problems */ + if(curntn->tgold < -1*BIG) { + fprintf(fnews,"2.\tVariable Overflow - gold in nation %s\n",curntn->name); + curntn->tgold=BIG; + } + if(curntn->tfood < -1*BIG) { + fprintf(fnews,"2.\tVariable Overflow - food in nation %s\n",curntn->name); + curntn->tfood=BIG; + } + if(curntn->jewels < -1*BIG) { + fprintf(fnews,"2.\tVariable Overflow - jewels in nation %s\n",curntn->name); + curntn->jewels=BIG; + } + if(curntn->metals < -1*BIG) { + fprintf(fnews,"2.\tVariable Overflow - metal in nation %s\n",curntn->name); + curntn->metals=BIG; + } + } +} + +/****************************************************************/ +/* Conquer: Copyright (c) 1988 by Edward M Barlow +/* UPDLEADER() */ +/****************************************************************/ +void +updleader() +{ + int nation,armynum,born,type; + printf("working on national leaders\n"); + for(nation=0;nationactive)) continue; + + /* monster nations get monsters */ + if((SEASON(TURN) == SPRING)&&(magic(nation,MI_MONST)==TRUE)) { + born=100; /* born represents strength of monst */ + if(magic(nation,AV_MONST)==TRUE) born=200; + if(magic(nation,MA_MONST)==TRUE) born=BIG; + + do type = MINMONSTER + rand()%(MAXMONSTER-MINMONSTER+1); + while( *(unitminsth+(type%UTYPE)) > born); + + for(armynum=0;armynum < MAXARM;armynum++) { + if(P_ASOLD != 0) continue; + P_ATYPE = type; + P_ASOLD = *(unitminsth+(type%UTYPE)); + P_AXLOC = curntn->capx; + P_AYLOC = curntn->capy; + P_ASTAT = DEFEND; + P_AMOVE = 2*curntn->maxmove; + if( ispc( ntn[nation].active ) ){ + if (mailopen( nation )!=(-1)) { + fprintf(fm,"Message to %s from Conquer:\n\n",ntn[nation].name); + fprintf(fm,"\t\tMonster born in your nation!\n"); + mailclose(nation); + } + } + printf("\tmonster born in nation %s\n",curntn->name); + break; + } + } + + switch(curntn->class){ /* get national born rate */ + case C_NPC: + case C_KING: + case C_TRADER: + case C_EMPEROR: born = 50; break; + case C_WIZARD: + case C_PRIEST: + case C_PIRATE: + case C_WARLORD: + case C_DEMON: born = 25; break; + case C_DRAGON: + case C_SHADOW: born = 2; break; + default: + printf("ERROR - national class (%d) undefined\n",curntn->class); + abrt(); + } + /* born represents yearly birth rate */ + if( rand()%400 >= born ) continue; + + for(armynum=0;armynum < MAXARM;armynum++) { /* add one leader */ + if(P_ASOLD != 0) continue; + P_ATYPE = getleader(curntn->class); + P_ASOLD = *(unitminsth+(P_ATYPE%UTYPE)); + P_AXLOC = curntn->capx; + P_AYLOC = curntn->capy; + P_ASTAT = DEFEND; + P_AMOVE = 2*curntn->maxmove; + if( ispc( ntn[nation].active ) ){ + if(mailopen( nation )!=(-1)) { + fprintf(fm,"Message to %s from Conquer:\n\n",ntn[nation].name); + fprintf(fm,"\t\tLeader born in your nation!\n"); + mailclose(nation); + } + } + printf("\tleader born in nation %s\n",curntn->name); + break; + } + } +} + +/* MOVE CIVILIANS based on the ratio of attractivenesses + * + * EQUILIBRIUM(1) = A1 / (A1 + A2) * (P1 + P2) + * EQUILIBRIUM(2) = A2 / (A1 + A2) * (P1 + P2) + * MOVE 1/5 of way to equilibrium each turn + * DELTA(1) = (EQUILIBRIUM(1) - P1) / 5 =(A1P2 - P1A2) / 5(A1 + A2) + * DELTA(2) = (EQUILIBRIUM(2) - P2) / 5 =(A2P1 - P2A1) / 5(A1 + A2) = -DELTA(1) + * (i, j) is refered to as 1, (x, y) as 2 + */ +void +move_people() +{ + register int x, y, i, j; + register struct s_sector *sptr; + int t_attr; + long *curpop, moved; + + /* store the first two rows for computation */ + for (x = 0; x < 3; x++) { + for (y = 0; y < MAPY; y++) { + if (sct[x][y].owner == country) + newpop[x][y] = sct[x][y].people; + else newpop[x][y] = 0L; + } + } + + /* go through entire map to move civilians */ + for (x = 0; x < MAPX; x++) { + for (y = 0; y < MAPY; y++) { + sptr = &sct[x][y]; + if ((sptr->owner == country) && (sptr->people != 0)) { + + for (t_attr = 0, i = x - 2; i < x + 3; i++) + for (j = y - 2; j < y + 3; j++) + if (ONMAP(i, j)) + t_attr += attr[i][j]; + + if (t_attr > 0) { + t_attr *= 5; + curpop = &newpop[x%5][y]; + for (i = x - 2; i < x + 3; i++) + for (j = y - 2; j < y + 3; j++) + if (ONMAP(i, j)) { + moved = sptr->people * attr[i][j]; + if (moved > 0) { + moved /= t_attr; + *curpop -= moved; + newpop[i%5][j] += moved; + } + } + } + } + } + /* store old row, and read in new */ + for (y = 0; y < MAPY; y++) { + if (x > 1) { + if (sct[x-2][y].owner == country) + sct[x-2][y].people = newpop[(x-2)%5][y]; + } + if (x < MAPX - 3) { + if (sct[x+3][y].owner == country) + newpop[(x+3)%5][y] = sct[x+3][y].people; + else newpop[(x+3)%5][y] = 0L; + } + } + } + + /* assign values for final rows */ + for (x = MAPX - 2; x < MAPX; x++) { + for (y = 0; y < MAPY; y++) { + if (sct[x][y].owner == country) + sct[x][y].people = newpop[x%5][y]; + } + } +} diff --git a/original/utilities/.gitignore b/original/utilities/.gitignore new file mode 100644 index 0000000..38dc870 --- /dev/null +++ b/original/utilities/.gitignore @@ -0,0 +1,11 @@ +*.o +xconqrast +makefile.x +sunconqrast +makefile.sun +lint.x +lint.sun +shar.* +*.diff +newfiles +difffiles diff --git a/original/utilities/.indent.pro b/original/utilities/.indent.pro new file mode 100644 index 0000000..768bccd --- /dev/null +++ b/original/utilities/.indent.pro @@ -0,0 +1,42 @@ +-pmt /* Preserve make times */ + +--line-length96 /* Overall width of code */ +--comment-line-length120 /* width of comment lines */ +--indent-level4 /* indent N spaces per level */ +--case-indentation4 /* indent case statements */ +--parameter-indentation4 /* indent old-style parameter declarations */ +--declaration-indentation40 /* variable declarations line up here */ +--tab-size8 /* tabs get expanded into N characters */ + +--break-before-boolean-operator /* break before boolean operators if possible */ +--dont-break-procedure-type /* keep function type on the same line as the name */ +--blank-lines-after-declarations /* space out declarations */ +--blank-lines-after-procedures /* space out bodies */ +--blank-lines-after-commas /* seperate lines for comma seperated declarations */ +--swallow-optional-blank-lines /* remove "extra" blank lines */ + +--braces-on-if-line /* place opening brace ON the if line */ +--cuddle-else /* put else with braces ala } else { */ +--cuddle-do-while /* put while inline ala do { } while */ +--braces-on-struct-decl-line /* put opening brace ON struct declaration line */ +--continue-at-parentheses /* line up continuations at parens */ + +--no-space-after-function-call-names /* function() not function () */ +--dont-space-special-semicolon /* no extra spacing of semicolons */ +--no-space-after-casts /* (type)cast not (type) cast */ + +--comment-indentation64 /* line up comments at column N */ +--declaration-comment-column64 /* line up comments after declarations in column N */ +--else-endif-column64 /* preprocessor #else and #endif comments line up here */ +--start-left-side-of-comments /* add stars in block comments */ +--format-all-comments /* try to reformat comments */ +--dont-format-first-column-comments /* unless they are on the left! */ +--comment-delimiters-on-blank-lines /* one lineers with no code should be made larger */ + +/* Various typedefs used in our code */ + +-T L_DATA +-T L_PTR +-T defn +-T classrec +-T bitmap diff --git a/original/utilities/Makefile b/original/utilities/Makefile new file mode 100644 index 0000000..d0a8535 --- /dev/null +++ b/original/utilities/Makefile @@ -0,0 +1,132 @@ +# +SHELL=/bin/sh +SHAR=/usr/bin/shar +MAKE=/usr/bin/make + +# +# Will most likely have to edit the location of the +# X Libraries. +# +Libs_sun= -lpixrect +Libs_x= -L/usr/lib -lX11 + +WHICHconqrast: WHICHconqrast.o error.o WHICHstuff.o file.o util.o + cc $(CFLAGS) -o WHICHconqrast WHICHconqrast.o WHICHstuff.o file.o\ + util.o error.o $(Libs_WHICH) + +error.o: error.c +file.o: file.c +util.o:util.c + +WHICHconqrast.o: conqrast.c WHICHconqrast.h file.h ../header.h + $(CC) $(CFLAGS) -c conqrast.c -DHEADERFILE=\"WHICHconqrast.h\" + mv conqrast.o WHICHconqrast.o + +WHICHstuff.o: WHICHstuff.c WHICHconqrast.h + +lint.WHICH: + lint -abchx -DHEADERFILE=\"WHICHconqrast.h\" \ + conqrast.c WHICHstuff.c error.c file.c util.c $(Libs_WHICH) + +### don't delete this line! + +all: sunconqrast xconqrast + +lint: lint.sun lint.x + +lint.sun: makefile.sun + $(MAKE) $(MFLAGS) -f makefile.sun lint.sun + +lint.x: makefile.x + $(MAKE) $(MFLAGS) -f makefile.x lint.x + +sun sunconqrast: makefile.sun conqrast.c sunstuff.c sunconqrast.h file.c\ + file.h util.c + $(MAKE) $(MFLAGS) -f makefile.sun sunconqrast + +makefile.sun : Makefile + sed -e '/^###/q' -e '/WHICH/s//sun/g' Makefile > makefile.sun + +x xconqrast: makefile.x conqrast.c xstuff.c xconqrast.h file.c file.h util.c + $(MAKE) $(MFLAGS) -f makefile.x xconqrast + +makefile.x : Makefile + sed -e '/^###/q' -e '/WHICH/s//x/g' Makefile > makefile.x + +shar.core: conqrast.c + shar -c -v conqrast.c > shar.core + +shar.sun: sunstuff.c sunconqrast.h + shar -c -v sunstuff.c sunconqrast.h > shar.sun + +shar.x: xstuff.c xconqrast.h + shar -c -v xstuff.c xconqrast.h > shar.x + +shar.general: Makefile README error.c file.c file.h util.c conqrast.man + shar -c -v Makefile README conqrast.man error.c file.c file.h util.c > shar.general + +shar: shar.general shar.sun shar.x shar.core + +checkpoint: + cp Makefile README *.[ch] *.man old + /bin/rm *.diff newfiles difffiles + +clean: + /bin/rm -f *.o *.diff patch shar.* *~ "#*" makefile.* newfiles difffiles + +diffs: + echo -n >patch + -for i in old/* ; do \ + j=`basename $$i` ;\ + if diff -c $$i $$j > $$j.diff ;\ + then \ + /bin/rm $$j.diff ;\ + else \ + cat $$j.diff >> patch ;\ + wc $$j.diff ;\ + fi ;\ + done + +newfiles: + echo -n > newfiles + -for i in *.[ch1] ; do\ + if test -f old/$$i ; then\ + : ;\ + else \ + echo $$i >> newfiles ;\ + fi ;\ + done + +difffiles: newfiles diffs + echo -n > difffiles + -for i in *.diff ; do\ + j=`basename $$i .diff` ;\ + echo -n $$j ;\ + is=`wc $$i |colrm 9`;\ + js=`wc $$j |colrm 9`;\ + echo " " $$js $$is ;\ + if test $$is -gt $$js ; then \ + echo is very new! ;\ + echo $$j >> newfiles ;\ + else \ + echo is changed ;\ + echo $$i >> difffiles ;\ + fi ;\ + done + +update: newfiles difffiles + -n=1;for i in `cat difffiles` `cat newfiles` ; do \ + lines=`wc $$them $$i| tail -1 | colrm 9` ;\ + echo $$them $$i $$lines ;\ + if test $$lines -gt 800 ; then\ + echo chop! ;\ + $(SHAR) -c -v $$them > shar.$$n ;\ + n=`expr $$n + 1` ;\ + them="$$i" ;\ + else \ + them="$$them $$i" ;\ + fi ;\ + done ;\ + $(SHAR) -c -v $$them > shar.$$n + /bin/rm newfiles difffiles + diff --git a/original/utilities/README b/original/utilities/README new file mode 100644 index 0000000..3c1987d --- /dev/null +++ b/original/utilities/README @@ -0,0 +1,13 @@ + +This directory contains the code for conqrast, a program for +displaying nice maps of conquer games on sun consoles and, sometime in +the future, on X windows displays. + +See the manual page conqrast.1 for more details. + +Bugs should probably be sent to me, Richard Caley. + + rjc@uk.ac.ed.aipna + +or permutations thereof that your local mailer demands. + diff --git a/original/utilities/conqrast.c b/original/utilities/conqrast.c new file mode 100644 index 0000000..1841507 --- /dev/null +++ b/original/utilities/conqrast.c @@ -0,0 +1,792 @@ +#include +#include +#include +#include "../header.h" +#include "file.h" +#include HEADERFILE + +/********************************************************************* +* * +* This program draws a map of the conquer world on a bitmap system * +* * +* Written by Richard Caley July 1989 and hacked extensively * +* thereafter. * +* * +* You may copy, distribute, modify or do what you will with this * +* code so long as this message remains in it and so long as you do * +* not charge for it, nor distribute the program without the source. * +* * +* There is a horrid hack for getpass - to make this read the * +* password from standard in one has to disconnect from the control * +* terminal. GAG! It should be possible to disconnect just the * +* conquer from the control terminal . . . someday. * +* * +* See Readme for more details. * +* * +*********************************************************************/ + +#define GAP (2) /* fudge factor - space above + * and below titles */ + +#define total_height (height*mag+ (do_title?4*GAP+2*font_height(titlefont):0)) + /* height of map and title bars */ + +#define yoffset(place) ((place)+(do_title?font_height(titlefont)+GAP+GAP:0)) + /* a y position */ + +#define tracef if(trace) printf + +char *getpass(); +void error(), ioerror(); +char *passwd=NULL; +char *nation=NULL; +int turn; +int trace=0; +int bg=0; +char conquer_version[100]; + +#define conqrast_version "1.0" + +#ifndef conqrast_name +# define conqrast_name "Some conqrast" /* this is redefined in the header */ +# define driver_version "unknown driver" +#endif + +#define HEADER_TAG "Conquer Version" /* just before first line of map */ +#define HEADER_TAG_LENGTH (sizeof(HEADER_TAG)/sizeof(char)-1) + +extern struct /* maps from size of map to the font */ + /* to use */ + { /* if size > mag use font */ + int mag; + char *romanfont,*boldfont; + } fonts[]; + +struct /* Maps from terrain to brightness */ + { + char c; + int val; /* must be between 0 and 255 */ + } values[] = + { + ' ', 256, + '~', 0, + '-', 64, + '%', 128, + '^', 192, + '#', 224, + '\0' + }; + +char *mapnames[] = + { + "This should never happen", + "Altitude", + "Vegetation", + "Nation", + "Designation" + }; + +#define num_mapnames (sizeof(mapnames)/sizeof(char *)) + +/********************************************************************* +* * +* Font mapping information. Fonts used by the system have symbolic * +* names so they can be referred to on the commend line. font_table * +* records which fonts go with which name. * +* * +*********************************************************************/ + +enum mapfont + { + f_nation, + f_designation, + f_title, + f_last + }; + +struct + { + char *name; + font romanfont; + font boldfont; + } font_table[(unsigned)f_last+1] = + { + {"nation"}, + {"designation"}, + {"title"}, + {NULL} + }; + +#define MAXDITHER 4 /* don't touch this */ + +short dit[1<= mag ) + break; + else if (fonts[i].mag < mag ) + { + if(bad_font(font_table[(unsigned)f].romanfont= + font_named(fonts[i].romanfont))) + error("Can't get font '%s' as %s font", + fonts[i].romanfont,font_table[(unsigned)f].name); + if ( font_table[(unsigned)f].boldfont==NULL && fonts[i].boldfont !=NULL) + if (bad_font(font_table[(unsigned)f].boldfont= + font_named(fonts[i].boldfont))) + error("Can't get font '%s' as bold %s font", + fonts[i].romanfont,font_table[(unsigned)f].name); + } + } + if(font_table[(unsigned)f].romanfont==NULL) + error("No font small enough for size %d %s",mag,font_table[(unsigned)f].name); + } + + } + +/********************************************************************* +* * +* Set up a single font. if the name is in the table ( or is a prefix * +* ) then insert the name into the font table. If the name begins * +* with 'b' then sets the bold font. * +* * +*********************************************************************/ + +void +set_a_font(name,fontname) + +char *name; +char *fontname; + +{ + int i,bold=0,l; + font thefont; + + if( name[0]=='b') + { + name++; + bold=1; + } + + l=strlen(name); + + for (i=0;i< (int)f_last;i++) + if (!strncmp(name,font_table[i].name,l)) + break; + + if ( i == (int)f_last) + error("Unknown font name '%s'",name); + + thefont=font_named(fontname); + + if ( bad_font(thefont) ) + error("Can't get font '%s'",fontname); + + if (bold) + font_table[i].boldfont=thefont; + else + font_table[i].romanfont=thefont; + } + +/********************************************************************* +* * +* scan over the header of the map. Returns the number of the map, or * +* 0 if the map is bad. If `pipe' is != 0 then the input is a pipe * +* and an eof implies a bad password. * +* * +* Tries to cope with DEBUG and none-DEBUG conquers * +* * +*********************************************************************/ + +scan_header(f,pipe) + +FILE *f; +int pipe; + +{ + char line[1024]; + char which[100]; + static char who[100]; + int mapid; + + while ( fgets(line,1024,f) != NULL) /* scan to top of map */ + { + if (!strncmp(line,HEADER_TAG,HEADER_TAG_LENGTH)) + break; + } + + if (feof(f)) + { + if(pipe) + error("Password incorrect"); + else + error("Unexpected end of map file"); + } + + if (sscanf(line,"Conquer Version %[0-9.] : %s Map %*s %*s %s on Turn %d",conquer_version,which,who,&turn)!=4) + error("Bad title line (wrong version?) '%s'",line); + + for(mapid=1;mapid < num_mapnames;mapid++) + if(!strcmp(mapnames[mapid],which)) + break; + + if ( mapid==num_mapnames) + mapid= 0; + else if ( trace && !pipe) + printf("Found %s map\n", which); + + if(!strcmp(who,"World")) + nation="god"; + else + nation=who; + + tracef("Nation is %s\n",nation); + + return mapid; + } + +/********************************************************************* +* * +* Find maps in a file and store away a file pointer and offset for * +* each * +* * +*********************************************************************/ + +void +process_map_file(name) + +char *name; + +{ + int which; + FILE *f; + char line[1024]; + + tracef("Searching file %s\n",name); + + if ((f=fopen(name,"r"))==NULL) + ioerror("Can't open map file '%s'",name); + + while(1) + { + long top; + + which=scan_header(f,0); + + if(which==0) + error("Bad map file '%s'",name); + + myopen(which,f); + top=ftell(f); + while(fgets(line,1024,f)!=NULL) + { + if (!strncmp(line,HEADER_TAG,HEADER_TAG_LENGTH)) + break; + top=ftell(f); + } + + if(feof(f)) + break; + + fseek(f,top,0); + } + } + +/********************************************************************* +* * +* Get a map. If the map was not in one of the files on the command * +* line it runs conquer -p to get it. * +* * +* Which selects the map. * +* Args are passed to conqrun. * +* Tmpname is the name of a temporary file to use. This is * +* deleted in this routine so you can reuse the name. * +* * +* All except `which' are ignored if the user has given a map * +* file of the correct type as an argumant. * +* * +*********************************************************************/ + +int +get_map_file(which,args,tmpname) + +int which; +char *args; +char *tmpname; + +{ + char command[100]; + FILE *tmp; + + if ( ! myisopen(which)) + { + if (nation==NULL) + { + tracef("Assuming god\n"); + + nation="god"; + } + + tracef("Asking conquer for %s map\n",mapnames[which]); + + if (passwd==NULL) + { + passwd=getpass("Enter conquer password: "); + } + + tracef("Disconnecting ( HACK! ) bye bye\n"); + + disconnect(); /* disconnect from controling tty */ + /* ( hack for getpass ) */ + + if (bg) /* go into background if asked */ + { + tracef("Going into background\n"); + + background(); + } + + sprintf(command,"conquer -p %s > %s 2>/dev/null",args,tmpname); + + if((tmp=popen(command,"w"))==NULL) + ioerror("can't run conquer"); + + if (fprintf(tmp,"%s\n%s\n%c\n",nation,passwd, which+'0')==EOF) + error("Couldn't get map. Conquer may be updating.\n"); + + pclose(tmp); + + if((tmp=fopen(tmpname,"r"))==NULL) + ioerror("can't open %s",tmpname); + + unlink(tmpname); /* delete it */ + + (void)scan_header(tmp,1); + myopen(which,tmp); + } + + return which; + } + +/*ARGSUSED*/ +main(argc,argv) + +int argc; +char *argv[]; + +{ + char line[1024]; + char desline[1024]; + char tmpname[20]; + char args[100]; + char *screen_name=get_default_screen_name(); + screen_type screen=NULL; + int mapfile; + int destmapfile; + int mag=11; + bitmap pr; + int width,height; + extern char *myname; + int x,y,i,j,val; + char c; + char *mapname=NULL; + char *world=NULL; + int do_nations=0,barbarians=0,markbarbs=0; + int all=0,live=0,altitude=1; + int desig=0; + int do_title=1; + font titlefont; + int boldtitle=0; /* indicates that the title font should be + emboldened - ie `titlefont' is roman and + so _we_ must do the bold */ + + + myname=argv[0]; + + strcpy(args,""); + + while(*(++argv)!=NULL) + if (!strncmp(*argv,"-o",2)) + { + mapname= *(++argv); + if ( is_screenname(mapname)) + { + screen_name=mapname; + mapname=NULL; + } + } + else if (!strcmp(*argv,"-l")) + live++; + else if (!strcmp(*argv,"-D")) + sprintf(args,"%s -d %s",args,world= *(++argv)); + else if (!strcmp(*argv,"-N")) + nation= *(++argv); + else if (!strcmp(*argv,"-bg")) + bg++; + else if (!strcmp(*argv,"-a")) + altitude=0; + else if (!strcmp(*argv,"-f")) + { + char *which= *(++argv), *fontname= *(++argv); + set_a_font(which,fontname); + } + else if (!strncmp(*argv,"-b",2)) + { + barbarians++; + if ( (*argv)[2]=='a') + markbarbs++; + } + else if (!strcmp(*argv,"-m")) + mag=atoi(*(++argv)); + else if (!strncmp(*argv,"-c",2)) + { + c=(*argv)[2]; + for (i=0;;i++) + { + if (values[i].c =='\0') + error("Unknown contour '%c'",c); + else if ( values[i].c == c) + { + values[i].val=atoi(*(++argv)); + break; + } + } + } + else if (!strncmp(*argv,"-n",2)) + { + do_nations++; + if ( (*argv)[2]=='a') + ++all; + } + else if (!strncmp(*argv,"-d",2)) + { + desig++; + } + else if (!strcmp(*argv,"-h")) + help_message(myname); + else if (!strcmp(*argv,"-t")) + do_title=0; + else if (!strcmp(*argv,"-v")) + trace++; + else if ( (*argv)[0]=='-') + { + printf("Unknown option '%s'\n",*argv); + help_message(myname); + } + else + process_map_file(*argv); + + if (do_nations) /* if we have to put in nations */ + set_default_fonts(mag,f_nation); + + if (desig) + { + if (all) + error("Only one of -d and -na allowed!"); + + set_default_fonts(mag,f_designation); + } + + if (do_title) + { + set_default_fonts(mag+2,f_title); + if ( (titlefont=font_table[(unsigned)f_title].boldfont)==NULL) + { + boldtitle=1; + titlefont=font_table[(unsigned)f_title].romanfont; + } + + } + + screen=screen_named(screen_name); + + sprintf(tmpname,"/tmp/conq%d",getpid()); + + mapfile=get_map_file(altitude?1:3, /* get a map */ + args,tmpname); + + if(mygets(line,1024,mapfile)==NULL) + error("empty map!"); + + width=strlen(line)-1; /* count height and width */ + + for(height=1;mygets(line,1024,mapfile)!=NULL;height++) + if(!strncmp(line,HEADER_TAG,HEADER_TAG_LENGTH)|| + !strncmp(line,"reading",7)) + break; + + tracef("Size %d X %d, image %d X %d\n",width,height,width*mag,height*mag); + + initialise_bitmaps(); + + if(live) /* if live do it on the screen */ + { + if ((pr=get_screen_bitmap(screen))==(bitmap)NULL) + ioerror("Can't open screen %s",screen_name); + } + else /* otherwise in memory */ + pr=create_bitmap(width*mag,total_height); + + myrewind(mapfile); + + if (altitude) /* if needed do altitude */ + { + int xx,yy; + tracef("Drawing topography\n"); + + build_dither_matrix(MAXDITHER); + + yy=yoffset(0); + for(y=0;y=val?1:0); + } + } + } + + myclose(mapfile); + } + + if(do_nations||desig) /* nations */ + { + font nf, bnf; + font df; + int xx,yy; + char des, + current='\0'; /* keeps track of which nation we are in */ + char last[1024]; /* ditto vertically for each column */ + + tracef("Drawing nations\n"); + + if (do_nations) + { + nf = font_table[(unsigned)f_nation].romanfont; + bnf = font_table[(unsigned)f_nation].boldfont; + } + + if (desig) + { + df = font_table[(unsigned)f_designation].romanfont; + } + + if (altitude) /* if no altitude this was gotten to */ + /* count the size */ + mapfile=get_map_file(3,args,tmpname); + + destmapfile=get_map_file(4,args,tmpname); + + yy=yoffset(mag); + for(y=0;y mapfile' +.PP +If you do not supply a mapfile which is needed to produce the map you +request ( altitude unless `\fB-a\fR'; nation and designation for `-n'; +designation for `\fB-d\fR' ) \fIconqrast\fR will prompt you for the nation's +password and attempt to run +.IP +conquer -p -n\fIname\fR +.PP +to get the map it wants. + +More than one map may be put into a single file as shown in the example below. + +.SH EXAMPLE +.IP +.br +% \fBconquer -p -nTolland >mapfile\fR +.br +conquer Version 4.4: Copyright (c) 1988 by Edward M Barlow +.br + +.br +What is your Nation's Password: +.br + +.br +For convenience, this output is to stderr, +.br +while the maps will be sent to stdout. +.br + +.br +The valid options are, +.br +1) altitudes +.br +2) vegetations +.br +3) nations +.br +4) designations +.br + +.br +What type of map? \fB1\fR +.br + +.br +doing print of altitude +.br +% \fBconquer -p -nTolland >> mapfile\fR +.br +conquer Version 4.4: Copyright (c) 1988 by Edward M Barlow +.br + +.br +What is your Nation's Password: +.br + +.br +For convenience, this output is to stderr, +.br +while the maps will be sent to stdout. +.br + +.br +The valid options are, +.br +1) altitudes +.br +2) vegetations +.br +3) nations +.br +4) designations +.br + +.br +What type of map? \fB3\fR +.br + +.br +doing print of nations +.br +% \fBsunconqrast -n -m 11 mapfile\fR +.br +Enter conquer password: +.br + +notice how it prompts for your password when it +finds it needs the designation map which was not given in the file. + +.SH PROBLEMS + +.I +xconqrast +does not work yet! not even slightly. Don't even think of it. + +The method used to produce bold when there is no bold font is +rather poor. + +no fonts for small maps ( < mag 9 ) on my machine so that is +the minimum. If you want a smaller one have a look in +/usr/lib/fonts/fixedwidthfonts on your machine or create your +own. In the latter case, you could send it to me too . . . + +The way -o works makes it impossible to draw live on a +non-standard screen then dump to a file. Doesn't seem to be +likely to cause anyone too many problems ( famous last words! +). + + +.SH "THINGS TO DO" + +create a set nice fonts ( different sizes ) for designations +so that they can be represented by a symbol rather than by a +letter. + +disconnect the conquer process from the terminal rathert then +sunconqrast. + +better help message. + +.SH SEE ALSO +conquer(6) rasterfile(5) screenload(1) bitmap(1x) +.SH AUTHER +Richard Caley diff --git a/original/utilities/error.c b/original/utilities/error.c new file mode 100644 index 0000000..80dc77a --- /dev/null +++ b/original/utilities/error.c @@ -0,0 +1,37 @@ +#include +#include +#include + +/* int errno; */ +/* char *sys_errlist[]; */ + +char *myname="Someone"; + +/*VARARGS1*/ +void +ioerror(str,arg1,arg2,arg3) + +char *str; +int arg1, arg2, arg3; + +{ +fprintf(stderr,"%s: ",myname); +fprintf(stderr,str,arg1,arg2,arg3); +fprintf(stderr," - %s\n",sys_errlist[errno]); +exit(1); +} + +/*VARARGS1*/ +void +error(str,arg1,arg2,arg3) + +char *str; +int arg1, arg2, arg3; + +{ +fprintf(stderr,"%s: ",myname); +fprintf(stderr,str,arg1,arg2,arg3); +fputc('\n',stderr); +exit(1); +} + diff --git a/original/utilities/file.c b/original/utilities/file.c new file mode 100644 index 0000000..0f9e948 --- /dev/null +++ b/original/utilities/file.c @@ -0,0 +1,90 @@ +#include +#include "file.h" + +/********************************************************************* +* * +* All the my* routines mimic stdio routines but manipulate struct * +* file's The point is that we can read from and otherwise manipulate * +* more than one place in a file ( for more than one map ). * +* * +*********************************************************************/ + +/********************************************************************* +* * +* struct file's play the roll of FILE *'s * +* * +*********************************************************************/ + +#define MAX_FILES 10 + +static struct file + { + FILE *fd; /* which file */ + long offset, /* where are we reading from now */ + top; /* where is the notional start */ + } file_table[MAX_FILES]; + + +void +myopen(which,file) + +int which; +FILE *file; + +{ +file_table[which].fd=file; +file_table[which].offset=file_table[which].top=ftell(file); +} + +myisopen(which) + +int which; + +{ +return file_table[which].fd != NULL; +} + +char * +mygets(buffer,num,which) + +char *buffer; +int num; +int which; +{ + fseek(file_table[which].fd,file_table[which].offset,0); + + buffer=fgets(buffer,num,file_table[which].fd); + + file_table[which].offset=ftell(file_table[which].fd); + + return buffer; + } + +void +myrewind(which) + +int which; + +{ + fseek(file_table[which].fd,file_table[which].top,0); + file_table[which].offset=file_table[which].top; + } + +void +myclose(which) + +int which; + +{ + int i; + + for(i=0;i + +typedef struct pixrect * bitmap; +typedef char * screen_type; +typedef struct pixfont * font; + +#define initialise_bitmaps() /* EMPTY */ +#define finish_bitmaps() /* EMPTY */ + +#define is_screenname(mapname) (!strncmp(mapname,"/dev/",5)) +#define get_default_screen_name() "/dev/fb" +#define screen_named(name) (name) +#define get_screen_bitmap(screen) (pr_open(screen)) +#define create_bitmap(width,height) (mem_create(width,height,1)) +#define destroy_bitmap(bitmap) pr_close(bitmap) +#define font_named(name) pf_open(name) +#define bad_font(font) ((font)==NULL) +#define font_height(font) ((font->pf_defaultsize).y) +#define font_width(font) ((font->pf_defaultsize).x) +#define font_baseline(font) (0-(font->pf_char)['A'].pc_home.y+1) + +#define BLACK PIX_SET +#define WHITE PIX_CLR +#define DRAW_BLACK (PIX_DST|PIX_SRC) +#define DRAW_WHITE (PIX_DST&PIX_NOT(PIX_SRC)) + +#define set_bit(bitmap,x,y,val) pr_put(bitmap,x,y,val) +#define draw_line(bitmap,x1,y1,x2,y2,colour) pr_vector(bitmap,x1,y1,x2,y2,colour,0) diff --git a/original/utilities/sunstuff.c b/original/utilities/sunstuff.c new file mode 100644 index 0000000..f8a5921 --- /dev/null +++ b/original/utilities/sunstuff.c @@ -0,0 +1,93 @@ +#include +#include "sunconqrast.h" + +struct /* maps from size of map to the font */ + /* to use */ + { /* if size > mag use font */ + int mag; + char *font,*bold; + } fonts[] = + { + 9, "/usr/lib/fonts/fixedwidthfonts/screen.r.7", NULL, + 11, "/usr/lib/fonts/fixedwidthfonts/cour.r.10", + "/usr/lib/fonts/fixedwidthfonts/cour.b.10", + 12, "/usr/lib/fonts/fixedwidthfonts/cour.r.12", + "/usr/lib/fonts/fixedwidthfonts/cour.b.12", + 14, "/usr/lib/fonts/fixedwidthfonts/cour.r.14", + "/usr/lib/fonts/fixedwidthfonts/cour.b.14", + 16, "/usr/lib/fonts/fixedwidthfonts/cour.r.16", + "/usr/lib/fonts/fixedwidthfonts/cour.b.16", + 18, "/usr/lib/fonts/fixedwidthfonts/cour.r.18", + "/usr/lib/fonts/fixedwidthfonts/cour.b.18", + 22, "/usr/lib/fonts/fixedwidthfonts/cour.r.24", + "/usr/lib/fonts/fixedwidthfonts/cour.b.24", + 999999, NULL + }; + +static int encoding_type = RT_STANDARD ; + +int +argument_parse(argv) + +char *argv[]; + +{ +if ( !strcmp(*argv,"-compact")) + { + encoding_type = RT_BYTE_ENCODED ; + return 1; + } +else + return 0; +} + +/*ARGSUSED*/ +int +write_bitmap(bm,file,width,height) + +bitmap bm; +char *file; +int width,height; + +{ + FILE *f; + + if ((f=fopen(file,"w"))==NULL) + ioerror("Can't open output file %s",file); + + return pr_dump( bm, f, RMT_NONE, encoding_type,0); + } + + + +void +display_bitmap(bm,x,y,w,h) + +bitmap bm; +int x,y,w,h; + +{ + struct pixrect *screen=pr_open("/dev/fb"); + + pr_rop(screen,x,y,w,h,PIX_SRC,bm,0,0); + + } + +bitmap_text(pr,x,y,colour,pf,str) + +bitmap pr; +int x,y; +int colour; +font pf; +char *str; + +{ + struct pr_prpos pos; + + pos.pos.x=x; + pos.pos.y=y; + pos.pr=pr; + + pf_text(pos,colour,pf,str); + } + diff --git a/original/utilities/util.c b/original/utilities/util.c new file mode 100644 index 0000000..54c7548 --- /dev/null +++ b/original/utilities/util.c @@ -0,0 +1,112 @@ +#include +#include +#include + +/********************************************************************* +* * +* various utility bits split off to try and get conqrast.c down to a * +* reasonable size * +* * +*********************************************************************/ + + +/********************************************************************* +* * +* routine to build the dither matrix used to shade * +* * +*********************************************************************/ + +#define MAXDITHER 4 /* don't touch this */ + +short dit[1<\n",me); + printf("\t\t-N \n"); + printf("\t\t-D \n"); + printf("\t\t-c \n"); + printf("\t\t-f \n"); + printf("\t\t-d -n{a} -b{a} -m -a -bg -l -t -v\n"); + exit(1); + } + diff --git a/original/utilities/xconqrast.h b/original/utilities/xconqrast.h new file mode 100644 index 0000000..adb4744 --- /dev/null +++ b/original/utilities/xconqrast.h @@ -0,0 +1,37 @@ + +/* header for X */ + +#define driver_version "preliminary" +#define conqrast_name "Xconqrast" + +#include + +typedef Drawable bitmap ; +typedef Display *screen_type; +typedef char *font; /* this needs doing */ + +#define is_screenname(name) (index(name,':')!=NULL) /* I think */ +#define get_default_screen_name() NULL /* I have no idea */ + +screen_type screen_named(); + +bitmap get_screen_bitmap(); +bitmap create_bitmap(); + +#define destroy_bitmap(bm) /* I don't know how to */ +#define font_named(name) (name) /* ditto */ +#define bad_font(font) ((font)==NULL) /* ??? */ +#define font_height(font) (0) /* ??? */ +#define font_width(font) (0) /* ??? */ +#define font_baseline(font) (0) /* ??? */ + +#define BLACK (1) +#define WHITE (0) /* guessing */ +#define DRAW_BLACK (1) /* ?? */ +#define DRAW_WHITE (2) + +void set_bit(); + +#define draw_line(bitmap,x1,y1,x2,y2,colour) /* again no idea! */ + + diff --git a/original/utilities/xstuff.c b/original/utilities/xstuff.c new file mode 100644 index 0000000..2e61455 --- /dev/null +++ b/original/utilities/xstuff.c @@ -0,0 +1,154 @@ +#include +#include "xconqrast.h" + +/* utilities for X */ + +Display *display; +Drawable root; +int screen; +GC gc; +short greyscale; + +struct /* maps from size of map to the font */ + /* to use */ + { /* if size > mag use font */ + int mag; + char *font,*bold; + } fonts[] = /* copied from the sun driver! need replacing */ + { + 9, "/usr/lib/fonts/fixedwidthfonts/screen.r.7", NULL, + 11, "/usr/lib/fonts/fixedwidthfonts/cour.r.10", + "/usr/lib/fonts/fixedwidthfonts/cour.b.10", + 12, "/usr/lib/fonts/fixedwidthfonts/cour.r.12", + "/usr/lib/fonts/fixedwidthfonts/cour.b.12", + 14, "/usr/lib/fonts/fixedwidthfonts/cour.r.14", + "/usr/lib/fonts/fixedwidthfonts/cour.b.14", + 16, "/usr/lib/fonts/fixedwidthfonts/cour.r.16", + "/usr/lib/fonts/fixedwidthfonts/cour.b.16", + 18, "/usr/lib/fonts/fixedwidthfonts/cour.r.18", + "/usr/lib/fonts/fixedwidthfonts/cour.b.18", + 22, "/usr/lib/fonts/fixedwidthfonts/cour.r.24", + "/usr/lib/fonts/fixedwidthfonts/cour.b.24", + 999999, NULL + }; + +int +argument_parse(argv) + +char *argv[]; + +{ +return 0; +} + +void +initialise_bitmaps() + + + + +{ + } + +screen_type +screen_named(name) + +char *name; + +{ +int sc; + +if ((display=XOpenDisplay(name)) == NULL) + error("No X server!"); + +root=XDefaultRootWindow(display); +sc=XDefaultScreen(display); +gc=XDefaultGC(display,sc); + +return display; +} + +bitmap +get_screen_bitmap(screen) + +screen_type screen; + +{ +int sc; +return root; +} + +bitmap +create_bitmap(width,height) + +int width,height; + +{ +int depth=1; + +if ( depth != 1 ) + greyscale=1; + +return XCreatePixmap(display,root,width,height,depth); +} + +void +set_bit(bm,x,y,val) + +bitmap bm; +int x,y; +int val; + +{ + +if (!greyscale ) + { + XSetForeground(display,gc,(unsigned long)val); + XDrawPoint(display,bm,gc,x,y); + } +else + if (val) + XDrawPoint(display,bm,gc,x,y); +} + +void +display_bitmap( bm,x,y,width,height) + +bitmap bm; +int x,y,width,height; + +{ +XCopyArea(display,bm,root,gc,0,0,width,height,x,y); + } + +int +write_bitmap(bm,file,width,height) + +bitmap bm; +char *file; +int width,height; +{ + +return XWriteBitmapFile(display,file,bm,width,height,-1,-1); + } + + +void +finish_bitmaps() + +{ +XCloseDisplay(display); +} + +bitmap_text(bm,x,y,colour,pf,str) + +bitmap bm; +int x,y; +int colour; +font pf; +char *str; + +{ + /* ??? */ + } + diff --git a/packaging/.DS_Store b/packaging/.DS_Store new file mode 100644 index 0000000..58ab1f4 Binary files /dev/null and b/packaging/.DS_Store differ diff --git a/packaging/melange/melange.yaml b/packaging/melange/melange.yaml index d11909d..a9a7ac9 100644 --- a/packaging/melange/melange.yaml +++ b/packaging/melange/melange.yaml @@ -38,22 +38,23 @@ pipeline: - name: "Fix Makefile for correct paths" runs: | - cd /home/build/conquer + cd /home/build/conquer/gpl-release + echo "=== ConquerV5 Build Process (in gpl-release/) ===" echo "=== Fixing Makefile paths ===" - + # Show current CDEFS echo "Original CDEFS:" grep -n "CDEFS" Makefile | head -3 - + # Create a backup cp Makefile Makefile.backup - + # Fix the CDEFS line in the Makefile itself (more reliable than command line override) sed -i 's|CDEFS = -DDEFAULTDIR=\\"$(DEFAULT)\\" -DEXEDIR=\\"$(EXEDIR)\\"|CDEFS = -DDEFAULTDIR=\\"/usr/lib/conquer\\" -DEXEDIR=\\"/usr/bin\\"|g' Makefile - + # Also ensure we don't have the comment line blocking this sed -i 's|^#CDEFS = -DDEFAULTDIR=\\"$(DEFAULT)\\" -DEXEDIR=\\"$(EXEDIR)\\"|CDEFS = -DDEFAULTDIR=\\"/usr/lib/conquer\\" -DEXEDIR=\\"/usr/bin\\"|g' Makefile - + echo "Fixed CDEFS:" grep -n "CDEFS.*usr/lib" Makefile @@ -61,14 +62,14 @@ pipeline: runs: | cd /home/build/conquer echo "=== Building with Makefile's own CDEFS ===" - + export LEGACY_CFLAGS="-std=gnu99 -D_GNU_SOURCE -Wno-implicit-function-declaration -Wno-incompatible-pointer-types -Wno-implicit-int -Wno-return-type -Wno-old-style-definition -Wno-unused-variable -Wno-unused-function -Wno-format" - + make clean || true - + # Build using the Makefile's fixed CDEFS (don't override on command line) make all OPTFLG="$LEGACY_CFLAGS" - + echo "=== Verifying paths in binaries ===" for exe in conquer conqrun; do if [ -x "./$exe" ]; then @@ -85,35 +86,35 @@ pipeline: fi done - - name: "Install game files" + - name: "Install Conquer" runs: | - cd /home/build/conquer - + cd /home/build/conquer/gpl-release + mkdir -p ${{targets.destdir}}/usr/bin mkdir -p ${{targets.destdir}}/usr/lib/conquer mkdir -p ${{targets.destdir}}/usr/share/licenses/conquer - + # Install executables install -m 755 conquer ${{targets.destdir}}/usr/bin/ install -m 755 conqrun ${{targets.destdir}}/usr/bin/ - + for exe in conqsort conqps; do if [ -x "$exe" ]; then install -m 755 "$exe" ${{targets.destdir}}/usr/bin/ fi done - + # Install help files for i in 0 1 2 3 4 5; do if [ -f "help$i" ]; then install -m 644 "help$i" ${{targets.destdir}}/usr/lib/conquer/ fi done - + # Install game data files directly install -m 644 nations ${{targets.destdir}}/usr/lib/conquer/nations install -m 644 rules ${{targets.destdir}}/usr/lib/conquer/rules - + # Install license if [ -f "COPYING" ]; then install -m 644 COPYING ${{targets.destdir}}/usr/share/licenses/conquer/COPYING diff --git a/richard-caley-utilities/AUTHORS.md b/richard-caley-utilities/AUTHORS.md new file mode 100644 index 0000000..e591103 --- /dev/null +++ b/richard-caley-utilities/AUTHORS.md @@ -0,0 +1,51 @@ +# # Authors and Contributors + +## Original Author + +**Richard Caley** +- **Email**: rjc@cstr.ed.ac.uk (historical) +- **Affiliation**: University of Edinburgh, Centre for Speech Technology Research +- **Contribution**: Complete original implementation (July 1989) +- **Status**: Passed away 2006 + +### About Richard Caley + +Richard Caley was a researcher at the University of Edinburgh's Centre for Speech Technology Research (CSTR). He created this map drawing utility in July 1989 as a visualization tool for the Conquer game world. + +His original code comments show attention to technical detail and a sense of humor about the implementation challenges of the era, particularly noting "There is a horrid hack for getpass" - typical of the pragmatic solutions needed in 1989 Unix programming. + +### Technical Contributions + +- **Map Visualization**: Created bitmap rendering system for Conquer game worlds +- **Game Integration**: Developed data reading mechanisms for Conquer world files +- **Unix Gaming**: Contributed to the early ecosystem of Unix-based multiplayer games +- **Open Sharing**: Released code with permissive license encouraging modification and distribution + +## Historical Context + +This code represents an important artifact from the early Unix gaming community: + +- **Era**: Written during the golden age of USENET source code sharing +- **Community**: Part of the collaborative Unix gaming development community +- **Innovation**: Early example of game world visualization tools +- **Preservation**: Maintained as historical documentation of 1989 programming practices + +## Preservation Team + +**Juan Manuel Méndez Rey (Vejeta)** +- **Role**: Historical preservation and documentation +- **Contribution**: Identified, documented, and preserved Richard Caley's code +- **Repository**: https://github.com/vejeta/conquer + +## Memorial + +Richard Caley's contribution to early Unix gaming and his generous sharing of source code represents the collaborative spirit that made the early computing community so innovative. His passing in 2006 was a loss to the academic and technical communities he served. + +This code is preserved not just as functional software, but as a memorial to his contribution to the early days of computer gaming and open source development. + +## No Modern Contributors + +Due to the original author's passing and the specific terms of his license, this code is preserved in its historical form. While the license permits modification, we maintain the original implementation as Richard wrote it. + +--- +*"You may copy, distribute, modify or do what you will with this code so long as this message remains in it and so long as you do not charge for it, nor distribute the program without the source."* - Richard Caley, 1989 diff --git a/richard-caley-utilities/LICENSE.md b/richard-caley-utilities/LICENSE.md new file mode 100644 index 0000000..9d81a7d --- /dev/null +++ b/richard-caley-utilities/LICENSE.md @@ -0,0 +1,69 @@ +# Richard Caley Map Drawing Utility License + +**Original Author**: Richard Caley +**Date**: July 1989 + +## License Terms + +``` +* This program draws a map of the conquer world on a bitmap system * +* * +* Written by Richard Caley July 1989 and hacked extensively * +* thereafter. * +* * +* You may copy, distribute, modify or do what you will with this * +* code so long as this message remains in it and so long as you do * +* not charge for it, nor distribute the program without the source. * +* * +* There is a horrid hack for getpass - to make this read the * +* password from standard in one has to disconnect from the control * +* terminal. GAG! It should be possible to disconnect just the * +* conquer from the control terminal . . . someday. * +* * +* See Readme for more details. * +``` + +## License Summary + +**Permissions**: +- ✅ Copy the software +- ✅ Distribute the software +- ✅ Modify the software +- ✅ Use for any purpose + +**Conditions**: +- 📋 License notice must be preserved +- 📋 Source code must be distributed with the program + +**Limitations**: +- ❌ Cannot charge money for the software +- ❌ Cannot distribute without source code + +## Legal Notes + +This license was written in 1989 by Richard Caley and represents his intentions for how this software should be shared. The license is: + +- **Permissive** in allowing copying, distribution, and modification +- **Copyleft-like** in requiring source distribution +- **Restrictive** regarding commercial use (no charging) + +## Compatibility + +This license is **NOT** compatible with: +- GNU GPL (due to no-charging restriction) +- Most commercial licenses +- Licenses that permit charging fees + +This license **IS** compatible with: +- Academic use +- Personal use +- Non-commercial distribution +- Open source projects that don't charge fees + +## Historical Context + +Written during the early days of free software sharing via USENET, this license reflects the collaborative spirit of the late 1980s Unix gaming community, where source code sharing was common and commercial software distribution was less prevalent. + +--- + +*This license text is preserved exactly as written by Richard Caley in 1989.* diff --git a/richard-caley-utilities/Makefile b/richard-caley-utilities/Makefile new file mode 100644 index 0000000..d0a8535 --- /dev/null +++ b/richard-caley-utilities/Makefile @@ -0,0 +1,132 @@ +# +SHELL=/bin/sh +SHAR=/usr/bin/shar +MAKE=/usr/bin/make + +# +# Will most likely have to edit the location of the +# X Libraries. +# +Libs_sun= -lpixrect +Libs_x= -L/usr/lib -lX11 + +WHICHconqrast: WHICHconqrast.o error.o WHICHstuff.o file.o util.o + cc $(CFLAGS) -o WHICHconqrast WHICHconqrast.o WHICHstuff.o file.o\ + util.o error.o $(Libs_WHICH) + +error.o: error.c +file.o: file.c +util.o:util.c + +WHICHconqrast.o: conqrast.c WHICHconqrast.h file.h ../header.h + $(CC) $(CFLAGS) -c conqrast.c -DHEADERFILE=\"WHICHconqrast.h\" + mv conqrast.o WHICHconqrast.o + +WHICHstuff.o: WHICHstuff.c WHICHconqrast.h + +lint.WHICH: + lint -abchx -DHEADERFILE=\"WHICHconqrast.h\" \ + conqrast.c WHICHstuff.c error.c file.c util.c $(Libs_WHICH) + +### don't delete this line! + +all: sunconqrast xconqrast + +lint: lint.sun lint.x + +lint.sun: makefile.sun + $(MAKE) $(MFLAGS) -f makefile.sun lint.sun + +lint.x: makefile.x + $(MAKE) $(MFLAGS) -f makefile.x lint.x + +sun sunconqrast: makefile.sun conqrast.c sunstuff.c sunconqrast.h file.c\ + file.h util.c + $(MAKE) $(MFLAGS) -f makefile.sun sunconqrast + +makefile.sun : Makefile + sed -e '/^###/q' -e '/WHICH/s//sun/g' Makefile > makefile.sun + +x xconqrast: makefile.x conqrast.c xstuff.c xconqrast.h file.c file.h util.c + $(MAKE) $(MFLAGS) -f makefile.x xconqrast + +makefile.x : Makefile + sed -e '/^###/q' -e '/WHICH/s//x/g' Makefile > makefile.x + +shar.core: conqrast.c + shar -c -v conqrast.c > shar.core + +shar.sun: sunstuff.c sunconqrast.h + shar -c -v sunstuff.c sunconqrast.h > shar.sun + +shar.x: xstuff.c xconqrast.h + shar -c -v xstuff.c xconqrast.h > shar.x + +shar.general: Makefile README error.c file.c file.h util.c conqrast.man + shar -c -v Makefile README conqrast.man error.c file.c file.h util.c > shar.general + +shar: shar.general shar.sun shar.x shar.core + +checkpoint: + cp Makefile README *.[ch] *.man old + /bin/rm *.diff newfiles difffiles + +clean: + /bin/rm -f *.o *.diff patch shar.* *~ "#*" makefile.* newfiles difffiles + +diffs: + echo -n >patch + -for i in old/* ; do \ + j=`basename $$i` ;\ + if diff -c $$i $$j > $$j.diff ;\ + then \ + /bin/rm $$j.diff ;\ + else \ + cat $$j.diff >> patch ;\ + wc $$j.diff ;\ + fi ;\ + done + +newfiles: + echo -n > newfiles + -for i in *.[ch1] ; do\ + if test -f old/$$i ; then\ + : ;\ + else \ + echo $$i >> newfiles ;\ + fi ;\ + done + +difffiles: newfiles diffs + echo -n > difffiles + -for i in *.diff ; do\ + j=`basename $$i .diff` ;\ + echo -n $$j ;\ + is=`wc $$i |colrm 9`;\ + js=`wc $$j |colrm 9`;\ + echo " " $$js $$is ;\ + if test $$is -gt $$js ; then \ + echo is very new! ;\ + echo $$j >> newfiles ;\ + else \ + echo is changed ;\ + echo $$i >> difffiles ;\ + fi ;\ + done + +update: newfiles difffiles + -n=1;for i in `cat difffiles` `cat newfiles` ; do \ + lines=`wc $$them $$i| tail -1 | colrm 9` ;\ + echo $$them $$i $$lines ;\ + if test $$lines -gt 800 ; then\ + echo chop! ;\ + $(SHAR) -c -v $$them > shar.$$n ;\ + n=`expr $$n + 1` ;\ + them="$$i" ;\ + else \ + them="$$them $$i" ;\ + fi ;\ + done ;\ + $(SHAR) -c -v $$them > shar.$$n + /bin/rm newfiles difffiles + diff --git a/richard-caley-utilities/README b/richard-caley-utilities/README new file mode 100644 index 0000000..3c1987d --- /dev/null +++ b/richard-caley-utilities/README @@ -0,0 +1,13 @@ + +This directory contains the code for conqrast, a program for +displaying nice maps of conquer games on sun consoles and, sometime in +the future, on X windows displays. + +See the manual page conqrast.1 for more details. + +Bugs should probably be sent to me, Richard Caley. + + rjc@uk.ac.ed.aipna + +or permutations thereof that your local mailer demands. + diff --git a/richard-caley-utilities/README.md b/richard-caley-utilities/README.md new file mode 100644 index 0000000..aec0369 --- /dev/null +++ b/richard-caley-utilities/README.md @@ -0,0 +1,146 @@ +# Richard Caley Map Drawing Utility + +**Original Author**: Richard Caley +**Written**: July 1989 +**Purpose**: Draws maps of the Conquer world on bitmap systems + +## About This Code + +This utility was written by Richard Caley in 1989 to create visual maps of Conquer game worlds. It reads Conquer game data and generates bitmap representations of the game world, useful for: + +- Visualizing the game world layout +- Creating reference maps for players +- Administrative overview of game state +- Historical documentation of games + +## Original Description + +From the original source code header: +> "This program draws a map of the conquer world on a bitmap system" + +## Technical Notes + +- **Era**: Written in 1989 for Unix bitmap systems +- **Language**: C (typical for the period) +- **Dependencies**: Historic Unix bitmap libraries +- **Compatibility**: May require adaptation for modern systems + +## License + +This code is distributed under Richard Caley's original license terms: + +``` +You may copy, distribute, modify or do what you will with this code +so long as this message remains in it and so long as you do not charge +for it, nor distribute the program without the source. +``` + +**Key Restrictions**: +- ❌ Cannot charge money for this software +- ✅ Can copy, distribute, and modify freely +- ✅ Must include source code when distributing +- ✅ Must preserve license notice + +See `LICENSE` file for complete terms. + + +### Contact Attempts + +In September 2025, we attempted to contact Richard Caley through the University of Edinburgh Alumni Services to request explicit permission for GPL relicensing. Due to data protection policies, the university was unable to provide contact information or forward messages. This preservation effort proceeds under his original permissive license terms, using his code exactly as he intended: freely shared with full attribution and source code availability. + +## About Richard Caley + +Richard Caley was a researcher at the University of Edinburgh's Centre for Speech Technology Research (CSTR), where he made significant contributions to computational linguistics and speech synthesis technology. He was a key contributor to the Festival Speech Synthesis System, an influential open-source text-to-speech platform that became widely used in research and industry. + +Beyond his professional research work, Richard's interests ranged far beyond speech technology. A self-described "long haired, beer drinking, bisexual, computer addicted, under-lifed, gravitationally gifted" individual, Richard embodied the curious, generous spirit of the early Unix computing community. + +His technical interests were impressively diverse: ray tracing and graphics programming (using Povray and custom tools), Unix system administration (he ran FreeBSD systems), web development, telecommunications work, and of course, gaming utilities like this map drawer. He was also a devoted Kate Bush fan who contributed to the early web by converting fan documentation to HTML. + +Richard's sense of humor shines through in his archived writings. When asked about USENET etiquette, he quipped that poor punctuation was "like bad handwriting" and suggested the offender "probably write[s] in green crayon anyway." He described source code as being "like ketchup but more taisty" and admitted his book-buying habit was so bad that libraries needed "a crowbar to force it out of my hands." + +This wit and technical generosity are perfectly captured in his software license: "You may copy, distribute, modify or do what you will with this code" - followed immediately by a self-deprecating comment about "horrid hack[s]" in his implementation. This was someone who shared freely while being refreshingly honest about the pragmatic compromises of 1989 Unix programming. + +### Academic and Professional Contributions + +Richard's professional work at Edinburgh CSTR included significant contributions to computational linguistics and speech technology: + +- **Festival Speech Synthesis System**: Key contributor to this influential open-source text-to-speech platform +- **Research Publications**: Academic work in speech technology and computational linguistics (see [AMiner profile](https://aminer.org/profile/r-caley/65d6f2bdc136ef133132e1d0)) +- **Open Source Development**: Applied the same generous sharing philosophy to both academic and hobby programming + +His involvement in Festival demonstrates how his collaborative approach extended from game utilities like this map drawer to serious academic software development. The same spirit of open sharing and technical pragmatism that characterizes this 1989 gaming utility also influenced major speech synthesis research tools. + +### Historical Context + +This utility represents an early example of game data visualization tools, created during the pioneering era of Unix-based multiplayer gaming. Richard's approach to sharing code with such permissive terms was typical of the collaborative culture that defined early Unix computing communities. + +## In Memory + +Richard Caley passed away in 2006. This code is preserved in his memory and as a testament to the early Unix gaming community's collaborative spirit. + +### Historical Materials + +For researchers interested in early Unix computing culture and Richard Caley's broader contributions: + +- **[Personal Homepage](https://web.archive.org/web/20060621153455/http://richard.caley.org.uk/)** - His main site showing diverse technical interests +- **[Academic Directory](https://web.archive.org/web/20050212154854/http://www.cogsci.ed.ac.uk/~rjc/)** - Research work at Edinburgh CSTR +- **[Festival Speech Synthesis](https://github.com/festvox/festival/blob/master/ACKNOWLEDGMENTS)** - His contributions to major speech synthesis research +- **[Research Publications](https://aminer.org/profile/r-caley/65d6f2bdc136ef133132e1d0)** - Academic work in computational linguistics +- **[Graphics Gallery](https://web.archive.org/web/20021209075818fw_/http://flowers.ofthenight.org/gallery/index.html)** - Ray tracing art "created with Povray, perl, qbasic, brute force and awkwardness" +- **[The Wit and Wisdom of Richard Caley](https://web.archive.org/web/20060428074215/http://richard.caley.org.uk/caleyisms.html)** - Collection of his humorous USENET posts +- **[Kate Bush Fan Work](https://gaffa.org/cloud/richard_caley.html)** - His contribution to early web fan communities + +These archived materials provide invaluable insight into the personalities and culture of the early Unix development community. Richard's combination of technical skill, generous code sharing, and self-deprecating humor represents the collaborative spirit that made early computing communities so innovative. + +### Note on Biographical Information + +The information about Richard Caley presented here has been compiled from publicly archived web materials and USENET posts. While we have made every effort to represent him accurately and respectfully, we acknowledge that internet archives may not provide the complete picture of his life and work. + +We welcome corrections, additional information, or clarification from anyone who knew Richard personally or professionally. If any of the information presented here causes discomfort to family members, colleagues, or friends, we are committed to updating or removing content as appropriate. + +Please contact the repository maintainers if you have: +- Corrections to biographical details +- Additional context about his work or contributions +- Concerns about how his memory is being represented +- Family or personal perspectives we should consider + +Our goal is to honor Richard Caley's contribution to early computing while being respectful of his memory and those who knew him. + +## Usage Notes + +1. **Historical Code**: This is 1989-era C code and may require significant adaptation for modern systems +2. **Game Integration**: Designed to work with Conquer game data files +3. **Bitmap Output**: Originally targeted Unix bitmap display systems +4. **Educational Value**: Excellent reference for understanding early game visualization techniques + +## Contributing + +Due to the original author's passing, we cannot accept contributions to this specific code. However: + +- Bug reports documenting historical behavior are welcome +- Documentation improvements are appreciated +- Modern ports or spiritual successors can be developed separately under different licensing + +## Building + +Original build instructions (may require adaptation): + +```bash +# Note: This is historical - modern systems will likely need modification +make +``` + +Modern developers should expect to: +- Update include files for current systems +- Adapt bitmap library calls +- Modify file I/O for current Conquer data formats + +## Related Files + +- Integrates with main Conquer game data (see `../gpl-release/`) +- May reference game world files and player data +- Output intended for period-appropriate bitmap viewers + +--- + +*This software component is preserved for historical and educational purposes, maintaining the original author's contribution to early Unix gaming.* diff --git a/richard-caley-utilities/conqrast.c b/richard-caley-utilities/conqrast.c new file mode 100644 index 0000000..1841507 --- /dev/null +++ b/richard-caley-utilities/conqrast.c @@ -0,0 +1,792 @@ +#include +#include +#include +#include "../header.h" +#include "file.h" +#include HEADERFILE + +/********************************************************************* +* * +* This program draws a map of the conquer world on a bitmap system * +* * +* Written by Richard Caley July 1989 and hacked extensively * +* thereafter. * +* * +* You may copy, distribute, modify or do what you will with this * +* code so long as this message remains in it and so long as you do * +* not charge for it, nor distribute the program without the source. * +* * +* There is a horrid hack for getpass - to make this read the * +* password from standard in one has to disconnect from the control * +* terminal. GAG! It should be possible to disconnect just the * +* conquer from the control terminal . . . someday. * +* * +* See Readme for more details. * +* * +*********************************************************************/ + +#define GAP (2) /* fudge factor - space above + * and below titles */ + +#define total_height (height*mag+ (do_title?4*GAP+2*font_height(titlefont):0)) + /* height of map and title bars */ + +#define yoffset(place) ((place)+(do_title?font_height(titlefont)+GAP+GAP:0)) + /* a y position */ + +#define tracef if(trace) printf + +char *getpass(); +void error(), ioerror(); +char *passwd=NULL; +char *nation=NULL; +int turn; +int trace=0; +int bg=0; +char conquer_version[100]; + +#define conqrast_version "1.0" + +#ifndef conqrast_name +# define conqrast_name "Some conqrast" /* this is redefined in the header */ +# define driver_version "unknown driver" +#endif + +#define HEADER_TAG "Conquer Version" /* just before first line of map */ +#define HEADER_TAG_LENGTH (sizeof(HEADER_TAG)/sizeof(char)-1) + +extern struct /* maps from size of map to the font */ + /* to use */ + { /* if size > mag use font */ + int mag; + char *romanfont,*boldfont; + } fonts[]; + +struct /* Maps from terrain to brightness */ + { + char c; + int val; /* must be between 0 and 255 */ + } values[] = + { + ' ', 256, + '~', 0, + '-', 64, + '%', 128, + '^', 192, + '#', 224, + '\0' + }; + +char *mapnames[] = + { + "This should never happen", + "Altitude", + "Vegetation", + "Nation", + "Designation" + }; + +#define num_mapnames (sizeof(mapnames)/sizeof(char *)) + +/********************************************************************* +* * +* Font mapping information. Fonts used by the system have symbolic * +* names so they can be referred to on the commend line. font_table * +* records which fonts go with which name. * +* * +*********************************************************************/ + +enum mapfont + { + f_nation, + f_designation, + f_title, + f_last + }; + +struct + { + char *name; + font romanfont; + font boldfont; + } font_table[(unsigned)f_last+1] = + { + {"nation"}, + {"designation"}, + {"title"}, + {NULL} + }; + +#define MAXDITHER 4 /* don't touch this */ + +short dit[1<= mag ) + break; + else if (fonts[i].mag < mag ) + { + if(bad_font(font_table[(unsigned)f].romanfont= + font_named(fonts[i].romanfont))) + error("Can't get font '%s' as %s font", + fonts[i].romanfont,font_table[(unsigned)f].name); + if ( font_table[(unsigned)f].boldfont==NULL && fonts[i].boldfont !=NULL) + if (bad_font(font_table[(unsigned)f].boldfont= + font_named(fonts[i].boldfont))) + error("Can't get font '%s' as bold %s font", + fonts[i].romanfont,font_table[(unsigned)f].name); + } + } + if(font_table[(unsigned)f].romanfont==NULL) + error("No font small enough for size %d %s",mag,font_table[(unsigned)f].name); + } + + } + +/********************************************************************* +* * +* Set up a single font. if the name is in the table ( or is a prefix * +* ) then insert the name into the font table. If the name begins * +* with 'b' then sets the bold font. * +* * +*********************************************************************/ + +void +set_a_font(name,fontname) + +char *name; +char *fontname; + +{ + int i,bold=0,l; + font thefont; + + if( name[0]=='b') + { + name++; + bold=1; + } + + l=strlen(name); + + for (i=0;i< (int)f_last;i++) + if (!strncmp(name,font_table[i].name,l)) + break; + + if ( i == (int)f_last) + error("Unknown font name '%s'",name); + + thefont=font_named(fontname); + + if ( bad_font(thefont) ) + error("Can't get font '%s'",fontname); + + if (bold) + font_table[i].boldfont=thefont; + else + font_table[i].romanfont=thefont; + } + +/********************************************************************* +* * +* scan over the header of the map. Returns the number of the map, or * +* 0 if the map is bad. If `pipe' is != 0 then the input is a pipe * +* and an eof implies a bad password. * +* * +* Tries to cope with DEBUG and none-DEBUG conquers * +* * +*********************************************************************/ + +scan_header(f,pipe) + +FILE *f; +int pipe; + +{ + char line[1024]; + char which[100]; + static char who[100]; + int mapid; + + while ( fgets(line,1024,f) != NULL) /* scan to top of map */ + { + if (!strncmp(line,HEADER_TAG,HEADER_TAG_LENGTH)) + break; + } + + if (feof(f)) + { + if(pipe) + error("Password incorrect"); + else + error("Unexpected end of map file"); + } + + if (sscanf(line,"Conquer Version %[0-9.] : %s Map %*s %*s %s on Turn %d",conquer_version,which,who,&turn)!=4) + error("Bad title line (wrong version?) '%s'",line); + + for(mapid=1;mapid < num_mapnames;mapid++) + if(!strcmp(mapnames[mapid],which)) + break; + + if ( mapid==num_mapnames) + mapid= 0; + else if ( trace && !pipe) + printf("Found %s map\n", which); + + if(!strcmp(who,"World")) + nation="god"; + else + nation=who; + + tracef("Nation is %s\n",nation); + + return mapid; + } + +/********************************************************************* +* * +* Find maps in a file and store away a file pointer and offset for * +* each * +* * +*********************************************************************/ + +void +process_map_file(name) + +char *name; + +{ + int which; + FILE *f; + char line[1024]; + + tracef("Searching file %s\n",name); + + if ((f=fopen(name,"r"))==NULL) + ioerror("Can't open map file '%s'",name); + + while(1) + { + long top; + + which=scan_header(f,0); + + if(which==0) + error("Bad map file '%s'",name); + + myopen(which,f); + top=ftell(f); + while(fgets(line,1024,f)!=NULL) + { + if (!strncmp(line,HEADER_TAG,HEADER_TAG_LENGTH)) + break; + top=ftell(f); + } + + if(feof(f)) + break; + + fseek(f,top,0); + } + } + +/********************************************************************* +* * +* Get a map. If the map was not in one of the files on the command * +* line it runs conquer -p to get it. * +* * +* Which selects the map. * +* Args are passed to conqrun. * +* Tmpname is the name of a temporary file to use. This is * +* deleted in this routine so you can reuse the name. * +* * +* All except `which' are ignored if the user has given a map * +* file of the correct type as an argumant. * +* * +*********************************************************************/ + +int +get_map_file(which,args,tmpname) + +int which; +char *args; +char *tmpname; + +{ + char command[100]; + FILE *tmp; + + if ( ! myisopen(which)) + { + if (nation==NULL) + { + tracef("Assuming god\n"); + + nation="god"; + } + + tracef("Asking conquer for %s map\n",mapnames[which]); + + if (passwd==NULL) + { + passwd=getpass("Enter conquer password: "); + } + + tracef("Disconnecting ( HACK! ) bye bye\n"); + + disconnect(); /* disconnect from controling tty */ + /* ( hack for getpass ) */ + + if (bg) /* go into background if asked */ + { + tracef("Going into background\n"); + + background(); + } + + sprintf(command,"conquer -p %s > %s 2>/dev/null",args,tmpname); + + if((tmp=popen(command,"w"))==NULL) + ioerror("can't run conquer"); + + if (fprintf(tmp,"%s\n%s\n%c\n",nation,passwd, which+'0')==EOF) + error("Couldn't get map. Conquer may be updating.\n"); + + pclose(tmp); + + if((tmp=fopen(tmpname,"r"))==NULL) + ioerror("can't open %s",tmpname); + + unlink(tmpname); /* delete it */ + + (void)scan_header(tmp,1); + myopen(which,tmp); + } + + return which; + } + +/*ARGSUSED*/ +main(argc,argv) + +int argc; +char *argv[]; + +{ + char line[1024]; + char desline[1024]; + char tmpname[20]; + char args[100]; + char *screen_name=get_default_screen_name(); + screen_type screen=NULL; + int mapfile; + int destmapfile; + int mag=11; + bitmap pr; + int width,height; + extern char *myname; + int x,y,i,j,val; + char c; + char *mapname=NULL; + char *world=NULL; + int do_nations=0,barbarians=0,markbarbs=0; + int all=0,live=0,altitude=1; + int desig=0; + int do_title=1; + font titlefont; + int boldtitle=0; /* indicates that the title font should be + emboldened - ie `titlefont' is roman and + so _we_ must do the bold */ + + + myname=argv[0]; + + strcpy(args,""); + + while(*(++argv)!=NULL) + if (!strncmp(*argv,"-o",2)) + { + mapname= *(++argv); + if ( is_screenname(mapname)) + { + screen_name=mapname; + mapname=NULL; + } + } + else if (!strcmp(*argv,"-l")) + live++; + else if (!strcmp(*argv,"-D")) + sprintf(args,"%s -d %s",args,world= *(++argv)); + else if (!strcmp(*argv,"-N")) + nation= *(++argv); + else if (!strcmp(*argv,"-bg")) + bg++; + else if (!strcmp(*argv,"-a")) + altitude=0; + else if (!strcmp(*argv,"-f")) + { + char *which= *(++argv), *fontname= *(++argv); + set_a_font(which,fontname); + } + else if (!strncmp(*argv,"-b",2)) + { + barbarians++; + if ( (*argv)[2]=='a') + markbarbs++; + } + else if (!strcmp(*argv,"-m")) + mag=atoi(*(++argv)); + else if (!strncmp(*argv,"-c",2)) + { + c=(*argv)[2]; + for (i=0;;i++) + { + if (values[i].c =='\0') + error("Unknown contour '%c'",c); + else if ( values[i].c == c) + { + values[i].val=atoi(*(++argv)); + break; + } + } + } + else if (!strncmp(*argv,"-n",2)) + { + do_nations++; + if ( (*argv)[2]=='a') + ++all; + } + else if (!strncmp(*argv,"-d",2)) + { + desig++; + } + else if (!strcmp(*argv,"-h")) + help_message(myname); + else if (!strcmp(*argv,"-t")) + do_title=0; + else if (!strcmp(*argv,"-v")) + trace++; + else if ( (*argv)[0]=='-') + { + printf("Unknown option '%s'\n",*argv); + help_message(myname); + } + else + process_map_file(*argv); + + if (do_nations) /* if we have to put in nations */ + set_default_fonts(mag,f_nation); + + if (desig) + { + if (all) + error("Only one of -d and -na allowed!"); + + set_default_fonts(mag,f_designation); + } + + if (do_title) + { + set_default_fonts(mag+2,f_title); + if ( (titlefont=font_table[(unsigned)f_title].boldfont)==NULL) + { + boldtitle=1; + titlefont=font_table[(unsigned)f_title].romanfont; + } + + } + + screen=screen_named(screen_name); + + sprintf(tmpname,"/tmp/conq%d",getpid()); + + mapfile=get_map_file(altitude?1:3, /* get a map */ + args,tmpname); + + if(mygets(line,1024,mapfile)==NULL) + error("empty map!"); + + width=strlen(line)-1; /* count height and width */ + + for(height=1;mygets(line,1024,mapfile)!=NULL;height++) + if(!strncmp(line,HEADER_TAG,HEADER_TAG_LENGTH)|| + !strncmp(line,"reading",7)) + break; + + tracef("Size %d X %d, image %d X %d\n",width,height,width*mag,height*mag); + + initialise_bitmaps(); + + if(live) /* if live do it on the screen */ + { + if ((pr=get_screen_bitmap(screen))==(bitmap)NULL) + ioerror("Can't open screen %s",screen_name); + } + else /* otherwise in memory */ + pr=create_bitmap(width*mag,total_height); + + myrewind(mapfile); + + if (altitude) /* if needed do altitude */ + { + int xx,yy; + tracef("Drawing topography\n"); + + build_dither_matrix(MAXDITHER); + + yy=yoffset(0); + for(y=0;y=val?1:0); + } + } + } + + myclose(mapfile); + } + + if(do_nations||desig) /* nations */ + { + font nf, bnf; + font df; + int xx,yy; + char des, + current='\0'; /* keeps track of which nation we are in */ + char last[1024]; /* ditto vertically for each column */ + + tracef("Drawing nations\n"); + + if (do_nations) + { + nf = font_table[(unsigned)f_nation].romanfont; + bnf = font_table[(unsigned)f_nation].boldfont; + } + + if (desig) + { + df = font_table[(unsigned)f_designation].romanfont; + } + + if (altitude) /* if no altitude this was gotten to */ + /* count the size */ + mapfile=get_map_file(3,args,tmpname); + + destmapfile=get_map_file(4,args,tmpname); + + yy=yoffset(mag); + for(y=0;y mapfile' +.PP +If you do not supply a mapfile which is needed to produce the map you +request ( altitude unless `\fB-a\fR'; nation and designation for `-n'; +designation for `\fB-d\fR' ) \fIconqrast\fR will prompt you for the nation's +password and attempt to run +.IP +conquer -p -n\fIname\fR +.PP +to get the map it wants. + +More than one map may be put into a single file as shown in the example below. + +.SH EXAMPLE +.IP +.br +% \fBconquer -p -nTolland >mapfile\fR +.br +conquer Version 4.4: Copyright (c) 1988 by Edward M Barlow +.br + +.br +What is your Nation's Password: +.br + +.br +For convenience, this output is to stderr, +.br +while the maps will be sent to stdout. +.br + +.br +The valid options are, +.br +1) altitudes +.br +2) vegetations +.br +3) nations +.br +4) designations +.br + +.br +What type of map? \fB1\fR +.br + +.br +doing print of altitude +.br +% \fBconquer -p -nTolland >> mapfile\fR +.br +conquer Version 4.4: Copyright (c) 1988 by Edward M Barlow +.br + +.br +What is your Nation's Password: +.br + +.br +For convenience, this output is to stderr, +.br +while the maps will be sent to stdout. +.br + +.br +The valid options are, +.br +1) altitudes +.br +2) vegetations +.br +3) nations +.br +4) designations +.br + +.br +What type of map? \fB3\fR +.br + +.br +doing print of nations +.br +% \fBsunconqrast -n -m 11 mapfile\fR +.br +Enter conquer password: +.br + +notice how it prompts for your password when it +finds it needs the designation map which was not given in the file. + +.SH PROBLEMS + +.I +xconqrast +does not work yet! not even slightly. Don't even think of it. + +The method used to produce bold when there is no bold font is +rather poor. + +no fonts for small maps ( < mag 9 ) on my machine so that is +the minimum. If you want a smaller one have a look in +/usr/lib/fonts/fixedwidthfonts on your machine or create your +own. In the latter case, you could send it to me too . . . + +The way -o works makes it impossible to draw live on a +non-standard screen then dump to a file. Doesn't seem to be +likely to cause anyone too many problems ( famous last words! +). + + +.SH "THINGS TO DO" + +create a set nice fonts ( different sizes ) for designations +so that they can be represented by a symbol rather than by a +letter. + +disconnect the conquer process from the terminal rathert then +sunconqrast. + +better help message. + +.SH SEE ALSO +conquer(6) rasterfile(5) screenload(1) bitmap(1x) +.SH AUTHER +Richard Caley diff --git a/richard-caley-utilities/error.c b/richard-caley-utilities/error.c new file mode 100644 index 0000000..80dc77a --- /dev/null +++ b/richard-caley-utilities/error.c @@ -0,0 +1,37 @@ +#include +#include +#include + +/* int errno; */ +/* char *sys_errlist[]; */ + +char *myname="Someone"; + +/*VARARGS1*/ +void +ioerror(str,arg1,arg2,arg3) + +char *str; +int arg1, arg2, arg3; + +{ +fprintf(stderr,"%s: ",myname); +fprintf(stderr,str,arg1,arg2,arg3); +fprintf(stderr," - %s\n",sys_errlist[errno]); +exit(1); +} + +/*VARARGS1*/ +void +error(str,arg1,arg2,arg3) + +char *str; +int arg1, arg2, arg3; + +{ +fprintf(stderr,"%s: ",myname); +fprintf(stderr,str,arg1,arg2,arg3); +fputc('\n',stderr); +exit(1); +} + diff --git a/richard-caley-utilities/file.c b/richard-caley-utilities/file.c new file mode 100644 index 0000000..0f9e948 --- /dev/null +++ b/richard-caley-utilities/file.c @@ -0,0 +1,90 @@ +#include +#include "file.h" + +/********************************************************************* +* * +* All the my* routines mimic stdio routines but manipulate struct * +* file's The point is that we can read from and otherwise manipulate * +* more than one place in a file ( for more than one map ). * +* * +*********************************************************************/ + +/********************************************************************* +* * +* struct file's play the roll of FILE *'s * +* * +*********************************************************************/ + +#define MAX_FILES 10 + +static struct file + { + FILE *fd; /* which file */ + long offset, /* where are we reading from now */ + top; /* where is the notional start */ + } file_table[MAX_FILES]; + + +void +myopen(which,file) + +int which; +FILE *file; + +{ +file_table[which].fd=file; +file_table[which].offset=file_table[which].top=ftell(file); +} + +myisopen(which) + +int which; + +{ +return file_table[which].fd != NULL; +} + +char * +mygets(buffer,num,which) + +char *buffer; +int num; +int which; +{ + fseek(file_table[which].fd,file_table[which].offset,0); + + buffer=fgets(buffer,num,file_table[which].fd); + + file_table[which].offset=ftell(file_table[which].fd); + + return buffer; + } + +void +myrewind(which) + +int which; + +{ + fseek(file_table[which].fd,file_table[which].top,0); + file_table[which].offset=file_table[which].top; + } + +void +myclose(which) + +int which; + +{ + int i; + + for(i=0;i + +typedef struct pixrect * bitmap; +typedef char * screen_type; +typedef struct pixfont * font; + +#define initialise_bitmaps() /* EMPTY */ +#define finish_bitmaps() /* EMPTY */ + +#define is_screenname(mapname) (!strncmp(mapname,"/dev/",5)) +#define get_default_screen_name() "/dev/fb" +#define screen_named(name) (name) +#define get_screen_bitmap(screen) (pr_open(screen)) +#define create_bitmap(width,height) (mem_create(width,height,1)) +#define destroy_bitmap(bitmap) pr_close(bitmap) +#define font_named(name) pf_open(name) +#define bad_font(font) ((font)==NULL) +#define font_height(font) ((font->pf_defaultsize).y) +#define font_width(font) ((font->pf_defaultsize).x) +#define font_baseline(font) (0-(font->pf_char)['A'].pc_home.y+1) + +#define BLACK PIX_SET +#define WHITE PIX_CLR +#define DRAW_BLACK (PIX_DST|PIX_SRC) +#define DRAW_WHITE (PIX_DST&PIX_NOT(PIX_SRC)) + +#define set_bit(bitmap,x,y,val) pr_put(bitmap,x,y,val) +#define draw_line(bitmap,x1,y1,x2,y2,colour) pr_vector(bitmap,x1,y1,x2,y2,colour,0) diff --git a/richard-caley-utilities/sunstuff.c b/richard-caley-utilities/sunstuff.c new file mode 100644 index 0000000..f8a5921 --- /dev/null +++ b/richard-caley-utilities/sunstuff.c @@ -0,0 +1,93 @@ +#include +#include "sunconqrast.h" + +struct /* maps from size of map to the font */ + /* to use */ + { /* if size > mag use font */ + int mag; + char *font,*bold; + } fonts[] = + { + 9, "/usr/lib/fonts/fixedwidthfonts/screen.r.7", NULL, + 11, "/usr/lib/fonts/fixedwidthfonts/cour.r.10", + "/usr/lib/fonts/fixedwidthfonts/cour.b.10", + 12, "/usr/lib/fonts/fixedwidthfonts/cour.r.12", + "/usr/lib/fonts/fixedwidthfonts/cour.b.12", + 14, "/usr/lib/fonts/fixedwidthfonts/cour.r.14", + "/usr/lib/fonts/fixedwidthfonts/cour.b.14", + 16, "/usr/lib/fonts/fixedwidthfonts/cour.r.16", + "/usr/lib/fonts/fixedwidthfonts/cour.b.16", + 18, "/usr/lib/fonts/fixedwidthfonts/cour.r.18", + "/usr/lib/fonts/fixedwidthfonts/cour.b.18", + 22, "/usr/lib/fonts/fixedwidthfonts/cour.r.24", + "/usr/lib/fonts/fixedwidthfonts/cour.b.24", + 999999, NULL + }; + +static int encoding_type = RT_STANDARD ; + +int +argument_parse(argv) + +char *argv[]; + +{ +if ( !strcmp(*argv,"-compact")) + { + encoding_type = RT_BYTE_ENCODED ; + return 1; + } +else + return 0; +} + +/*ARGSUSED*/ +int +write_bitmap(bm,file,width,height) + +bitmap bm; +char *file; +int width,height; + +{ + FILE *f; + + if ((f=fopen(file,"w"))==NULL) + ioerror("Can't open output file %s",file); + + return pr_dump( bm, f, RMT_NONE, encoding_type,0); + } + + + +void +display_bitmap(bm,x,y,w,h) + +bitmap bm; +int x,y,w,h; + +{ + struct pixrect *screen=pr_open("/dev/fb"); + + pr_rop(screen,x,y,w,h,PIX_SRC,bm,0,0); + + } + +bitmap_text(pr,x,y,colour,pf,str) + +bitmap pr; +int x,y; +int colour; +font pf; +char *str; + +{ + struct pr_prpos pos; + + pos.pos.x=x; + pos.pos.y=y; + pos.pr=pr; + + pf_text(pos,colour,pf,str); + } + diff --git a/richard-caley-utilities/util.c b/richard-caley-utilities/util.c new file mode 100644 index 0000000..54c7548 --- /dev/null +++ b/richard-caley-utilities/util.c @@ -0,0 +1,112 @@ +#include +#include +#include + +/********************************************************************* +* * +* various utility bits split off to try and get conqrast.c down to a * +* reasonable size * +* * +*********************************************************************/ + + +/********************************************************************* +* * +* routine to build the dither matrix used to shade * +* * +*********************************************************************/ + +#define MAXDITHER 4 /* don't touch this */ + +short dit[1<\n",me); + printf("\t\t-N \n"); + printf("\t\t-D \n"); + printf("\t\t-c \n"); + printf("\t\t-f \n"); + printf("\t\t-d -n{a} -b{a} -m -a -bg -l -t -v\n"); + exit(1); + } + diff --git a/richard-caley-utilities/xconqrast.h b/richard-caley-utilities/xconqrast.h new file mode 100644 index 0000000..adb4744 --- /dev/null +++ b/richard-caley-utilities/xconqrast.h @@ -0,0 +1,37 @@ + +/* header for X */ + +#define driver_version "preliminary" +#define conqrast_name "Xconqrast" + +#include + +typedef Drawable bitmap ; +typedef Display *screen_type; +typedef char *font; /* this needs doing */ + +#define is_screenname(name) (index(name,':')!=NULL) /* I think */ +#define get_default_screen_name() NULL /* I have no idea */ + +screen_type screen_named(); + +bitmap get_screen_bitmap(); +bitmap create_bitmap(); + +#define destroy_bitmap(bm) /* I don't know how to */ +#define font_named(name) (name) /* ditto */ +#define bad_font(font) ((font)==NULL) /* ??? */ +#define font_height(font) (0) /* ??? */ +#define font_width(font) (0) /* ??? */ +#define font_baseline(font) (0) /* ??? */ + +#define BLACK (1) +#define WHITE (0) /* guessing */ +#define DRAW_BLACK (1) /* ?? */ +#define DRAW_WHITE (2) + +void set_bit(); + +#define draw_line(bitmap,x1,y1,x2,y2,colour) /* again no idea! */ + + diff --git a/richard-caley-utilities/xstuff.c b/richard-caley-utilities/xstuff.c new file mode 100644 index 0000000..2e61455 --- /dev/null +++ b/richard-caley-utilities/xstuff.c @@ -0,0 +1,154 @@ +#include +#include "xconqrast.h" + +/* utilities for X */ + +Display *display; +Drawable root; +int screen; +GC gc; +short greyscale; + +struct /* maps from size of map to the font */ + /* to use */ + { /* if size > mag use font */ + int mag; + char *font,*bold; + } fonts[] = /* copied from the sun driver! need replacing */ + { + 9, "/usr/lib/fonts/fixedwidthfonts/screen.r.7", NULL, + 11, "/usr/lib/fonts/fixedwidthfonts/cour.r.10", + "/usr/lib/fonts/fixedwidthfonts/cour.b.10", + 12, "/usr/lib/fonts/fixedwidthfonts/cour.r.12", + "/usr/lib/fonts/fixedwidthfonts/cour.b.12", + 14, "/usr/lib/fonts/fixedwidthfonts/cour.r.14", + "/usr/lib/fonts/fixedwidthfonts/cour.b.14", + 16, "/usr/lib/fonts/fixedwidthfonts/cour.r.16", + "/usr/lib/fonts/fixedwidthfonts/cour.b.16", + 18, "/usr/lib/fonts/fixedwidthfonts/cour.r.18", + "/usr/lib/fonts/fixedwidthfonts/cour.b.18", + 22, "/usr/lib/fonts/fixedwidthfonts/cour.r.24", + "/usr/lib/fonts/fixedwidthfonts/cour.b.24", + 999999, NULL + }; + +int +argument_parse(argv) + +char *argv[]; + +{ +return 0; +} + +void +initialise_bitmaps() + + + + +{ + } + +screen_type +screen_named(name) + +char *name; + +{ +int sc; + +if ((display=XOpenDisplay(name)) == NULL) + error("No X server!"); + +root=XDefaultRootWindow(display); +sc=XDefaultScreen(display); +gc=XDefaultGC(display,sc); + +return display; +} + +bitmap +get_screen_bitmap(screen) + +screen_type screen; + +{ +int sc; +return root; +} + +bitmap +create_bitmap(width,height) + +int width,height; + +{ +int depth=1; + +if ( depth != 1 ) + greyscale=1; + +return XCreatePixmap(display,root,width,height,depth); +} + +void +set_bit(bm,x,y,val) + +bitmap bm; +int x,y; +int val; + +{ + +if (!greyscale ) + { + XSetForeground(display,gc,(unsigned long)val); + XDrawPoint(display,bm,gc,x,y); + } +else + if (val) + XDrawPoint(display,bm,gc,x,y); +} + +void +display_bitmap( bm,x,y,width,height) + +bitmap bm; +int x,y,width,height; + +{ +XCopyArea(display,bm,root,gc,0,0,width,height,x,y); + } + +int +write_bitmap(bm,file,width,height) + +bitmap bm; +char *file; +int width,height; +{ + +return XWriteBitmapFile(display,file,bm,width,height,-1,-1); + } + + +void +finish_bitmaps() + +{ +XCloseDisplay(display); +} + +bitmap_text(bm,x,y,colour,pf,str) + +bitmap bm; +int x,y; +int colour; +font pf; +char *str; + +{ + /* ??? */ + } + diff --git a/scripts/build-debian.sh b/scripts/build-debian.sh index 4b7163f..e5ca9c9 100755 --- a/scripts/build-debian.sh +++ b/scripts/build-debian.sh @@ -1,23 +1,69 @@ -#!/usr/bin/env sh +#!/usr/bin/env bash -#!/bin/bash -# Equivalent to your build-melange.sh but for Debian packages +# Debian package build for ConquerV5 from gpl-release source +# Updated to work with source code in gpl-release/ folder without copying back to root set -e +# Get the directory containing this script +SCRIPT_DIR="$(dirname "$0")" +# Get the repo root (parent of scripts directory) +REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" + +echo "Script directory: $SCRIPT_DIR" +echo "Repository root: $REPO_ROOT" + # Build the Docker image if it doesn't exist if ! docker images | grep -q conquer-debian-builder; then echo "Building Debian packaging Docker image..." - docker build -t conquer-debian-builder packaging/debian/docker/ + docker build -t conquer-debian-builder "$REPO_ROOT/packaging/debian/docker/" fi # Build the Debian package -echo "Building Debian package..." +echo "Building Debian package from gpl-release source..." docker run --privileged --rm \ - -v "$PWD":/work \ + -v "$REPO_ROOT":/work \ -w /work \ conquer-debian-builder \ - /work/packaging/debian/docker/build.sh + bash -c " + # Create a temporary build directory to avoid polluting the repo root + mkdir -p /tmp/build-conquer + cd /tmp/build-conquer + + # Copy source from gpl-release to the temporary build directory + echo 'Copying source from gpl-release to temporary build directory...' + cp -r /work/gpl-release/* . 2>/dev/null || true + + # Copy debian packaging files to the build directory + cp -r /work/packaging/debian ./ + + # Run the build from the temporary directory + echo 'Building Debian package...' + /work/packaging/debian/docker/build.sh + + # Copy the built packages back to the mounted work directory + mkdir -p /work/packages/debian + if [ -d packages/debian ]; then + cp packages/debian/* /work/packages/debian/ 2>/dev/null || true + fi + + # Also check for packages in parent directory (common debian build location) + if [ -f ../*.deb ]; then + cp ../*.deb /work/packages/debian/ 2>/dev/null || true + fi + + echo 'Package files copied to /work/packages/debian/' + " echo "Debian package built successfully!" echo "Package location: packages/debian/" + +# Verify packages were created +if [ -d "$REPO_ROOT/packages/debian" ] && [ "$(ls -A "$REPO_ROOT/packages/debian" 2>/dev/null)" ]; then + echo "✅ Found Debian packages:" + ls -la "$REPO_ROOT/packages/debian/" +else + echo "⚠️ No packages found in packages/debian/" + echo "Checking for packages in other locations..." + find "$REPO_ROOT" -name "*.deb" -type f 2>/dev/null | head -5 +fi diff --git a/scripts/build-melange.sh b/scripts/build-melange.sh index a999112..f19a1c4 100755 --- a/scripts/build-melange.sh +++ b/scripts/build-melange.sh @@ -1,2 +1,63 @@ -docker run --privileged --rm -v "$PWD":/work -w /work \ - cgr.dev/chainguard/melange build packaging/melange/melange.yaml --arch x86_64 \ No newline at end of file +#!/bin/bash +# ConquerV5 Melange package build script - using local copy approach + +set -e + +# Get the directory containing this script +SCRIPT_DIR="$(dirname "$0")" +# Get the repo root (parent of scripts directory) +REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" + +echo "Script directory: $SCRIPT_DIR" +echo "Repository root: $REPO_ROOT" + +# Change to repo root directory +cd "$REPO_ROOT" + +# Ensure we have the melange configuration +if [ ! -f "packaging/melange/melange.yaml" ]; then + echo "Error: melange.yaml not found in packaging/melange/" + exit 1 +fi + +# Verify gpl-release directory exists +if [ ! -d "gpl-release" ]; then + echo "Error: gpl-release directory not found in repo root" + echo "Contents of repo root:" + ls -la + exit 1 +fi + +# Create packages directory +mkdir -p packages/alpine + +echo "=== Building ConquerV5 APK package with Melange ===" + +# Install melange if not available +if ! command -v melange &> /dev/null; then + echo "Installing melange..." + # Using Docker with melange + docker run --privileged --rm -v "$PWD":/work -w /work \ + cgr.dev/chainguard/melange build packaging/melange/melange.yaml --arch x86_64 + +else + # Use local melange installation + melange build \ + --arch=x86_64 \ + --out-dir=packages/alpine \ + packaging/melange/melange.yaml +fi + +echo "=== APK package built successfully! ===" +echo "Package location: packages/alpine/" +ls -la packages/alpine/ + +# Verify the package was created +APK_COUNT=$(find packages/alpine/ -name "*.apk" | wc -l) +if [ "$APK_COUNT" -eq 0 ]; then + echo "ERROR: No APK packages were created!" + exit 1 +fi + +echo "✅ Found $APK_COUNT APK package(s)" +find packages/alpine/ -name "*.apk" -exec ls -lh {} \; diff --git a/scripts/test-alpine.sh b/scripts/test-alpine.sh index 712d9ea..33228fd 100755 --- a/scripts/test-alpine.sh +++ b/scripts/test-alpine.sh @@ -1,3 +1,20 @@ +#!/usr/bin/env sh + +# Test the Alpine package built from gpl-release source +# Packages should be in packages/x86_64/ after running build-melange.sh + +# Check if package exists +if [ ! -f packages/x86_64/conquer-4.12-r0.apk ]; then + echo "Error: Package not found at packages/x86_64/conquer-4.12-r0.apk" + echo "Please run scripts/build-melange.sh first" + echo "" + echo "Available packages:" + ls -la packages/x86_64/ 2>/dev/null || echo "packages/x86_64/ directory doesn't exist" + exit 1 +fi + +echo "Found package: packages/x86_64/conquer-4.12-r0.apk" + # Start Alpine container with the APK available docker run --rm -it -v "$PWD":/work alpine:latest sh -c " # Install dependencies and the game @@ -16,6 +33,12 @@ docker run --rm -it -v "$PWD":/work alpine:latest sh -c " echo 'conquer # Start the game' echo 'conqrun -m # Create a world (admin)' echo '' + echo 'Package info:' + apk info conquer + echo '' + echo 'Installed files:' + apk info -L conquer | head -10 + echo '' # Drop into interactive shell /bin/sh diff --git a/scripts/test-debian.sh b/scripts/test-debian.sh index f87f98e..ce8f488 100755 --- a/scripts/test-debian.sh +++ b/scripts/test-debian.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Equivalent to your test-alpine.sh but for Debian +# Test the Debian package built from gpl-release source set -e @@ -8,6 +8,7 @@ SCRIPT_DIR="$(dirname "$0")" REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" cd "$REPO_ROOT" +echo "Testing Debian package built from gpl-release source" echo "Debug: Script location: $SCRIPT_DIR" echo "Debug: Repo root: $REPO_ROOT" echo "Debug: Current PWD: $PWD" @@ -75,4 +76,4 @@ docker run --rm -it -v "$REPO_ROOT":/work debian:trixie bash -c " # Drop into interactive shell /bin/bash -" +" \ No newline at end of file