commit d8b7fdfae1c42f6ab23e74a011d3ed12c4c78f16 Author: Markus Armbruster Date: Sat Aug 23 12:23:04 2003 +0000 Import of Empire 4.2.12 diff --git a/COPYING b/COPYING new file mode 100644 index 00000000..4e19bc56 --- /dev/null +++ b/COPYING @@ -0,0 +1,3 @@ + See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + related information and legal notices pertaining to the copying, + modification and distribution of this software. diff --git a/CREDITS b/CREDITS new file mode 100644 index 00000000..992647e6 --- /dev/null +++ b/CREDITS @@ -0,0 +1,154 @@ +This file contains a list of known contributors to Empire (either +in coding, testing, ideas or moral support. :) ) + +Empire is a multi-player, client/server Internet based war game. It +is distributed in two main parts, a server, where the game actually +runs, and clients that connect to the server. The server portion +ships with a basic client. This basic client is also available +seperately. There are also many third-party clients available. + +Empire is based on a game written in the late 70s/early 80s by Peter +Langston. Since he wouldn't give out the source code, a large reverse +engineering/re-coding project was undertaken to create a new version +of this game and make the source available for all. Since that time, +the Empire code has changed drastically and been re-written numerous +times, and none of that original code exists (other than in fond +memories) in this code base anymore. + +There have been various "stages" of Empire development. At this point +in time (October, 1998) there have been 5 major stages identified, +each with a leading author. They are as follows (with successsive +projects building on the projects before it): + + Dave Pare (mr-frog@smarttouch.com) (UCSD/BSD) + Jeff Bailey (bailey@mcs.kent.edu) (KSU (1.04) Distribution of BSD) + Thomas Ruschak (ts@ecn.purdue.edu) (Chainsaw) + Ken Stevens (KStevens@GlobeandMail.ca) (3.0.x) + Steve McClure (ionica@empire.cx) (Wolfpack) + +It is due to these above people pulling projects together that the +Empire server has gotten to where it is today. + +Empire is copyrighted and released by the 5 people above under the GNU +GPL. See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all +the related information and legal notices. It is expected that any +future projects/authors will amend these files as needed. The source +files have been updated to reflect this license, and much erroneous +data (such as bogus file headers) has been fixed. + +Empire source code has always been freely available, with the intent +of it always being freely available, it was just never properly +copyrighted or licensed until the first release under the GNU GPL +(4.2.0) It is our goal to keep Empire source free and available at all +times. + +Also see the "History" info file for a more detailed listing of +the history of Empire. + +Currently (June, 2003), Empire development is being led by the +Wolfpack team. You can find them at "http://www.wolfpackempire.com" +or e-mail "wolfpack@wolfpackempire.com". + +In addition, the people below are recognized as having either given +code to the above authors, submitted patches, helped on various +aspects of the projects (such as info pages), play tested, submitted +bug reports, bounced ideas, etc. + +Many of the source files have no listed known contributors due to the +fact that many, many people contributed anonymously. For those where +we knew who contributors were, we listed them in the header. It is +hoped that in the future contributors will put their names into this +list at the top of the file, and that new files have the same type of +header applied to them for future tracking (though obviously it is +not required.) + +We are sure that the list below is most likely incomplete, and anyone +who doesn't see your name on the below list, don't be offended, we +didn't mean it! Just send us an e-mail letting us know and we'll be +more than happy to add you. Also, let us know your latest e-mail +address if you'd like it included. + +--- + +James Anderson (jwa@k.cs.cmu.edu) +Jeff Anton (anton@postgres.berkeley.edu) +Markus Armbruster +Jeff Bailey (bailey@mcs.kent.edu) +Mark Ballinger +Jan van Beethoven +Paul Byrne +Geoff Cashman (cashman@sherrill.kiva.net) +Bill Canning +Trannie Carter +Sean Casey +David Davis +Aaron Dewell (dewell@greatland.net) +Jorge Diaz +Drake Diedrich (Drake.Diedrich@anu.edu.au) +Yaser Doleh +Ed Down +Phill Everson (everson@compsci.bristol.ac.uk) +Scott Ferguson +Robert Forsman (thoth@beach.cis.ufl.edu) +Bill Frolick +Steven Grady +Keith Graham +Jim Griffith (griffith@scam.Berkeley.EDU) +Steven Grimm (koreth@ucscb.UCSC.EDU) +Karl Hagen +Doug Hay (Doug_Hay@tsb.ca) +Ken Huisman +Lewis R. Jansen (lrj@helios.tn.cornell.edu) +Mike St. Johns (stjohns@edn-vax.arpa) +Beorn Johnson +William S. Kaster +Jeremy Kennebel +Kevin Klemmick +Ron Kuris (rk@unify.com) +Nick Lai (lai@cs.ucla.edu) +Phil Lapsley +Curtis Larsen +Robert A. Larson (blarson@skat.usc.edu) +Jonathan Lee +Craig Leres +Dan Logcher (dan@i-kinetics.com) +Pat Loney (overlord@empire.cx) +Shelley Louie (slouie@cory.berekely.edu) +Steve McClure (ionica@empire.cx) +Chris Metcalf (metcalf-christopher@yale.arpa) +Sasha Mikheev +Kevin Morgan +Richard Moss +Keith Muller (muller@sdcc7.ucsd.edu) +Chuck Musciano (chuck@trantor.harris-atd.com) +Dave Nye +Kevin O'Connor +Jeff Okamoto (okamoto%hpccc@hplabs.hp.com) +Julian Onions (jpo@computer-science.nottingham.ac.uk) +Jim Ortlieb +Dave Pare (mr-frog@smarttouch.com) +Gregory Paris +Kurt Pires (kjpires@ic.berkeley.edu) +Brett Reid +Bernhard Reiter (breiter@mathematik.Uni-Osnabrueck.DE) +Jim Reuter (reuter@decwrl.dec.com) +James Risner (risner@akira.stdio.com) +Thomas Ruschak (ts@ecn.purdue.edu) +Edward M. Rynes +David Muir Sharnoff (muir@cogsci.berkeley.edu) +Alex Shatsky +Walter Smith +Ken Stevens (KStevens@GlobeandMail.ca) +Michael Straub +Tom Tedrick +Sam Tetherow +Yannick Tremblay (yt1@eng.cam.ac.uk) +Janjaap van Velthooven +Ville Virrankoski +Peter Vukovich (peterv@monet.berkeley.edu) +Jeff Wallace (jeffw@scam.berkeley.edu) +Sverker Wiberg +Mike Wise +John Yockey (johny@verinet.com) +Chad Zabel + diff --git a/LEGAL b/LEGAL new file mode 100644 index 00000000..ca0fef50 --- /dev/null +++ b/LEGAL @@ -0,0 +1,26 @@ +****************************************************************************** + Empire - A multi-player, client/server Internet based war game. + Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + Ken Stevens, Steve McClure + + 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 2 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, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +--- + + See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + related information and legal notices. It is expected that any future + projects/authors will amend these files as needed. + +****************************************************************************** diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..60549be5 --- /dev/null +++ b/LICENSE @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) 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 +this service 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 make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. 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. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute 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 and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +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 +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the 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 a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, 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. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE 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. + + 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 +convey 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) 19yy + + 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 2 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, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision 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, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This 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 Library General +Public License instead of this License. diff --git a/Make.sysdefs b/Make.sysdefs new file mode 100644 index 00000000..33674ba6 --- /dev/null +++ b/Make.sysdefs @@ -0,0 +1,152 @@ +# +# Empire - A multi-player, client/server Internet based war game. +# Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, +# Ken Stevens, Steve McClure +# +# 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 2 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, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# --- +# +# See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the +# related information and legal notices. It is expected that any future +# projects/authors will amend these files as needed. +# +# +# Make.sysdefs - Wolfpack, 1996-2000 +# +# To add a new architecture, just copy one of the models below. Change the +# CFLAGS as needed, and then put in a target build in the Makefile. See +# the examples there on what to do. +# + +OSXCFLAGS = -g -fwritable-strings -traditional-cpp -D_EMPTH_POSIX=1 +OSXLFLAGS = -flat_namespace -undefined warning +OSXMASTER = GLOBALCFLAGS="$(OSXCFLAGS)" GLOBALLFLAGS="$(OSXLFLAGS)" + +FREEBSDRANLIB = /usr/bin/ranlib +FREEBSDCFLAGS = -DRel4 -DFBSD -ansi -pedantic #-Wall +FREEBSDLFLAGS = +FREEBSDMASTER = GLOBALCFLAGS="$(FREEBSDCFLAGS)" GLOBALLFLAGS="$(FREEBSDLFLAGS)" RANLIB="$(FREEBSDRANLIB)" + +APOLLOCFLAGS = -g +APOLLOLFLAGS = +APOLLOMASTER = GLOBALCFLAGS="$(APOLLOCFLAGS)" GLOBALLFLAGS="$(APOLLOLFLAGS)" + +NTCFLAGS = /D_WIN32 /Od /G3 /Zp2 /nologo /MT +NTLFLAGS = +NTMASTER = CC=CL GLOBALCFLAGS="$(NTCFLAGS)" GLOBALLFLAGS="$(NTLFLAGS)" + +NEXTCFLAGS = -bsd -fwritable-strings -traditional -Dconst="" -Dinline="" +NEXTLFLAGS = -lsys_s +NEXTMASTER = GLOBALCFLAGS="$(NEXTCFLAGS)" GLOBALLFLAGS="$(NEXTLFLAGS)" + +LINUXCFLAGS = -Wall -W -Wno-unused -Dlint -D__USE_BSD -D__USE_BSD_SIGNAL -DLISTENMAXCONN=5 -DRel4 +LINUXLFLAGS = +LINUXMASTER = GLOBALCFLAGS="$(LINUXCFLAGS)" GLOBALLFLAGS="$(LINUXLFLAGS)" CLIENTLIBS=-lncurses + +LINUXPTHCFLAGS = -Wall -W -Wno-unused -Dlint -D_EMPTH_POSIX=1 -U_EMPTH_LWP -D__USE_BSD -D__USE_BSD_SIGNAL -DLISTENMAXCONN=5 -DRel4 +LINUXPTHLFLAGS = -lpthread +LINUXPTHMASTER = GLOBALCFLAGS="$(LINUXPTHCFLAGS)" GLOBALLFLAGS="$(LINUXPTHLFLAGS)" CLIENTLIBS=-lncurses + +HPRANLIB = true +HPCFLAGS = -Aa -Dsys5 -DNOFLOCK -Dhpc -D_HPUX_SOURCE -Dhpux +HPLFLAGS = +HPMASTER = GLOBALCFLAGS="$(HPCFLAGS)" GLOBALLFLAGS="$(HPLFLAGS)" RANLIB="$(HPRANLIB)" CLIENTLIBS=-ltermcap + +HPUXRANLIB = true +HPUXCFLAGS = -Dsys5 -DNOFLOCK +HPUXLFLAGS = +HPUXMASTER = GLOBALCFLAGS="$(HPUXCFLAGS)" GLOBALLFLAGS="$(HPUXLFLAGS)" RANLIB="$(HPUXRANLIB)" CLIENTLIBS=-ltermcap + +IRIX5RANLIB = echo +IRIX5CFLAGS = -DSVR4 -DRel4 -DUCONTEXT -DPOSIXSIGNALS -O3 -fullwarn -woff 835,709 +IRIX5LFLAGS = -lnsl +IRIX5MASTER = GLOBALCFLAGS="$(IRIX5CFLAGS)" GLOBALLFLAGS="$(IRIX5LFLAGS)" RANLIB="$(IRIX5RANLIB)" + +IRIXRANLIB = echo +IRIXCFLAGS = -g -O -cckr -D_BSD_SIGNALS +IRIXLFLAGS = +IRIXMASTER = GLOBALCFLAGS="$(IRIXCFLAGS)" GLOBALLFLAGS="$(IRIXLFLAGS)" RANLIB="$(IRIXRANLIB)" + +ISICFLAGS = +ISILFLAGS = +ISIMASTER = GLOBALCFLAGS="$(ISICFLAGS)" GLOBALLFLAGS="$(ISILFLAGS)" + +RTPCCFLAGS = -DBSD_INCLUDES -Daix -Dsys5 $(LOCALCFLAGS) -DNOFLOCK -a +RTPCLFLAGS = +RTPCMASTER = GLOBALCFLAGS="$(RTPCCFLAGS)" GLOBALLFLAGS="$(RTPCLFLAGS)" + +SOLCFLAGS = -g -DSVR4 -DRel4 -DUCONTEXT -DPOSIXSIGNALS -DNOFLOCK -Dsolaris +SOLLFLAGS = -lnsl -lsocket -lthread +SOLMASTER = GLOBALCFLAGS="$(SOLCFLAGS)" GLOBALLFLAGS="$(SOLLFLAGS)" + +SEQCFLAGS = -O -DALLYHARBOR -DSHOWPLANE -DDROPANY -DREJECTS -DBMAP -DAUTONAV -DSCUTTLE -DCONVASAT -DORBIT -DABM -DGRIND -DPINPOINTMISSILE -DFALLOUT -DSAIL -DLOWSTARTMOB -DFIXREALMS -DBUYTAX -DNUKEFAILDETONATE -DMISSINGMISSILES +SEQLFLAGS = /usr/att/lib/libc.a -lresolv +SEQIFLAGS = -I/usr/include -I/usr/att/usr/include +SEQMASTER = GLOBALCFLAGS="$(SEQCFLAGS)" GLOBALLFLAGS="$(SEQLFLAGS)" LOCALIFLAGS="$(SEQIFLAGS)" + +SEQFPACFLAGS = -g +SEQFPALFLAGS = /usr/att/lib/libfpac.a +SEQFPAIFLAGS = -I/usr/include -I/usr/att/usr/include -fpa +SEQFPAMASTER = GLOBALCFLAGS="$(SEQFPACFLAGS)" GLOBALLFLAGS="$(SEQFPALFLAGS)" LOCALIFLAGS="$(SEQFPAIFLAGS)" + +SUN3CFLAGS = -g -f68881 +SUN3LFLAGS = +SUN3MASTER = GLOBALCFLAGS="$(SUN3CFLAGS)" GLOBALLFLAGS="$(SUN3LFLAGS)" + +SUN4CFLAGS = -DSUN4 +SUN4LFLAGS = +SUN4MASTER = GLOBALCFLAGS="$(SUN4CFLAGS)" GLOBALLFLAGS="$(SUN4LFLAGS)" + +SUN4DBGCFLAGS = -g -DSUN4 +SUN4DBGLFLAGS = +SUN4DBGMASTER = GLOBALCFLAGS="$(SUN4DBGCFLAGS)" GLOBALLFLAGS="$(SUN4DBGLFLAGS)" + +SUN4OPTCFLAGS = -O -DSUN4 +SUN4OPTLFLAGS = +SUN4OPTMASTER = GLOBALCFLAGS="$(SUN4OPTCFLAGS)" GLOBALLFLAGS="$(SUN4OPTLFLAGS)" + +AIXCFLAGS = -Daix -Dsys5 $(LOCALCFLAGS) -DNOFLOCK -D_BSD_INCLUDES -D_BSD -D_NO_PROTO -D_NONSTD_TYPES -U__STR__ -DAIX32 +AIXLFLAGS = -lbsd +AIXMASTER = GLOBALCFLAGS="$(AIXCFLAGS)" GLOBALLFLAGS="$(AIXLFLAGS)" CLIENTLIBS="-lcurses" + +ALPHACFLAGS = -DALPHA -g -std1 +ALPHALFLAGS = -non_shared -lots +ALPHAMASTER = GLOBALCFLAGS="$(ALPHACFLAGS)" GLOBALLFLAGS="$(ALPHALFLAGS)" + +ALPHAPOSCFLAGS = -D_EMPTH_POSIX=1 -U_EMPTH_LWP -D_PTHREAD_USE_D4 -D_REENTRANT -DALPHA -g -std1 +ALPHAPOSLFLAGS = -lpthreads +ALPHAPOSPFLAGS = +ALPHAPOSMASTER = GLOBALCFLAGS="$(ALPHAPOSCFLAGS)" GLOBALLFLAGS="$(ALPHAPOSLFLAGS)" GLOBALPFLAGS="$(ALPHAPOSPFLAGS)" + +MIPSULTCFLAGS = -DMIPS -DNOSTRDUP -signed +MIPSULTLFLAGS = +MIPSULTMASTER = GLOBALCFLAGS="$(MIPSULTCFLAGS)" GLOBALLFLAGS="$(MIPSULTLFLAGS)" + +MIPSULTGCFLAGS = -DMIPS -DNOSTRDUP -fsigned-char -g -O +MIPSULTGLFLAGS = +MIPSULTGMASTER = GLOBALCFLAGS="$(MIPSULTGCFLAGS)" GLOBALGLFLAGS="$(MIPSULTGLFLAGS)" + +MACH25CFLAGS = -O +MACH25LFLAGS = +MACH25MASTER = GLOBALCFLAGS="$(MACH25CFLAGS)" GLOBALLFLAGS="$(MACH25LFLAGS)" + +MIPSBSDCFLAGS = -DMIPS -DNOSTRDUP -G 33 -signed +MIPSBSDLFLAGS = -G 33 +MIPSBSDMASTER = GLOBALCFLAGS="$(MIPSBSDCFLAGS)" GLOBALLFLAGS="$(MIPSBSDLFLAGS)" + +VAXULTCFLAGS = -O -DNOSTRDUP -DPOSIXSIGNALS +VAXULTLFLAGS = +VAXULTMASTER = GLOBALCFLAGS="$(VAXULTCFLAGS)" GLOBALLFLAGS="$(VAXULTLFLAGS)" diff --git a/Makefile b/Makefile new file mode 100644 index 00000000..49f44e37 --- /dev/null +++ b/Makefile @@ -0,0 +1,561 @@ +# +# Empire - A multi-player, client/server Internet based war game. +# Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, +# Ken Stevens, Steve McClure +# +# 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 2 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, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# --- +# +# See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the +# related information and legal notices. It is expected that any future +# projects/authors will amend these files as needed. +# +# Makefile - Wolfpack, 1996-2000 +# Do a generic build just by typing in "make " +# +# Note that the NT builds were done using MSVC 5.0 and using "nmake nt" +# So, to build anything on NT, just put an "nt" in front (for example, +# "ntclean", "ntinstall", etc. + +include build.conf +include Make.sysdefs + +TOBUILD = all +GENMASTER = $(TOBUILD) GLOBALCFLAGS="$(GLOBALCFLAGS)" GLOBALLFLAGS="$(GLOBALLFLAGS)" +CLIENTLIBS = -ltermcap + + +# +# Specific targets - make a new one for each new architecture or +# build environment. +# + +all: + @echo 'You must type "make " to build for a specific system.' + @echo 'Currently buildable architectures are:' + @echo ' aix' + @echo ' alpha' + @echo ' alpha-pthreads' + @echo ' apollo' + @echo ' freebsd' + @echo ' hp' + @echo ' hpux' + @echo ' irix' + @echo ' irix5' + @echo ' isi' + @echo ' linux' + @echo ' linux-pthreads' + @echo ' mach2.5' + @echo ' mipsbsd' + @echo ' mipsultrix' + @echo ' mipsultrix.gcc' + @echo ' next' + @echo ' nt' + @echo ' osx' + @echo ' rtpc' + @echo ' sequent' + @echo ' sequent.fpa' + @echo ' solaris' + @echo ' sun3' + @echo ' sun4' + @echo ' sun4.debug' + @echo ' sun4.opt' + @echo ' vaxultrix' + +alpha: + @echo 'building a $(WORLDX) by $(WORLDY) server...' + (cd src/doconfig; $(MAKE) $(ALPHAMASTER)) + ($(MAKE) genlibs $(ALPHAMASTER)) + (cd src/lib/lwp; $(MAKE) $(ALPHAMASTER)) + ($(MAKE) binaries $(ALPHAMASTER)) + ($(MAKE) install) + +alpha-pthreads: + @echo 'building a $(WORLDX) by $(WORLDY) server...' + (cd src/doconfig; $(MAKE) $(ALPHAPOSMASTER)) + ($(MAKE) genlibs $(ALPHAPOSMASTER)) + (cd src/lib/lwp; $(MAKE) $(ALPHAPOSMASTER)) + ($(MAKE) binaries $(ALPHAPOSMASTER)) + ($(MAKE) install) + +apollo: + @echo 'building a $(WORLDX) by $(WORLDY) server...' + (cd src/doconfig; $(MAKE) $(APOLLOMASTER)) + ($(MAKE) genlibs $(APOLLOMASTER)) + (cd src/lib/lwp; $(MAKE) $(APOLLOMASTER)) + ($(MAKE) binaries $(APOLLOMASTER)) + ($(MAKE) install) + +freebsd: + @echo 'building a $(WORLDX) by $(WORLDY) server...' + (cd src/doconfig; $(MAKE) $(FREEBSDMASTER)) + ($(MAKE) genlibs $(FREEBSDMASTER)) + (cd src/lib/lwp; $(MAKE) $(FREEBSDMASTER)) + ($(MAKE) binaries $(FREEBSDMASTER)) + ($(MAKE) install) + +hp: + @echo 'building a $(WORLDX) by $(WORLDY) server...' + (cd src/doconfig; $(MAKE) $(HPMASTER)) + ($(MAKE) genlibs $(HPMASTER)) + (cd src/lib/lwp; $(MAKE) $(HPMASTER)) + ($(MAKE) binaries $(HPMASTER)) + ($(MAKE) install) + +hpux: + @echo 'building a $(WORLDX) by $(WORLDY) server...' + (cd src/doconfig; $(MAKE) $(HPUXMASTER)) + ($(MAKE) genlibs $(HPUXMASTER)) + (cd src/lib/lwp; $(MAKE) $(HPUXMASTER)) + ($(MAKE) binaries $(HPUXMASTER) CLIENTLIBS="") + ($(MAKE) install) + +next: + @echo 'building a $(WORLDX) by $(WORLDY) server...' + (cd src/doconfig; $(MAKE) $(NEXTMASTER)) + ($(MAKE) genlibs $(NEXTMASTER)) + (cd src/lib/lwp; $(MAKE) $(NEXTMASTER)) + ($(MAKE) binaries $(NEXTMASTER)) + ($(MAKE) install) + +osx: + @echo 'building a $(WORLDX) by $(WORLDY) server...' + (cd src/doconfig; $(MAKE) $(OSXMASTER)) + ($(MAKE) genlibs $(OSXMASTER)) + ($(MAKE) binaries TOBUILD=osx $(OSXMASTER) CLIENTLIBS="") + ($(MAKE) install) + +irix: + @echo 'building a $(WORLDX) by $(WORLDY) server...' + (cd src/doconfig; $(MAKE) $(IRIXMASTER)) + ($(MAKE) genlibs $(IRIXMASTER)) + (cd src/lib/lwp; $(MAKE) $(IRIXMASTER)) + ($(MAKE) binaries $(IRIXMASTER)) + ($(MAKE) install) + +irix5: + @echo 'building a $(WORLDX) by $(WORLDY) server...' + (cd src/doconfig; $(MAKE) $(IRIX5MASTER)) + ($(MAKE) genlibs $(IRIX5MASTER)) + (cd src/lib/lwp; $(MAKE) $(IRIX5MASTER)) + ($(MAKE) binaries $(IRIX5MASTER)) + ($(MAKE) install) + +isi: + @echo 'building a $(WORLDX) by $(WORLDY) server...' + (cd src/doconfig; $(MAKE) $(ISIMASTER)) + ($(MAKE) genlibs $(ISIMASTER)) + (cd src/lib/lwp; $(MAKE) $(ISIMASTER)) + ($(MAKE) binaries $(ISIMASTER)) + ($(MAKE) install) + +linux: + @echo 'building a $(WORLDX) by $(WORLDY) server...' + @echo 'This build is only tested on x86 machines. Try using' + @echo 'linux-pthreads for other architectures.' + (cd src/doconfig; $(MAKE) $(LINUXMASTER)) + ($(MAKE) genlibs $(LINUXMASTER)) + (cd src/lib/lwp; $(MAKE) $(LINUXMASTER)) + ($(MAKE) binaries $(LINUXMASTER)) + ($(MAKE) install) + +linux-pthreads: + @echo 'building a $(WORLDX) by $(WORLDY) server...' + (cd src/doconfig; $(MAKE) $(LINUXPTHMASTER)) + ($(MAKE) genlibs $(LINUXPTHMASTER)) + (cd src/lib/lwp; $(MAKE) $(LINUXPTHMASTER)) + ($(MAKE) binaries $(LINUXPTHMASTER)) + ($(MAKE) install) + +mipsbsd: + @echo 'building a $(WORLDX) by $(WORLDY) server...' + (cd src/doconfig; $(MAKE) $(MIPSBSDMASTER)) + ($(MAKE) genlibs $(MIPSBSDMASTER)) + (cd src/lib/lwp; $(MAKE) mipsultrix $(MIPSBSDMASTER)) + ($(MAKE) binaries $(MIPSBSDMASTER)) + ($(MAKE) install) + +mach2.5: + @echo 'building a $(WORLDX) by $(WORLDY) server...' + (cd src/doconfig; $(MAKE) $(MACH25MASTER)) + ($(MAKE) genlibs $(MACH25MASTER)) + (cd src/lib/lwp; $(MAKE) mipsultrix $(MACH25MASTER)) + ($(MAKE) binaries $(MACH25MASTER)) + ($(MAKE) install) + +mipsultrix: + @echo 'building a $(WORLDX) by $(WORLDY) server...' + (cd src/doconfig; $(MAKE) $(MIPSULTMASTER)) + ($(MAKE) genlibs $(MIPSULTMASTER)) + (cd src/lib/lwp; $(MAKE) mipsultrix $(MIPSULTMASTER)) + ($(MAKE) binaries $(MIPSULTMASTER)) + ($(MAKE) install) + +mipsultrix.gcc: + @echo 'building a $(WORLDX) by $(WORLDY) server...' + (cd src/doconfig; $(MAKE) $(MIPSULTGMASTER)) + ($(MAKE) genlibs $(MIPSULTGMASTER)) + (cd src/lib/lwp; $(MAKE) mipsultrix $(MIPSULTGMASTER)) + ($(MAKE) binaries $(MIPSULTGMASTER)) + ($(MAKE) install) + +nt: + @echo 'building a $(WORLDX) by $(WORLDY) server...' + cd src/doconfig + $(MAKE) nt $(NTMASTER) + cd ../.. + $(MAKE) ntgenlibs TOBUILD=nt $(NTMASTER) + cd src/lib/lwp + $(MAKE) nt $(NTMASTER) + cd ../../.. + $(MAKE) ntbinaries TOBUILD=nt $(NTMASTER) + $(MAKE) ntinstall + +vaxultrix: + @echo 'building a $(WORLDX) by $(WORLDY) server...' + (cd src/doconfig; $(MAKE) $(VAXULTMASTER)) + ($(MAKE) genlibs $(VAXULTMASTER)) + (cd src/lib/lwp; $(MAKE) $(VAXULTMASTER)) + ($(MAKE) binaries $(VAXULTMASTER)) + ($(MAKE) install) + +aix: + @echo 'building a $(WORLDX) by $(WORLDY) server...' + (cd src/doconfig; $(MAKE) $(AIXMASTER)) + ($(MAKE) genlibs $(AIXMASTER)) + (cd src/lib/lwp; $(MAKE) aix $(AIXMASTER)) + ($(MAKE) binaries $(AIXMASTER)) + ($(MAKE) install) + +rtpc: + @echo 'building a $(WORLDX) by $(WORLDY) server...' + (cd src/doconfig; $(MAKE) $(RTPCMASTER)) + ($(MAKE) genlibs $(RTPCMASTER)) + (cd src/lib/lwp; $(MAKE) aix $(RTPCMASTER)) + ($(MAKE) binaries $(RTPCMASTER)) + ($(MAKE) install) + +sequent: + @echo 'building a $(WORLDX) by $(WORLDY) server...' + (cd src/doconfig; $(MAKE) $(SEQMASTER)) + ($(MAKE) genlibs $(SEQMASTER)) + (cd src/lib/lwp; $(MAKE) $(SEQMASTER)) + ($(MAKE) binaries $(SEQMASTER)) + ($(MAKE) install) + +sequent.fpa: + @echo 'building a $(WORLDX) by $(WORLDY) server...' + (cd src/doconfig; $(MAKE) $(SEQFPAMASTER)) + ($(MAKE) genlibs $(SEQFPAMASTER)) + (cd src/lib/lwp; $(MAKE) $(SEQFPAMASTER)) + ($(MAKE) binaries $(SEQFPAMASTER)) + ($(MAKE) install) + +solaris: + @echo 'building a $(WORLDX) by $(WORLDY) server...' + (cd src/doconfig; $(MAKE) $(SOLMASTER)) + ($(MAKE) genlibs $(SOLMASTER)) + (cd src/lib/lwp; $(MAKE) $(SOLMASTER)) + ($(MAKE) binaries $(SOLMASTER)) + ($(MAKE) install) + +sun3: + @echo 'building a $(WORLDX) by $(WORLDY) server...' + (cd src/doconfig; $(MAKE) $(SUN3MASTER)) + ($(MAKE) genlibs $(SUN3MASTER)) + (cd src/lib/lwp; $(MAKE) $(SUN3MASTER)) + ($(MAKE) binaries $(SUN3MASTER)) + ($(MAKE) install) + +sun4: + @echo 'building a $(WORLDX) by $(WORLDY) server...' + (cd src/doconfig; $(MAKE) $(SUN4MASTER)) + ($(MAKE) genlibs $(SUN4MASTER)) + (cd src/lib/lwp; $(MAKE) $(SUN4MASTER)) + ($(MAKE) binaries $(SUN4MASTER)) + ($(MAKE) install) + +sun4.opt: + @echo 'building a $(WORLDX) by $(WORLDY) server...' + (cd src/doconfig; $(MAKE) $(SUN4OPTMASTER)) + ($(MAKE) genlibs $(SUN4OPTMASTER)) + (cd src/lib/lwp; $(MAKE) $(SUN4OPTMASTER)) + ($(MAKE) binaries $(SUN4OPTMASTER)) + ($(MAKE) install) + +sun4.debug: + @echo 'building a $(WORLDX) by $(WORLDY) server...' + (cd src/doconfig; $(MAKE) $(SUN4DBGMASTER)) + ($(MAKE) genlibs $(SUN4DBGMASTER)) + (cd src/lib/lwp; $(MAKE) $(SUN4DBGMASTER)) + ($(MAKE) binaries $(SUN4DBGMASTER)) + ($(MAKE) install) + +# +# Generic stuff that is called from the architecture specific stuff. +# + +binaries: + @echo 'building the binaries' + (cd src/client; $(MAKE) $(GENMASTER) CLIENTLIBS=$(CLIENTLIBS)) + (cd src/server; $(MAKE) $(GENMASTER)) + (cd src/util; $(MAKE) $(GENMASTER)) + +ntbinaries: + @echo 'building the binaries' + cd src/client + $(MAKE) $(GENMASTER) CLIENTLIBS=$(CLIENTLIBS) + cd ../.. + cd src/server + $(MAKE) $(GENMASTER) + cd ../.. + cd src/util + $(MAKE) $(GENMASTER) + cd ../.. + +genlibs: + @echo 'building generic libraries' + (cd src/lib/as; $(MAKE) $(GENMASTER)) + (cd src/lib/commands; $(MAKE) $(GENMASTER)) + (cd src/lib/common; $(MAKE) $(GENMASTER)) + (cd src/lib/empthread; $(MAKE) $(GENMASTER)) + (cd src/lib/gen; $(MAKE) $(GENMASTER)) + (cd src/lib/global; $(MAKE) $(GENMASTER)) + (cd src/lib/player; $(MAKE) $(GENMASTER)) + (cd src/lib/subs; $(MAKE) $(GENMASTER)) + (cd src/lib/update; $(MAKE) $(GENMASTER)) + @echo 'done building generic libraries' + +ntgenlibs: + @echo 'building generic libraries' + -(mkdir lib) + cd src/lib/as + $(MAKE) $(GENMASTER) + cd ../../.. + cd src/lib/commands + $(MAKE) $(GENMASTER) + cd ../../.. + cd src/lib/common + $(MAKE) $(GENMASTER) + cd ../../.. + cd src/lib/empthread + $(MAKE) $(GENMASTER) + cd ../../.. + cd src/lib/gen + $(MAKE) $(GENMASTER) + cd ../../.. + cd src/lib/global + $(MAKE) $(GENMASTER) + cd ../../.. + cd src/lib/player + $(MAKE) $(GENMASTER) + cd ../../.. + cd src/lib/subs + $(MAKE) $(GENMASTER) + cd ../../.. + cd src/lib/update + $(MAKE) $(GENMASTER) + cd ../../.. + @echo 'done building generic libraries' + +clean: + (cd src/lib/as; $(MAKE) clean) + (cd src/lib/commands; $(MAKE) clean) + (cd src/lib/common; $(MAKE) clean) + (cd src/lib/gen; $(MAKE) clean) + (cd src/lib/global; $(MAKE) clean) + (cd src/lib/player; $(MAKE) clean) + (cd src/lib/subs; $(MAKE) clean) + (cd src/lib/update; $(MAKE) clean) + (cd src/lib/lwp; $(MAKE) clean) + (cd src/lib/empthread; $(MAKE) clean) + (cd src/client; $(MAKE) clean) + (cd src/server; $(MAKE) clean) + (cd src/util; $(MAKE) clean) + (cd src/doconfig; $(MAKE) clean) + (rm -f lib/*.a) + +ntclean: + cd src/lib/as + $(MAKE) clean + cd ../../../ + cd src/lib/commands + $(MAKE) clean + cd ../../../ + cd src/lib/common + $(MAKE) clean + cd ../../../ + cd src/lib/gen + $(MAKE) clean + cd ../../../ + cd src/lib/global + $(MAKE) clean + cd ../../../ + cd src/lib/player + $(MAKE) clean + cd ../../../ + cd src/lib/subs + $(MAKE) clean + cd ../../../ + cd src/lib/update + $(MAKE) clean + cd ../../../ + cd src/lib/lwp + $(MAKE) clean + cd ../../../ + cd src/lib/empthread + $(MAKE) clean + cd ../../../ + cd src/client + $(MAKE) clean + cd ../../ + cd src/server + $(MAKE) clean + cd ../../ + cd src/util + $(MAKE) clean + cd ../../ + cd src/doconfig + $(MAKE) clean + cd ../../ + cd lib + -(del /Q *.lib) + +realclean: + ($(MAKE) clean) + (rm -f bin/*) + (rm -rf data/*) + -(rm -rf $(EMPDIR)/data/*) + -(rm -rf $(EMPDIR)/bin/*) + (cd src/lib/as ; echo "# Empty" > Makedepend) + (cd src/lib/commands ; echo "# Empty" > Makedepend) + (cd src/lib/common ; echo "# Empty" > Makedepend) + (cd src/lib/gen ; echo "# Empty" > Makedepend) + (cd src/lib/global ; echo "# Empty" > Makedepend) + (cd src/lib/player ; echo "# Empty" > Makedepend) + (cd src/lib/subs ; echo "# Empty" > Makedepend) + (cd src/lib/update ; echo "# Empty" > Makedepend) + (cd src/lib/lwp ; echo "# Empty" > Makedepend) + (cd src/lib/empthread ; echo "# Empty" > Makedepend) + (cd src/client ; echo "# Empty" > Makedepend) + (cd src/server ; echo "# Empty" > Makedepend) + (cd src/util ; echo "# Empty" > Makedepend) + (cd src/doconfig ; echo "# Empty" > Makedepend) + +ntrealclean: + $(MAKE) ntclean + cd bin + -(del /Q *.*) + cd .. + cd data + -(del /Q *.*) + cd .. + cd src/lib/as + echo # Empty > Makedepend + cd ../../../ + cd src/lib/commands + echo # Empty > Makedepend + cd ../../../ + cd src/lib/common + echo # Empty > Makedepend + cd ../../../ + cd src/lib/gen + echo # Empty > Makedepend + cd ../../../ + cd src/lib/global + echo # Empty > Makedepend + cd ../../../ + cd src/lib/player + echo # Empty > Makedepend + cd ../../../ + cd src/lib/subs + echo # Empty > Makedepend + cd ../../../ + cd src/lib/update + echo # Empty > Makedepend + cd ../../../ + cd src/lib/lwp + echo # Empty > Makedepend + cd ../../../ + cd src/lib/empthread + echo # Empty > Makedepend + cd ../../../ + cd src/client + echo # Empty > Makedepend + cd ../../ + cd src/server + echo # Empty > Makedepend + cd ../../ + cd src/util + echo # Empty > Makedepend + cd ../../ + cd src/doconfig + echo # Empty > Makedepend + cd ../../ + cd $(EMPDIR)\data + -(del /Q *.*) + -(rmdir tel) + cd $(EMPDIR)\bin + -(del /Q *.*) + cd $(EMPDIR)\data\tel + -(del /Q *.*) + +depend: + (cd src/lib/as; $(MAKE) depend) + (cd src/lib/commands; $(MAKE) depend) + (cd src/lib/common; $(MAKE) depend) + (cd src/lib/gen; $(MAKE) depend) + (cd src/lib/global; $(MAKE) depend) + (cd src/lib/player; $(MAKE) depend) + (cd src/lib/subs; $(MAKE) depend) + (cd src/lib/update; $(MAKE) depend) + (cd src/lib/lwp; $(MAKE) depend) + (cd src/lib/empthread; $(MAKE) depend) + (cd src/client; $(MAKE) depend) + (cd src/server; $(MAKE) depend) + (cd src/util; $(MAKE) depend) + (cd src/doconfig; $(MAKE) depend) + +# The last three lines here ensure that we don't overwrite an existing +# econfig file, by moving it first then moving it back. The '-''s +# ignore any errors (like if the files don't exist.) +# So, after an install, you will have an "econfig" file in the +# data directory if you didn't have one before. + +install: + (cd src/client; $(MAKE) install) + (cd src/server; $(MAKE) install) + (cd src/util; $(MAKE) install) + -(mv $(EMPDIR)/data/econfig $(EMPDIR)/data/econfig.bak) + ($(EMPDIR)/bin/pconfig > $(EMPDIR)/data/econfig) + -(mv $(EMPDIR)/data/econfig.bak $(EMPDIR)/data/econfig) + +ntinstall: + -(mkdir bin) + cd src\client + $(MAKE) ntinstall + cd ..\.. + cd src\server + $(MAKE) ntinstall + cd ..\.. + cd src\util + $(MAKE) ntinstall + cd ..\.. + cd data + ($(NTINSTDIR)\bin\pconfig.exe > $(NTINSTDIR)\data\econfig.new) + -(move econfig.new econfig) + cd .. + diff --git a/README b/README new file mode 100644 index 00000000..73398870 --- /dev/null +++ b/README @@ -0,0 +1,82 @@ +Welcome to Empire 4, codenamed Wolfpack. Congratulations on your choice! + +See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the +related information and legal notices. It is expected that any future +projects/authors will amend these files as needed. + +For questions and comments, please contact "wolfpack@wolfpackempire.com". + +If you want to build the server, follow the few simple steps below. If +you are looking for more information on the files here, options for +the server, etc. take a look in the "doc" directory, then follow the steps +below to build and start the server. + +(1) Unpacking the server + To unpack the server, simply gunzip and untar the source. + +(2) Building a server + Note that you may not have to build a server. If you received the + server in binary format, go to the next step, "Creating the world." + + To build the server, you need to do the following steps: + + 1) Get a copy of the source. Since you're reading this, we assume + you have done that. + 2) Gunzip the source. Again, since you're reading this . . . ;-) + 3) edit the build.conf file in this directory, and answer the questions + it asks you. + 4) type "make" to see what architectures are currently supported. + 5) choose the architecture that best suits you, and type "make " + where is the architecture you want to build. + 6) type "make depend" to build the dependencies (not required, but + helps a lot when you want to recompile something again.) + Note: "make depend" doesn't work under NT yet. + +(3) Creating the world + (NOTE: If you received a binary, you must edit the included data/econfig + file to represent the paths where your data and info directories are.) + 1) First, pick the world size you want to use. Once you have chosen + a world size, edit the "data/econfig" file (it was either created + at build time, or shipped with the binary) and change the WORLD_X + and WORLD_Y to be the sizes you want. The default world size is 64x32. + IMPORTANT: WORLD_X *MUST* be divisible by 2. In addition, if you + change the world size later, you *MUST* re-create the world by + running "bin/files" again. + 2) Go into the "bin" directory, and run "./files". + 3) If you want to create a new world, run "./fairland 10 30" to create + a sample world (read the documentation for fairland for more info on + it's arguments.) + Note that "files" and "fairland" use the world size in the econfig file + if it exists in the data directory. If this file doesn't exist, and you + don't specify one, it will use the default world size the server was + compiled with (Wolfpack binaries ship with a 64x32 world size) You can + create an econfig file with default values using the "bin/pconfig" + executable. + +(4) Running the server + 1) Run the bin/emp_server executable to start the server. + +That's it. Once running, you can log on to the server using the emp_client +program found in the "bin" directory. The initial deity country name/password +is POGO/peter. + +If you get a "You're not a deity!" message and logged off, check the +"data/server.log" file and look at the end for a "NON-AUTH" entry. +There should be a "user@host" message in there that failed to log in. +The user and host that your system is using may be different than the +one you put in your build.conf file. So, enter this new user and host +in the auth file, and you should be able to log into the server as a +deity now. Note that if you rebuild the server again, the auth file +will be overwritten. + +For more information on options, programs, files and other general hints +look in the "doc" directory. The README there describes the files there and +what they talk about. + +For more information or help, send e-mail to "wolfpack@wolfpackempire.com" and +we'll try to answer if we can. Also check out our web site at +"http://www.wolfpackempire.com" + +Have fun! + + -- The Wolfpack development team... diff --git a/build.conf b/build.conf new file mode 100644 index 00000000..aa0a18e5 --- /dev/null +++ b/build.conf @@ -0,0 +1,72 @@ +# +# Below are a list of questions you may or may not need to answer. They +# are all one-liner. Just change the default value if needed, and save +# the file when done. Have fun!!! +# + +# Please enter your name: +MYNAME = Wolfpack + +# Please enter your user name: +# (For NT and the basic emp_client build, use "USERNAME = win-empcl2.8") +USERNAME = wolfpack + +# Please enter your e-mail address: +EMAIL = wolfpack@wolfpackempire.com + +# Please enter the host name you will be running on: +# (For NT you can use "HOSTNAME = localhost" as this seems to be what it +# always resolves to if you use 127.0.0.1 below) +HOSTNAME = blitz.wolfpackempire.com + +# Please enter the ip address of the host you will be running on: +# (For NT you can use "IPADDR = 127.0.0.1") +IPADDR = 216.162.200.183 + +# Please enter the port you will be running on: +PORTNUM = 6665 + +# Please enter the directory where you want the files for the game: +# (Note: Use a '/' to delimit directories. For NT, include a +# drive letter.) +EMPDIR = /home/wolfpack/emp4 + +# Ignore this next value for all builds except NT builds. +# For NT builds, use the above path, but replace the '/' with a '\'. +# Note that NTINSTDIR is not used for non-NT builds, and can be ignored. +# This is needed for the 'copy' comamnds, since they get very confused +# with the normal path names. +NTINSTDIR = C:\home\wolfpack\emp4 + +# Please enter the C-compiler you are using (full path is allowed): +# (For NT builds using MSVC, use "CC = CL") +CC = gcc + +# Please enter the linker you are using (full path is allowed): +# (For NT builds using MSVC, using "LD = ld" works fine.) +LD = ld + +# Please enter the maximum number of countries you want: +MAXNOC = 99 + +# Please enter the world size you would like (WORLDX must be +# divisible by 2): +WORLDX = 64 +WORLDY = 32 + +# Please enter if you are setting up a blitz (1 - yes, 0 - no) +BLITZ = 1 + +# Please enter the number of ETUs per update (must be divisible by 4): +ETUS = 60 + +# Please enter the frequency of the updates. For example: +# Once per day - 1d +# Once every 20 minutes - 20m +# Once every 4 hours - 4h +ETUFREQ = 10m + +# That's it... Save this file, and type "make " to build the +# server. If you are not sure of what architectures are supported, +# just type "make" and it will tell you. (If you are building the +# NT port, use "nmake" instead of "make".) diff --git a/doc/CHANGES b/doc/CHANGES new file mode 100644 index 00000000..625343ac --- /dev/null +++ b/doc/CHANGES @@ -0,0 +1,691 @@ +This file contains a list of patches/upgrades made to the server for a specific +version. It also contains the name of the author of that particular code. It +may not be complete. + +*version 2.0 beta 1 release 1* +Fixed age.c so reserves degrade normally instead of growing! - Chad Zabel +Fixed arch.c - replaced wrapp with what was supposed to be there - Ken Huisman +Patched bug in atta.c - a temporary patch that could be done better +( and will be later ) - Ken H. +patched bug in lib/commands/mail.c - Dave Pare +added patches to make code compile under linux - Ken H. based on linux chain 3 +patches by someone else whose name I forget. Note at this time the code +*compiles* under linux, but there are still bugs - the server seems to +stop taking socket connections or something after someone logs out of the +game. +fixed a null pointer bug in lib/subs/bigmap.c - Chad Zabel + +*version 2.0 beta 1 release 2* +Patch for exec bug - Chad Zabel + +*version 2.0 beta 1 release 3* +Patch for zepplin bug - Jim Ortlieb +Added unixware(svr4.2) specific stuff to arch.c - Doug Hay +Changes to h/lwp.h and lib/lwp/lwp.c for thread stack checker - Doug Hay + +*version 2.0 beta 1 release 4* +Modified fairland.c to 1.6.2 and made it so translate_continents is only +called when BLITZ is defined - Ken Huisman, Ken Stevens +Modifications to lwp.h and arch.c to fix linux threads - Scott Ferguson + +*version 2.0 beta 1 release 5* +Changed version number to 2.0.0 - Ken Huisman +fixed unterminated path bug in lib/common/path.c - Scott Ferguson +fixed first part of bug described in wish list item c6 ( false resupply ) - +Scott Ferguson +fixed part of bug described in wish list item t3 ( you have 666 new telegrams +bug ) - the bug that tells you you have 1 new telex after just reading it is +not fixed - Scott Ferguson + +*version 2.0 beta 1 release 6* +Three letter abbreviations for all ships in ship.c - Chad Zabel +the following by Kevin Klemmick: +/lib/commands/rea.c // fixed telegram's problem reading '%' +/lib/commands/mail.c // ditto for mail and wmail +/lib/subs/aircombat.c // New air code and bug fixes +/lib/subs/mission.c // New air code and bug fixes +/lib/subs/pr.c // new prnf function an bug fixes +/lib/subs/paths.c // fixes the getpath() bug. +added NEWPAF and HIDDEN to options.h ( commented out for now until +testing is complete ) - Ken H. + +*version 2.0 beta 1 release 7* +Fix for fix for exec bug ( lib/player/player.c ) - Chad Zabel +fixed minor bug in aircombat.c ( missing quote on line 613 ) - Ken H. + +*version 2.0 beta 1 release 8* +lib/commands/mfir.c Bugfix... in quiet_bigdef, added in a check +for forts >60%. They were getting cheated out of their bonus in the return +fire process. - Chad Zabel +AIX Port: files +lib/lwp/{GNUmakefile,arch.c,lwp.c,lwpint.h} and +make/Systems/aix modified + - All changes are surrounded by #ifdef AIX32. + - one change to lwp.c that will apply to everyone one error + message changed so it says underflow instead of overflow in the stack + checking code. +- Bill Canning + +*version 2.0 beta 1 release 9* +You can now specify how many mil to board a ship with (wishlist item a1) so +you don't strand your ship. This is implemented as another parameter +in the board command. Documentation for board updated too! - Chad Zabel + +- Addition of the HIDDEN and NEWPAF Mods (Major addition). - Kevin Klemmick + +*version 2.0 beta 1 release 10* +lib/player/player.c compilation under linux was broken by previous patches +this is fixed now - Ken H. + +*version 2.0 beta 1 release 11* +fixed compilation under sunos (lib/lwp/lwp.c had a couple odd '\' characters +in it that caused the sun compiler to complain) - Ken H. + +*version 2.0 beta 1 release 12* +added 3 character abbreviations for land unit names - Chad Zabel +fixed bug in "show sect build" command - Ken Huisman +added check in neweff command to see if sector is stopped - Chad Zabel +added test for war declaration before abm launch - Chad Zabel + +*version 2.0 beta 1 release 13* +added thread debugging stuff - Dave Pare +changes to autonav code - Chad Zabel +fixes for minor bug in land unit names - Chad Zabel +fix for build.t in docs - Chad Zabel +simple fix for spy command - Chad Zabel +fix for telegrams - Julian Onions +fixup of makefile in util - Julian Onions + +*version 2.0 beta 1 release 14* +fix bugs in lwp - Julian Onions +fix bug in edit that caused server crash - Julian Onions +fix bugs in attack command that allowed free resource creation - Chad Zabel +fix bug that made countries in sanctuary lose money - Chad Zabel + +*version 2.0 beta 1 release 15* +io bug fixes and misc code changes - Dave Pare +removal of sanctuary print statements to reduce logfile sizes - Ken Huisman +DEC Alpha port - Dave Pare and Ken Stevens + +*version 2.0 beta 1 release 16* +made compiling/configuring easier (see READ_THIS_FIRST) - Ken Stevens +fix bug in info.c that caused crash - Janjaap van Velthooven +fix for land units - Chad Zabel + +*version 2.0 beta 1 release 17* +major improvements/cleanup of info pages and related files - Ken Stevens +changes to compile scripts - Ken Stevens + +*version 2.0 beta 1 release 18* +fixed missile sub abbreviation in ship file - Ken Stevens +added "are you sure" in build command to prevent accidents - Ken Stevens +fixed production simulation report showing "e" sectors producing - Ken Stevens +fixed LandUnits subject not being listed in "info". - Ken Stevens +fixed so unload only works in your sector or ally's sector - Ken Stevens +fixed error in sweep when sector efficiency is printed - Ken Stevens +fixed telegrams reporting bombing damage - Ken Stevens +fixed cede so you can only cede to allies - Ken Stevens +fixed coastwatch to show ship names - Ken Stevens +build command gives informative error message if you are building +in the wrong type of sector or the sector is < 60% eff. - Ken Stevens +build command does not prompt for tech level if not given on command +line - assumes current tech level - Ken Stevens +tech for aegis cruisers was increased - Ken Stevens +payoff command lists how many sectors ship has travelled - Ken Stevens +fixed bug that allowed planes to bomb from an airport <60% efficient - Ken Stevens +fairland now adds two visitor countries in its newcap script - Ken Stevens +fixed bug that crashes the server when 'power' is first done in game +without doing a 'power new' first - Ken Stevens +test command no longer aborts if you don't have enough of an item in a sector, +it still performs the test but gives a warning - Ken Stevens +you now get a telegram when someone loads something onto your ship - Ken Stevens +fixed documentation on happiness - Ken Stevens +you now get the country name when a country becomes hostile, not just the +country number - Ken Stevens +fixed so start land unit is if1 instead of if2 - Ken Stevens + +*version 2.0 beta 2 release 1* +Build command has last two arguments switched ( tech and number - documentation +updated as well ) - Ken Stevens +Added new info page summarizing whats new in Empire2 - Ken Stevens +/info/Subjects/TOP.t now includes LandUnits subject - Ken Stevens +info/Subjects/Server.t refers to the Empire2 info page now - Ken Stevens +Bug in happiness and education calculation on zero population fixed +- Ken Stevens +Aircombat aborted wasn't being printed properly - fixed - Ken Stevens +Plane types sorted to be consistant with ships and units - Ken Stevens +Wish list item m2! fixed - missiles on interdiction missions on subs +won't fire - missiles are now allowed to be on ships with "miss" capability +- the missile code and the load code now agree as to what kinds of planes +can be on what kinds of units - Ken Stevens +Comments added to ship.c explaining why M_XLIGHT, M_UNIT and M_MSL no +longer need to be set there ( they are automatically set in global_init() +- Ken Stevens +fixed wishlist item s16! - subs on interdiction missions no longer fire +on other subs, when they don't have sub-torp ability. - Ken Stevens +fixed division by zero error in lib/subs/supply.c ( occurs when a cargo +ship supplies itself to increase its efficiency in a harbour) - Ken Stevens +cosmetic change to lib/commands/load.c - Ken Stevens +Fixed wishlist item p9! ( non-VTOL missiles won't fly missions unless they +are in a 60% airport) - fixed by making all missiles VTOL by definition. +- Ken Stevens +lmine command now allows you to specify more shells than the unit has, +and the unit will automatically resupply until all the mines specified are +laid ( wishlist item l1?) - Ken Stevens +The problem with land mines becoming sea mines is now fixed entirely +(wishlist item c2!) - Ken Stevens +0% banks, etc. no longer resist shell fire better than a 0% other sector type. +( wishlist item c3!) - Ken Stevens +fixed printing problem in sweep command - Ken Stevens +fixed telegrams using the word "Oamage" instead of damage when reporting +bombing damage. - Ken Stevens +lib/global/init.c - cosmetic change - Ken Stevens +added wall and shutdown commands and corrected syntax on some deity +commands - Ken Stevens +added pr_wall() which is like pr_flash() except that it prints to +all connected players. - Ken Stevens +added shutdown comand to shutdown server with warnings to connected +players - Ken Stevens +fixed reference to "info syntax" - Ken Stevens +added toggle command, which allows players to set their "inform" flag, which, +when set, causes the server to send a line to the client the +instant the player receives a telegram - Ken Stevens +flash command now checks for valid country number - Ken Stevens +Added support for an empire configuration file so that the server can +be reconfigured without recompiling (documentation on this included in +README directory) - Julian Onions +fix for standard empire client so it doesn't drop characters on long +scripts - Dave Pare +Changed flash command so that you only get flashes from your alllies if +you have toggled your flash flag on - using 'toggle flash' to +toggle your flash command on and off and documentation changed - Ken Stevens +designate command now warns you if you are spending >50% of your money +designating forts, and will ask you "are you sure?" if you are going +to go broke from it - Ken Stevens +A temporary input buffer needed a size increase in buil.c - Ken Stevens +Wish list item c5! - fixes it so you are told how much it will cost when +you are designating sectors, or converting civs to slaves, and it warns +you if you are going to go broke from it. The server will also not let you +build, harden, or upgrade anything you cannot afford - Ken Stevens +fixed -h parameter on server ( caused crash ) - Ken Huisman +new commands added for use during navigation and unit marching - 'M' for + drawing a map and 'B' for drawing a bmap - Ken Stevens + +*version 2.0 beta 2 release 2* +Deleted some files no longer necessary. + - deity "map" fixed - wasn't showing sector designations. + - deity "shutdown" fixed - didn't work. + - player "board" fixed - was loosing all mil on ships. + - Now when you "kill" emp_server (from your unix shell), it will send + the flash message "Server shutting down..." to all players logged on, + it will "abort" any command they were in the middle of with the message + "Shutdown aborted command" (like the way update aborts commands), + it will terminate the players connection (like the way idle + connections are terminated) and it will close all the database files. + In other words, "kill" fromoutside the server now does the same thing + as the deity "shutdown" command does from inside the server. + - New player command "strength" calculates sector defense strength + (including bonuses from reacting units but excluding air/fort/arty support). + I think this command will help newbies set up a defense better. + - If you've already compiled once, and you're just working on stuff in + the server, then you can now type "compile quick" which will skip + dependall, util, and client (and compile in about a quarter the time). + +The above were all done by Ken Stevens ( I think ) on b2r1b + + - added "toggle beep" so that you can now play Empire without beeping + every time you fire if you so choose (handy for those emergency + updates in the department computer room). + - "configure" now asks you where you keep your "gnumake". + - Fixed a couple of bugs in the configure script + - "toggle" flags moved from player to natstr so they're saved + - fixed malloc() pointer mismatches to make cc happy + - ported "shutdown" to Sun4 + - Julian Onions ported his econfig code to Sun4 + +The above are from b2r1c + +The following are fixed ( as of b2r1d ): + - The infamous "scuttle" bug. Now the owner of units is always set + to zero as soon as the unit is created. (By "created" I am referring + to when you build 1 plane and ef_extend() creates 49 more -- the owner + of all 50 is now initialized to zero.) + - A C_INFORM packet was being sent to the client when an announcement was + made. Oopsie on my part. Now fixed. + - "fortifying" a unit no longer clears the unit's mission. + - New script "keepitup" is a modified isempireup except that you don't + have to put any info about the game in the file itself, so if + you're like me and you have more than one game running, you now only + need to keep one script around. + +b2r1e patch moved files from util into old/util + +b2r1f contained the following: +This patch was submitted by Julian Onions. + - General option handling, + BLITZ option changes + throughout. There is one new file lib/global/options.c which has the + option definitions in. + - The following options are now dynamically switchable + NOFOOD, BLITZ, EASY_BRIDGES, RES_POP, NEW_WORK, + NEW_STARVE, NO_PLAGUE, NEWPOWER ALL_BLEED, DRNUKE + SUPER_BARS, NUKEFAILDETONATE, PINPOINTMISSILE + - also fix up a stupid test in laun.c, and some reworking of the + SHIPNAME (plus a bug fix for Sub launched SHIPNAMES). + +b2r1g fixed a bug in b2r1f. +b2r1h moved a file from old/util back to util +b2r1i contained the following: +This patch was submitted by Julian Onions. + - The following options are now dynamically switchable + FUEL, ORBIT, NEUTRON + - The new file README/README.config describes how to use the new "econfig" + runtime configuration stuff.. + - Now when you type "version", you will also get the patchlevel of + the code. + +b2r1j contained the following: +This patch was submitted by Kevin Morgan. + - xdist and ydist are now in player coordinates (wish list item i2) + - emp_client now calls termio until all bytes have been copied into + the socket (wish list item x19). + +b2r1k contained the following: +This patch was submitted by Sasha Mikheev. + - This patch ports lwp threads to Linux. + +b2r1l contained the following: +This patch was submitted by Julian Onions. + - Options NOMOBCOST and GRAB_THINGS are now runtime configurable. + +b2r1m contained the following from Ken Stevens: + +WARNING: Although I have heavily tested the code, I'm sure that it still has +a significant number of bugs. + +This patch contains the following changes: + - fixed a bug in configure which was not making compile a csh script which + resulted in grep not working. + - shipdamage() now always multiplied by 63/m_armor. I made the + appropriate changes to all places that call shipdamage(). Also, + shipdamage() will now tell the player exactly how much their ship + was damaged. + - a new function mpr(cnum, format, args) will pr() to cnum if they + are player and send them a telegram otherwise. + - sail, autonav, and nav now all call the same functions. Thus mine + damage and interdiction damage are now calculated using exactly the + same formulas. This makes heavy use of mpr(). + - navigation now has two more lcommands. "i" will list the ships you're + navigating, and "f" will change the flagship. + - Now you can type commands like this: + nav 72 jlsruMluBursh + That is, you can mix directions with other navigation commands. + - Interdiction of navigating ships now works as follows: + 1. Forts interdict. + 2. If there are any ships left, land arty interdiction fires. + 3. If there are any ships left, ships on interdiction fire. + 4. If there are any ships left, interdiction missiles fire one at a time. + 5. If there are any ships left, interdicting planes pinbomb. + - I'm sure that I've made some changes which have slipped my mind + +b2r1n contained the following from Ken Stevens: + +WARNING: Although I have tested most of the new code, I'm sure that it +still has a significant number of bugs. + +This patch contains the following changes: + - I went through all of the Empire info pages and updated them to + match the current code. I completely rewrote large portions of the + following info pages: "move", "bomb", "launch", "navigate", and + "Plane-types". + - Fixed a bug in the "configure" script which was resulting in a pile + of "kw_read" erros in the logfile. + - Changed the logfile output to make it much easier to read. Note: + this will break current logfile parsers. I'll rewrite any that people need. + - It is now possible to specify start-tech/happ/research/edu in + econfig (Thanks Julian!). I'm using this in my blitz to start + countries at tech 100. + - When things are damaged by interdiction, the sector they were + moving into will suffer collateral damage. + - Surface missiles can now be put on interdiction mission. To + distinguish them from anti-ship missiles, the latter have been given + "marine" capability. + - Planes and missiles can now hold at most one nuclear warhead. + - Nuclear warheads on planes and missiles will now detonate when that + plane or missile flies an interdiction mission. + - I have removed the "n" option from the "bomb" command. If you want + to nuke something, just arm the plane with a nuke and bomb "s". This + simplification makes the above change consistant with "bomb". + - When you launch a satellite, then any country AT_WAR with you will + try to intercept it with a-sats. This uses exactly the same code as + abm defense - two missiles are fired. Also, if a satellite is + positioned over a sector which is not owned by your ally, then they + will get a telegram informing of the positioning. + - missiles on missions will stop launching once 100 damage has been + done (in the case of surface interdiction) or all the ship s have been + sunk (in the case of ship interdiction). + - deliver now costs the same as distribute (4x cheaper). + - there is now only one function called to determine whether a plane/missile + hits its target and how much damage is done (this includes abms and + asats). Thus the chance of a plane hitting its target is now the same + whether the plane was flying a mission or flown by hand. The only + exception to this is pinbombing land units where interdicting planes + have a 100% chance of hitting unlike pinbombers flown by hand which + have a chance of missing. I plan to fix this later. + - many functions were rewritten to use mpr() instead of pr(). mpr() + checks to see if the person is interactive, and if they are calls + pr(), and otherwise calls wu(). All PR() functions should really + be changed to mpr() but I'm too lazy to do it. Also, I'm sure that I + missed a few pr()'s and so the server may still occassionally try to + pr() to a player not logged on. + - I used lint to remove alot of unused variables, declare some + functions void, and fix unsigned char comparisons with zero. + +b2r1o contained the following from Ken Stevens: + +WARNING: Although I have tested most of the new code, I'm sure that it +still has a significant number of bugs. + +This patch contains the following changes: + - Added "Friendly" relations--you can nav/load/unload in friendly harbours. + See info Empire2 or info relations. + - Changed the order of relations so now you can write code like + if (rel < FRIENDLY) ... or ... if (rel >= HOSTILE) + - Cap sacking now makes the news. + - Fixed a bug in sub interdiction (bug introduced by me in r1n). + - Fixed a bug in supply code (introduced by Julian in r1f). + - Moved relation-change stuff out of decl.c and into subs/rej.c setrel(). + So now, no matter how a country becomes hostile, both parties will + get a tele and it will make the news. Also, much of this code was + simplified using the new heuristic that bad rel is always < good rel. + - Changed spy output. New headers are: + sect type own oldown eff civ mil shl gun pet food bars units planes + - Changed all relevant info pages. + - Completely rewrote info relations. + +*version 2.0 beta 2 release 3* +CC is now configurable - Ken Stevens +"scuttle", "scrap", "mission", and "fuel" commands now let you put "l" +instead of having to type "la" like before - Ken Stevens +BIG_CITY option added - Ken Stevens +fixed bugs in "demob", "navi", and setrel() - Ken Stevens +fixed bug in flash command - Ken Stevens +removed spurious \B from pr statement in torp.c - Julian Onions +fixed missing issneak variable for SLOW_WAR case in atta.c and + assa.c - Julian Onions +rej.c not using correct variable for SLOW_WAR option, fixed - Julian Onions +parameters added to fairland.c as follows: +-o -- don't allocate ore (default is to allocate as before) +-q -- non chatty mode - little if any output +-a -- use the '*' mark to mark contents (AIRPORT_MARKER) +-i -- allow islands to crash and merge +-s -- alternate script file (default newcap_script) +- Julian Onions +maketgame script added - used to make a temporary test game +use as + maketgame -d /tmp/data 5 100 +to make a temporary game in /tmp/data with 5 countries and 100 sectors each. +- Julian Onions +fix to make compile script call bin/pconfig instead of util/pconfig +- Craig Leres + +*version 2.0 beta 2 release 4* +forts must be 5% efficient to fire or provide support( effic. level settable in + options.h - default is 5%) - Ken Huisman +fixes for the BIG_CITY option - Ken Stevens +another fix for compile.in - Ken Stevens +added skywatch command - Ken Stevens +fixed bug in "conv" command - Ken Stevens +fixed error message in "launch" - Ken Stevens +now you get a telegram if an enemy sat moves over your sector at the update +- Ken Stevens +attack command partially rewritten to clean up several problems - Chad Zabel +launch command now checks to see if a ship was sunk by a ship-ship +missile and tells the attacker - Chad Zabel +new missile/anti-missile code - Chad Zabel +configure script chokes if you are logged in more than once - Craig Leres +fix for compiling with gcc 2.6.0 under sunos 4.1.4 regarding the +sprintf() prototype in misc.h.in - Craig Leres +got rid of two lines of code that didnt do anything in sail.c - Craig Leres +fixed several other compiler warnings - Craig Leres +server checks for invalid values of s_p_etu - Craig Leres +some variables did not get initialized in lwp.c (fixed) + - Janjaap van Velthooven +fixed and heavily modified deliver command - Ken Stevens + +*version 2.0 beta 2 release 5* +fixed spelling error in desi.c - Ken Huisman +new command "players" which lists all players currently logged on with idle +time and last command - Ken Stevens +several plane damage bugs fixed - Ken Stevens +Interdiction damage now same as it would be interactively (ie. through +shelling or bombing or whatever ) - Ken Stevens +march command rewritten with a smoother interface - Ken Stevens +fixed bug in attack command that crashed the server - Ken Stevens +code changed so if your action caused a bridge to fall you see a message +on the screen instead of getting a telegram - Ken Stevens +man pages for the empire executables now available in the man +directory - Ken Stevens +fixed a server crashing bug in fuel command - Ken Stevens +'c' sector is now called a "city" when BIG_CITY option used - Ken Stevens +nuke subs now come at the same tech as nuke warheads - Ken Stevens +deities no longer ever run out of BTUs - Ken Stevens + +*version 2.0 beta 2 release 6* +Max range of anti-ship missiles reduced - Ken Stevens +fixed it so you dont have to logout and log back in to re-enable commands +when you come out of bankruptcy - Ken Stevens +new skywatch command added for finding sats - Ken Stevens +you can no longer fortify land units that are on ships - Ken Stevens +missile range in launch vs. interdiction has been reconciled - Ken Stevens +'tend' syntax now same as 'load', and you can now tend land units which +have 'assault' capability - Ken Stevens +fix for bug in realm command - Ken Stevens +fixed a sector damage bug introduced in 2b2r4 - Ken Stevens +fixed bug in show n b - Ken Stevens +fixed typo in Interdiction.t - Ken Stevens +fixed bug in telegram that caused server crash in certain instances - Ken Stevens +commodity damage routines reconciled to ensure that people damage is always +factored by the global variable people_damage. - Ken Stevens +fixed news items that were mis-reporting - Ken Stevens +fixed bug in missile-ship interdiction - Ken Stevens +added support in emp_client for C_FLASH and C_INFORM messages - Ken Stevens +fixed major bug in takeover() - Ken Stevens +fixed an incorrect message which would get printed when nukes were +dropped from bombers. - Ken Stevens +pinbombing output changed slightly - Ken Stevens +fixed bug in "land" - Ken Stevens +fixed bug in "power" - Ken Stevens +news cleaned up a bit - Ken Stevens +new info page on clients added - Ken Stevens +fixed several typos - Ken Stevens +new map code - Chad Zabel +fixes bug in BIG_CITY code when redesignated - Ken Stevens +fixes bug in redesignating of warehouses when sector has large amount of an +item - Ken Stevens +fixed bug in new empire client - Ken Stevens +improved 'play' command - Ken Stevens + +*version 2.0 beta 2 release 7* +people with toggle inform on are now told at login if they have telegrams +- Ken Stevens +fixed bug in client - Ken Stevens +fixed scheduled update scheme (updates were not firing) - Ken Stevens +fixed negative avail bug - Ken Stevens +mail and wmail commands removed from server due to bugs - Ken Stevens +configure by default does not overwrite the hours file now - Ken Stevens +"build b 2,2 j" now permitted - Ken Stevens +fixed rounding error resulting in negative avail - Ken Stevens +fixed several typos in the docs - Ken Stevens +fixed sub-detect chance for asw planes - Ken Stevens +prevent players from rejecting stuff from the deity - Ken Stevens +removed missingmissiles option ( not used ) - Ken Stevens +removed reference to now standard SHIPSAM option - Ken Stevens +added "Balance of Power" page at the bottom of the news - Ken Stevens +re-introduced "pray" command - Ken Stevens +added collateral damage from missiles hitting units - Ken Stevens +fixed bug in attack - Ken Stevens +fixed bug in budget command - Ken Stevens +fixed command cutoff command - Ken Stevens +fixed bug in retr command - Ken Stevens +"realm x" now gives error - Ken Stevens +mfir and torp were not telling the attacker if the ship got sunk - Ken Stevens +planes on carriers which were >80% eff were being reduced to 80% eff, fixed. +- Ken Stevens + +*version 2.0 beta 2 release 8* +fixed bug in pinbombing and interdiction - Ken Stevens +server crashed when trying to get friendly nations to interdict - Ken Stevens +bombers were being launched as interdiction missiles ( oops!) - Ken Stevens +server crashing bug in flash - Ken Stevens + +*version 2.0 beta 2 release 9* +got rid of annoying "destroying done" message - Ken Stevens +compile.in changed - by default dont overwrite econfig - Ken Stevens +new global configurable variable assault_penalty = 0.50 - Ken Stevens +fixed commodity damage - Ken Stevens +added global string var used by attsub.c - Ken Stevens +added new option INTERDICT_ATT - Ken Stevens +cities are now navigatable if BIG_CITY is on - Ken Stevens +fixed server crash on friendly overfly - Ken Stevens +changed march and lndsub to use attsub routines - Ken Stevens +no longer get kicked out of navi prompt of you bump into something - Ken Stevens +doubled ship pinbomb damage - Ken Stevens +get warned if your message is truncated in flash - Ken Stevens +fixed bug in strength command - Ken Stevens + +*version 2.0 beta 2 release 10* +new starvation command checks for starving ships and units as well - Ken Stevens +fixed a bug causing land units to starve - Ken Stevens +added new [ynYNq?] syntax to attack - Ken Stevens +fixed a bug that resulted in stranded units - Ken Stevens +caps are called cities if BIG_CITY is on - Ken Stevens +new power command allows syntax "power c 3/6/14" - Ken Stevens +fixed bug in news report - Ken Stevens +fixed spelling errors in info pages - Ken Stevens +can now type sector number at marc and navi prompt to move unit there - Ken +Stevens +changed output format of budget - Ken Stevens +can load and unload in 2% cities - Ken Stevens +fixed bug that caused blitzes to starve if food was on - Ken Stevens +fixed bug in plane maps - Ken Stevens +changed YN to mean units in same army - Ken Stevens +added "Attack aborted" message - Ken Stevens +fixed bugs in plnsub.c, bomb.c budg.c - Ken Stevens +fixed ship sunk bug in mfir.c - Ken Stevens +added "Assault aborted" message - Ken Stevens +fixed ship sunk bug in torp.c - Ken Stevens +you can now unload to up to 9999 in a sector - Ken Stevens +fixed bug in news - Ken Stevens +removed BETTERABM option - Ken Stevens +shutdown now asks you before automatically disabling updates - Ken Stevens +fixed lots of nuclear detonation related bugs - Ken Stevens +fixed supply bug - Chad Zabel +fixed bug so nukes now dissapear when you use them - Ken Stevens +harbour police bug fix - Chad Zabel +land units no longer see planes on ships with look command - Ken Stevens +fixes for autonav - Chad Zabel +fixed bug that crashed server - Ken Stevens +fixed paradrop bug - Ken Stevens +ship damage improved - Ken Stevens +made land unit abbreviations 4 chars long - Chad Zabel +shortened the tele time tolerance from 60 sec. to 5 sec. - Ken Stevens +rewrote atta/assa/para/boar - see Attack.t for details - Ken Stevens +fixed bug in strength command - Ken Stevens + +*version 2.0 beta 2 release 11* +fixed bug in strength command - Ken Stevens +documented all the new attack stuff - Ken Stevens +new arm command lets you specify groundburst or airburst at arming time - Ken +Stevens +fixed bug in cede command - Ken Stevens +lowered damage land mines do to units - Ken Stevens +consolidated commodity landmine damage code - Ken Stevens +fixed minor bug in flash - Ken Stevens +new documentation - Ken Stevens +fixed bug in ship damage - Ken Stevens +mi1's were interdicting commodities - fixed - Ken Stevens +added to pre_write a check for 0 civ => oldown = own - Ken Stevens +fixed minor bug in attack sub file - Ken Stevens +fixed major bug in lmine - Ken Stevens +changed repo output format to give more information - Ken Stevens +fixed bug in setsect (deity command ) - Ken Stevens +fixed ship and land unit starve routines - Ken Stevens +new code replaces the old missdef code - Ken Stevens +fixed bug in land unit starve code - Ken Stevens +new deity command "swap" swaps two sectors - Ken Stevens +fixed board estimate bug - Ken Stevens +fixed bug in repo command - Ken Stevens +updated more documentation - Ken Stevens +updated keepitup script - Ken Stevens +3 letter abbreviations for asats - Ken Stevens +harbors now get warehouse packing bonus - Ken Stevens +you can now type "decl h *" to declare hostile with everyone - Ken Stevens +deities no longer start out at war with everyone - Ken Stevens +coun command disabled (doesnt work right anyways) - Ken Stevens +re-fixed news bug in torp - Ken Stevens +made non-deity version of players command with limited info - so players +can see if deity is on - Ken Stevens +changed name of swap command to swapsector - Ken Stevens +more documentation - Ken Stevens +increased stack space and got rid of "idle connection terminated" message +that would appear sometimes when you logged in - Ken Stevens +fixed server crashing bug in decl command - Ken Stevens +fixed a bug in repo command - Ken Stevens +fixed bug in that you were becoming the oldown of conquered sectors +immediately - Ken Stevens +implemented prship() prland() and prplane() functions to simplify +the SHIPNAMES stuff - Ken Stevens +moved prbuf() to xy.c - Ken Stevens +players now being told where missile is being launched from - Ken Stevens +chance of missile exploding on launch pad reduced to +5% * (1 - tech factor). - Ken Stevens +fixed crash in missiles - Ken Stevens +changed "geosynchronous" to "geostationary" - Ken Stevens +fixed crash in torp command - Ken Stevens +fixed a bug in nuke damage - Ken Stevens +fixed a bug in getpath() - Ken Stevens +fixed up the newbie intro info pages - Ken Stevens +fixed bug in strength command using offense rather than defense strength - Ken +Stevens +improved launch output - Ken Stevens +improved the way players interact with nukes - Ken Stevens +gave update priority over shutdown - Ken Stevens +fixed thread stacksize causing crash - Ken Stevens +Planes will no only abort once they are less than 80% - Ken Stevens +fixed bug causing scuttled object not to be printed - Ken Stevens +fixed memory leak in atta/boar/assa commands - Ken Stevens +removed the "warning: this isn't a warehouse" message in dist - Ken Stevens +engineers with 0 mob can no longer hit a mine when trying to sweep - Ken Stevens +changed "115% damage" to "115 damage" and added info on how to +convert in "info Damage" - Ken Stevens +changed shoot syntax to make it like move - Ken Stevens +fixed bug in interdicting nukes - Ken Stevens +added safety check for negative nukes - Ken Stevens +75% sat now only sees 75% of sectors ( rest are blank ) - always the same +25% are blank - Ken Stevens +if you are over tech 290, you cannot build planes that are < tech 150 +- Ken Stevens +fixed a bug preventing you from assaulting your own sectors - Ken Stevens +no more multiple telegram updates - Ken Stevens +cede 2,0 "sector" now works ( before only "sect" would) - Ken Stevens +removed a couple noisy output lines in dist - Ken Stevens +fixed bug in "test" command - Ken Stevens +changed load and tend syntax to be same as move ( see info Move ) and +rewrote lload, load, unload, and lunload, improving prompts, etc +- Ken Stevens +planes wich are less than 40% cannot fly - Ken Stevens +improved the output of "report" - Ken Stevens +fixed bug in budget - Ken Stevens +fixed bug in "players" command - Ken Stevens +if an attacker aborts an attack, the victim now gets a telegram - Ken Stevens +extended toggle syntax so you can now type "toggle inform on" - Ken Stevens +show output changed - Ken Stevens +engineers stop working once a sector reaches 100% - Ken Stevens +you are no longer asked if you'd like to "nuclear" bomb ( see info arm ) +- Ken Stevens +cleaned up scripts and deity docs - Ken Stevens + + +2b2r11 became empire 2.3.0 +further changes documented in CHANGES2.3 + diff --git a/doc/CHANGES2.3 b/doc/CHANGES2.3 new file mode 100644 index 00000000..babcbec4 --- /dev/null +++ b/doc/CHANGES2.3 @@ -0,0 +1,335 @@ +Unless otherwise specified, the changes in this file were made by Ken Stevens + +emp2.3.0.a.tar +- port to IRIX - Janjaap van Velthooven +- added "info Hidden" +- added "doc/econfig" +emp2.3.0.b.tar +- fixed abm news message +- reduced sam ranges to 2/3/4 +- fixed MAJOR bug in unload +- arty now have to be 20% to fire +- widened range in "player" command +- fixed bug in "fuel" +- fixed "starv l" +- updated info pages +emp2.3.1.a.tar +- harbours weren't getting packing bonus when importing on dist. +emp2.3.2.a.sh +- removed a bunch of *.orig files +emp2.3.2.b.tar +- added #include to util/*.c for Linux compatability +emp2.3.2.c.tar +- removed -g flag for linux because it made fairland crash on getopt() +emp2.3.3.a.tar +- fixed MAJOR bug in load +- cleaned up some old global variables that weren't used any more +- config.status no longer creates econfig (compile does it now) +- gave _exit() an argument for Linux +emp2.3.4.a.tar +- fixed server crashing bug in pinbomb +emp2.3.4.b.sh +- cleaned out GNUdepend files for Linux +emp2.3.4.c.tar +- changed configure script to ask for IP address +- made authorization check strict. NOTE: this will make it harder to install. +- added this file +emp2.3.4.d.tar +- fixed a MAJOR bug in attack that was taking too much mobility. +emp2.3.4.e.tar +- fixed a but that was dividing by # of civs rather than multiplying + by them for mountain caps. OOPS. This bug has been in the code for years! +- changed the output of the "player" command. +- fixed a minor bug in "load" +- changed "return fire does 190% damage" to "return fire does 190 damage" +- changed "power" so now you can specify country names in "power -c" +- added "info BTU" +emp2.3.4.f.tar +- info pages are now separated into "Basic" and "Expert" level pages. + "Basic" level pages have a * beside them on the Subjects info pages. +- reduced "flapping" of "players" random output. +- now include self in repo * output. +emp2.3.4.g.tar +- a couple more IRIX patches - Janjaap van Velthooven +- bugfix for upgrade command - Janjaap van Velthooven +- extended syntax for one way orders - Julian Onions +- fixed a bug that would crash the server if an abm blew up on the launch pad +- fixed "was sunk at" message. +- you are now told if you abandon a sector by marching out of it. +- if you give someone back their cap by marching/moving/exploring out + of it, it gets changed into an agribusiness. +emp2.3.4.h.tar +- fixed a server crashing bug in mfir +- telegrams to yourself no longer show up in the news +- fixed a server crashing bug in show +emp2.3.4.i.tar +WARNING: I am not sure how portable this code is... +- added hostname to struct player +- all hostaddr validation now also checks against hostname +- changed "player" command output to show time used and user@hostname +emp2.3.4.j.tar +- fixed a bug introduced in emp2.3.4.i.tar +emp2.3.4.k.tar +- players can now see which of their allies are logged on using the + "players" command. +- fixed a server crashing bug in "players". +- you are now allowed to scrap in friendly harbours +- ask for double confirmation for scrapping trade ships (and tell + people to use "scuttle" instead). +- fixed documentation for scuttle/scrap +- you are no longer allowed to attack with supply, aa, arty, or + security units. +- the procedure for determining tech, research, edu, and happiness are + now explained in precice detail in the info pages. +emp2.3.5.a.tar +- applied 3 patches from someone (sorry I forget who) they had to do + with POSIX compatability +- fixed a MAJOR bug in ltend +- fixed a bug in "starva" which was stealing food from harbours +- fixed a server crashing bug which occurred when you hit return at an + attack prompt. +- added a new command "echo" at Kevin Morgan's request +- fixed a few minor formatting errors +- fixed an output warning which you got when you aborted assaulting + your own sector +emp2.3.5.b.tar +- fixed a bug which gave land units positive mobility if they went + below -127 (e.g. marching into a mountain) +- fixed a bug which required nuc missiles to have shells to launch +- fixed a bug which was preventing choppers from landing on ships +- fixed an error which prevented the server from compiling with + the ORBIT option off. +- fixed a bug which would throw the server into an infinite loop if + two ships followed each other. +- fixed a typo in scra.c that someone else's smart compiler caught. +emp2.3.5.c.tar +- cut sector damage in half (except for nukes) +- fixed "WARNING: sector ownership changed" integrity check message +- fixed "not in supplied harbour" message in "fuel" command +- fixed "lost x% to starvation" message in production report +- boarding mil no longer pack a lunch +- The following changes were made to the sonar command: + - will only work from ships at sea + - will only detect ships at sea + - will now detect the shoreline + - will only detect things if there is a straight line of water + between the detector and the detected (no longer works around corners) + - now displays a map and changes your bmap + - for ships with tech > 310, shows mines on the map with an X and + puts the X on your bmap +- fixed minor bug in input routine of "fire" command +emp2.3.5.d.tar + - Never again will you see in the news: + TheBorg execution squads gun down helpless TheBorg civilians + - If you lay, sweep, or hit a sea mine, then an 'X' will automatically + be put on your bmap + - All ships (including subs) in harbors are now visible via the "lookout" + command by all ships (including subs) in adjacent sectors + - Fixed a bug in sonar which was hiding subs beneath 'X's +emp2.3.5.e.tar + - Fixed a server crashing bug in supply routines (supply units were + drawing petrol from themselves in infinite recursion) + - Fixed a server crashing bug in attack code (bad return value) + - Fixed a server crashing bug in "declare" command (null pointer) + - Fixed a server crashing bug in "fire" command (use of freed + memory) - Yannick Tremblay + - Fixed bug in "edit ship" which wasn't displaying ship properly + - Engineers assaulting from landing ships were being charged too + much mob (bug fixed) + - User defined plane ranges were not being used by the mission code + (bug fixed) +emp2.3.5.f.tar + - Fixed a number fo bugs related to shelling - Yannick Tremblay + - Fixed a MAJOR ship damage bug + - The budget command has been changed so that now you may choose not to + pay maintenance costs. Also, "mil" on ships/planes/units has been + moved from the maintenance costs for those items to the "Military" section + of the budget. + - If you can not afford to maintain your ships/planes/units or you + choose not to maintain them using the "budget" command, then they will + loose ETU/5 % efficiency at the update. + - If you are broke at the point of the update when it comes time to + build something, then that thing will not be built. + - Broke countries are now allowed to use all commands except for: + arm assault attack board bomb build convert disarm drop enlist explore + fire fly grind harden launch lmine mine paradrop recon satellite scrap + shoot sweep torpedo treaty upgrade work + - Broke countries are now allowed to use these commands: + demobilize lload llookout load lookout lradar lrange lretreat ltend + lunload march mission morale mquota navigate order qorder radar range + retreat sail sonar sorder spy supply tend transport unload unsail +emp2.3.5.g.tar + - Fixed a server crashing bug in budget command + - increased sea mine hitchance from mines/(mines+50) to mines/(mines+40) + - increased sector damage from 50 * dam / (dam + 50) to + 100 * dam / (dam + 100). + - fixed a bug which was preventing engineers from tearing down 100% sectors + - added new argument to sonar output which suppresses map + - reduced land mine damage from 10 + random(20) to 6 + random(10) +emp2.3.5.h.tar + - Fixed server crashing bug in "morale" command. + - Engineers no longer "raise" eff from 100 to 92, they "lower" it. + - Engineers working are now only charged mobility for work they do + - Ships fueling themselves now loose petrol/oil + - Now, when a sector is abandoned or revolts, the takeover() function + is called to stop production, wipe distribution levels, etc... + - Engineers are now charged 1 mobility point per land mine laid + - Added number of land mines in the sector to the "strength" output + - Fixed lots of typos +emp2.3.5.i.tar + - Fixed a bug in "bomb" which was preventing light bombers on acc's + from being able to take off. + - Artillery no longer consume petrol or food when they fire (they + only consume shells). + - increased land mine damage from 6 + random(10) to 10 + random(10) + - if land units are accompanied by engineers, then their chance of + hitting a land mine is divided by 3. E.g. if there + are 25 mines in the sector, then a land unit has a 33% + chance of hitting a land mine. If it is accompanied by an + engineer, then that chance drops to 11%. + - If an engineer sweeps a land mine that it cannot carry, it drops + it as a shell into the sector. + - Engineers now sweep a number of times equal to 2 times the number + of shells they can carry. + - The chance of an engineer finding a land mine in a sector is now + 50% time the "att" value of the unit: + # of sweeps chance of finding a mine +old system 5 66% +eng1 130 6 60% +eng2 165 8 75% +meng 260 8 90% + - The "visibility" of a sub to an ASW plane has been increased from + vis to 10 + vis * 5. This should dramatically improve the chances + of ASW planes locating and hitting subs. +emp2.3.5.j.tar + - changed visibility of subs from 10 + vis * 5 to vis * 4 in the + asw hitchance calculation. + - when subs on interdiction miss, both parties are now informed + (in the old system, neither party was informed) + - you are no longer allowed to hit subs with missiles (oops!) +emp2.3.6a.tar + - Forts will now only automatically interdict ships that the country + would be able to see using the "coastwatch" command. Ships out of + visual range will not be interdicted by forts. Note that + ship/ship, unit/ship, plane/ship interdiction was not changed, + and also the "fire" command was not changed. _only_ fort/ship + interdiction was changed. + - If a NEUTRAL (or worse) ship sails within your coastwatch range, + then you will receive a telegram like this: +TheBorg lc2 light cruiser 2 (#666) sighted at -9,-1 + This telegram is sent before any interdiction is done. + - When an ASW plane flies an interdiction mission to hit subs, it will + now also report on any subs it happens to see along the way (in + the same way it would if it were flown using the "sonar" command). +emp2.3.6b.tar +- now when you march or navi, any new sector designations + automatically appear on your nav map and get added to your bmap (you + no longer need to do a "look" to find out their designation. Note + that subs will only see sea, harbors, and bridges and will have to + "look" (and risk detection) to see anything more. +- you can now filter your satellite output to list, for example, only + banks owned by country #7 which are over 60% efficient. The selectors + available are exactly the same as those used by the "census", "ship", + and "land" commands. See "info satellite" for more details. +- added two new toggle flags (default on): + - if "toggle coastwatch" is on, then you will receive a telegram every + time a neutral ship moves within your coastwatch range. + - if "toggle sonar" is on, then you will receive a telegram every + time one of your sonar cabale ships detects a sonar ping. +- now a 20% engineer only does 20% of the "work" that a 100% eng does. +- fixed a bug which was counting ghost units in "spy" output. +- fixed a bug which was including sats as planes in "spy" output. +- fixed a bug which was giving rebels ownershiip of sats over the sector +emp2.3.6c.tar +I have made asw interdiction more extensive and subs more sneaky. +Here is the new system: +- ASW planes will now fly out to track any non-FRIENDLY (including + NEUTRAL) sub movement. +- However there is a chance that the plane won't even leave the ground + and notice any sub movement at all. The chance of detection is + identchance = (1 - (1 - hitchance)^2). +- ASW planes will no longer detect subs they fly over while flying an + interdiction mission. +- Once the planes have arrived at the sector where the sub movement + was detected, then identchance is checked again. If success, then + the plane is able to identify the owner of the sub. If the owner + is neutral, then the player gets the message: + np1 naval plane 1 #2 tracks TheBorg subs at 2,-6 + If the plane is unable to identify the owner of the sub, then the + player gets the message: + np1 naval plane 1 #2 detects sub movement in -3,-3 + If the ship was identified as HOSTILE or AT_WAR, then the plane will + drop depth charges. +- If depth-charges miss, then the ship owner will get + the message: +RUMBLE... your sub in 24,0 hears a depth-charge explode nearby +- torp and fire will now only tell the victim that a "sub" torped + them, or that return fire damaged a "sub" (rather than giving out + detailed information about the sub number, type, and owner...) +- max sonar range has been reduced to 7 and sonar output no longer + prints blank lines. +- sonar has been changed in the following way: + detection = (source "spy" value) + (target "vis" value) + If the detection value is less than 8, then sonar will just print + Sonar detects sub #12 + If the detection value is above 7, then sonar will report the type of sub. + Only if the detection value is above 9 will the owner of + the sub be revealed. +- For ASW planes flying "sonar" or "recon" missions, a similar change + has been made. The plane needs to pass one identchance check to see + the type of sub, and needs to pass two identchance checks to see the + owner of the sub. +- Note in both of the above cases, owner and type of FRIENDLY and + ALLIED subs will always be revealed. +emp2.3.6d.tar +- made scrap and scuttle more flexible +- supply units, security units, aa-units and artillery can no longer + be put on reserve mission, and they will no longer react to a battle. +- asw planes were tracking their own subs (oops!) +- interest from banks no longer turns off at 60% efficiency. Now the amount + of money you get from your bank is simply scaled by the banks efficiency. +emp2.3.6e.tar +- fixed MAJOR bugs in budget, scrap, and scuttle (oops!) +emp2.3.6f.sh +emp2.3.6g.tar +- Fixed a bug in "work" which wasn't charging them enough mobility +- Changed "capitol" to "capital" in a hundred million places +- Updated a number of info pages +- Fixed output formatting error in "sorder" command +- Applied a patch from Jan van Beethoven (AIX port) +emp2.3.6h.tar +- fixed a bug which was causing dd's to interdict neutral subs. +- wrote "info Hitchance" which outlines in detail the chance of + anything hitting anything else. This page compliments "info Damage" + which gives all the damage formulas. +- the defense strength of mountains was reduced to 16 to 8 (the + defense strength of a fort). There was a problem of land units + in mountains being invulnerable to everything but nukes. +emp2.3.7a.tar +- missile interception (both abm and a-sat) has been changed so that + interceptors are chosen from the owner of the target sector first (so + that your ally's abm1's won't launch instead of your abm3's) +- if a tradeship won't give the player any cash if it is scuttled + where it is, then the player will be asked for a second confirmation + before they are allowed to scuttle it. +- applied a patch from Ville Virrankoski which fixes a bug in budget + (the cost to repair planes on aircraft carriers was not being included + in the budget) +- fixed a bug which was preventing bombers from being able to drop nukes. +- fixed a bug which let asw planes bomb subs they couldn't see +- fixed a bug that was sending a telegram to the deity when planes on + an acc flew air defense missions. An obscure but annoying bug. +- changed isblank() to blankrow() in lib/commands/sona.c for portability +- fixed a server crashing bug in lradar (some coder put a global + variable in lib/commands/rada.c BAD BAD BAD) +emp2.3.7b.tar +- fixed a bug in bomb which put the server into an infinite loop when + the player aborted at the "commodity to bomb?" prompt. +- when your cap is sacked, you now get a telegram telling you how much + money you lost and they gained. +- when your cap is sacked, then your cap will be moved to a random + adjacent (possibly unowned) sector (the treasurers fleeing the + palace). This was mainly done because players were retaking mountain + capitals every update (you can't redes a mountain to be an aggie!) +- added three new files in the doc directory: "PRIORITY", "WISH_LIST" + and "WACKY_IDEAS". diff --git a/doc/CHANGES3.0 b/doc/CHANGES3.0 new file mode 100644 index 00000000..fa097579 --- /dev/null +++ b/doc/CHANGES3.0 @@ -0,0 +1,449 @@ +Empire 3.0.0 +- Implemented the C_SYNC RFC + - New commands: + sync + toggle sync + toggle async + - New files: + h/edb.h + h/toolkit.h + lib/commands/sync.c + lib/global/edb.c + lib/subs/prsync.c + info/Commands/sync.t + doc/CHANGES3.0 +- New struct members (currently not used) + - player.comhistory command history (for debugging) last 10 commands + - nat.nat_mission_trigger set which relation you want to trigger + various missions and autodefenses at. + - Added land.lnd_scar -- how experienced the land unit is. + - sect.sct_mobil was changed from unsigned char to short (to permit + the removal of updates--note I don't plan to remove updates, but + someday someone might try and they will need this so that sectors can + go to negative mob). +- New struct members (currently used): + - Added type field to all objects so they can identify themselves + - Moved var structs to the top of all class structs for easy location + (see struct genchrstr defined in h/genitem.h) + - nat.nat_hostaddr, nat.nat_hostname, nat.nat_userid, userid and hostname + of last person to connect to that country. If when you login, + your userid or hostname is different from the last person to conenct + to that country, then you will get a message like: +Last connection from: Mon Nov 13 01:48:04 1995 + to: Mon Nov 13 01:48:12 1995 + by: children@RedDragon.Empire.Net + this will improve security and be helpful for co-rulers. Also + added were nat.nat_last_login and nat.nat_last_logout. + - Nation now has 50 realms. +- New global constants: + - Extended nsc ("next selection conditionals" e.g. cen * ?mil=5) to + support C_SYNC messages and include the objects "map" (bmap), and "nation". + These will transmit to the client the equivalent of "dump", "ship", + "car", "land", "lcar", "bmap", and "nation" output and more. + - Added nsc entries for the following classes: sect, ship, plane, + land, nuke, map, item, product, and version. These will transmit to + the client the equivalent of the "show" and "version" command output + and more. + +Empire 3.0.1 C_SYNC 0.0.1 +- changed the order of the struct members of sect, ship, plane, land unit, + nuke to put own and uid out front (note this results in a new version + of the C_SYNC protocol) +- fixed a bug in "sync object" which was sending erronious data +- for now all C_SYNC messages will automatically send uid (or x,y for sects). + this should be changed to implement "surfacing noises" and interdiction. +- whenever any of your sect, ship, plane, land unit, or nuke changes, + you will get a C_SYNC message describing the entire new struct. + - Note this occurs everytime the data changes EXCEPT for changes + which happen durring an update. For now, I will require clients + to call "sync object all" after an update if they want to sync their + database after the update. + - If you loose a sect, ship, plane, land unit, or nuke, then you will + get a very partial C_SYNC message only telling you the id and new owner. +- look, spy, coastwatch (async & sync), now all send you partial + C_SYNC messages telling you information about your enemy's stuff. + - Note: For now, you get precise information about the number of mil in + the sector etc... This will be fixed in 3.0.2 + +Empire 3.0.2 C_SYNC 0.0.2 +- there is now only one announcement file which all countries post to + and read from. the wire syntax has changed to "wire [y|n|]" to + allow you to read announcements from days ago if you want. +- at each update, all announcements older than 7 days (deity + configureable as #define ANNO_KEEP_DAYS in misc.h) are automatically + deleted. +- a player's bmap can now be changed (e.g. by planes flying missions) + even when they're not logged on. +- added a new command "sharebmap ". If + is friendly towards you and your bmaps already share enough information + in common, then your bmap will be added to their bmap. For more details + (there are alot more details) connect to empire.net 7773 1-10 and type + "info sharebmap". +- now whenever a designation gets added to your bmap, the client will + receive a very small C_SYNC MAP_CLASS message +- when your country's money, reserves, cap location, name or origin + changes, you will get a C_SYNC NAT_OBJECT message with your new nation + data. Client writers take note: there is a new field in the nat + struct called "xstart,ystart" which is the start location of the + origin. So if the client needs to make some transformation of the + co-ordinates, it can refer to this variable. +- when you type "nation", that will also send a C_SYNC NAT_OBJECT + message to the client. +- removed a bunch of fields from the C_SYNC nat struct (to cut down bandwidth) + (this results in a new version of C_SYNC). +- information about enemy commodities, tech, or efficiency are now + rounded to the nearest 10. + +Empire 3.0.3 C_SYNC 0.0.3 +- added three new land units: "cavalry 2", "light infantry", and + "aau1". Here's the basic scheme. The old cavalry are an average + between the somewhat weaker cav1 and somewhat stronger cav2. + light infantry are half the size of and slightly fastar than inf1's. + "aau1" come at the same tech as Zepplins and let low tech countries + try to throw rocks at low tech planes... +- reduced the size of "ts1 trade ship 1" to 100 lcm, 50 hcm, $1500 + (from 200 lcm, 100 hcm, $2500). Most players were waiting for ts2 + so this is a nice way to deal with that. +- after each update, all countries receive the message "C_SYNC EDB_UPDATE". + (this results in a new version of C_SYNC). +- all telegram files have been moved into a subdirectory called "tel". +- new subdirectory of the data directory "sync" holds spooled C_SYNC messages. +- if the player is not logged on when they receive a C_SYNC message, + then it will be spooled to their sync file. If the sync file + contains spooled messages older than 3 days (deity + configurable as SYNC_KEEP_DAYS in misc.h), then the C_SYNC message will + not be spooled. +- New command "sync read [yes|no]" reads all spooled C_SYNC messages. + If the [yes|no] argument is not specified, the player will be asked: + "Can I throw this information away now?". +- Removed the "bdes" command. It is no longer necessary (since the + server now automatically adds 'X' sectors to your bmap, and it also + automatically adds sectors that your planes fly over when they're + flying missions). The "bdes" command in conjunction with the new + "sharebmap" could lead to abuses, and since it is no longer really + necessary, I removed it. Given the choice between sharebmap and bdes, + I think most players would choose sharebmap. +- The delivery and distribution stuff was removed from the output of + "commodity" and each column was widened to 5 characters (to accomodate + the new system where sectors are now allowed to hold up to 9999 of stuff) +- IP addresses will now only be resolved into hostnames if RESOLVE_IPADDRESS + (in misc.h) is defined. +- Mountains will now mine gold at 1/5th the rate that gold mines do (thar's + gold 'n them thar hills!) + +Empire 3.0.4 beta C_SYNC 0.0.4 +- If the game is a blitz, then the "players" command will list other + countries which are logged on. This will cut down on the "is anybody + else logged on?" announcements. Note that for players, "last command" + and "user@hostname" are not printed (only deities get to see this stuff). +- fixed a server crashing bug in "sync class all". +- each country now has two bmaps, their 'working' bmap and their + 'true' bmap. The true bmap contains only information put there by the + server. The working bmap also contains information put there by the + bdes and sharebmap commands. The "bmap" command usually displays the + working bmap unless the player specifies "bmap true". Also, + if the players working bmap somehow becomes corrupted, then they can + type "bmap revert" to revert their working bmap back to their + true bmap. This change was necessary to prevent abuse of the new + "sharebmap" command (which now compares the players true bmaps when + determining whether they overlap). +- There is a new info page 'info Empire3' which contains game changes + of particular interest to players. +- Put the bdes command back in. +- Added a new question in the "configure" script: "Do you require your + server to be unusually small?". If the deity answers "yes" to this + question, then many bells and whistles will be turned off to generate + a lightweight "bare bones" Empire server. +- I have padded each object struct out by a spare char, int, and long. + This is to give me room in the coming months in case I need to make + a change which needs data in the object structs, and I don't want to + invalidate currently running long term games. +- Tested the HIDDEN and SLOW_WAR mods (these hadn't been tested for + the Empire2+ server yet). + +Empire 3.0.5 beta + +Note: the primary focus of this upgrade is to address the f1 +SAM-soaking problem. The solution I adapted is a mixture of ideas +from various people--mostly not myself. I appologize for forgetting +whose ideas these were, and I hope that in consolation for not +acknowledging you, you will at least be happy that I implemented +your ideas. This was a pretty big job. + +- In the old system, planes would be charged either 10 mobility + (interceptors), 12 mobility (escorts) or 20 mobility (the rest) per + flight. This cost was then multiplied by (100/eff) with the + restriction that plane mobility could not go below -32. Planes flying + missions were charged only 1/4 of this. In the new system, planes are + charged a base rate of 5 mobility to prepare for takeoff. On top of + this, they are charged a "flight cost" which is either 10 (interceptors + and escorts) or 20 (the rest), however this flight cost is scaled down + according to the length of the flight--it is multiplied by (flight + length) / (max plane range). The flight cost is then scaled by + (100/eff) with the restriction that a plane can't go below -32 + mobility. Planes flying missions are charged 1/2 of this. +- The mobility of a plane will now go down by one point for every two + points of damage it took from air-to-air combat, to a limit of -32 + mob. This is to simulate the high mobility cost of air-to-air combat, + and the fact that air-to-air combat is more effort for low tech planes. +- SAM interception is now separate from plane interception; for each + attacking plane, if the plane cost at least $1000 to build, then one + SAM will be launched at it. After SAMs have been fired, fighter + planes will intercept what's left over. +- The restriction that high tech nations can not build low tech planes + has been removed (the above changes address the f1 SAM-soaking problem). +- marine missiles on interdiction now fire at a single ship rather + than the whole fleet. They pick the ship which is the most valuable + according to (cost to build) * efficiency. Furthermore, marine + missiles will only launch at a ship if the ship cost at least $1000 + to build or if it can carry land units or planes. +- the NEWPAF option has been made standard. +- fixed a bug which wasn't giving a +1 radius bonus to units in 60% HQ's. +- "toggle sync on" now sends back a "sync version" as per the RFC. +- fairland now prints an error to stderr if it can't grow the + continents (it used to just print the last partially built map). +- when you break sanctuary, your 100% sanctuaries turn into cities and + all your other sanctuaries turn into roads (this is helpful for + games which use "bigstart"). + +Empire 3.0.6 C_SYNC 0.0.5 +- Fixed a bug in the attack code which was underestimating defense + strength (it was only giving the sector defense bonus to land + units--not mil). Note--the bug was only in the estimation part, so + countries were not being given a chance to abort attacks where the + odds were clearly against them. +- Mountains can now only hold 1/10th as many civs as normal sectors. +- Raised the gold production efficiency of mountains from 20% to 75%. +- Changed fairland to put gold in mountains. +- flash and wall messages are no longer truncated. Instead the message + is split into 60 character pieces which are transmitted one at a time. +- If the game is HIDDEN then non-contacted countries no longer show up + on your "relations" output. +- If the game is HIDDEN and you try to declare relations with a + country you haven't contacted yet, then you will now get an error + message (before you got nothing at all). +- Update production reports are now Production Reports again (they + were BULLETINS since Empire2.0.0). This will fix a bug which was + preventing players from being "informed" when they get an update telegram. +- The new info page "info Mobility" gives the formulas for all + mobility costs in the game. +- Before you type a telegram, you will now see: + Enter telegram for Fodderland + undo last line with ~u, print with ~p, abort with ~q, end with ^D or . + 1024 left: + The new tilde escapes work very nicely. +- The prompt for escorts has been changed from "plane(s)? " to "escort(s)? ". +- Changed the mobility cost to move into a sector from + cost = (mcost - eff) / 5 + to: + if (mcost < 25) + cost = (2 + (3 - mcost) * eff) / 5 + else + cost = (mcost - 20 * eff) / 5 + +OLD SYSTEM: eff 0% 100% NEW SYSTEM: eff 0% 100% + + 0.2 0.0 + 0.4 0.0 + m 0.4 0.2 m 0.4 0.2 + ^ 5.0 4.8 ^ 5.0 1.0 + + Note that this means land units can attack 100% mountains now, so + there will be a tradeoff for the defender--either they can have a low + efficiency mountain that costs more mobility to attack but gets a + lower defense bonus, or they can have a high efficiency mountain that + costs less mobility to attack but gets a higher defense bonus. +- New conditional query "coastal" which gets set when you take a + "census" of the sector. Type "cens * ?coast=1" to get a list of all + of your sectors which are adjacent to water (and thus vulnerable to + assault). +- Added a new C_SYNC field to SCT_OBJECT called "coastal". This results + in a new version of the C_SYNC protocol. + +Empire 3.0.7 +- Fixed a server crashing bug in the sneak attack code +- Sectors with 0 mobility can no longer enlist mil +- In a HIDDEN game, you can now only see relations for countries you + haven't met yet +- Fixed a bug in the "Last login from" part of the login sequence. +- added new global array player_commands which keeps a list of the + last 100 commands typed by players. Added a file doc/debugging which + explains to deities how they can access this list. +- Fixed a bug that would prevent you from being able to assault your + own sector if SLOW_WAR was enabled. +- In a HIDDEN game, llook will now contact. +- Fixed a bug in the SLOW_WAR mods which was charging people WarCost to + declare war when their enemy was Sitzkrieg towards them. +- Fixed a bug in HIDDEN--sending a telegram or auto-coastwatch + sighting ships will now both contact. +- Fixed a bug in SNEAK_ATTACK--you are no longer charged for boarding + a non-at-war ship. + +Empire 3.0.8 +- Removed an infinite from the autonav code. +- Fixed the "client" login command. + +Empire 3.0.9 +- Consolidated budget code for ships, land units, & planes (Ville Virrankoski) + +Empire 3.0.10 +- Fixed a bug in radar (anonymous) +- Ported the server to Ultrix (Yannick Tremblay) + +Empire 3.0.11 +- Port to FreeBSD (submitted by Janjaap van Velthooven) +- Fixed a server crashing bug in range command +- Fixed a bug which gave players free info when they shelled deity bridges + (reported by Jim Gillogly) +- Small ships can now fuel in cities (reported by Walter Smith) +- Fixed compile bug in wu.c (reported by Curtis Larsen) +- Documented toggle sync and toggle async (reported by Bernhard Reiter) +- Fixed a bug in shoot which was leading to abuses (reported by + Nathaniel Thurston) +- route now prints % sectors (reported by Nathaniel Thurston) + +Empire 3.0.12 +- mkmf is no longer needed to compile the server (Michael Straub) + NOTE: This change depends on "cpp -M" working on your system. +- A number of bug fixes to the "budget" command (Ville Virrankoski) + +Empire 3.0.13 +- Fixed a bug in "budget" command +- If cpp doesn't exist on the system, then "cc -MM" is used in place + of "cpp -M" + +Empire 3.0.14 +- Extensive consolidation of "budget" command with update routines + (Ville Virrankoski) +- Fixed some of the portability problems arising from the switch to "mkdep" +Empire 3.0.14a +- Fixed a server crashing bug in the update routines (introduced at 3.0.14) + +Empire 3.0.15 +- Fix of a MAJOR bug in the budget/update routines which was + overcharging countries for military reserves (Ville Virrankoski) +- Simplification & fix of mkdep/configure (Yannick Tremblay) +- Port to Solaris 5.5 (Ron Kuris ). Here are the notes +that came with the Solaris port: +---------------- +These are the patches to make the new server work on Solaris. +Some notes: + + My environment is that we have cc from Sun, but no license. + We have gcc installed as /opt/gnu/bin/gcc. Although it was + built with Solaris 5.4, it works fine on 5.5. If you need + gcc, use archie to exact search for FSFgcc.gz (I found it + on qiclab.scn.rain.com in /pub/solaris). You also need + FSFtools.gz for gnumake. These packages install very easily. + + While running configure, your 'gnumake' is /opt/gnu/bin/make, + and the compiler you should use is /opt/gnu/bin/gcc. + + My build path is something like: + PATH=/opt/gnu/bin:/usr/ucb:/usr/bin:/usr/sbin:. + + Once you apply the patches, everything seems to work. + +Whoever integrates this into the mainstream: + The change to client/GNUmakefile is the only one I think + that might need tweaking. It sets the default build flags + to Solaris (somehow I don't think you want that). I tried + pretty hard not to break anything else. + + The change in lwp.c I think is just an outright bug, but + most versions of the lwp system dependent stuff just happen + to get lucky by not saving the registers. This should NOT + be relied upon! +---------------- + +Empire 3.0.16 +- Optimization of mkdep (Yannick Tremblay) +- Moved solaris from emp3 to emp3/make/Systems (Ron Kuris) +- Minor enhancement to "lcargo" code (Ron Kuris) +- Fixed a bug which had setting budget priorities on land units + result in being charged twice for them (Ville Virrankoski) + +Empire 3.0.17 +- "read" command now sends a C_SYNC nation message. (Curtis Larsen) +- Fixed a bug which was deleting the announcement file when there were + no announcements (reported by Ed Down). +- Fixed "~u" tilde-escape for "telegram" and "announce" commands (it was + possible to undo back past the beginning of the buffer and crash the + server (reported by Nathaniel Thurston). +- mkdep optimization (Yannick Tremblay). +- Changed syntax for "cede" command so that you can specify "se" or + "sh" on the command line (reported by Tero Paananen). + +Empire 3.0.18 +- fixed a serious bug in configure and mkdep which prevented the + server from compiling + +Empire 3.0.19 Ken Stevens 17 Apr 96 +- Fixed a serious bug in the Empire3 server which allowed players to + create an infinite number of shells and food out of nothing. + I added a new field "simulation" to the player struct and set this + field to 1 in all update simulation commands (budg, prod, neweff). + Then in the update code, instead of checking the variable update_pending + to determine whether the update is "for real", I check the player->simulation + variable. Note that when the commands sneweff, pneweff, and lneweff + get added to the server, they should also set player->simulation to 1. +- subs/takeover.c added a check to make sure the number of che doesn't + overflow (Paul Byrne) +- update/revolt.c. It fixes two problems. First, after security + forces kill che, if there are no che left, the function returns + without saving the zero-che value. Worse, it never checks for + negative che values, which looks like it could happen. The second one + is in che moving. It loops through the neighbors looking for the best + place to move. Problem is, if it finds a place to move it doesn't + move to that place, but simply to whichever place it last looked. + (Paul Byrne) + +Empire 3.0.20 Ken Stevens 21 May 96 +[from 3.1.2] +- fixed a serious bug in the "production" command which could cause + a server crash (Steve McClure). +- fixed a bug in the "starve" command which could suck all the food + off of a ship or land unit on the ship (Steve McClure). +- fixed a bug in the "deliver" command mis-interpreting the return + value of the putvar function (Steve McClure). + +[from 3.1.3] +- Fixed a bug in road mobcost calculation (Steve McClure) +- Fixed a bug in the toggle command (reported by Keir Novik) + +[from 3.1.6] +- Fixed a bug in the attacking code where moving mil into a sector was + going on. It would probmpt for the max amount of mil to move in + by mobility, but when you moved in it never checked, so you could still + move all the attacking mil in (Steve McClure) +- Fixed a bug in fairland (Ken Stevens - reported by Janjaap van Velthooven) +- Fixed a bug in map C_SYNC (Ken Stevens - reported by Markus Armbruster) + +[from 3.1.7] +- fairland.c. Better representation of the map for >30 continents. + The markings for continents start wrapping for more than 62 continents, + the map won't get any control characters anymore (Janjaap van Velthooven). +- C_SYNC. forces a newline whenever data with a different id is appended to a + partial line. Caveat: this sacrifices the line structure to correct + the line tagging (Markus Armbruster). +- Fixed a bug which wasn't printing the last row of `sync object bmap' + in god's coordinate system (Markus Armbruster). + +[from 3.1.16] +- port to Ultrix (Markus Armbruster) + +Empire 3.0.21 Ken Stevens 1 July 96 +- fixed a bug in reco & sat which wasn't putting a carriage return + after land units. +- fixed a bug in starvation command which sent the user a telegram + telling them how much each of their land units lost due to starvation. +- fixed a bug which would send you a message "RUMBLE...your sub hears + a depth-charge explode nearby" when you weren't navigating subs + (reported by Keir E. Novik) +- increased buffer size in emp_client from 1024 to 4096 for sync + class version (reported by Markus Armbruster) +- fixed a bug in revolt code which could damage a sector below 20% + without checking if it was a bridge (reported by Pat Loney) +- fixed a bug in SLOW_WAR which prevented you from re-inforcing your + own sector by assaulting (Aaron Dewell). +- fixed a bug in sack capping news item (reported by Ed Down) +- fixed a server crashing bug in "offer" command (reported by Jon Wright) +- fixed a bunch of info files (reported by Keir E. Novik) diff --git a/doc/CHANGES4.X b/doc/CHANGES4.X new file mode 100644 index 00000000..1115ce11 --- /dev/null +++ b/doc/CHANGES4.X @@ -0,0 +1,1294 @@ +Changes to Empire 4.2.12 - Mon Aug 18 16:54:21 MDT 2003 + * Corrected contact information for Wolfpack. + * Sector isn't abandoned until move or explore is complete. + * Fixed multiple cases where return value of getstarg() was + used without being checked which crashed the server. + * Used stdarg.h instead of varargs.h. + * Call only_subs and save result before mission frees attacker + list. Call with free list could cause server crash. + * Fixed spy sat map for units on opposite side of world wrap. + * Don't sleep in main thread when called from signal handler. + * Fixed error checking in pthreads. + * Properly detach pthreads. + * Pass unlocked mutex to pthread_mutex_unlock. + * Cope with interrupted sleep in pthread empth_sleep to prevent + double update. + * Added server configurable update window. + * Initialized variables passed to setsockopt in accept.c. + * Fixed bug where sharing bmap with uncontacted country crashes + server. + +Changes to Empire 4.2.11 - Sun Sep 1 09:54:59 MDT 2002 + * Added compile option for the Mac OSX architecture. + * Fixed bug in cargo where unit array was indexed by shp_maxno + instead of lnd_maxno. + * Fixed bug in reject where aborting the command crashes the + server. + * Can't buy land units into enemy headquarters. + * Added sabotage command and commando unit. + * Spies moving by themselves will not trigger interdiction. + * Fixed error in map distance calculation that caused errant + interdiction. + * Ships going under -127 mobility will be set to -127 mob and + not roll over to positive mobility. + * Corrected plane cost in info Maintenance. + * Changed error message for loans rejected for being too big. + * Land units will take casualty damage proportional to their + ability to carry mil. + * Fixed bug where "route i *" crashes server. + * Cannot upgrade planes in orbit. + * Fixed bug in declare with deity aborting command at last + prompt crashes the server. + * Coastwatch notify works with NO_FORT_FIRE option. + * Thread that kills idle connection will charge player for + minutes the player was logged on. + * Removed separate sendeof at end of execute from emp_client + that logged players off on certain platforms. + * Updated player idle counter during read prompt so players + wouldn't be kicked off during long flashes or writing telegrams. + * LOSE_CONTACT will work as advertised. + * Allied units marching through 0 mobility conquered sectors + are charged at least LND_MINMOBCOST. + +Changes to Empire 4.2.10 - Mon Aug 13 14:34:39 MDT 2001 + * Assault can reinforce own sector when SLOW_WAR is enabled. + * emp_client no longer converts lines into tags but still verifies executes, + pipes, and file redirect match players input. + * Added pboard command to capture enemy planes in your territory. + * Declaring war when at Sitzkrieg won't return relations to Mobilizing. + * Declaring war won't charge money if you're already Mobilizing. + * Added multiple territory fields. + * "show nuke build" displays the proper avail. + * retreating land units will only retreat to sectors owned by the player + that owns the unit. + * added hard cap of "250 + easy" to limit_level. + * education p.e. calculation divides edu constant by etu per update. + * Added patch for Linux for the PowerPC. + +Changes to Empire 4.2.9 - Sun Jan 7 15:49:13 PST 2001 + * Fixed data corruption when bogus target gets fired upon. + * Increased size of ancillary stacks to prevent stack overflow. + * Changed all references to empire.cx. + * Ships, planes, and land units lost to lack of maintenance will now be + lost. + * No longer allowed to sack deity's capital. + * Accuracy calculation in land unit support was backwards. + * Corrected formula for likelihood of plague in info Plague. + * Fixed files to correctly size map and bmap files from econfig file. + * No longer allowed to add country 0. It corrupts deity country. + +Changes to Empire 4.2.8 - Mon Oct 9 17:35:35 MDT 2000 + * Fixed range in radar.t and Sector-types.t. Maximum range at infinite + tech is 16. + * Changed so that player can't drop civilians into occupied sectors. + * Fixed bug that crashes update if etus/update is less than 8. + * Fixed sometimes not reporting overflights + * Fixing flak for units/ships to be in all sectors as they should be + * Updated order of firing flak in Flak.t. + * Fixed 80% efficient planes on ships must be maintained. + * Fixed initial MOB_ACCESS check thread sleep time was set by an uninitialized + variable. + * Removed "TEMPORARILY DISABLED" message from mission command for escort + missions. Escort missions have been re-enabled since 4.0.15. + * Using sonar from the navigate command will print the sonar map. + * Eliminated annoying error messages when using navigate with conditionals. + * Fixed Technology.t to correctly add 1 before taking the logarithm. + * Fixed bug that allowed players to steal opponents maps. + * Put time limit for bidding on market and trade in econfig file. + * Moved hours file information into econfig file. + * Added comments on setting update policy in econfig file. + * Added logging of cases where write extends data file by more than one id. + * Option MARKET is turned off by default. + +Changes to Empire 4.2.7 - Fri Mar 10 18:41:04 PST 2000 + * Added new NF_SACKED flag to indicate when a country has had it's + capital sacked. This flag is only cleared when the country actively + redesignates it's capital using the "capital" command, and changed + capital.t to reflect this (no more re-sacking after an update if the + country doesn't reset and repeating until they are out of cash.) + * Added land unit to edit command for planes. + * Added nuketype to edit command for planes. + * Changed so that if the leader of a group of units is a train, the + railways are used for bestpath instead of roadways. + * Changed mission command to also print reaction radius of reserve + missions when set for land units. + * Changed Flak.t to reflect guns having to be loaded onto a land unit + for flak to fire. + * Changed so that visitor countries cannot change their name or password. + * Changed so that you cannot upgrade deity planes, ships or units. + * Changed so that you know where missions are flown from. + * Changed so that the airport owner you fly a mission from is informed. + * Changed so that preperations for takeoff are reported to the owner of + the sector, ship or unit a plane is taking off from if it is not owned + by the owner of the plane. + * Changed so that when a sector reverts during a guerrilla revolt, the + mobility is not reset. When MOB_ACCESS is not enabled, this used to mean + you would always get at least an updates worth of mobility. With + MOB_ACCESS, sectors that reverted during the update were useless, since you + got no mobility for a long time. This fixes that problem, and makes che + more useful as well. + * Changed so that air defense missions don't always send up every plane in the + area, but instead always send up at most two times the number of incoming + planes (for each interdicting country.) This helps to stop 1 plane from + stripping the mobility from 25 air defense planes all at once, but doesn't + limit it to n+1 as there is for regular interception. + * Clarified deity reversion of sectors in Sector-ownership.t + * Clarified production efficiency and added pointer to "show sector cap" + in Product.t + * Clarified nuketype selector for planes in Selector.t + * Clarified that fortifying units does not affect mission status in info + pages for mission and fortify. + * Clarified fuel syntax upon error in fuel command in empmod.c. + * Cleaned up comments causing minor complaints in some builds. + * Fixed bug in loans where you could collect on proposed loans. + * Fixed production command to be more accurate (though it *still* has some + rounding errors, it's better.) + * Fixed potential memory leak in air defense missions. + * Fixed bug where you couldn't pinbomb some commodities if other commodities + didn't already exist in the sector. + * Fixed bug where you couldn't build 0 crew planes without military in the + sector. (This is different from needing at least 1 military to build all + planes that need a crew which introduced another related bug earlier.) + * Fixed bug where scrapping land unit 0 could cause erroneous transfer + messages to be displayed for deity owned planes. + * Fixed bug where land units on ships in a sector taken over were blown + up or captured. + * Fixed bug where planes on ships in a sector taken over were blown up + or captured. + * Fixed bug in sdump printing origx and origy in deity coordinates. + * Fixed bug in satellites showing wrong sectors (sometimes) when using the + optional arguments. + * Fixed bug in launch showing wrong satellite target (showed asat instead + of the target satellite.) + * Fixed bug where you could gain information not normally available using + the "fire" command to determine sector type information. + * Fixed bug in market/trade creating extra money when loans are taken out. + * Fixed problem with land units not being reported sunk after being sunk + on a ship that was nuked or wastelanded in a sector. + * Fixed problem with Spies.t using "llook" instead of "llookout". + * Fixed problem in lwp/arch.c including jmp_buf.h instead of setjmp.h + on some Linux boxes. + * Fixed problem with plague infection being way too high in cities when + the BIG_CITY option is enabled. + * Fixed bug in edit command getting confused with arguments. + * Fixed bug in ask_move_in_off asking you to move in a negative number of + troops (hey, it could happen. :) ) + * Fixed bug in add command not keeping flags or relations initially correct. + * Fixed bug in torpedo command sometimes telling victim about torpedo + sightings even when way out of range. + * Fixed bug in spy command not reporting planes in adjacent sectors, as well + as not formatting them properly when reporting them. + * Fixed bug in satellite with noisy transmission causing a potential + crash of the server with non-100% efficient satellites. + * Fixed potential crashing of the server during satellite display when not + calculating distances to ships and units correctly. + * Fixed bug where planes in non-allied sectors, ships and units could be + used on missions. + * Fixed bug where planes on the trading block could be used on missions. + * Fixed bug where planes and units that get traded don't have mobility set + correctly when using MOB_ACCESS option. + * Fixed bug which made security units virtually useless. + * Fixed access times and mobility not being set right when building planes, + ships, units, bridges and bridge towers when MOB_ACCESS is enabled. + * Fixed minor formatting problem with launch of satellites. + * Fixed minor formatting problem with planes with greater than 999 tech. + * Fixed minor formatting problem with ships with greater than 999 tech. + * Fixed problem with "llook" showing up in TOP info file. + * Fixed problem with lwp Makefile choking on NT builds with clean target. + * General cleanup of potentially ambiguous statements. + +Changes to Empire 4.2.6 - Fri Jun 4 05:55:20 PDT 1999 + * Added "TECH_POP" as an option where technology costs more to make + as your population grows past 50K civilians. It is disabled by + default. + * Changed "produce" command to accurately print what the true p.e. is. + * Changed "update" command to display if mobility updating is enabled for + MOB_ACCESS option. + * Fixed bug where toggling off the coastwatch flag also turned off + forts firing on hostile ships coming into range. + * Fixed bug where assaulting your own land would violate any treaties + you have where assaults are a violation. + * Fixed bug where all planes (even those without need for a crew, such + as missiles) needed at least 1 military to build. + * Fixed bug where when a ship sinks during the update due to lack of maint, + land units and planes on it were left stranded. + * Fixed bug where when a land unit dies during the update due to lack of + maint, land units and planes on it were left stranded on it. + * Fixed bug where nukes could be lost due to MOB_ACCESS updating mobility + while arming. + * Fixed bug in "show sector capabilities" not showing products correctly. + * Fixed bug in "show tower build" printing "bridges" instead of "bridge + towers". + * Fixed bug in sectors that don't revolt not showing up as lost items. + * Fixed bug where maps with an X of exactly 200 is not drawing third line. + * Fixed bug where MOB_ACCESS was not updating the mobility just before + the update. + * Fixed bug in the way treaties are examined and sometimes produce + wrong results. + * Fixed edit to allow creating negative mobility for sectors. + * Fixed setsector to allow creating negative mobility for sectors. + * Fixed bug where when writing out the value of a sector that had + negative mobility and was damaged in combat, mobility was being + set back to 0. + * Fixed Taxes.t info page to reflect that captured civvies only pay + 1/4 taxes. + * Fixed Technology.t info page to reflect TECH_POP option. + * Fixed navigate.t info page to reflect that only ships in the fleet + in the same sector that are fired upon have damage divided up. + * Made techlists toggle on by default (so things are shown in order of + technological advances.) + +Changes to Empire 4.2.5 - Mon Mar 1 06:42:24 PST 1999 + * Added optimization to increasing mobility to check if an object is + already at max mob, just return since it can't be increased. + * Added "-ltermcap" for client libs for hp build (it was already in + hpux build.) + * Added clearing of telegram flags after the update so that the next + telegram is flagged as new and not part of the update. + * Fixed Update-sequence.t to reflect MOB_ACCESS. + * Fixed bug where fortification amount was not being limited to + maximum mobility for land units (land_mob_max). + * Fixed bug where land unit fortification strength was being calculated + by using 127 instead of land_mob_max. + * Fixed bug where scrapping land units was creating military. + * Fixed description of sect_mob_neg_factor in econfig file. + * Increased speed of PT boats. + +Changes to Empire 4.2.4 - Tue Feb 2 05:47:44 PST 1999 + * Added check to make military values match up correctly for land + units. + * Fixed bug in doconfig not putting ipglob.c in the right place. + * Fixed bug where attacking deity sectors will violate a treaty. + * Fixed newspaper.t information file. + * Fixed potential bug in fixing up timestamp information when restarting a + game with MOB_ACCESS turned on. + * Fixed bug in explore command not setting mobility to correct + value when MOB_ACCESS was enabled. + * Fixed bug in enlist setting mobility incorrectly sometimes. + * Added doc/backup file for deities which recommends how backups and + restores of the data directory should be done. + +Changes to Empire 4.2.3 - Wed Jan 13 06:02:35 PST 1999 + * Added linux-pthreads target and build for using pthreads under Linux. + * Added NO_FORT_FIRE option which disables the ability of forts to + fire when enabled. + * Added more error checking and recovery for corrupt data files. + * Changed alphapos target to alpha-pthreads for better clarity. + * Changed fairland to allow 0 sector distance to other islands and + continents (James Risner) + * Changed "frg" and "dam" land unit stats to "rng" and "fir" so they + match the way ships are described (since this is how they really work.) + * Changed Unit-types.t to now describe "rng" as firing range of a unit, + and "fir" as the number of guns that a land unit fires. + * Cleaned up misc. build warnings. + * Changed artillery damage to be 5 + d6 per gun firing from just d6 + per gun firing and updated Damage.t to reflect this change. + * Changed artillery firing ranges to be like ships ranges - divided + by two, and modified them to make more sense. + * Changed artillery units to be "slightly" :) more powerful. + * Changed "cavalry" unit to tech 30 and lowered mil content to 20. + * Changed "artillery" unit to tech 35. + * Changed so that guns are no longer required to build units, and + that guns must be loaded onto artillery units for them to fire. + Client developers note: the show command has not changed yet to + remove the 'guns' column (since guns are no longer required) but + will in a future revision (possibly 4.2.4) so "be prepared" for + "show land build" to change. :) + * Fixed landunitgun to handle all the damage calculations like it should. + * Fixed bug sinking planes when the ship they are on sinks. + * Fixed bug destroying planes when the land unit they are on is destroyed. + * Fixed bug where land units could fire support without enough military. + * Fixed bug in abandoning sectors by marching out a land unit where it + would not let you sometimes (uninitialized variable problem.) + * Fixed gets problem in files.c (James Risner) + * Fixed bug in determinig operations range of a ship. + * Fixed bug in building planes where you could manufacture military. + * Fixed warnings in threading package(s). + * Fixed fire.t to reflect new firing changes. + * Fixed lstat.t to reflect new firing changes. + * Fixed sstat.t to reflect the way things really work. + * Fixed Ship-types.t to reflect the way things really work. + * Fixed the way shutdowns work to hopefully better protect data files. + * Fixed bug in attacking when sector mobility is less than 0 and it would + prompt for attacking with a negative amount of military. + * Fixed typo in fire.t stating wrong parameters for firing from a sector. + * Fixed bug in client when it prompts for country name it was putting + an extraneous end of line on the end that needed to be stripped off. + * Fixed problems running on Linux running on an Alpha machine. Thanks + to Rocky Mountain Internet and Jeremy A. Cunningham for giving us time + on a machine to work out the bugs. (Note that the only build that + works on Linux/Alpha is the linux-pthreads) + +Changes to Empire 4.2.2 - Sun Dec 27 12:46:34 PST 1998 + * Added some code optimizations into the update code when building paths. + * Added some new cacheing for building paths to help speed up updates. + * Added so that you can use "name" and "password" with the change command + as well as "country" and "representative". + * Added flag to power command so that if you are a deity and enter + a negative number of countries you want to see, you see the power chart + for that many countries without power numbers on the next line. Only + useful for deities that want to see the chart un-broken up by that line. + * Added new functionality to fortify command. You can now use a negative + fortification value to cause the unit to be fortified and leave at + least that much mobility on the unit. I.E. "fort * -67" will fortify + all units and make sure the mobility of each unit doesn't go below + 67. If the mobility is already below that level (or equal) the unit + is left unchanged. + * Added that the realm command prints "Realm #n is x:x,y:y" after + you set a new realm. + * Added TREATIES option and enabled it by default. + * Added "no depth-charging subs" and "no new land units" treaty + clauses. + * Added Trannie Carter's basic client fix to use fgets instead of gets. + * Changed market and command to only print the lowest priced lot of + each given commodity by default. If you specify "all" it shows + all lots on the market, and if you specify a specific item, it shows + all lots of that item type. + * Changed start command to only write out sector if it changed. + * Changed stop command to only write out sector if it changed. + * Changed how plane names were changed on server startup if the + PLANENAMES option was enabled. + * Changed move command to use standard askyn function for abandoning + sector prompt. + * Changed plane overlight sightings to take stealth into account, + and if the planes managed to evade all flak and interceptors, they + are not marked as "spotted" over enemy sectors. + * Changed all units with the supply flag to have their marching speeds + based on efficiency since that is their purpose. What this means is + that supply units and trains are more effective at 100% than at 10% + (just as fighting units are more effective at 100% than at 10%, but + their effectiveness is determined by how well they fight, not how well + they "run away, run away!" :) ) + * Changed so that flash toggle is on by default for POGO at setup + time. + * Changed so that when a sector is taken, all land units owned by the + current owner are treated as planes are during takeovers (i.e. there + is a pretty good chance they are blown up, and if not, they change owner + to the attacker and are beat up pretty good.) + * Fixed treaties to work again. + * Fixed bug in taking over land units not using correct pointer (can + cause a crash or data corruption.) + * Fixed collect command to wipe deliver and distribution information + correctly. + * Fixed potential bug in bmap not working when destination bmap has + blank spaces in it. + * Fixed bug in shark command not getting right nation structure. + * Fixed bug in server where empty commands (for example, all spaces + or tabs) were being reported as bogus commands. They are now just + ignored. + * Fixed bug in scrap not dropping land units off of scrapped units carrying + them. + * Fixed bug in news where boarding of land units was reported backwards. + * Fixed bug in calculating new people when growing them during an update. + * Fixed missing -ltermcap in HP/UX build. + * Fixed setsector to limit mobility to 127 not 255 (255 was being caught + later and being reset to 0 anyway) + * Fixed Sector-types.t to show a '\' instead of a '/' for wasteland, + since that is what it really is. + * Fixed retreat.t documentation to reflect the "retreat upon failed + boarding" flag. + * Fixed bug where satellites were not orbiting the world during the + update. + * Fixed bug in torpedos being too smart. They knew how to jump over + land! :) Now the "line_of_sight" routine is used to determine if a + torpedo has a straight path to the destination. If it doesn't, the + torpedo no longer jumps over land, but instead slams into it. This was + an interesting bug because you could torp ships on the other side of + a very skinny island as long as they were in range, even if there was + no sea route possible. + * Fixed bug when pinbombing and you run out of an object to pinbomb (land + units for example) but you still have to pick something to bomb. For + ships it worked ok (just aborted that it couldn't find any more ships) + and this was fixed for land units and planes. + * Fixed server crashing bug when flying a plane and not carrying + any cargo. + * Fixed bug in move losing commodities when it runs out of room in the + destination sector. Goods are now attempted to be returned to the + start sector, and apporpriate steps taken if the start sector is no + longer available. + * Fixed march to prompt you before you abandon a sector you own by + marching out the last land unit. + * Fixed check functions to only check the relevant portions of the structure + and not the timestamp info that doesn't affect how the object functions. + * Fixed bug in spy command that always told you if a spy unit was in a + non-owned sector. + * Fixed bug in displaying of land unit missions not showing correct land + unit range. + * Fixed bug in wire command where new announcements that you read at + the last second don't get wiped out properly. + * Fixed bug where announcement file could be corrupted by very long lines. + * Fixed bug where bmap was not set when player was told what kind of + sector they were attacking (this was an old abusable bug that was + removed long ago to fix the abuse, and it's been fixed in a non-abusable + way finally.) + * Fixed bug where change command would warn you about monetary and + BTU costs, but not prompt you to break out if you didn't want to really + change your country name. + * Fixed bug in sub-launched nukes that are intercepted being reported in + the news incorrectly. + * Fixed bug in load where you could abandon a sector and not know it by + loading your last civilians or military onto a ship. + * Fixed potential memory leak in autonav code. + * Fixed potential bug where you could possibly determine if a sector is + owned or not using one way plane missions. + * Fixed Damage.t info page to properly show damages for planes and + land unit shelling. + * Fixed deliver.t to include syntax for command. + * Fixed country.t to include syntax for command. + * Fixed bug where ships on orders were not adding radar information to + the bmap during an update. + * Fixed bug where ships on sail were not adding radar information to + the bmap during an update. + * Fixed bestownedpath code to use the bmap properly. Note this is a very + important bug fix. When navigating a ship, players are no longer given + free information that they would not normally know. For example, if you + try sailing your ship off into uncharted areas of your bmap, the bestpath + code will only use as much information as you have on-hand (i.e. your + bmap) to plan out your path for you. If you have no information on an + area, it just keeps forging on, until bumping into something. Of course, + after the initial exploration through an area, the bmap will be set and + used for all future sailings through that area. Harbors and bridges + are still checked for construction worthiness if you know where they + are (i.e. they are on your bmap.) (Overall, what happened before + was that the bestpath code would route your ship around islands that + you didn't even know were there, and you could use various commands + to see how that ship was going to sail during the update and thus you + gained information that you wouldn't normally know.) + * Merged bestpath and bestownedpath and wrote new wrappers, "BestShipPath" + and "BestAirPath" to use it properly. It is also good to note that + bestownedpath is used to determine paths for ships and for planes, + and that best_path (which uses the A* algorithm) is used for all land + based paths, and that the two are never interchanged. + * Removed "jet recon" plane (it slipped in during the PLANENAMES conversion, + and RECON was never used before.) + * Removed extraneous "resnoise" and "resbenefit" functions and combined + the two for setresource and setsector commands. + +Changes to Empire 4.2.1 - Tue Nov 3 12:56:20 PST 1998 + * Fixed problem with global/plane.c not defining last structure element + properly, and thus causing crashes when accessing certain plane + routines. This happened during the move to make the PLANENAMES option + run-time configurable. + +Changes to Empire 4.2.0 - Thu Oct 29 06:27:15 PST 1998 + * Bumped rev to 4.2.0 since this is a major release (the server is now + run-time configurable for just about everything and is released under + the GNU GPL.) + * Put in official licensing information. + * Re-arranged and commented the econfig (Empire Configuration) file. The + auto-generated "data/econfig" file is now pumped out chock full of + comments (which may or may not be useful.) Since the server is + pretty much fully run-time configurable (MAXNOC is not, but it gets + a default of 99 anyway) deities will probably be spending more time + in the config file. + * Added server support for building under NT, including mods from + Doug Hay and Steve McClure to get the server building and running + under NT. (This was built using MSVC++ 5.0 on NT 4.0 and command + line "nmake nt") + * Added Doug Hay's ntthread.c implementation for NT threading. + * Added max pop column to "show sector stats" output. + * Added lboard command for boarding land units from sectors. Only raw + mil can board land units, and only mil and land units aboard the unit + being boarded fight back. + * Added GODNEWS option. When enabled, the deity giving people stuff + is shown in the news. + * Added bridge tower sector ('@') + * Added BRIDGETOWERS option. When enabled you can build bridge towers + from a bridge span. You can then build bridge spans from the tower. + If the tower is destroyed ( <20% eff) bridges connected fall unless + supported on the other side. You can only build bridge towers in open + water not adjacent to land and other towers. Expensive. + * Added plains sector ('~') - Max pop is 1/40th regular sectors, and + it is deity creatable only (can't redesignate unless you wasteland it + with a nuke :) ) + * Changed "info all" to no longer use printdir, instead it just uses the "all" + info page which contains this information. + * Changed so you can now load up to 2 spy units onto non-land unit carrying + submarines if the LANDSPIES option is enabled. Useful for sneaking up + to shore and spying on your neighbors. + * Changed so spies unloaded from ships are not given as gifts, they are just + unloaded quietly. + * Changed build command to handle building towers ("build t") + * Changed show command to show tower stats ("show t b") + * Changed reject so you can now reject things from any country except + deity countries (this now includes sanctuary countries and visitor + countries you don't want to deal with) + * Changed ndump to dump nuclear stockpile ID as well. + * Changed flash so that if someone allied to you is either not logged on or + not accepting flashes, you are notified. This is info you could gain + otherwise since you can see other countries that are allied to you via + players. + * Fixed bug in news command when HIDDEN mods are enabled. + * Fixed distribute command to only write out to the database if we + actually changed the sector (i.e. if we really moved the dist + center, we write. Otherwise, it makes no point.) + * Fixed threshold command to only write out to the database if + we actually changed the sector (i.e. if we really changed the + threshold, we write. Otherwise, it makes no point.) + * Fixed - population growth and truncation in "Update-sequence.t" info + file is now clearer + * Fixed the way fortify takes mobility away from a land unit if + engineers are present. + * Fixed bug in buying commodities at the last minute not resetting the + time correctly in all situations. + * Fixed bug in building nukes where it would always ask if you tried + building more than one at a time. + * Fixed bug where if you put (either by building or by transporting) + more than 127 of one type of nuke in a sector, they all got lost. A + negative wrapover sort of thing. + * Fixed ndump to print # of stockpiles dumped. + * Fixed ndump.t to reflect changes + * Fixed bug in build command that didn't account for EOL characters. + * Fixed bug where you could use planes to drop conquered populace + * Fixed bug in distribute command in how it checked for current distribution + sector. + * Fixed pr_flash and pr_inform to no longer send messages if the player + is still in the process of logging in (i.e. not in the PLAYING state) + * Fixed report command output for deities. + * Fixed bug in nuclear damage either taking out submarines when it + shouldn't, or not taking them out when it should. + * Fixed bug in loading units that are carrying units onto other units + (note that it doesn't happen since only HEAVY units can carry other + units and that check works, but that might change some day, and we + don't want units carrying units to be carried by other units, etc. :) ) + * Fixed info pages to reflect new sector types. + * Fixed info pages to reflect new spy unit capabilities. + * Fixed show commands to only show trade ships if the TRADESHIPS option + is enabled. + * Fixed build command to only allow building of trade ships if the + TRADESHIPS options is enabled. + * Fixed up some definitions located in many places used for checking + sectors for navigation rights. + * Fixed power.t to correctly describe NEW_POWER formula. + * Made HIDDEN option run time configurable. + * Made LOSE_CONTACT option run time configurable. + * Made ORBIT option run time configurable. + * Made SAIL option run time configurable. + * Made MOB_ACCESS option run time configurable. + * Made FALLOUT option run time configurable. + * Made SLOW_WAR option run time configurable. + * Made SNEAK_ATTACK option run time configurable. + * Made WORLD_X and WORLD_Y run time configurable. + * Made MARKET option run time configurable. + * Made LOANS option run time configurable. + * Made BIG_CITY option run time configurable. + * Made TRADESHIPS option run time configurable. + * Made SHIPNAMES option run time configurable. + * Made DEMANDUPDATE option run time configurable. + * Made UPDATESCHED option run time configurable. + * Made LANDSPIES option run time configurable. + * Made NONUKES option run time configurable. + * Made PLANENAMES option run time configurable. + * Removed SMALL_SERVER stuff (unused baggage) + * Removed trading post sector ('v') + +Changes to Empire 4.0.18 - Thu Sep 24 06:54:27 PDT 1998 + * Fixed bug in aircombat where planes in flight could intercept air + defense planes and take no damage (i.e. they got to fight twice, + once for free.) + * Fixed bug in freeing memory after performing missions that could crash + the server (it mainly happened after an interdiction mission using + planes and escorts, where some escorts came from airports that didn't have + bombers going up. Freeing the leftover escorts was crashing the server.) + * Fixed bug where you could load non-existant units if you were allied + with country #0. + * Fixed bug where you could pin-bomb a plane with itself. + * Fixed bug where satellites over a bridge may get killed if the bridge + is sunk. + * Fixed bug where land units on a ship in the same sector as a bridge + that is splashed may get sunk. + * Fixed bug where planes on a ship in the same sector as a bridge + that is splashed may get sunk. + * Fixed doconfig with correct empire site text. + * Fixed major problem with abms not firing, and sometimes crashing + server. + * Fixed bug in land units counting up loaded units wrong. + * Fixed doconfig makefile to have doconfig.c as a dependency. + * Fixed bug in resetting commodities (the comm_uid was not being + properly set.) + * Fixed bug in repaying loans not working correctly (the l_uid was not + being properly set.) + * Fixed bug in buying items from the trading block not allowing you + to due to a perceived change in item status. + * Fixed bug in mfir.c where a bogus input to a target could crash + the server. + * Fixed bug that after you read telegrams new telegrams may not send + an inform message (the old telegram flags were not cleared.) + * Fixed bug where fort support distance calculations are calculated + twice instead of just once. This bug caused a lower percentage + of support fire than designed. + * Fixed bomb.t to reflect land unit changes. + * Put in some integrity checking for planes returing from bombing runs. + * Added ability to edit land unit that a land unit is loaded on in + edit command. + * Consolidated bridgefall code into "knockdown" function (this code + existed in at least 3 places, and was different in all of them.) + * Subs returning fire are no longer reported in the news. + * Visitor countries can now use the 'motd' command. + * When trying to use a visitor country, if it is in use, you are not told + by whom, just that it is in use. + * Optimized (slightly) support fire from forts not getting supply and + shells if not needed (out of range) + * Updated Education.t + * Modified (increased) chances of hitting mines slightly. + * Removed unused variables from shp_check_mines. + +Changes to Empire 4.0.17 - Fri Jul 31 06:12:21 PDT 1998 + * Added ability in edit to change coastal flag for sectors. + * Added ability in edit to edit plague values for ships. + * Added ability for "spy" to report all units/planes not owned by you + that exist in the sector you are spying from. + * Modified naval planes and anti-sub planes. + * Changed so that missiles and bombs that miss their targets cause + collateral damage in the target sector (they have to land somewhere!) + * Changed llook so that non-spy units are required to have at least 1 + military personnel on board to see anything. + * Fixed "llookout.t" to reflect change for military requirement. + * Updated Plague.t + * Updated upgrade.t + * Added "lmine" flag for deities to see what sectors have mines in them + (works for sea and land mines, used "lmine" to distinguish it from "min" + which determines mineral (iron) content of a sector.) + * No longer able to pin bomb land units on a ship. + * Land units are required to have at least one military loaded to perform + a mission. + * Firing land units are required to have at least on military loaded to + be able to fire (or return fire.) + * Spies are not always seen when being pinbombed. You have to look very + carefully for them (as you usually would.) + * Fixed typo in "Spies.t" + * Added new info about spy ability to spy.t. + * Updated tax information in Innards.t and Update-sequence.t + * Fixed typo in fire.t information about units firing on ships. + * Loading military onto land units now resets fortification. (You gotta + re-fortify the new guys.) + * Fixed bug where planes that were mine capable could not drop mines if + they were not cargo capable. + * Fixed bug in potentially crashing in update code for nations tech/research. + * Fixed bug in execute putting you into execute mode incorrectly. + * Fixed bug in board not allowing land units to board from 0 mobility + sectors. + * Fixed bug where interdicted land units that were missed displayed + a "SPLASH! Bombs miss your ships" message. + * Fixed bug in minesweeping sectors where, even with mobility or + having the sweep ability, ships would get hit by mines for doing + nothing. + * Fixed bug in count_land_planes always writing out land units unnecessarily. + * Fixed bug in count_planes always writing out ships unnecessarily. + * Fixed bug in lnd_count_units always writing out land units unnecessarily. + * Fixed bug in count_units always writing out ships unnecessarily. + * Fixed bug in llook that reported units on ships. + * Fixed bug in llook that reported satellites launched over the unit. + * Fixed bug in llook that always reported spies (it should be a 10-100% + chance) + * Fixed bug in anti possibly not saving lost items correctly. + * Fixed bug in planes getting extended range when on missions and the + op center is not where the plane is located. + * Fixed bug in land unit defensive strength not being based on the eff of + the unit when calculating odds of a battle. + * Fixed bug in board not reporting consistant information. + * Fixed bug in the way land unit casualties were being taken. + * Fixed bug where land units on ships could return fire. + * Fixed bug where land units on other land units could return fire. + * Fixed bug where land units on other land units could fire. + * Fixed bug in attacks/assaults/boardings spreading plague incorrectly. + * Fixed bug in updating plague for ships. + * Fixed bug in updating plague for land units. + * Fixed bug in updating plague for attacking/defending land units. + * Fixed bug where you couldn't pin-bomb land units that were < 20% eff. + * Fixed bug which revealed the owner of torping subs when on a mission. + +Changes to Empire 4.0.16 - Fri Jun 12 08:52:06 EDT 1998 + * Added patches sent in by Steve McClure, Sverker Wiberg and Curtis + Larsen. They are described with other changes below. + * Fixed bugs in the following commands that allowed two cooperating + countries to create infinite numbers of any commodity and/or cash + at any time (race conditions in the server): build, board, deliver, + designate, distribute, explore, fuel, improve, load, ltend, mobquota, + move, name, order, reset, sail, sell, set, tend, territory, test, + threshold, torpedo, transport, unload + * Fixed bug in board command giving out too much information about a + non-owned sector when it shouldn't be. + * Fixed bug in board command when firing on a sector in defense before + checking mobility. + * Fixed bug in rangeedit allowing plane(s) to possibly be stored wrong. + * Fixed bug in launch allowing plane to possibly be stored wrong after + launch. + * Fixed bug in lrangeedit allowing land unit(s) to possibly be stored wrong. + * Fixed bug in morale allowing land unit(s) to possibly be stored wrong. + * Fixed bug in arm/disarm allowing a plane to possibly be stored wrong. + * Fixed bug in loan sometimes not writing database correctly. + * Fixed bug in collect. + * Fixed bug in dropping mines from land units. + * Fixed crashing bug in sector_strength routine when oceans take + collateral damage. + * Fixed bug in transport possibly decrementing too much mobility when + moving a nuke. + * Fixed some little warning type messages building with gcc -Wall. + * Fixed problem compiling lwp threads with glibc6 under Linux. + * Changed flash so that players can always flash deities. + * Changed players command to always show deities and visitor countries + that are logged on, and only show allied countries for normal player + countries. + * Fixed bug in anti command not stopping sectors when they revolt. + * Fixed bug in set_coastal function not counting bridge spans as + water based sectors (after all, the land is still a coastal sector, + even if next to a bridge span.) + * "flash" and "players" is re-enabled for visitor accounts. + * Fixed bug in bleeding of technology and research to other players. + * Fixed bug in explore not spreading plague correctly. + * Fixed bug in move not spreading plague correctly. + * Fixed bug in deliver not spreading plague correctly. + * Fixed bug in distribute not spreading plague. + * Included "postresults" script in the scripts directory which can be + used to auto-post daily power chart/announcements to rec.games.empire. + * Updated Plague.t + * Updated Innards.t + * Removed OVCONFIG from build.conf, and patched doconfig to match. + * doconfig is only run if needed + * emp_client and emp_server are only linked if needed + * Added list of disabled options to the version command. + * Fixed bug in survey allowing you to see hidden variables. + * Re-enabled escort missions due to above bug fix most likely the problem. + * Changed one instance of "restrict" to "restricted" in bestpath.c. For + some reason, this was causing a problem on one of the Linux builds (??). + * Added "show sector capabilities" functionality (this didn't exist + before.) + * Fixed bug in neweff not reporting stopped sectors. It now (correctly) + reports them as not changing eff. + +Changes to Empire 4.0.15 - Wed May 20 12:35:53 EDT 1998 + * Fixed the spelling of Markus' name in CHANGES4.0 files. + * Added Markus' patches/fixes. Some are detailed below. + * Added 'mipsultrix.gxx' build target. + * Fixed doconfig to write ipglob.c in the correct target area. + * Fixed a bunch of type casting that needed to be done correctly. + * Only print out last connect by for non-visitor accounts. + * 'players' command is only useable by non-visitor accounts. + * Fixed ask_off in attsub.c to not print out allied sector mil counts + when attacking from neighboring sectors. + * Fixed targetting of che when taking over sectors. + * 'anti' command only fights che that are targetted at you. + * Fixed update not updating timestamps of objects (ships, planes, land + units, sectors.) + * Fixed bug delivering conquered populace. + * Fixed potential bug scuttling ship with land units on it. + * Moved heavy bombers to tech 90. + * Fixed bug in setsector telling the deity coordinates of sectors being + granted/taken away. + * Fixed bug in setting budget of enlistment sectors to 0. + +Changes to Empire 4.0.14 - Wed Apr 8 08:47:54 EDT 1998 + * Fixed time_t problem in common/log.c + * Fixed bug in headlines + * Replaced vaxultrix build flags with proper vanilla ones. + * Fixed bug in update/prepare.c (sometimes not getting charged for + mil on units and ships) + * Fixed bug in printing of "No ship(s)" twice in cargo command when no + ships were selected. + * Temporarily disabled escort missions until a fix is found. They are + randomly crashing the server. + * Fixed morale.t to reflect that retreat percentage is based off of + morale_base and not 75. + * Fixed bug in bridgefall where planes and units on ship in a sector + that has a bridge collapse are being sunk. + * Fixed bug in update/produce.c when a sector overflows it's capacity + on production. + * Fixed bug in produce command reporting incorrect costs (sometimes). + * Land units on ships will now try to draw supply from the ship they + are on. + +Changes to Empire 4.0.13 - Mon Mar 2 11:04:28 EST 1998 + * Fixed bug in distribute when world sizes are other than 64x32 + * Fixed bug in getcommand (not really a bug, just made it work like + it used to so that the players command is useful for deities + again) + * Fixed building of POSIX threads on Alpha running Digital Unix. + * Fixed line_of_sight prototype in sona.c + * Fixed fairland not to conuse stupid C++ compilers. + +Changes to Empire 4.0.12 - Tue Feb 24 11:27:31 EST 1998 + * Fixed client build on linux (whoops) + +Changes to Empire 4.0.11 - Tue Feb 10 10:53:10 EST 1998 + * AIX build seems to only work with gcc right now (but at least that works) + * Vax Ultrix (vaxultrix) build should work now (hopefully) out of the box. + * Took out autosupply of airports when bombing or dropping shells. + (This was the only commodity this was done for, and it was creating + problems since supply is still somewhat broken somewhere) + * Included Curtis Larsen's, Markus Armbruster's and Sverker Wiberg's + submitted patches, which collectively included cleaning up most + of the server prototypes and bogus declarations. Many thanks. + * Increased incoming command buffer to 1024 from 512 bytes + * Increased the # of parsed arguments from 64 to 100 + * Fixed bug where spies were not dying when damaged. + * Fixed bug in HIDDEN mods in declare command not printing country # of + uncontacted country correctly (or at all as a matter of fact) + +Changes to Empire 4.0.10 - Mon Aug 18 12:34:58 EDT 1997 + * Fixed bug where fleets were being interdicted but the damage was being + spread to ships not in the same sectors. + * Fixed but in market when buying goods without enough cash. + * Planes in orbit over airports are no longer fixed up during updates. + * Planes in orbit are no longer damaged when the sectors they are over + are damaged. + * Planes on ships are no longer damaged when the sectors they are in are + damaged, unless the ship is damaged. + * Fixed problem with no newline after partisan activity telegram in + anti.c + * Fixed problem in chan.c printing out change costs incorrectly. + * Fixed problem in dispatch.c screwing things up on redirection. + * financial should now handle 6 and 7 digit loans. + * Planes on ships that are in sectors that revolt are no longer taken + over. + * Fixed bug in powe.c where the power report was mis-calculating the + efficiency of planes. + * Fixed doconfig.c to use STDC instead of multi-level #ifdefs. + * Fixed bug in parse.c that was screwing up double quotes in conditional + arguments. + * Military in a sector now only produce up to maxpop, just like civvies + and uw's. No more stuffing 6K mil into a mountain to max it out. You + can still hold more mil there over the updates, but the extras just + won't produce anymore. + * Fixed bug in shark that allowed you to shark up loans even if you couldn't + cover the debt. + * Fixed bug in day of week calculation for server up time in common/keyword.c + that is used for gamedays. + * Documented what happens to standing military in collect.t when you collect + a sector. + * Documented mountains only holding and using 1/10th of the normal sector + population in Sector-types.t. + * Fixed documentation on ship's firing ranges in fire.t to be less + ambiguous. + * Updated nukes in nuke.t + * Added apropos command (thanks to Mike Wise) + * Added case-insensitivity to the info command (thanks to Mike Wise). If + there are two files of the same name, and you don't get a complete match, + then whichever file is found first in the directory is used. + * Changed documentation in wantupd.h + +Changes to Empire 4.0.9 - Sat Apr 19 23:01:51 EDT 1997 + * Fixed dump info pages that were getting formatted funny. + * Fixed improve info page. + * Fixed bug in allied planes/units not moving when the carriers move. + * Fixed bug in satellite output for <100% satellites. + * Fixed bug in load/unload not putting a newline after some unloadings + in allied sectors. + * Fixed bug in harden not printing correct values. + * Fixed bug in creating/moving/etc. nuclear stockpiles. + * Fixed bug where subs were trying to torp commodities moving on land when + on interdiction. (This was funny ;-) ) + * Fixed bug in "move" where you could keep a sector even after someone else + took it from you. + * Budget now correctly reports the # of units being built. + * Mil on units & ships are now reported as normal military costs, not + ship or unit maintainence costs in budget. + * Fixed bug in update code where taxes could potentially be initialized + incorrectly (affected budgets too.) + * Fixed bug in nat.h header so that it uses SCT_MAXDEF instead of a fixed + number (that was incorrect.) + * Fixed bug with trains - they needed the xlight flag to carry planes. + * Revamped and improved flak. + * Added "Flak" info page. + * Added "Fallout" info page. + * Fixed repay/offer/consider to all need a capital to be used. + * Fixed bug with air defense missions not running when not AT WAR. They now + fly when HOSTILE. + * plane/ship/unit short names are all now 4 characters, padded if needed. + * pdump/sdump/ldump/ndump now just print the short name for the type. + * sdump now has ship name at very end in quotes. + These were done at the request of some client developers for ease of use. + * Fixed extra space in the dump output. + * Fixed fallout - not quite so nasty anymore. + * Fixed fallout - things on ships/units are damaged now. + * Fixed and balanced planes/ships/units/nukes in conjunction with each other. + * Fixed bug in doconfig.c calculating wrong s_p_etu sometimes. + * Fixed bug where harbors weren't being used to resupply. + * Fixed bug where selling units loaded with planes and units wouldn't take + the loaded planes or units - they are now dropped. + * Fixed bug in arm/disarm where you could arm/disarm planes on the trading + block. + * Deities can now remove things from the trading block/market. + * Fixed bug in "work" not charging engineers enough mob. + * Fixed bug in "work" not adding teardown and buildup avail costs together. + * Subs no longer need mobility to return fire when fired upon. + * Fixed "reset". + * Fixed bug in "trade" allowing 2 players to pay for the same item, but only + the last player gets it. + * Fixed bug where you couldn't launch missiles from allied ships or sectors. + * Fixed bombing so that pin-bombing can cause collateral damage too. + * Fixed sector damage to damage planes there too. + * Fixed flag in lload so that it doesn't always print if not needed. + * Fixed "sell.t" info page. + * Fixed bug in "buy" where not entering the price correctly could cause + a crash. + * Fixed "sell" so that at least 1 mobility is required to sell goods. Keeps + the midnight "raid and sell" abuse down. :) + * Fixed "show plane cap" to move the last column over 1 more where it should + be. + * Fixed timestamps to be updated for units/planes on ships/units that move, + since those units/planes move too. + +Changes to Empire 4.0.8 - Wed Feb 26 23:00:51 EST 1997 + * Fixed bug in nstr_exec that was wiping out the previous conditional. + This was major because it affected timestamp values which are more + than 65535. + * Fixed bug in sdump.c for typo in reporting the trade ships origin. + +Changes to Empire 4.0.7 - Mon Feb 24 22:48:54 EST 1997 + * Fixed bug in aircombat.c when calculating the air combat odds. Negative + numbers were screwing things up good... + * Fort sector's coordinates are no longer printed when auto-firing at + ships. + * Subs can now surface and fire deck guns (again) They can also be + hit by return fire when doing so. + * Fixed bug in setting of plane attack and defensive values so that + negative numbers don't keep going further negative. + * Fixed incorrect military control calculation in the sell command. + * Trading posts are no longer required to sell goods from. You can sell + from harbors and warehouses now too. + * Spy now prints out the owner of land units you see when spying. Before + this was assumed to be sector owner, which is no longer true. + * Loading land units now prints out what was loaded onto each unit, + just as loading ships do. + * Added fallout, coast, c_del, m_del, c_cut and m_cut to dump output. + * Added "GO_RENEW" option. This option means that gold and oil resources + are renewable. + * Added "lost_items_timeout" config variable, and set the default to + 48 hours. This determines how long lost items stay in the lost items + database. + * Fixed land unit names to be more consistent. + * Fixed mission.t info page. + * Fixed bug in that if mission_mob_cost was set to 0, even negative + mob units should be able to be put on missions. + * Removed restriction on things needing to be at least 60% to be put + on a mission. Note that while you can put them on missions at < 60% + now, when trying to do the mission, it still checks the eff. This + is to help in automatic setup (build, put on mission, forget) instead + of having to come back repeatedly. + * Spies caught in Neutral or Friendly countries cause the Neutral or + Friendly country to go Hostile towards the owner of the spy. + * Tweaked ammunition numbers for artillery units. + * No more automatic declarations of War should be made. You will go + hostile, but since going to war doesn't increase your countries + defenses, and is purely political, it is left to the player to go + that final step. + * Fixed bug in trade that wasn't incrementing the time if last second bidding. + * Fixed bug in "lmine" that was crashing the server if the land unit was + out of mobility. + * Fixed buy so that if you specify a product, you can only bid on that + type of product. + * Added "lost.t" info page. + * Added "lost items" database (EF_LOST) + * Fixed bug where you could move in allied forces after an attack if they + bordered the victim area. + * Fixed nstr_comp to deal with values > 16 bits coming in from + client for comparisons. + * Changed last minute market/trade timers to increment 5 minutes. 2 minutes + was too quick. + * Fixed decode in lib/common/nstr_subs.c to deal with NSC_TIME better. + * Commented out the logging of the market checking in server/marketup.c, + lib/commands/buy.c and lib/commands/trad.c It was generating lots of + pretty much useless data that made parsing the server.log file more + more difficult than it needed to be. + * Fixed crashing bug in ldump. + * sdump, ldump, ndump, pdump and dump now print out the current + timestamp on the "DUMP XXX" line. + * Fixed denial of service bug in lib/player/accept.c in + player_find_other function. + * Fixed bug in shark reporting incorrect buyer of the loan. + * Fixed bug in sdump.c (case 0 should have been case 10) + * ldump and sdump now always print the fuel column if asked for, + even if opt_FUEL is turned off. In the case that it is turned + off, the fuel is listed as 0. + * Added "timestamp" field, which is updated every time an item is + changed. + * Fixed up the Clients.t info page. + * sdump now prints trade ship building origin. + * sdump now always prints name even if SHIPNAMES isn't defined. If + it is not defined, then the name is empty. + * Added "timestamp" to info/Concepts/Selector.t + * Added some more relevant info to info/Server/Empire4.t + * Fixed Infrastructure.t info page to reflect the fact that infrastructure + is no longer torn down when a sector is re-designated. + * Fixed sell.t to more accurately reflect the time-delay market. + * Fixed read.t and wire.t to reference accept and reject. + * Fixed reject.t not referencing accept command. + * Fixed collect.t to more accurately reflect what goes on when collecting + sectors. + * Fixed financial.t to reflect defaulted loans. + * Fixed dump.t, sdump.t, ldump.t, ndump.t, pdump.t to reflect new + timestamp info. + * Fixed "census.t" (had incorrect reference to "info syntax" instead + of "info Syntax". + +Changes to Empire 4.0.6 - Thu Jan 16 11:33 EST 1997 + * Increased damage from depthcharges because on increased damage from + torpedos. Sub frange decreased to be more balanced with destroyer frange. + * Intelligence reports (spy) on units will now report the estimated number + of mil on the unit. + * Fixed equation for ship visibility so it will drop as tech increases. + * Added new commands sdump, ldump, pdump, and ndump to dump data on ships, + land units, planes, and nukes. + * If fields are provided, dump will only supply those fields requested. + * Decreased speed of subs. + * When options NO_LCMS or NO_HCMS are set, those commodities are no longer + required for infrastructure improvements. + * Units that lose an assault or a boarding attempt from a ship will no + longer swim back to the ship they came from. + * Units that take extra casualties will no longer lose all their mil at + once. + * Infrastucture is retained when redesignating a sector. + * Dieing spies will no longer crash the server. + * Units, planes, and ships must have mobility to perform missions. + * Units on ship being scrapped are transferred to harbor. + * Food is no longer autoloaded onto units when they are built. + * Fixed show plane stat to show correct range. + * Infantries now take damage at same rate as casualties. + * Fixed bug with hap_fact. Having more happiness now helps with fighting + che. + * Fixed anti to write back target country so che will continue to fight + when they survive. + * Fixed llookout to show correct estimate on number of mil on unit. + * Added buildable architecture "hp". This type will build the server on + a HP/UX machine using the standard compiler instead of gcc. + +Changes to Empire 4.0.5 - Thu Dec 12 10:28:48 EST 1996 + * Fixed bug in update/distribute.c where pathcost was not being called with + the MOB_ROAD argument (and thus distribution costs could be GREATLY + affected.) - Thanks Ice! + +Changes to Empire 4.0.4 - Mon Dec 9 11:00:00 EST 1996 + * Fixed Solaris port using gcc. + * Fixed doconfig.c to create directories with right modes. + * Fixed install macros in makefiles to move binaries to the right + places. + +Changes to Empire 4.0.3 - Wed Dec 4 22:46:53 EST 1996 + * Added HP/UX port. + * Fixed doconfig.c (put exit(0) at the end of main.) + * Fixed improve.c (moved the prompt[] string outside the fcn.) + +Changes to Empire 4.0.2 - Mon Oct 14 12:26:40 EDT 1996 + * Put in LND_MINMOBCOST in land.h + * Put in change in lnd_mobcost in lndsub.c + * Put in new nuke costs in nuke.c + * Put in fix so that total work can only be done by the max pop. No more extra + civvies tossed in will do it anymore in human.c. + * Put in fix for src/util/Makefile - beefed it up. + * Put in fix to show where your ship is when it gets shelled in mfir.c. + * Changed infrastructure of roads from .040 to .020 (122 instead of 150 in + common/move.c) + * Fixed Update-sequence.t. + * Put in fix for mobcost bonus for 0% highways. + * Fixed stop.t + * Fixed commodity.t + * Spruced up torpedo damage somewhat. :) :) + * Fixed "assault bmap bug" in attsub.c + * Fixed Produce.t (bars cost) + * Changed mountains to get an automatic "2" for defensive bonus in attsub.c + * Fixed consider.t + * Fixed repay.t + * Fixed offer.t + * Fixed "offer" and "consider" not being legal commands in player/empmod.c + * Fixed Damage.t + * Fixed sstat.t + * Fixed lstat.c, pstat.c and sstat.c + * Fixed cutoff command in cuto.c + * Fixed attack value in attack_val in lndsub.c + * Fixed lload in commands/load.c + * Fixed defense_val in lndsub.c - Made it a minimum of 1, so that units will + always fight until dead or retreating. 0 makes them get stuck. + * Fixed update/deliver.c - no delivery of non-oldowned civvies (or anything + else for that matter.) + * Fixed llook in commands/look.c + * Fixed che bug in subs/nstr.c + * Fixed bug in strv.c by overcompensating by 1 food per sector (minute amounts + of people would starve.) + * Fixed update/human.c - feed_people rounding problems (I hope.) + * Fixed morale problem in update/land.c + * Fixed count_bodies in attsub.c + * Fixed lnd_mobcost. + * Fixed subs/land,plane,ship.c to handle sunken units and planes correctly. + * Fixed interest rate in commands/offe.c + * Fixed bug in buy.c. + * Put in DEFENSE_INFRA soption o you can turn on/off the use of the defensive + infrastructure. When off, the defensive infrastructure is the same + as the sector efficiency, and you can't improve it. This is OFF by + default. + * Fixed Empire4.t + * Added Wolfpack.t + * Land units are now built with a default reaction radius of 0. + * Changed name of lt artilleries to "lat" from "lart" so you can now build + "lar"s again. + * Lowered the speed and firing range of pt boats. + * Lowered the initial att strength of cavs from 1.5 to 1.3 (they were TOO + powerful.) + * Changed the max mob gain defaults of units/planes to 1.0 and ships to 1.5 + (This is * ETU_RATE, so it is equal to ETU_RATE for units/planes and + 1.5 * ETU_RATE for ships.) + * Conquered civvies only pay 1/4 taxes. + * Railways don't get torn down when you rebuild sectors anymore (but roads + and defenses do (if enabled.) + +Changes to Empire 4.0.1 - Wed Aug 28 11:35:40 EDT 1996 + * Added "extern double tradetax" to check_trade in trad.c + * Improved description of data directory in build.conf + * Fixed bug in attacking land units that retreat so they now get + charged mobility for attacking. + * Fixed dump to report road, rail and defense of a sector at the end. + * Fixed doconfig bug in not checking the right directory to see if the + "data" directory existed or not before trying to create it. + * "change" now works for sanctuary countries. + * Fixed the description of "sinfrastructure". + * Added more info to "Infrastructure". + * Units/planes are no longer reduced to 75% when bought from the trading + block. + * Supply units were slowed down to the speed of infantry units. + * Trade-ship payoffs have been lowered to 2.5, 3.5 and 5.0 + * Bars interest is up to $250 per 1K again. + * Civ taxes were raised back up to a 10:1 mil/civ tax ratio (was 20:1) + * Fixed various info pages. + * Fixed bug in people not getting truncated when broke (this was thought + to be fixed, but wasn't. Now it is, dammit!) + * Fixed bug with units marching across oceans (scuba gear not included. ;-) ) + * Market/trade taxes and trade ship payoff figures were added to version. + * "cede" has been removed as a default command. + * Makefile rule was fixed for depend build. + * Fixed bug in mapdist not taking world edges into account nicely enough. + * Added a "scuttle" order for autoscuttling trade ships. Makes using them + easier. Cleaned up scuttle code while in there. + * Fixed bug with scuttling a ship with units on it not scuttling the units + too. + +Changes to Empire 4.0.0 - Initial release + * Initial Wolfpack release - Long live the Wolfpack!!!! + * Cleaned up the build environment. Now all that is needed is to edit the + build.conf file, answer the questions there and type "make " to + build for a specific architecture. Thus, no more reliance on gnumake + or special shell scripts. + * We are now shipping the pre-built info pages with the server for those who + Don't want to build them. You can also still just type "make" and have + the info pages build, but it doesn't completely work (i.e. rebuild new + Subjects) if you don't have perl5 installed. + * Put in the "help" command that does the same thing as "info". + * Removed C_SYNC. This is done for 2 reasons. 1) None of us like it or + wish to support it. 2) We envision a better scheme for doing similar + things will come along. + * Put in MOB_ACCESS - This allows real-time updating of mobility. + * Put in MARKET - This is the time-based market (yes, still teleports, + but it's not as bad as it was.) + * Lots of the documenation has been updated, but there is more to do. + * Added NO_LCMS, NO_HCMS and NO_OIL options. When any of these options are + enabled, you don't need any of that type of material to build things. + If NO_HCMS is enabled, you don't need HCMS to build bridges, you need + lcms. If both NO_HCMS and NO_LCMS are enabled, then you don't need + any materials to build a bridge. + * There is no mobility cost for assigning missions. But, there is also + no longer any benefit for being on a mission either. + * Damage is the same for all commodities (people too.) This means you + can deity shell/bomb sectors again. + * Units are now dependant on tech. What this means is that their statistics + now increase with tech. In addition, there is only 1 type of each basic + unit now (i.e. just "cavalry" instead of "cavalry 1", "cavalry 2", etc.) + This reflects the idea that as you learn more, you learn how to not only + build better units, but you learn to build units better. :) This also + opens the door for a "lupgrade" command along the same lines as the + "upgrade" command for ships. + * Units now have a minimum mob cost for attacking a sector. Marching + mob costs have not changed. + * Starting units have been removed. This means that at the beginning, people + may live a little longer since their neighbor can't come visiting quite + as quick. + * Shells are no longer required to build units. + * Mil are no longer required to build units. + * Mil are no longer an intrinsic part of a unit. They are now a loadable + commodity. The way a unit's defense/att bonuses work now are + attack = (att * mil * eff) + defense = (def * mil * eff) + In addition, when a unit takes damage, both the eff and the mil go + down. You can quickly toss in new hacks, but you need to wait to repair + the unit at the update. Thus, you can now look at unit's efficiency + as their training. + * You need at least 1 mil on a unit to march it (spies are the exception.) + * Units always react if in range and they have the mobility, no matter + what their efficency. + * Units may now march anywhere - in your own sectors, deity owned sectors + or allied sectors, with 1 exception, spies. Also, your units can get + trapped if your ally declares non-alliance with you while your units + are still in his country.) + * Units always march at their speed, efficiency doesn't matter. + * LANDSPIES was added - This creates land unit based spies. Spies may march + anywhere, with a chance of getting caught (except in allied territory.) + See "info Spies" for more info on them. + * Planes may now be based out of allied airports. Landing planes on + ships/sectors you do not own no longer changes thier owner. You can only + land on owned/allied sectors/ships, and you may only + fly/bomb/para/recon/drop from owned/allied sectors. So, if a country + you are allied with goes hostile at you, your planes are now stuck there. + Note that if you are using an allied airport, their commodities get + sucked up, not yours (obviously.) + * Planes are now tech-based. Their statistics increase as their tech + increases. Deleted extraneous planes. + * There is a new toggle, "techlists", which allows you to see what you + can build/stats/capabilities sorted by tech instead of groupings. + * Ships are now tech-based. Their statistics increase as their tech + increases. Deleted extraneous ships. + * Che can now be lessened by making happiness. If you have more happiness + than your conquered populace, they don't fight as hard or recruit as + much. If you have less than them, they fight harder and recruit more. + It's not much though - it ranges from 2.0 in your favor to only 0.8 + against you (whereas it was always 1.0 before.) So, it definitely + favors the attackers to make lots of happy now. + * Bridgeheads can only be built on coasts. + * Players command was fixed so you only see allies, and don't get + approx #'s of players anymore. + * POSIX threads support has been added. + * The attack bmap bug has been fixed. + * BTUs regenerate 3 times faster now. + * GRAB_THINGS is off by default. + * Big nuclear bombs are back, and FALLOUT has been fixed and enabled + as a default (you couldn't make wasteland before with FALLOUT, now + you can.) + * You can now deliver military and civilians. + * Added SHIP_DECAY option - off by default (turns off ships decaying out + at sea if not enough mil.) + * The reverting owner bug has been fixed in territory, thresh, dist + and deliver. There are probably more, and when found, will be fixed. + * The "sectors don't starve when stopped or broke" bug has been fixed. + * The "people never get truncated" bug has been fixed. + * Added infrastructure to sectors. What this means is that a sector + can now have it's mobility improved by building both roads and + railways. It also means that a sectors defense is now based on the + defensive infrastructure you build into the sector (no more intrinsic + better defenses based on the sector, you determine which sectors are + defended heavily, and which aren't.) + * The defensive value of a sector no longer relies on the efficiency of + the sector. Instead, it relies on the defensive efficiency of the sector. + Thus, the "production" and "defensive" aspects of sectors have been + separated. + * "show sect stats" now shows the maximum defensive value for sectors. + * Changed sector structure to take floats for off/def values so we can use + a base of 1 instead of 2. + * Added "improve" and "sinfrastructure" to support the infrastructure + concepts. + * Added L_TRAIN units which can only travel along railways. Very fast on + efficient railways, slow on non-efficient ones. + * Added the ability for units to carry other units. + * Fixed census (shortened up "fallout" and "coast" to "fall" and "coa".) + * Forts only cost $500 to build and 100 hcms now (since they don't get any + better defenses automagically.) + * Modified "show sect build" to show the costs for building up the + infrastructure of a sector. + * Changed "spy" and the satellite recon stuff (which shows sector stuff for + spyplanes too) to show the new infrastructure stuff, rounded of course. + * Added Drake's info->html scripts, with some modifications, so you can + now type "make html" and have your info pages built as html files too. + This adds a new directory, "info.html", to the build tree. + * Modified upgrade so that planes and land units may now be upgraded. + * Added pstat command to list the statistics of your planes. + * Added lstat command to list the statistics of your land units. + * Added sstat command to list the statistics of your ships. + * Added nmap command to show a map of your sectors after their new + designations have taken place. + diff --git a/doc/README b/doc/README new file mode 100644 index 00000000..1807db71 --- /dev/null +++ b/doc/README @@ -0,0 +1,54 @@ +This directory contains the following files: + +files + What's where. + +backup + Recommendations for how to do backups when running a game. + +troubleshooting + Some common problems and solutions. + +disk_space + Stuff you can delete to make more disk space. + +compiling + How to compile the Empire2 server. + +configuration + How to turn options on and off, change game parameters, etc... + +econfig + Details about the syntax of data/econfig. + +bug-reports + What to do if you find a bug. + +threads + Dave Pare explains how lwp threads work. + +coding + Guidelines for coding style + +CHANGES + Revision history for all the changes that were coded in the Empire2 + project. A much more readable version of this may be found in + "info History" (brief) or "info Empire2" (detailed). + +CHANGES2.3 + All changes since revision 2.3 + +CHANGES3.0 + All changes since revision 3.0 + +CHANGES4.0 + All changes since revision 4.0 + +PRIORITY + things which need to be coded soon. + +WISH_LIST + things which maybe should be coded sometime. + +WACKY_IDEAS + things which shouldn't be coded except possibly as an option. diff --git a/doc/WACKY_IDEAS b/doc/WACKY_IDEAS new file mode 100644 index 00000000..faa8ebc9 --- /dev/null +++ b/doc/WACKY_IDEAS @@ -0,0 +1,171 @@ +-=O EMPIRE WACKY IDEAS LIST O=- + +This file contains the more bizarre and outlandish proposals for +changing the game of Empire. See the EMPIRE WISH LIST for an +explanation of the indexing system. + + _________________________________________________________________ + +--- TABLE OF CONTENTS --- + +Attack, Assault and Board.................a +Missions..................................m +Ships.....................................s +Planes....................................p +Land Units................................l +Commodities and Sectors...................c +Information Commands......................i +Telegrams, Announcements, News............t +Updates...................................u +Deity.....................................d +Miscellanious and Documentation...........x +Error Messages............................e + + --- ATTACK, ASSAULT AND BOARD --- + +a4 +frontline +When a unit is created, it is automatically put on the frontline +(except for artillery and supply units). This means that when you +attack an adjacent sector, you will be asked if you want to include +this unit in the attack. +backline +When a unit is put on a mission, it is automatically put on the +backline. This means that when you attack, you won't be asked about +attacking with this unit. Also, supply units and artillery are born on +the backline. When attacking with units, allow the user to type Y, +rather than typing y for all the units you want to attack with. Y +would mean "attack with all units on the frontline". At the attack +prompt, you will be asked: Attack with infantry #3 (y/n/Y/N/b)? and +the "b" will mean "backline". This would be particularly handy when +attacking with a bunch of units and you want to leave some of them +behind to hold the beach-head. And you want to stop being prompted for +them. + + --- SHIPS --- + +s9 +swap [s|p|l] +Swap the id numbers of units so you can control the order in which +they are built. In order to swap the numbers, the units must be in the +same sector, and the sector must be either a h/*/! as appropriate. +WARNING: this could be seriously abused! + +s11 +nuclear subs consume rads as fuel? need rads to build nuc sub? + +s17 +in fuel command, one petrol should be worth 20 oil. right now it is +more efficient to fuel ships and units with oil rather than with +petrol. +( in this one, it would probably be better IMHO to get rid of fueling +with oil altogether - Ken H.) + +s20 +Make assaulting cost ship mobility. This would help stop the ability +to assault with a small amount of mil over and over until +reacting units run out of mobility. + + --- PLANES --- + +p3 +Allow transport planes to paradrop land units. (This would be +realistic.) Would use the following analogy: + +Units on Planes Units on Ships +x-light assault +para marine +cargo light + +So, "cargo" units could be transported, "x-light" units could paradrop +but at a serious disadvantage and would lose all mob, and "para" units +could paradrop like marines could assault (with full attack and +reduced mob loss). + +p8 +planes should mobility when loaded and unloaded from a ship. + +p12 +Have an aquatic plane type. This would be a medium to small cargo +plane, that must be built in an airport but can only take off froma +harbor, or sea sector. While on the water, it could tend, however, not +be able to nav. It might, or might not be able to lay/sweep mines. And +fuel is another issue that would need to be looked into. + +p14 +perhaps the range a plane can fly should be limited by its efficiency. + + --- LAND UNITS --- + +l2 +trans l +to use sector mobility to transport a land unit from one sector to +another. + +l3 +Make a new kind of land unit (transport trucks) which can carry land +units in a similar way that ships can carry units. This would allow +you to transport heavy artillery and unmechanized infantry around +faster. (This would be a realistic change). + +l5 +Have very expensive land units called a spies: + + lcm hcm mil guns shells avail tech $ +spy 1 10 0 1 0 0 2 0 $2000 +spy 2 10 0 1 0 0 2 0 $5000 +spy 3 10 0 1 0 0 2 0 $8000 + + + +Spies can march through enemy territory and llook in there. Every +update, there will be a chance the spy is caught. Also there is a +chance it will be caught every time it moves in enemy territory and +every time it does an "lloo". It will be completely unaffected by +combat. The chance of detection should be something like: spy 1 10%, +spy 2 5%, spy 3 2%. + +l6 +land units should lose mob when loaded/unloaded from a ship. + +l10 +mobile headquarters unit type - capable of repairing land units by +using mobility, supplies, and mil. How about just letting engineers +work on units also? + + --- COMMODITIES AND SECTORS --- + +c9 +Limit the amount of commodities (by weight) allowed to be kept on a +bridge, and have a stacking limit for units on a bridge. (Bridges can +only support so much weight eh?) + +c10 +build tu +At a price, build a tunnel through a mountain sector. This would turn +a ^ into a + at some great cost. + +c12 +autodemob 11,11 35 y +"autodemob" is to "demob" what "autonav" is to "nav". The principle is +simple: "autodemob 11,11 35 y" means every update, demob all the mil +in 11,11 except for 35. ( note - makes budget more complex - Oliver +Ricou ) + +c14 +We need some Empire command which lets you do a lot of moving at once +with minimal BTU cost. Here would be one possible syntax: multimove + This is just like +distribute at the update. It would distribute commodities between + and depending on (which applies to the +), and only doing moves provided that the mobility doesn't fall +below in any of the sectors involved: empire [124,512]% +multimove f * ?civ>20 40 1,1 40 An alternate symtax could be: +multimove +where existing distribution thresholds are used. + + --- MISCELLANIOUS AND DOCUMENTATION --- + +x25 +national happiness should be affected by your victories/losses, and if +you drown your mil (by scuttle/scrap) or starv your populace. diff --git a/doc/WISH_LIST b/doc/WISH_LIST new file mode 100644 index 00000000..664fc43d --- /dev/null +++ b/doc/WISH_LIST @@ -0,0 +1,208 @@ +-=O EMPIRE WISH LIST O=- + +This is the complete Empire Wish List. Each item on the wish list has +been given a unique reference number. The reference number does not +indicate priority; it is only there so that we may easily refer to +various items on the list. The reference numbers are permanent, and +any new item added to the wish list in the future will be given a new +unique reference number. + +The blank index number at the bottom of each section refers to the +next available index number for that section. + +Note that the most radical have been moved out of the EMPIRE WISH LIST +and onto the EMPIRE WACKY IDEAS LIST which shares the same indexing system +as this file. + + _________________________________________________________________ + +--- TABLE OF CONTENTS --- + +Attack, Assault and Board.................a +Missions..................................m +Ships.....................................s +Planes....................................p +Land Units................................l +Commodities and Sectors...................c +Information Commands......................i +Telegrams, Announcements, News............t +Updates...................................u +Deity.....................................d +Miscellanious and Documentation...........x +Error Messages............................e + + --- ATTACK, ASSAULT AND BOARD --- + +a12 +aborting an attack should cost you btus or possibly mobility +(otherwise you get info for free). + +a13 + + --- MISSIONS --- + +m7 +Allow people to specify relation level to trigger different missions +(note there is already space for this in the nation struct). + +m8 + + --- SHIPS --- + +s4 +For ship/plane/unit specification, allow a/13/b/15/16/c type +specification where fleets, wings, and armies may be included along +with numbers. (WARNING: This would require massive restructuring.) + +s13 +once ships on sail have arrived at their destination, the "Your fleet +lead by ship #x has reached x,y." in production report every time. + +s22 +Another suggestion related to s21. The gain in efficiency of planes on +carriers or sufficiently crewed ships on sea should use construction +materials etc. This is to make it consistent with land units gaining +efficiency in a sector where the necessary materials are present. +Otherwise it leads to abuse: Say in the beginning of the game I build +a ship but don't want to spend the hcms to build it completely - so I +just crew it it will gain efficiency by itself. I think it could +easily be implemented by giving every ship some capacity for lcms and +hcm's. + +s24 + + --- PLANES --- + +p10 +chh [38:382]% scrap p 28,0 ?eff<50 +Really scrap all planes in 28,0 [n]? n +The prompt is misleading. (Same goes for scuttle). Scuttle and scrap +should probably be consolidated. + +p17 + + --- LAND UNITS --- + +l14 +perhaps since land units in mountains are so hard to attack, we shuold +just not let land units into mountains to begin with. + +l16 + + --- COMMODITIES AND SECTORS --- + +c8 +Change bridges (and towers) so that they only crumble when shelled +below 15%. Allows attackers an extra chance for a bridge attack. + +c13 +feed +If a sector in needs more food, send it food from . + +c16 - WARNING - may be difficult to code +forts should return fire even if shot missed + +c19 + + --- INFORMATION COMMANDS --- + +i5 +neweff [s |p |l ] to show the efficiency these +things will have after the update. At present you can only get this +info by doing some heavy calculations. + +i10 +gstarve +lists sectors that need more food if they want to attain maximum civ +growth. + +i12 +prod +should list the commodities consumed in f h * ! sectors for building +stuff. (This would help you calculate your production deltas.) + +i16 +bmap sh +to show enemy ships (that you would see with radar or coastwatch). + +i17 +bmap sa +to show enemy satellites (that you would see on radar). + +i18 +dump +should give you the oldown number, rather than just a *. (Does dump +only give you a * if you're not the oldown? I don't know. You can find +the oldown using ?oldown= so dump should give it to you). + +i20 +radar [ | ] S +shows enemy ships but not your own. + +i22 +cen * ?connect= +lists all sectors connected by land to . Handy for setting up +territories. + +i24 +Allow | as well as & in selection syntax. e.g. res * ?des=o|des=g +(WARNING: cannot use single bar as the or character because "|" is +used as a pipe in the standard client and possibly in other clients. +Another character should be used instead ( or maybe "||"?) + +i27 + + --- TELEGRAMS, ANNOUNCEMENTS, NEWS --- + +t2 +Separate BULLETIN's from Telegrams (so that when we're in the middle +of a fight we will know if we were just attacked or we simply have +just received a letter from a friend). + +t9 +When you are writing a telegram or an announcement and an update hits, +then your telegram or announcement gets lost. ( is it even POSSIBLE to +fix this?) + +t10 + + --- UPDATES --- + +u5 +Planes should not be built by conquered populace. (The problem here is +that building planes uses mil, and you can lose the sector because all +your mil that was being used to hold the sector disappeared into the +planes so you loose the sector at the update.) ALREADY FIXED? + +u9 + + --- DEITY --- + +d3 +Add che (target and number) to deity dump format. + +d8 + + --- MISCELLANIOUS AND DOCUMENTATION --- + +x1 +Often BTU's aren't updated immediately, and the prompt is out of sync +with the actual amount of BTU's they have. + +x6 +info takeover, avail, loyalty +There should be man pages on these. + +x26 + + --- ERROR MESSAGES --- + +e3 + _________________________________________________________________ + +If you have any comments/additions regarding this list, mail them to +me at wolfpack@wolfpackempire.com with the word "wish" in the subject line. + +Wolfpack! + +Last updated: January, 1999 diff --git a/doc/backups b/doc/backups new file mode 100644 index 00000000..53f99fd0 --- /dev/null +++ b/doc/backups @@ -0,0 +1,14 @@ +It is recommended that you take a backup of the "data" directory once +in a while in case of system crashes, data corruption, or whatever. + +It is VERY important to note that you should only take complete snapshots +of the data directory and only restore complete snapshots of the data +directory. Restoring individual files from backups can cause problems. +Some of the known problems with partial restores are: + + * In games with MOB_ACCESS enabled, mobility will be extremely out of + sync if you do not do a complete data directory restore. + + * Land units, ships and planes may think they are loaded onto ships + or land units that do not exist, or have changed owner (been sunk + or destroyed and then rebuilt) since the last backup. diff --git a/doc/bug-reports b/doc/bug-reports new file mode 100644 index 00000000..db4120d8 --- /dev/null +++ b/doc/bug-reports @@ -0,0 +1,42 @@ + Reporting Bugs + +Code Correctness + + What's a bug? Well, if a game program core-dumps under normal + conditions, that's definitely a bug. If a player can manufacture + game items (circumventing the intended game semantics) then + that's a bug too. + + If you don't agree about an existing semantic, or you don't like + the format of a particular command output, that's NOT a bug! + + If you do have a bug to report, I will only pay attention if + I have a chance of fixing it. Bug reports which vaguely + describe behavior, e.g., "Sometimes when I run the ship + command, it gives me funny output" will be ignored! Bug + reports should include game output, stack traces if possible + (assuming a core dump is produced), and the major, minor, and + patch level of the version you're running. + + Once you find a bug, try and reproduce it. If you can't, + then say so. If you can, say that too. If you can't reproduce + it, chances are pretty good that I can't either. + + If you have a debugger, try running the offending game + section under your debugger -- preferably gdb -- and try + and locate the area of code responsible. + + If you can fix the bug and verify the fix, then you can bet + that I'll be much more interested in your bug report. Response + time is likely to be greater too! + +Semantics + + If you want to get into a discussion of game semantics, the + best place to do that is rec.games.empire, or your favorite + empire-hackers mailing list. Don't send me a bug report + about it! + + Naturally, I hope you don't find any bugs. If you do, + go through the above steps, and mail the resulting output + to us -- wolfpack@wolfpackempire.com diff --git a/doc/coding b/doc/coding new file mode 100644 index 00000000..7083c3b2 --- /dev/null +++ b/doc/coding @@ -0,0 +1,143 @@ + Guidelines for writing Empire code + + +Remarks from Dave Pare: + +And now, a few editorial remarks on my views on Good Techniques for +Modifying Existing Software: + +My safari through the hot and bug-ridden jungle that Empire has become +has given me some new insights on the modification of large software +packages. My adventure has prompted me to propose some simple coding +guidelines for those dreaming of hacking on the code: + +1) Be invisible. When you make a change, think not about marking your +place in history, or about showing off how much nicer your two-space +tabs are than those old, icky eight-space tabs that the stupid empire +hackers of old used, but think instead about the asethetics of the whole. +The resulting lines of code should flow smoothly from the beginning of the +procedure to the end. Empire is 60,000 lines of code. If you're the +general case, you're only changing fifty lines, so be aware of that. + +2) Procedurize. If you find yourself in a triple-nested loop, or a five +hundred line procedure, perhaps it's because you need to split some of +that code off into a procedure. In general, if you've got more than two +levels of tabs (or indentations), or more than one or two major loops in +a procedure, something may well be amiss. + + +Sasha Mikheev on indentation: + +The empire indentation style can be achived by using +indent -orig -i8 foo.c + +or in old c-mode emacs (versions before 19.29): +;add this to .emacs +(setq c-indent-level 8) +(setq c-continued-statement-offset 8) +(setq c-argdecl-indent 8) +(setq c-brace-offset -8) +(setq c-label-offset -8) + + +Further comments by Ken Stevens: + +1) Global variables +The only variables which should be global are constants. If you write +a routine which changes a global variable, then you will corrupt the +data when two different players run that routine at the same time. + +2) Portability. +The following code: + char a; + #ifdef FOO + unsigned char b; + #endif FOO +Should be rewritten as: + s_char a; + #ifdef FOO + u_char b; + #endif /* FOO */ + +AIX has different conventions for signed chars, and IRIX requires the +/* comments */ after #endif. + +3) Cut-and-Paste +Cut-and-Paste coding is by far the biggest problem that the current +Empire suffers from. This is how cut-and-paste coding happens. Joe +Shmuck decides that he wants to add a new function to the server. So +he goes hunting through the server to find some already existing code +which does something similar to what he wants to do. This is good. +You should always write new code to imitate old code. What is bad is +when Joe Shmuck decides to simply "copy" 200 lines of code from the old +function into his new function, and then just change a couple of +little things here and there to suit his needs. This method, known as +Cut-and-Paste coding is the fastest and easiest way to code. However, +it results in a server that is impossible to maintain. What Joe +_should_ have done, is "move" the 200 lines of code into a new _third_ +function which the first two both call. This is called writing a +"general solution" to handle both cases. Most of my work in the +Empire2 project consisted in cleaning up after a bonch of Joe Shmucks. +I took repeated code and "consolidated" it into general function +libraries. + +4) Good style. +Just to add to Dave's "Be Invisible" motto, I'd like to give a little +example to illustrate some basic do's and don'ts for coding style: + +The following function has bad style: + +double att_combat_eff(com,own) +struct combat *com; +natid own;{ + double str; + double eff=1.0; + if(com->type==EF_SECTOR) + { + eff=com->eff/100.0; + if(com->own==own){ + str=com->sct_dcp->d_ostr; + }else{ +str=com->sct_dcp->d_dstr;eff=2.0+(str-2.0)*eff; + }else if(com->type==EF_SHIP&&com->own!=own) + eff=(1.0+com->shp_mcp->m_armor/100.0); + return eff;} + +Here is the same function written with "good" style: + +double +att_combat_eff(com, own) + struct combat *com; + natid own; +{ + double eff = 1.0; + double str; + + if (com->type == EF_SECTOR) { + eff = com->eff / 100.0; + if (com->own == own) + str = com->sct_dcp->d_ostr; + else + str = com->sct_dcp->d_dstr; + eff = 2.0 + (str - 2.0) * eff; + } else if (com->type == EF_SHIP && com->own != own) + eff = (1.0 + com->shp_mcp->m_armor / 100.0); + + return eff; +} + +These are all the things I fixed when changing the bad to the good: +- Function names should always start a new line (so you can search for them) +- There should always be a space after a "," +- Function arguments should be indented 8 spaces +- There should always be a tab after a type declaration +- Opening function bracket should be on a line by itself +- Indentation should be 8 spaces +- There should always be a space on both sides of every operator +- There should always be a space after if, for, while, switch +- The opening bracket should be on the same line as the if +- There should always be a space on either side of a { +- There should always be a new line after a ; +- The closing function bracket should be on a line by itself + + diff --git a/doc/compiling b/doc/compiling new file mode 100644 index 00000000..275392b4 --- /dev/null +++ b/doc/compiling @@ -0,0 +1,42 @@ + + Compiling the Game + +Required software: + make + cc + +Machine-wise configuration + + Determine what kind of machine you're on (sun4, sun3, sequent, + mipsultrix machine, alpha, etc). + + Type "make" at the high level, and see if your machine is in the + resulting list. + + If it is not, you will need to edit the high-level Makefile and + add support for your architecture in. Send e-mail to: + "wolfpack@wolfpackempire.com" + if you need help doing this. + +Constructing Binaries + + First, run "make depend" to build the dependencies. You only need + to do this once before the first build. You may run this again if + you make significant changes to the code (including new files, etc.) + + Second, Run "make &" at the top level. + +Installing Info Pages + + The INFO pages aren't run as a part of the normal make session. + In order to install them, you must cd into the "info" subdirectory, + and run "make". This will nroff all the info documents and place + them in the "../info.nr" directory, from where players can + access them during the game. + + You will need perl5 installed as your version of perl for this to + work. + + If you add or change any info pages, then be sure to follow + the instructions in info/README to generate new Subjects pages. + diff --git a/doc/configuration b/doc/configuration new file mode 100644 index 00000000..d18e2663 --- /dev/null +++ b/doc/configuration @@ -0,0 +1,23 @@ + Configuring your Empire server + +Every option within the server has been made Run-time configurable. + +But, certain things may break if you begin a game and start changing +options. One specific thing you cannot change once you have created +a world is the WORLD_X and WORLD_Y. If you change these values, you +will need to rebuild your world. + +Most of the other options you should be able to change on the fly. Of +course, you probably won't want to be changing options in the middle of +a game. But, you should be able to turn them on/off safely. Certain +things might get funny (like if you turn on/off HIDDEN in the middle +of a game for example) but the server should remain stable. + +See the "doc/econfig" for a better description of how the Empire config +works, and see the "data/econfig" file for a better description of each +of the configurable settings in the server. (You may also want to +check out the "info.nr/Options" file for more information on individual +options.) + +Steve McClure, 1998 + diff --git a/doc/debugging b/doc/debugging new file mode 100644 index 00000000..357b6ce0 --- /dev/null +++ b/doc/debugging @@ -0,0 +1,12 @@ +emp_server will only dump core if you run with the -d flag. + +If you decide not to dump core, then the most recent player commands +should be listed in data/server.log. Each command will be preceeded +by the country number of the player which issued it. When the player +is prompted, then [prompt] is printed. + +If you decide to dump core, then the most recent player commands will +be in the global array called player_commands which is indexed by +player_commands_index. The array will contain strings of the form: + "%3d %3d %s", index, player->cnum, command + diff --git a/doc/disk_space b/doc/disk_space new file mode 100644 index 00000000..91faaba5 --- /dev/null +++ b/doc/disk_space @@ -0,0 +1,15 @@ + What can I delete? + + +If disk space is a concern, then there are a number of files which you can +safely delete without affecting your game. + +You can type this immediately: + rm -fr xland old + +Once you have compiled your info pages, you can type: + rm -fr info + +Once you have compiled your server, you can type: + make clean + diff --git a/doc/econfig b/doc/econfig new file mode 100644 index 00000000..b9902cc2 --- /dev/null +++ b/doc/econfig @@ -0,0 +1,141 @@ +This is a short note on the empire configuration stuff. Some of this +is for deities to enable them to configure things, some of it is for +coders to see how this stuff works. + +Julian Onions 15/7/95 + +-- +Also, the Empire config files are now self-documenting (to a point.) +Each option/variable now has a comment associated with it to hopefully +make life easier on deities wanting to change things. + +-- Steve McClure, 10/21/1998 +-- + + +Deity Notes. +----------- + +To find out the current configuration, the simplest method is to +compile up util/pconfig and the run it. It can be run either with no +arguments, in which case it will printout in config format the current +compiled in options. Otherwise with a file containing a configuration +it will first read in this file, and overright any copmiled in +variables and then printout the merged options. + +So the first method shows you whats compield in, the 2nd how a config +file would modify this. + +Blank lines are ignored, as are lines starting with a # character. + +Most of the options are straight forward, they take either a string +(quote using " to get spaces in it) or a number - integer or floating +point depending on the option. + +For instance + privname "The Deity" +sets the internal privname variable to that string, and + port "7777" +sets the empire port to 7777. + btu_build_rate 0.0004 +sets the internal floating point number for btu building rate, +and so on. + +The only other type of variable currently defined are the +options. These may be specified as one or more lines starting +"option" and turned off with the keyword "nooption". + +So, for instance + + option FUEL ORBIT +and + option FUEL + option ORBIT + +are equivalent + +To turn off an option that is compiled in, you can similarly have + + nooption FUEL + nooption ORBIT +or + nooption FUEL ORBIT + + +As a check, pconfig will printout some of the internal file names as +comments at the end just to check they are in the right place. + +The server can take a -e config file as a command line option so that +it will read a specific config file. If not, it will default to +looking for a file econfig in the built in data directory, but it +won't mind if one is absent. Similarly, util/files and util/fairland +et al all take a -e config file to run from a different config. +Thus, to start two games on the same host, you might have + +Game1: +files -e econfig1 +fairland -e econfig1 +emp_sever -e econfig1 + +Game2 +files -e econfig2 +fairland -e econfig2 +emp_server -e econfig2 + +econfig1 might have the lines +data "/empire/data1" +info "/empre/info" +port "7777" + +and econfig2 might have the lines + +data "/empire/data2" +info "/empre/info" +port "7778" + +You only need the lines in that file that you require to override the +compiled in definitions, however having all the definitions may help +you to understand what is on and off. You could do this with + +pconfig econfig1 > e1 && mv e1 econfig1 +pconfig econfig2 > e2 && mv e2 econfig2 + +which will fill in all the missing options and values with their defaults. + + + +Coders information +------------------ + +The simplest way to describe this is to step through how a new option +would be added. + +1. Think of the option name, say, "DUMB". +2. In lib/global/options.c define an integer and set it to 1 or 0 as +appropriate. This is usually done as +#ifdef DUMB +int opt_DUMB = 1; +#else +int opt_DUMB = 0; +#endif + +3. At the end of that file, add an entry into the table so it is +configurable. This is done with a line like +{ "DUMB", &opt_DUMB }, +Make sure the table is still terminated by two NULL values! + +4. In h/optlist.h add an external definition of this variable + +extern int opt_DUMB; + +5. Now the variable is defined, and configurable through the option +keyword in the config file. So you can go ahead and make changes +elsewhere in the code. This normally looks like + + if (opt_DUMB) { + pr("You're being dumb\n"); + } else { + pr ("You're being really dumb\n"); + } +but it may call subroutines, return early from functions or whatever. + diff --git a/doc/files b/doc/files new file mode 100644 index 00000000..b4b1d55f --- /dev/null +++ b/doc/files @@ -0,0 +1,33 @@ +doc/ + Deity Documentation. + +man/ + Man pages. + +scripts/ + Scripts to help you run a game. + +bin/ +data/ +info.nr/ + Game binaries, data, and compiled info pages. + +info/ + Nroff source for the Empire info pages. + +include/ + Empire include files (headers, .h files) + +src/doconfig/ + Self-compiling and configuring program for building the server. + +src/client/ + Source code for the Empire client program. + +src/server/ +src/lib/ + Source code for the Empire server. + +src/util/ + Programs used to generate Empire data files. + diff --git a/doc/message b/doc/message new file mode 100644 index 00000000..a476998b --- /dev/null +++ b/doc/message @@ -0,0 +1,16 @@ +Hello. You have been identified as a potential author of Empire source +code. We are currently in the process of trying to release the code under +the GPL to protect the code and to allow for it's wide-spread distribution. + +We would like to get your comments (either positive or negative) and/or +your approval. + +Thanks! + +Wolfpack! + +Wolfpack! Bringing you the latest and greatest in Empire development and + support, and, in our minds, the best multi-player game around. + +Check out Empire at http://www.wolfpackempire.com + wolfpack@wolfpackempire.com diff --git a/doc/pthreads b/doc/pthreads new file mode 100644 index 00000000..ecdd4108 --- /dev/null +++ b/doc/pthreads @@ -0,0 +1,98 @@ +Below is Sasha Mikheev's documentation on the pthreads support (POSIX threads) +which is valid on June 7th, 1996 (date of message.) I have changed the +path names only since the tree has changed. Otherwise, the docs are correct. + +-- Wolfpack + +--- Begin message + +Hi, + +I have finished documenting pthreads implementation. Pls look at the +results and tell me what can be improved. + +Implementation: + Empire now uses its own thread layer. It makes using another +threading library much easier. The interfase is modeled after +the LWP library which is what empire server uses by default. + The interface is specified in the include/empthread.h file. Implementations +should go into src/lib/empthread/xxx.c. + Empire assumes that thread can not be preempted while it is +running. The _only_ places where context switch between threads can +occur are: + empth_sleep(), empth_yield(), empth_select(), empth_sem_wait(). +That is in sleep, in waiting for I/O on filedescriptor, semaphore or +voluntary yielding control or exiting. In empire empth_select is +called only on sockets so the context switch can occur only on the +network I/O. + Also each empire thread can have it is own context which is restored +automatically after the context switch. Currently it is used for each +thread to have player specic data. (struct player) + +LWP implementation: + Almost nothing has changed there. src/lib/empthread/lwp.c is a very +simple wrapper around the LWP library. The only change is that thread +inherits its flags if they are not explicitly set. + For more details on LWP internals read Dave Pare's description in +doc/threads. + +POSIX threaads: (pthreads) + Unlike LWP pthreads are preemtive. The steps must be taken to insure +that thread is preempted only as described above. It is done by +creating a global mutex mtx_ctxsw. At the any given moment only one +thread can be running and have a lock on mtx_ctxsw. Every other thread +is waiting for the mtx_ctxsw to become avaiable. It is done by calling +pthread_mtx_lock(). When thread enters into empth_sleep(), +empth_yield(), empth_exit(), empth_sem_wait() empth_select() it +releases the mutex by calling pthread_mtx_unlock() and thus allowing +other thread to get a lock. + Thread context is implemented by using pthread_getspecific and +pthread_setspecific functions. + Killing other thread is done by setting victim thread state into +EMPTH_KILLED and sending alarm signal to the victim thread. The later +has to be done to wake up a thread waiting on I/O in +empth_select. Then the victim will examine its state and if it is set +to KILLED it will terminate its execution. Unfortunately pthread_kill +seems not to be working/exists in some pthread implementations. But +fortunately empire always does some I/O before doing +empth_terminate(). + Semaphores are not available in pthreads thus mutexes and conditional +variables are used to implement them. See the code and or OS design +book for details. + +Problems: + On linux with libc 2.1.18 mit pthread library does not wake up a thread upon +the delivery of a signal. Which means that server can not be stopped +short by kill -9 and empth_wakeup() is not working. Fortunately in +current server data are always written to player before the call to +empth_wakeup so players threads will never wait in select forever. + +Probably it will be solved when linux libc gets upgraded to latest +pthread library. + +In addition installing pthreads on Linux is difficult. By default +linux libc has pthread stubs in but pthread code is disabled. So you +have either recompile libc or grab mit pthreads and install them +manually. + Meanwhile I do not recommend to use pthreads on linux unless you +know what you are doing. + +On solaris 2.5 select does not set errno to EINTR when select is broken +by soignal sent by pthread_kill. It doesnt affect anything. + +On OSF/1 the older version of pthread is used. It has slightly changed +function semantics. Also it lacks pthread_kill funcion which means +that empth_wakeup() is not working. + Calling pthread_exit() from the main thread crashes the +program. According to the manual program should not exit until all +threads exited. + The workaround is to send main into while(1) { sleep(60); } loop; + + +-- + Sasha Mikheev There is a saying in Cairhienin, + though i have heard it as far away + NetVision Israel, Ltd as Tarabon and Saldaea: + sasha@netvision.net.il + Tel +972-4-8550330 Take what you want and pay for it. + http://aldan.netvision.net.il/~sasha diff --git a/doc/threads b/doc/threads new file mode 100644 index 00000000..be5b50b7 --- /dev/null +++ b/doc/threads @@ -0,0 +1,161 @@ + +The game has been threaded. Major changes have occurred. +Emp_update, emp_login, emp_tm, and emp_player have been merged. +Basically, there isn't anything else besides server. It's big. +60,000-lines of code big. + +The lib directory now contains nine subdirectories: + common + gen + global + as + player + commands + subs + update + lwp + +The main directory contains five (code) directories: + client + lib + server + util + h + +The server has seven basic threads: + + main: + creates accept, killidle, and update scheduler. + sets signals, opens files. + accept: + opens a socket, binds, listens, and accepts new players. + creates a player thread for each new socket. + player: + negotaties the player's login, and then interprets + the player's game commands. + killidle: + eyeballs the logged-in players every sixty seconds and + closes the connections of those who have been idle for + longer than 15 minutes. + update scheduler: + Sleeps until update is due to go off, then instructs all + player threads currently running commands to abort them. + It waits for a few seconds so that this can occur, and + then creates the update thread, and schedules the next + update. (This scheduler should produce single, accurate + updates instead of double-updates and delayed updates) + update: + The standard update procedure. It runs at high priority + and performs no network i/o, so the game effectively hangs + while the update is in progress. + select: + This thread and its interface provides a mechanism for + other threads to deschedule until either a a file descriptor + is read/write ready, or a particular amount of time has passed. + When the select thread actually runs, the whole process + blocks until the select system call returns. However, + select runs at the lowest possible priority so other + threads get to run to completion before the select gets + executed. + +Overall Notes: + + Unit and sector files are kept in-core for Your Viewing Pleasure. + (It was actually required in order to merge in emp_update) + This means the server will use significant memory for the larger + games. + + Per-player bigmap files have been merged into one EF_MAP file, with + each player getting one record. This is also kept in-core. + + Estimated memory cost of a 64-player 256x256 world game with + each player having 100 land units, 100 planes, 100 ships, and + a bigmap comes to a little over eleven megabytes of space, + including the 700k text segment. + + the "wai()" command doesn't work yet. + +Implementation Notes: My Opportunity to Spout Empire Technical Jargon + + Empire is now a miniature operating system, with all that entails. + Threads are not simple to use. I know the threads package + intimately, and I was confused several times -- probably because + the threads interface I provide isn't all that straightforward, + even though it seems like it. Hopefully a second iteration by + someone who knows what they're doing will be better. + + I expect this will be much worse for everyone else who hasn't gone + through my experience. Bottom line for all you part-time hackers + out there: don't mess with the current process model, or you'll get + yourself into all kinds of trouble. + + Thread scheduling and descheduling happens in the io_input and + io_output calls. The higher level interfaces in the player thread + to these are the getstarg/getstring and pr procedures. If your + process ever has to wait for input or output, it will block, allowing + other threads to run. Those other threads may well modify data + out from under you, so be prepared to have your shared in-memory + constructs (ships, planes, sectors, land units, etc) modified out + from under you whenever you do i/o. + + There's a new player global context structure that is shared + amongst all the player threads. When a given thread starts + or restarts, it sets the global player variable to the appropriate + value. Thus, part of the logic of a "context switch" is the setting + of player. If you go and add calls to the lightweight process + system, you *must* be sure to set the player variable as the + io_output and io_input routines do. Otherwise, things will be + extremely confused. (I'm not very happy with this global + variable, but I didn't have the gumption to do anything more) + + Most routines that used to return pointers to static space no + longer do so. Instead, you're expected to pass in a buffer which + will be filled up by the routine. This hit a *lot* of routines, + so check the new syntax before using an old and trusted routine + blindly. + + Any files that are loaded into core (like the sector, map, nation, + ship, plane, and land unit files) are shared between all the threads. + That's good news. If your thread modifies another player's nat_tgms + field, he'll see it next time through the command loop, without + anyone having to read anything from disk! Furthermore, he'll have + no delay in zeroing out that field, so there won't be the annoying + double telegram reports which were caused by the delay induced by + emp_tm. + + Unfortunately, modifications to entries to these mapped files must + be followed by the appropriate "write record" command (like putship, + putnat, etc) or else the changes won't be stored to disk permanently. + Update is the exception to this rule, because it writes all records + to disk using ef_flush when it's done. This is important, since + if and when the players learn how to coredump the server *and* they've + managed to build some object w/o their nation record having been + updated, they essentially get the item without paying for it. + + There are two interfaces to the empire file code: the pointer + interface exemplified by np = getnatp(cnum), and the copy interface + shown by getsect(x, y, §)/putsect(§). Both still work fine. + However, you have to be careful when using the pointer interface + not to change things prematurely, because any changes to the pointer + actually change the data itself -- including putvar, etc. Some + commands use the copy interface now, change some variables, and + then decide to bail out of the command when something goes wrong. + Be careful if you decide to use pointers and then bail out early. + Even if *you* don't write the pointer to disk, other subsequent + activity probably *will*, resulting in a surprise for the players. + + Each player thread gets 64k of stack space + more depending on the + size of WORLD_X*WORLD_Y. I hope that's enough. If not, we'll have + to remove the larger stack variables and move them into static space. + + Adding new records to core-loaded (EFF_MEM) files is annoying now. + Instead of simply writing out a new record, you have to call + ef_extend(type, count) to enlarge the file by count records. + Additionally, any outstanding pointers you obtained from that + file are now invalid. This command results in a "close/open" + for the file, requiring the entire contents to be read in from + disk again. Luckily, the only instance I saw of this was the + "build" command, and my call to ef_extend does it in groups of + fifty. + +Dave diff --git a/doc/troubleshooting b/doc/troubleshooting new file mode 100644 index 00000000..781d8e1a --- /dev/null +++ b/doc/troubleshooting @@ -0,0 +1,13 @@ +Here are some of the most common problems with solutions. This file +will probably grow over time. + +(Q) I try to log in as POGO, but the server says, "You're not a deity". Why? + +(A) If you get a "You're not a deity!" message and logged off, check the + "data/server.log" file and look at the end for a "NON-AUTH" entry. + There should be a "user@host" message in there that failed to log in. + The user and host that your system is using may be different than the + one you put in your build.conf file. So, enter this new user and host + in the auth file, and you should be able to log into the server as a + deity now. Note that if you rebuild the server again, the auth file + will be overwritten. diff --git a/include/bit.h b/include/bit.h new file mode 100644 index 00000000..de0eaf68 --- /dev/null +++ b/include/bit.h @@ -0,0 +1,71 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * bit.h: Definitions for variable sized bitfields + * + * Known contributors to this file: + * + */ + +#ifndef _BIT_H_ +#define _BIT_H_ + +typedef unsigned int bit_mask; +typedef bit_mask *bit_fdmask; + +#ifndef bit +#define bit(x) (1 << (x)) +#endif + +/* + * File descriptor bit manipulation macros for use with select(2) + */ +#define BIT_NBBY 8 +#define BIT_BITSPERMASK (sizeof(bit_mask) * BIT_NBBY) + +#define BIT_SETB(a,b) \ + ((b)[(a)/BIT_BITSPERMASK] |= 1 << ((a) % BIT_BITSPERMASK)) +#define BIT_CLRB(a,b) \ + ((b)[(a)/BIT_BITSPERMASK] &= ~(1<< ((a) % BIT_BITSPERMASK))) +#define BIT_ISSETB(a,b) \ + ((b)[(a)/BIT_BITSPERMASK] & (1<< ((a) % BIT_BITSPERMASK))) +#define BIT_ISCLRB(a,b) \ + (((b)[(a)/BIT_BITSPERMASK] & (1<<((a) % BIT_BITSPERMASK))) == 0) + +extern bit_fdmask bit_newfdmask(); + +extern bit_fdmask bit_newfdmask(void ); +extern void bit_zero(bit_fdmask ); +extern void bit_not(bit_fdmask ); +extern void bit_copy(bit_fdmask , bit_fdmask ); +extern void bit_or(bit_fdmask , bit_fdmask ); +extern void bit_or3(bit_fdmask , bit_fdmask , bit_fdmask ); +extern void bit_and(bit_fdmask , bit_fdmask ); +extern void bit_and3(bit_fdmask , bit_fdmask , bit_fdmask ); +extern int bit_fd(bit_fdmask ); + +#endif /* _BIT_H_ */ diff --git a/include/budg.h b/include/budg.h new file mode 100644 index 00000000..06150cfb --- /dev/null +++ b/include/budg.h @@ -0,0 +1,40 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * budget.h: Budget related definitions + * + * Known contributors to this file: + * Ville Virrankoski, 1995 + */ + +void fill_update_array(); +int *get_wp(); +int gt_bg_nmbr(); +void pt_bg_nmbr(); +void get_materials(); + +extern int mil_dbl_pay; diff --git a/include/com.h b/include/com.h new file mode 100644 index 00000000..ab56d63d --- /dev/null +++ b/include/com.h @@ -0,0 +1,51 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * com.h: Definitions used to parse Empire commands + * + * Known contributors to this file: + * + */ + +#ifndef _COM_H_ +#define _COM_H_ + +struct cmndstr { + s_char *c_form; /* prototype of command */ + int c_cost; /* btu cost of command */ + int (*c_addr)(); /* core addr of appropriate routine */ + int c_flags; + int c_permit; /* who is allowed to "do" this command */ +}; + +#define C_MOD 0x1 /* modifies database */ + +/* variables associated with this stuff */ + +extern struct cmndstr coms[]; + +#endif /* _COM_H_ */ diff --git a/include/combat.h b/include/combat.h new file mode 100644 index 00000000..d99404fe --- /dev/null +++ b/include/combat.h @@ -0,0 +1,107 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * combat.h: Definitions for things having to do with combat + * + * Known contributors to this file: + * Ken Stevens, 1995 + */ + +#ifndef _COMBAT_H_ +#define _COMBAT_H_ + +#include "sect.h" +#include "queue.h" + +struct combat { + int type; /* EF_BAD, EF_SECTOR, EF_SHIP, or EF_PLANE */ + int set; /* Has the struct been initialized? */ + int last; /* The index of the last element in off array */ + coord x; /* location of attacking sector/ship/plane */ + coord y; + natid own; + int eff; + int mob; + int mobcost; + int mil; /* mil in the sector/ship/unit */ + int troops; /* mil in the combat */ + int plague; + int sct_type; + int shp_uid; + int lnd_uid; + struct dchrstr *sct_dcp; + struct mchrstr *shp_mcp; + struct lchrstr *lnd_lcp; + s_char shp_name[MAXSHPNAMLEN]; + int relations_checked; +}; + +/* Types of combat for use by attack routines */ +#define A_DEFEND 0 +#define A_ATTACK 1 +#define A_ASSAULT 2 +#define A_PARA 3 +#define A_BOARD 4 +#define A_LBOARD 5 + +/* src/lib/subs/attsub.c */ +extern double att_calcodds(int , int ); +extern double att_combat_eff(struct combat * ); +extern void att_move_in_off(int , struct combat * , struct emp_qelem * , + struct combat * ); +extern int att_combat_init(struct combat * , int ); +extern int att_get_combat(struct combat * , int ); +extern int att_abort(int , struct combat * , struct combat * ); +extern int att_approach(struct combat * , struct combat * ); +extern int att_show(struct combat * ); +extern int att_ask_support(int , int * , int * , int * , int * ); +extern int att_ask_offense(int , struct combat * , struct combat * , + struct emp_qelem * , int * , int * ); +extern double sector_strength(struct sctstr * ); +extern int att_estimate_defense(int , struct combat * , struct emp_qelem *, + struct combat * , int ); +extern int att_empty_attack(int , int , struct combat * ); +extern int att_get_defense(struct emp_qelem * , struct combat * , + struct emp_qelem * , int , int ); +extern int att_reacting_units(struct combat * , struct emp_qelem * , int , + int * , int ); +extern int att_get_support(int , int , int , int , int, struct emp_qelem *, + struct combat * , struct emp_qelem * , + struct combat * , double * , double * , int ); +extern int att_fight(int , struct combat * , struct emp_qelem * , double , + struct combat * , struct emp_qelem * , double ); +extern int att_free_lists(struct emp_qelem * , struct emp_qelem * ); + + +extern double att_asupport(); +extern double att_dsupport(); +extern double att_mine_dsupport(); +extern double combat_mob; +extern s_char *att_mode[]; + +#endif /* _COMBAT_H_ */ + diff --git a/include/commands.h b/include/commands.h new file mode 100644 index 00000000..87df3e12 --- /dev/null +++ b/include/commands.h @@ -0,0 +1,60 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * commands.h: Definitions used for command stuff + * + * Known contributors to this file: + * + */ + +#ifndef _COMMANDS_H_ +#define _COMMANDS_H_ + +#include +#include +#include +#if !defined(_WIN32) +#include +#endif +#include "misc.h" +#include "plane.h" +#include "sect.h" +#include "ship.h" +#include "land.h" +#include "nsc.h" +#include "nat.h" +#include "queue.h" +#include "subs.h" +#include "gen.h" +#include "common.h" +#include "lost.h" +#include "map.h" +#include "update.h" + +#include "prototypes.h" /* must come at end, after defines and typedefs */ + +#endif /* _COMMANDS_H_ */ diff --git a/include/commodity.h b/include/commodity.h new file mode 100644 index 00000000..b3f05c90 --- /dev/null +++ b/include/commodity.h @@ -0,0 +1,60 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * commodity.h: Definitions for buy/market/sell commands in a time delay + * market + * + * Known contributors to this file: + * Pat Loney, 1992 + * Steve McClure, 1996 + */ + +#ifndef _COMMODITY_H_ +#define _COMMODITY_H_ + +struct comstr { + short ef_type; + natid com_owner; + short com_uid; + char com_type; + int com_amount; + float com_price; + int com_maxbidder; + float com_maxprice; + time_t com_markettime; + coord com_x; + coord com_y; + coord sell_x; + coord sell_y; +}; + +#define getcomm(n, p) \ + ef_read(EF_COMM, n, (caddr_t)p) +#define putcomm(n, p) \ + ef_write(EF_COMM, n, (caddr_t)p) + +#endif /* _COMMODITY_H_ */ diff --git a/include/common.h b/include/common.h new file mode 100644 index 00000000..2271ec4c --- /dev/null +++ b/include/common.h @@ -0,0 +1,49 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * common.h: Includes for common stuff + * + * Known contributors to this file: + * + */ + +#ifndef _COMMON_H_ +#define _COMMON_H_ + +#include /* FILE */ +#include /* caddr_t */ +#include "misc.h" /* s_char coord natid */ +#include "sect.h" /* struct sctstr */ +#include "ship.h" /* struct shpstr */ +#include "land.h" /* struct lndstr */ +#include "plane.h" /* struct plnstr */ +#include "nuke.h" /* struct nchrstr */ +#include "nsc.h" /* struct castr struct nstr_sect struct nstr_item */ +#include "xy.h" /* struct range */ +#include "prototypes.h" /* must come at end, after defines and typedefs */ + +#endif /* _COMMON_H_ */ diff --git a/include/damage.h b/include/damage.h new file mode 100644 index 00000000..38ce260e --- /dev/null +++ b/include/damage.h @@ -0,0 +1,48 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * damage.h: Damage formulas + * + * Known contributors to this file: + * Ken Stevens, 1995 + * Steve McClure, 1998 + */ + +#ifndef _DAMAGE_H_ +#define _DAMAGE_H_ + +#define PERCENT_DAMAGE(x) (100 * (x) / ((x) + 100)) +#define DPERCENT_DAMAGE(x) ((double)(100.0 * (x) / ((x) + 100.0))) +#define DMINE_HITCHANCE(x) ((double) ( (x) / ((x)+20.0) ) ) +#define DMINE_LHITCHANCE(x) ((double) ( (x) / ((x)+35.0) ) ) +#define MINE_DAMAGE() (22 + random()%21) +#define MINE_LDAMAGE() (10 + random()%11) +#define DTORP_HITCHANCE(range, vis) ((double)(0.9/((range)+1)+(((vis)<6)?(5-(vis))*0.03:0))) +#define TORP_DAMAGE() (torpedo_damage + (random() % torpedo_damage) + \ + (random() % torpedo_damage)) + +#endif /* _DAMAGE_H_ */ diff --git a/include/deity.h b/include/deity.h new file mode 100644 index 00000000..c0f1d6d5 --- /dev/null +++ b/include/deity.h @@ -0,0 +1,41 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * deity.h: Definitions for things associated with deity ownership + * + * Known contributors to this file: + * + */ + +#ifndef _DEITY_H_ +#define _DEITY_H_ + +extern s_char *privname; +extern s_char *privlog; +extern int privuid; + +#endif /* _DEITY_H_ */ diff --git a/include/distribute.h b/include/distribute.h new file mode 100644 index 00000000..5cdba486 --- /dev/null +++ b/include/distribute.h @@ -0,0 +1,40 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * distribute.h: Definitions for distribution stuff + * + * Known contributors to this file: + * + */ + +#ifndef _DISTRIBUTE_H_ +#define _DISTRIBUTE_H_ + +#define IMPORT 0 +#define EXPORT 1 + +#endif /* _DISTRIBUTE_H_ */ diff --git a/include/empio.h b/include/empio.h new file mode 100644 index 00000000..cad53004 --- /dev/null +++ b/include/empio.h @@ -0,0 +1,77 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * empio.h: Describes io pointers used in Empire + * + * Known contributors to this file: + * + */ + +#ifndef _EMPIO_H_ +#define _EMPIO_H_ + +#include /* struct timeval */ + +typedef struct iop *iop_t; + +#define IO_READ 0x1 +#define IO_WRITE 0x2 +#define IO_NEWSOCK 0x4 +#define IO_NBLOCK 0x8 +#define IO_EOF 0x10 +#define IO_CONN 0x20 +#define IO_ERROR 0x40 + +#define IO_BUFSIZE 4096 + +#define IO_NOWAIT 0 +#define IO_WAIT 1 + +extern struct iop * io_open(int , int , int , int (* )(void) , s_char * ); +extern void io_init(void ); +extern int io_noblocking(struct iop * , int ); +extern void io_close(struct iop * ); +extern int io_input(struct iop * , int ); +extern int io_inputwaiting(struct iop * ); +extern int io_outputwaiting(struct iop * ); +extern int io_output(struct iop * , int ); +extern int io_select(struct timeval * ); +extern void io_flush(int ); +extern int io_peek(struct iop * , s_char * , int ); +extern int io_read(struct iop * , s_char * , int ); +extern int io_write(struct iop * , s_char * , int , int ); +extern int io_output_all(struct iop * ); +extern int io_gets(struct iop * , s_char * , int ); +extern int io_puts(struct iop * , s_char * ); +extern int io_shutdown(struct iop * , int ); +extern int io_conn(struct iop * ); +extern int io_error(struct iop * ); +extern int io_eof(struct iop * ); +extern int io_fileno(struct iop * ); +extern struct iop * io_iopfromfd(int ); + +#endif /* _EMPIO_H_ */ diff --git a/include/empthread.h b/include/empthread.h new file mode 100644 index 00000000..2ca7e5b1 --- /dev/null +++ b/include/empthread.h @@ -0,0 +1,137 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * empthread.h: Definitions for Empire threading + * + * Known contributors to this file: + * Sasha Mikheev + * Doug Hay, 1998 + * Steve McClure, 1998 + */ + +#ifndef _EMTHREAD_H_ +#define _EMTHREAD_H_ + +#include "prototype.h" +#include "misc.h" + +#if defined(_WIN32) +#undef _EMPTH_LWP +#undef _EMPTH_POSIX +#define _EMPTH_WIN32 +#endif + +#ifdef _EMPTH_LWP +#include "lwp.h" +typedef struct lwpProc empth_t; +typedef struct lwpSem empth_sem_t; +#define EMPTH_FD_READ LWP_FD_READ +#define EMPTH_FD_WRITE LWP_FD_WRITE +#define EMPTH_PRINT LWP_PRINT +#define EMPTH_STACKCHECK LWP_STACKCHECK +#endif + +#ifdef _EMPTH_POSIX +#ifdef __linux__ +#define _MIT_POSIX_THREADS 1 +#endif +#include +#define EMPTH_FD_READ 0x1 +#define EMPTH_FD_WRITE 0x2 + +#define EMPTH_PRINT 0x1 +#define EMPTH_STACKCHECK 0x2 + +typedef void (*vf_ptr)(); +#define EMPTH_KILLED 1 +typedef struct empth_ctx_t { + char *name; /* thread name */ + char *desc; /* description */ + void *ud; /* user data */ + int state; /* my state */ + vf_ptr ep; /* entry point */ + pthread_t id; /* thread id */ +}empth_t; + +typedef struct { + pthread_mutex_t mtx_update; /* use it to update count */ + int count; + char name[80]; + pthread_mutex_t mtx_sem; + pthread_cond_t cnd_sem; +}empth_sem_t; + +#endif + +/* DEC has slightly different names for whatever reason... */ +#ifdef _DECTHREADS_ +#define pthread_key_create pthread_keycreate +#define pthread_attr_init pthread_attr_create +#define pthread_attr_destroy pthread_attr_delete + +#endif + + +#if defined(_EMPTH_WIN32) +/* The Windows NT Threads */ +#define EMPTH_FD_READ 0x1 +#define EMPTH_FD_WRITE 0x2 + +#define EMPTH_PRINT 0x1 +#define EMPTH_STACKCHECK 0x2 + +typedef void empth_t; + +typedef void empth_sem_t; + +#endif + +int empth_init _PROTO((char **ctx, int flags)); +empth_t *empth_create _PROTO((int, void (*)(), int, + int, char *, char *, void *)); +empth_t *empth_self(); +void empth_exit _PROTO((void)); +void empth_yield _PROTO((void)); +void empth_terminate _PROTO((empth_t *)); +void empth_select _PROTO((int fd, int flags)); +void empth_wakeup _PROTO((empth_t *)); +void empth_sleep _PROTO((long until)); +empth_sem_t *empth_sem_create _PROTO((char *name, int count)); +void empth_sem_signal _PROTO((empth_sem_t *)); +void empth_sem_wait _PROTO((empth_sem_t *)); +emp_sig_t empth_alarm _PROTO((int)); + + +#include "prototypes.h" /* must come at end, after defines and typedefs */ +#endif + + + + + + + diff --git a/include/event.h b/include/event.h new file mode 100644 index 00000000..90993221 --- /dev/null +++ b/include/event.h @@ -0,0 +1,51 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * event.h: Describes how to send an event to a user thread + * + * Known contributors to this file: + * + */ + +#ifndef _EVENT_H_ +#define _EVENT_H_ + +/* country #1's battleship #2 hit your battleship #3 for 30% damage */ +/* actor's from_type #from_id hit your to_type #to_id for data% damage */ +struct event { + short verb; + natid actor; + natid victim; + short from_type; + short data; + int from_id; + short to_type; + int to_id; + time_t time; +}; + +#endif /* _EVENT_H_ */ diff --git a/include/file.h b/include/file.h new file mode 100644 index 00000000..e9045c22 --- /dev/null +++ b/include/file.h @@ -0,0 +1,117 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * file.h: Describes Empire files and their contents + * + * Known contributors to this file: + * + */ + +#ifndef _FILE_H_ +#define _FILE_H_ + +struct empfile { + s_char *name; /* file name (e.g., "treaty") */ + s_char *file; /* file path */ + int flags; /* misc stuff */ + int mode; /* O_flags */ + int size; /* size of object */ + void (*init)(int , s_char *);/* call this when object is created */ + int (*postread)(int, s_char *); /* specific massage routines for items */ + int (*prewrite)(int , s_char *); + int varoffs[3]; /* struct offs for nv, vtype, vamt */ + int maxvars; /* max # vars for type */ + int fd; /* file descriptor */ + int baseid; /* starting item in cache */ + int cids; /* # ids in cache */ + int csize; /* size of cache in bytes */ + caddr_t cache; /* pointer to cache */ + int fids; /* # of ids in file */ + struct castr *cadef; /* ca defs selection list */ +}; + +#define EFF_COM bit(0) /* item has commodities attached */ +#define EFF_XY bit(1) /* has location */ +#define EFF_MEM bit(2) /* stored entirely in-memory */ +#define EFF_OWNER bit(3) /* has concept of owner */ +#define EFF_GROUP bit(4) /* has concept of group */ + +#define EF_BAD -1 /* illegal file type */ +#define EF_SECTOR 0 +#define EF_SHIP 1 +#define EF_PLANE 2 +#define EF_LAND 3 +#define EF_NUKE 4 +#define EF_NEWS 5 +#define EF_TREATY 6 +#define EF_TRADE 7 +#define EF_POWER 8 +#define EF_NATION 9 +#define EF_LOAN 10 +#define EF_MAP 11 +#define EF_BMAP 12 +#define EF_COMM 13 +#define EF_LOST 14 +#define EF_MAX 15 + +#define EF_NMAP 222 /* Kinda bogus, but used to describe a newdesmap + instead of bmap or map. */ + +typedef void (*ef_fileinit)(int, s_char *); + +struct fileinit { + void (*init)(int , s_char *); + int (*postread)(int, s_char *); + int (*prewrite)(int, s_char *); + struct castr *cadef; +}; + + +extern struct castr * ef_cadef(int ); +extern int ef_read(int , int , caddr_t ); +extern s_char * ef_ptr(int , int ); +extern s_char * ef_nameof(int ); +extern time_t ef_mtime(int ); +extern int ef_open(int , int , int ); +extern int ef_check(int ); +extern int ef_close(int ); +extern int ef_flush(int ); +extern int ef_write(int , int , caddr_t ); +extern int ef_extend(int , int ); +extern void ef_zapcache(int ); +extern int ef_nelem(int ); +extern int ef_flags(int ); +extern int ef_lock(int ); +extern int ef_unlock(int ); +extern int ef_vars(int , register s_char * , u_char * * , + u_char * * , u_short * * ); +extern int ef_byname(s_char * ); + +extern int ef_nbread(); +extern struct empfile empfile[]; + +#endif /* _FILE_H_ */ diff --git a/include/gen.h b/include/gen.h new file mode 100644 index 00000000..ad9380e0 --- /dev/null +++ b/include/gen.h @@ -0,0 +1,45 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * gen.h: Includes for generic stuff + * + * Known contributors to this file: + * + */ + +#ifndef _GEN_H_ +#define _GEN_H_ +#include +#if !defined(_WIN32) +#include /* struct in_addr */ +#endif +#include /* atoi etc. */ +#include "misc.h" /* s_char etc */ +#include "xy.h" /* struct range */ +#include "prototypes.h" /* must come at end, after defines and typedefs */ + +#endif /* _GEN_H_ */ diff --git a/include/genitem.h b/include/genitem.h new file mode 100644 index 00000000..1a928207 --- /dev/null +++ b/include/genitem.h @@ -0,0 +1,72 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * genitem.h: Definition for generic items + * + * Known contributors to this file: + * + */ +/* + * XXX cheap hack; this depends on the fact + * that units are all the same starting from the top. + * If you change the units, DON'T CHANGE the tops to + * be non-identical. Also, if you change types of + * parts of the tops, be sure to change this file! + */ + +#ifndef _GENITEM_H_ +#define _GENITEM_H_ + +struct genitem { + short ef_type; + natid own; + short uid; + coord x; + coord y; + s_char type; + s_char effic; + s_char mobil; + short sell; + short tech; + s_char group; + coord opx,opy; + short mission; + short radius; +}; + +struct genobject { + short ef_type; + natid own; +}; + +struct genchrstr { + u_char nv; /* current number of variables */ + u_char vtype[MAXCHRNV]; + u_short vamt[MAXCHRNV]; +}; + +#endif /* _GENITEM_H_ */ diff --git a/include/global.h b/include/global.h new file mode 100644 index 00000000..e61a3425 --- /dev/null +++ b/include/global.h @@ -0,0 +1,38 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * global.h: Used to include prototypes + * + * Known contributors to this file: + * + */ + +#ifndef _GLOBAL_H_ +#define _GLOBAL_H_ +#include "prototypes.h" /* must come at end, after defines and typedefs */ + +#endif /* _GLOBAL_H_ */ diff --git a/include/io_mask.h b/include/io_mask.h new file mode 100644 index 00000000..425f38f1 --- /dev/null +++ b/include/io_mask.h @@ -0,0 +1,53 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * io_mask.h: Describes an i/o mask + * + * Known contributors to this file: + * + */ + +#ifndef _IO_MASK_H_ +#define _IO_MASK_H_ + +struct io_mask { + int what; + int maxfd; + bit_fdmask readmask; + bit_fdmask user_readmask; + bit_fdmask writemask; + bit_fdmask user_writemask; +}; + +extern struct io_mask * iom_create(int ); +extern void iom_getmask(struct io_mask * , int * , bit_fdmask * , + bit_fdmask * ); +extern void iom_set(struct io_mask * , int , int ); +extern void iom_clear(struct io_mask * , int , int ); +extern void iom_zero(struct io_mask * , int ); + +#endif /* _IO_MASK_H_ */ diff --git a/include/ioqueue.h b/include/ioqueue.h new file mode 100644 index 00000000..b92909df --- /dev/null +++ b/include/ioqueue.h @@ -0,0 +1,69 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * ioqueue.h: Stores and frees data associated with a file descriptor. + * uses writev to write, and read to read + * Known contributors to this file: + * + */ + +#ifndef _IOQUEUE_H_ +#define _IOQUEUE_H_ + +#define IOQ_BUFSIZE 2048 +#define MAXIOV 16 + +struct io { + struct emp_qelem queue; + int size; + int nbytes; + int offset; + s_char *data; +}; + +struct ioqueue { + struct io list; + int bufsize; + int cc; +}; + +extern struct ioqueue *ioq_create(int size); +extern void ioq_destroy(struct ioqueue *ioq); +extern void ioq_drain(struct ioqueue *ioq); +extern int ioq_makeiov(struct ioqueue *ioq, struct iovec *iov, int cc); +extern int ioq_peek(struct ioqueue *ioq, s_char *buf, int cc); +extern int ioq_dequeue(struct ioqueue *ioq, int cc); +extern void ioq_append(struct ioqueue *ioq, s_char *buf, int cc); +extern int ioq_qsize(struct ioqueue *ioq); +extern int ioq_gets(struct ioqueue *ioq, s_char *buf, int cc); +extern int ioq_puts(struct ioqueue *ioq, s_char *buf); + +#if defined (_WIN32) +extern int ioq_makebuf(struct ioqueue *ioq, char *pBuf, int nBufLen); +#endif + +#endif /* _IOQUEUE_H_ */ diff --git a/include/item.h b/include/item.h new file mode 100644 index 00000000..c9ca0c96 --- /dev/null +++ b/include/item.h @@ -0,0 +1,60 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * item.h: Definitions for item characteristics stuff + * + * Known contributors to this file: + * + */ + +#ifndef _ITEM_H_ +#define _ITEM_H_ + +#define NUMPKG 4 /* number of different kinds of packaging */ + +struct ichrstr { + int i_mnem; /* usually the initial letter */ + int i_vtype; /* var type */ + int i_value; /* mortgage value */ + int i_sell; /* can this be sold? */ + int i_lbs; /* how hard to move */ + int i_pkg[NUMPKG]; /* units for reg, ware, urb, bank */ + s_char *i_name; /* full name of item */ +}; + +/* variables using this structure */ + +extern struct ichrstr ichr[]; +extern int maxitem; + +/* procedures using/returning this struct */ + +extern struct ichrstr *whatitem(); + +extern int itm_maxno; + +#endif /* _ITEM_H_ */ diff --git a/include/keyword.h b/include/keyword.h new file mode 100644 index 00000000..620fbcbb --- /dev/null +++ b/include/keyword.h @@ -0,0 +1,51 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * keyword.h: Definitions for parsed keyword package + * + * Known contributors to this file: + * + */ + +#ifndef _KEYWORD_H_ +#define _KEYWORD_H_ + +#include +#include "misc.h" + +#define CF_VALUE 1 +#define CF_TIME 2 +#define CF_TIMERANGE 3 +#define CF_WEEKDAY 4 + +extern s_char * kw_find(s_char * ); +extern s_char * kw_parse(int , s_char * , int * ); +extern int kw_read(FILE * ); +extern s_char * get_time(s_char * , int * ); +extern s_char * weekday(s_char * , int * ); + +#endif /* _KEYWORD_H_ */ diff --git a/include/land.h b/include/land.h new file mode 100644 index 00000000..d60999db --- /dev/null +++ b/include/land.h @@ -0,0 +1,235 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * land.h: Definitions for land units + * + * Known contributors to this file: + * Thomas Rushack, 1992 + * Ken Stevens, 1995 + * Steve McClure, 1998 + */ + +#ifndef _LAND_H_ +#define _LAND_H_ + +#include "sect.h" +#include "ship.h" +#include "queue.h" +#include "nsc.h" +#include "retreat.h" + +#define LAND_MINEFF 10 +#define LAND_MINFIREEFF 40 /* arty must be this effic to fire */ +#define MAXLNDV 14 +#define LND_MINMOBCOST 0.200 + +struct lndstr { + short ef_type; + natid lnd_own; /* owner's country num */ + short lnd_uid; /* unit id (land unit) */ + coord lnd_x; /* x location in abs coords */ + coord lnd_y; /* y location in abs coords */ + s_char lnd_type; /* ship type */ + s_char lnd_effic; /* 0% to 100% */ + s_char lnd_mobil; /* mobility units made int for RS/6000 */ + short lnd_sell; /* pointer to trade file */ + short lnd_tech; /* tech level ship was built at */ + s_char lnd_army; /* group membership */ + coord lnd_opx,lnd_opy;/* Op sector coords */ + short lnd_mission; /* mission code */ + short lnd_radius; /* mission radius */ + s_char lnd_flags; /* unit flags */ + short lnd_ship; /* pointer to transporting ship */ + s_char lnd_harden; /* for missiles */ + short lnd_retreat; /* retreat percentage */ + u_char lnd_fuel; /* How much fuel do we have */ + u_char lnd_nxlight; /* How many xlight planes on board? */ + int lnd_rflags; /* When do I retreat? */ + s_char lnd_rpath[RET_LEN]; /* retreat path */ + u_char lnd_rad_max; /* max radius for this unit */ + u_char lnd_scar; /* how experienced the unit is (not used) */ + s_char lnd_nv; /* current number of variables */ + u_char lnd_vtype[MAXLNDV]; + u_short lnd_vamt[MAXLNDV]; + short lnd_land; /* pointer to transporting unit */ + u_char lnd_nland; + time_t lnd_access; /* Last time mob was updated (MOB_ACCESS) */ + float lnd_att; /* attack multiplier */ + float lnd_def; /* defense multiplier */ + int lnd_vul; /* vulnerability (0-100) */ + int lnd_spd; /* speed */ + int lnd_vis; /* visibility */ + int lnd_spy; /* Seeing distance */ + int lnd_rad; /* reaction radius */ + int lnd_frg; /* firing range */ + int lnd_acc; /* firing accuracy */ + int lnd_dam; /* # of guns firing */ + int lnd_ammo; /* firing ammu used per shot */ + int lnd_aaf; /* aa fire */ + u_char lnd_fuelc; /* fuel capacity */ + u_char lnd_fuelu; /* fuel used per 10 mob */ + u_char lnd_maxlight; /* maximum number of xlight planes */ + u_char lnd_maxland; /* maximum number of units */ + time_t lnd_timestamp; /* Last time this unit was touched */ +}; + +#define LND_NOTANY bit(0) /* Just a placeholder, not used */ + +struct lchrstr { + u_char l_nv; /* number of variables it can hold */ + u_char l_vtype[MAXCHRNV]; + u_short l_vamt[MAXCHRNV]; + s_char *l_name; /* full name of type of land unit */ + int l_lcm; /* units of lcm to build */ + int l_hcm; /* units of hcm to build */ + int l_mil; /* how many mil it takes to build */ + int l_gun; /* how many guns it takes to build */ + int l_shell; /* how many shells it takes to build */ + int l_tech; /* tech required to build */ + int l_cost; /* how much it costs to build */ + float l_att; /* attack multiplier */ + float l_def; /* defense multiplier */ + int l_vul; /* vulnerability (0-100) */ + int l_spd; /* speed */ + int l_vis; /* visibility */ + int l_spy; /* Seeing distance */ + int l_rad; /* reaction radius */ + int l_frg; /* firing range */ + int l_acc; /* firing accuracy */ + int l_dam; /* # of guns firing */ + int l_ammo; /* firing ammu used per shot */ + int l_aaf; /* aa fire */ + u_char l_fuelc; /* fuel capacity */ + u_char l_fuelu; /* fuel used per 10 mob */ + u_char l_nxlight; /* maximum number of xlight planes */ + u_char l_mxland; /* maximum number of units */ + long l_flags; /* what special things can this unit do */ +}; + +/* Land unit ability flags */ +#define L_XLIGHT bit(0) /* Hold xlight planes */ +#define L_ENGINEER bit(1) /* Do engineering things */ +#define L_SUPPLY bit(2) /* supply other units/sects */ +#define L_SECURITY bit(3) /* anti-terrorist troops */ +#define L_LIGHT bit(4) /* can go on ships */ +#define L_MARINE bit(5) /* marine units, good at assaulting */ +#define L_RECON bit(6) /* recon units, good at spying */ +#define L_RADAR bit(7) /* radar unit */ +#define L_ASSAULT bit(8) /* can assault */ +#define L_FLAK bit(9) /* flak unit */ +#define L_SPY bit(10) /* spy unit - way cool */ +#define L_TRAIN bit(11) /* train unit - neato */ +#define L_HEAVY bit(12) /* heavy unit - can't go on trains */ + +#define LND_ATTDEF(b, t) (((b) * (1.0 + ((sqrt((double)(t)) / 100.0) * 4.0))) \ + > 127 ? 127 : \ + ((b) * (1.0 + ((sqrt((double)(t)) / 100.0) * 4.0)))) +#define LND_SPD(b, t) ((b * (1.0 + ((sqrt((double)t) / 100.0) * 2.1))) > 127\ + ? 127 : (b * (1.0 + ((sqrt((double)t) / 100.0) * 2.1)))) +#define LND_VUL(b, t) ((b * (1.0 - ((sqrt((double)t) / 100.0) * 1.1))) < 0\ + ? 0 : (b * (1.0 - ((sqrt((double)t) / 100.0) * 1.1)))) +#define LND_VIS(b, t) (b) +#define LND_SPY(b, t) (b) +#define LND_RAD(b, t) (b) +#define LND_FRG(b, t) ((t) ? \ + ((b) * (logx((double)(t), (double)35.0) < 1.0 ? 1.0 : \ + logx((double)(t), (double)35.0))) : (b)) +#define LND_DAM(b, t) ((t) ? \ + ((b) * (logx((double)(t), (double)60.0) < 1.0 ? 1.0 : \ + logx((double)(t), (double)60.0))) : (b)) +#define LND_ACC(b, t) ((b * (1.0 - ((sqrt((double)t) / 100.0) * 1.1))) < 0\ + ? 0 : (b * (1.0 - ((sqrt((double)t) / 100.0) * 1.1)))) +#define LND_AMM(b, d, t) ((b) ? ((LND_DAM((d), (t)) / 2) + 1) : 0) +#define LND_AAF(b, t) ((b * (1.0 + ((sqrt((double)t) / 100.0) * 3.0))) > 127\ + ? 127 : (b * (1.0 + ((sqrt((double)t) / 100.0) * 3.0)))) +#define LND_FC(b, t) (b) +#define LND_FU(b, t) (b) +#define LND_XPL(b, t) (b) +#define LND_MXL(b, t) (b) +#define LND_COST(b, t) ((b) * (1.0 + (sqrt((double)(t)) / 100.0))) + +#define getland(n, p) \ + ef_read(EF_LAND, n, (caddr_t)p) +#define putland(n, p) \ + ef_write(EF_LAND, n, (caddr_t)p) +#define getlandp(n) \ + (struct lndstr *) ef_ptr(EF_LAND, n) + +extern struct lchrstr lchr[]; +extern int lnd_maxno; + +struct llist { + struct emp_qelem queue; /* list of units */ + coord x,y; /* x,y it came from */ + struct lchrstr *lcp; /* pointer to desc of land unit */ + struct lndstr land; /* struct land unit */ + int eff; + double mobil; + int supplied; +}; + +/* src/lib/subs/lndsub.c */ +extern void lnd_sweep(struct emp_qelem * , int , int , natid ); +extern int lnd_interdict(struct emp_qelem * , coord , coord , natid ); +extern void lnd_sel(struct nstr_item * , struct emp_qelem * ); +extern void lnd_mess(s_char * , struct llist * ); +extern int lnd_check_mines(struct emp_qelem * ); +extern double lnd_mobcost(struct lndstr * , struct sctstr * , int ); +extern s_char * lnd_path(int , struct lndstr * , s_char * ); + +extern int attack_val(int , struct lndstr * ); +extern int total_mil(struct lndstr * ); +extern int defense_val(struct lndstr * ); +extern int lnd_getmil(struct lndstr * ); +extern void lnd_print(struct llist * , s_char * ); +extern void lnd_delete(struct llist * , s_char * ); +extern int lnd_take_casualty(int , struct llist * , int ); +extern void lnd_submil(struct lndstr * , int ); +extern void lnd_takemob(struct emp_qelem * , double ); +extern int lnd_spyval(struct lndstr * ); +extern int intelligence_report(int , struct lndstr * , int , s_char * ); +extern int count_sect_units(struct sctstr * ); +extern void count_units(struct shpstr * ); +extern void lnd_count_units(struct lndstr * ); +extern void lnd_mar(struct emp_qelem * , double * , double * , int * , + natid ); +extern void lnd_put(struct emp_qelem * , natid ); +extern int lnd_hit_mine(struct lndstr * , struct lchrstr * ); +extern void lnd_list(struct emp_qelem * ); +extern int lnd_hardtarget(struct lndstr * ); +extern int lnd_mar_one_sector(struct emp_qelem * , int , natid , int ); +extern int lnd_support(natid , natid , coord , coord ); +extern int lnd_can_attack(struct lndstr * ); + + +void landdamage(); +void lnd_nav(); +int lnd_check_nav(); +double sqrt(); +s_char *prland(); + +#endif /* _LAND_H_ */ diff --git a/include/loan.h b/include/loan.h new file mode 100644 index 00000000..7cd1844c --- /dev/null +++ b/include/loan.h @@ -0,0 +1,66 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * loan.h: Definitions for loans + * + * Known contributors to this file: + * + */ + +#ifndef _LOAN_H_ +#define _LOAN_H_ + +#define MAXLOAN 100000 +#define SECS_PER_DAY (60*60*24) + +struct lonstr { + short ef_type; + natid l_loner; /* loan shark */ + short l_uid; + natid l_lonee; /* sucker */ + s_char l_status; /* loan status */ + short l_sell; /* pointer to trade file */ + int l_irate; /* interest rate */ + int l_ldur; /* intended duration */ + long l_amtpaid; /* amount paid so far */ + long l_amtdue; /* amount still owed */ + time_t l_lastpay; /* date of most recent payment */ + time_t l_duedate; /* date after which interest doubles, etc */ +}; + +#define LS_FREE 0 +#define LS_PROPOSED 1 +#define LS_SIGNED 2 + +#define getloan(n, lp) \ + ef_read(EF_LOAN, n, (caddr_t)lp) +#define putloan(n, lp) \ + ef_write(EF_LOAN, n, (caddr_t)lp) +#define getloanp(n) \ + (struct lonstr *) ef_ptr(EF_LOAN, n) + +#endif /* _LOAN_H_ */ diff --git a/include/lost.h b/include/lost.h new file mode 100644 index 00000000..e0a53270 --- /dev/null +++ b/include/lost.h @@ -0,0 +1,55 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * lost.h: Definitions for lost items + * + * Known contributors to this file: + * Steve McClure, 1997 + */ + +#ifndef _LOST_H_ +#define _LOST_H_ +struct loststr { + short ef_type; + natid lost_owner; /* Who lost it */ + int lost_uid; /* This lost # */ + char lost_type; /* Type of thing (ship, plane, nuke, land, sector) */ + short lost_id; /* ID of thing */ + coord lost_x; + coord lost_y; + time_t lost_timestamp; /* When it was lost */ +}; + +#define getlost(n, p) ef_read(EF_LOST, n, (caddr_t)p) +#define putlost(n, p) ef_write(EF_LOST, n, (caddr_t)p) + +/* src/lib/subs/lostsub.c */ +extern int findlost(char , natid , short , coord , coord , int ); +extern void makelost(char , natid , short , coord , coord ); +extern void makenotlost(char , natid , short , coord , coord ); +#endif /* _LOST_H_ */ + diff --git a/include/lwp.h b/include/lwp.h new file mode 100644 index 00000000..61395a55 --- /dev/null +++ b/include/lwp.h @@ -0,0 +1,105 @@ +/* + * lwp.h -- prototypes and structures for lightweight processes + * Copyright (C) 1991-3 Stephen Crane. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * author: Stephen Crane, (jsc@doc.ic.ac.uk), Department of Computing, + * Imperial College of Science, Technology and Medicine, 180 Queen's + * Gate, London SW7 2BZ, England. + */ +#ifndef _LWP_H_ +#define _LWP_H_ +#include "prototype.h" +#ifdef UCONTEXT +#include +#else /* UCONTEXT */ +#include +#endif /* UCONTEXT */ +#include +#include "misc.h" +#define LWP_STACKCHECK 0x1 +#define LWP_PRINT 0x2 + +/* process control block. do *not* change the position of context */ +struct lwpProc { +#ifdef UCONTEXT + ucontext_t context; /* context structure */ +#else /* UCONTEXT */ + jmp_buf context; /* processor context area */ +#endif /* UCONTEXT */ + void *sbtm; /* bottom of stack attached to it */ + int size; /* size of stack */ + void (*entry)(); /* entry point */ + int dead; /* whether the process can be rescheduled */ + int pri; /* which scheduling queue we're on */ + long runtime; /* time at which process is restarted */ + int fd; /* fd we're blocking on */ + int argc; /* initial arguments */ + char **argv; + void *ud; /* user data */ + void *lowmark; /* start of low buffer around stack */ + void *himark; /* start of upper buffer around stack */ + char *name; /* process name and description */ + char *desc; + int flags; + struct lwpProc *next; +}; + +/* queue */ +struct lwpQueue { + struct lwpProc *head; + struct lwpProc *tail; +}; + +/* semaphore */ +struct lwpSem { + int count; + struct lwpQueue q; + char *name; +}; + +#define LWP_FD_READ 0x1 +#define LWP_FD_WRITE 0x2 + +#define LWP_MAX_PRIO 8 + +struct lwpProc *lwpInitSystem _PROTO((int prio, char **ctxp, int flags)); +struct lwpProc *lwpCreate _PROTO((int prio, void (*)(), int size, + int flags, char *name, char *desc, int argc, + char **argv, void *ud)); +void lwpExit _PROTO((void)); +void lwpTerminate _PROTO((struct lwpProc *p)); +void lwpYield _PROTO((void)); +void lwpSleepFd _PROTO((int fd, int flags)); +void lwpSleepUntil _PROTO((long until)); +void lwpWakeupFd _PROTO((struct lwpProc *p)); +void *lwpGetUD _PROTO((struct lwpProc *p)); +void lwpSetUD _PROTO((struct lwpProc *p, char *ud)); +void lwpSetDesc _PROTO((struct lwpProc *p, char *name, char *desc)); +int lwpSetPriority _PROTO((int prio)); +void lwpReschedule _PROTO((void)); + +struct lwpSem *lwpCreateSem _PROTO((char *name, int count)); +void lwpSignal _PROTO((struct lwpSem *)); +void lwpWait _PROTO((struct lwpSem *)); +void lwpSelect _PROTO((int argc, char **argv)); +void lwpStatus _PROTO((struct lwpProc *proc, char *format, ...)); + +extern struct lwpProc *LwpCurrent; + +#include "prototypes.h" /* must come at end, after defines and typedefs */ + +#endif /* _LWP_H_ */ diff --git a/include/map.h b/include/map.h new file mode 100644 index 00000000..b627904b --- /dev/null +++ b/include/map.h @@ -0,0 +1,64 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * map.h: Definitions for making maps + * + * Known contributors to this file: + * + */ + +#ifndef _MAP_H_ +#define _MAP_H_ + +#include "misc.h" +#include "xy.h" + +#define MAPWIDTH(persec) ((WORLD_X/2)*(persec + 1)+1) + +extern s_char *routech[7][2]; + +extern void blankfill(s_char * , register struct range * , int ); +/* src/lib/subs/border.c */ +extern int map_set(natid , coord , coord , s_char , int ); +extern void writebmap(natid ); +extern void writemap(natid ); +/* src/lib/subs/border.c */ +extern void border(struct range * , s_char * , s_char * ); + +#define MAP_SHIP bit(0) +#define MAP_LAND bit(1) +#define MAP_PLANE bit(2) +#define MAP_ALL MAP_SHIP | MAP_LAND | MAP_PLANE + +struct mapstr { + short ef_type; + coord map_x; + coord map_y; + s_char map_des; +}; + +#endif /* _MAP_H_ */ diff --git a/include/match.h b/include/match.h new file mode 100644 index 00000000..dc9fa45f --- /dev/null +++ b/include/match.h @@ -0,0 +1,48 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * match.h: Used for string compare matching + * + * Known contributors to this file: + * + */ + +#ifndef _MATCH_H_ +#define _MATCH_H_ + +/* returned by stmtch() */ +#define M_IGNORE -3 +#define M_NOTUNIQUE -2 +#define M_NOTFOUND -1 +/*#define M_INDEX [0...N-1] */ + +/* returned by mineq() */ +#define ME_MISMATCH 0 +#define ME_PARTIAL 1 +#define ME_EXACT 2 + +#endif /* _MATCH_H_ */ diff --git a/include/misc.h b/include/misc.h new file mode 100644 index 00000000..dcfb7f92 --- /dev/null +++ b/include/misc.h @@ -0,0 +1,222 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * misc.h: Misc. definitions which don't really belong anywhere, + * but have to go somewhere! + * + * Known contributors to this file: + * Doug Hay, 1998 + */ + +#ifndef _MISC_H_ +#define _MISC_H_ + +#include +#include +#include + +#if defined(hpux) || defined(SUN4) || defined(solaris) || defined(_WIN32) +#include +#else +#include +#endif + +#if defined(_WIN32) +typedef unsigned char u_char; +typedef unsigned short u_short; +typedef char * caddr_t; +typedef unsigned int u_int; + +/* Promote warning to error - undefined function. assuming eternal int */ +#pragma warning (error : 4013 ) +/* Promote warning to error - Too many actual parameters */ +#pragma warning (error : 4020 ) +/* Promote warning to error - different types for formal and actual parameter */ +#pragma warning (error : 4024 ) +/* Promote warning to error - Formal parameter different from declaration */ +#pragma warning (error : 4028 ) +/* Promote warning to error - Parameters to void function. */ +#pragma warning (error : 4087 ) + +/* integral mismatch, due to misuse of sector short */ +#pragma warning (disable : 4761 ) + +#define bzero(d, s) memset(d, 0, s) +#define bcopy(s, d, z) memcpy(d, s, z) + +#include +#include + +#define random rand +#define srandom srand + +#define index strchr +#define rindex strrchr +/*#define _POSIX_ */ +#endif + +#include "prototype.h" +#include "options.h" + +/* This is the structure we use to keep track of the global mobility + things, such as when the server is supposed to start/stop updating + mobility and the timestamp of when the game was last up. These + times are in seconds. */ +struct mob_acc_globals { + time_t timestamp; /* Last timestamp of when the game was up */ + time_t starttime; /* When we should start updating mobility again. */ +}; + +#define ANNO_KEEP_DAYS 7 /* Keep announcements around for this many days */ +#define RESOLVE_IPADDRESS /* resolve ip addresses into hostnames */ + +typedef u_char natid; /* also change NSC_NATID in nsc.h */ + +#if defined(__linux__ ) || defined(__osf__) +#define POSIXSIGNALS 1 +#endif + +#if !defined (_EMPTH_LWP) && !defined (_EMPTH_POSIX) +#define _EMPTH_LWP 1 +#endif + +#if defined(_EMPTH_POSIX) && !defined(POSIXSIGNALS) +#define POSIXSIGNALS +#endif + +#if defined(POSIXSIGNALS) || defined(__STDC__) +typedef void emp_sig_t; +#else +typedef int emp_sig_t; +#endif + + +#if !defined(aix) && !defined(sgi) +#ifndef ultrix /* already defined in ultrix */ +typedef char s_char; /* change to signed char for aix */ +#endif /* ultrix */ +#else +typedef signed char s_char; +#endif /* !aix && !sgi */ +typedef short coord; /* also change NSC_COORD in nsc.h */ +/* + * watch it; your compiler might not like this. + * If you think this is bogus, look at /usr/include/struct.h + */ +#define OFFSET(stype, oset) ((int)(&(((struct stype *)0)->oset))) +#define SETOFF(sinst, oset) ((s_char *) (sinst) + (oset)) + +#ifndef bit +#define bit(x) (1<<(x)) +#endif + +#define minutes(x) (60*(x)) +#define hours(x) (60*60*(x)) +#define days(x) (60*60*24*(x)) + +typedef void (*voidfunc)(); +typedef int(*qsort_func_t)(const void *, const void *); + + /* return codes from command routines */ +#define RET_OK 0 /* command completed sucessfully */ +#define RET_FAIL 1 /* command completed unsucessfully [?] */ +#define RET_SYN 2 /* syntax error in command */ +#define RET_SYS 3 /* system error (missing file, etc) */ + +#define MAX_DISTPATH_LEN 10 /* Has to go somewhere */ + +/* + * references to library functions which aren't related to any + * particular object, and are of general interest + */ +#if !defined(ALPHA) && !defined(__osf__) && !defined(__linux__) && !defined(_WIN32) +extern long random(); +#endif + +double dmax _PROTO((double n1, double n2)); +double dmin _PROTO((double n1, double n2)); + +extern s_char *copy _PROTO((s_char *s1, s_char *s2)); +extern s_char *numstr _PROTO((s_char buf[], int n)); +extern s_char *esplur _PROTO((int n)); +extern s_char *splur _PROTO((int n)); +extern s_char *iesplur _PROTO((int n)); +extern s_char *plur _PROTO((int n, s_char *no, s_char *yes)); +extern s_char *getstarg _PROTO((s_char *input, s_char *prompt, s_char buf[])); +extern s_char *getstring _PROTO((s_char *prompt, s_char buf[])); +extern s_char *prbuf(s_char *format, ...); + +/* + * frequently used libc functions + */ + +#if !defined(_WIN32) +#if defined(linux) +#ifndef __STDC__ +extern char *malloc(); +extern char *calloc(); +#endif +#else +#if !defined(ALPHA) && !defined(__osf__) && !defined(ultrix) && !defined(hpux) && !defined(FBSD) +extern char *malloc(); +extern char *calloc(); +#endif +#endif +#endif + +#if (!defined (aix) && !defined (sgi)) +extern char *ctime(); +extern char *strncpy(); +extern char *strcpy(); +#ifndef NeXT +extern char *index(); +extern char *rindex(); +#endif /* NeXT */ +#endif /* !aix && !sgi*/ + +extern time_t time(); +#if !defined(_WIN32) +#ifdef linux +#ifndef atof +extern double atof(); +#endif +#else +extern double atof(); +#endif +#endif + +#if !defined(_WIN32) +#if !defined (__ppc__) && !defined (hpux) && !defined (aix) && !defined (linux) && !defined(ALPHA) && !defined(__osf__) && !defined(SUN4) && !defined (Rel4) && !(defined (ultrix) && (defined (__STDC__) || defined (__SYSTEMFIVE) || defined (__POSIX))) +extern char *sprintf(); +#endif /* aix */ +#endif + +#define MAXCHRNV 12 + +#include "prototypes.h" /* must come at end, after defines and typedefs */ + +#endif /* _MISC_H_ */ diff --git a/include/mission.h b/include/mission.h new file mode 100644 index 00000000..a2a5d2b8 --- /dev/null +++ b/include/mission.h @@ -0,0 +1,68 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * mission.h: Definitions for things having to do with missions. + * + * Known contributors to this file: + * Ken Stevens, 1995 + */ + +#ifndef _MISSION_H_ +#define _MISSION_H_ + +#include "queue.h" + +#define MI_INTERDICT 1 +#define MI_SUPPORT 2 +#define MI_RESERVE 3 +#define MI_ESCORT 4 +#define MI_SINTERDICT 5 /* sub interdiction */ +#define MI_AIR_DEFENSE 6 +#define MI_DSUPPORT 7 +#define MI_OSUPPORT 8 + +/* The following "missions" do not need to be set--they are automatic */ +#define MI_FINTERDICT 9 /* forts interdicting ships */ +#define MI_MINTERDICT 10 /* missiles interdicting ships or land units */ +#define MI_MINTERCEPT 11 /* missile interception */ +#define MI_SINTERCEPT 12 /* sattelite interception */ +#define MI_PINTERCEPT 13 /* intercept planes */ +#define MI_SAM 14 /* SAM interception */ +#define MI_LREACT 15 /* land units react */ +#define MI_MAX 15 + +struct genlist { + struct emp_qelem queue; /* list of units */ + int type; /* type of unit */ + int x,y; /* x,y it came from */ + s_char *cp; /* pointer to desc of thing */ + s_char *thing; /* thing's struct */ +}; + +#define SECT_HARDTARGET (-92917) /* a very low number that no-one might pick */ + +#endif /* _MISSION_H_ */ diff --git a/include/nat.h b/include/nat.h new file mode 100644 index 00000000..cbb4200d --- /dev/null +++ b/include/nat.h @@ -0,0 +1,206 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * nat.h: Definitions for things having to do with nations + * + * Known contributors to this file: + * Thomas Rushack + * Ken Stevens, 1995 + * Steve McClure, 1998-2000 + */ + +#ifndef _NAT_H_ +#define _NAT_H_ + +#include "mission.h" +#include "sect.h" + +#define MAXNOR 50 /* max # realms */ + +struct boundstr { + short b_xl, b_xh; /* horizontal bounds */ + short b_yl, b_yh; /* vertical bounds */ +}; + +struct natstr { + short ef_type; + s_char nat_cnam[20]; /* country name */ + s_char nat_pnam[20]; /* representative */ + s_char nat_hostaddr[32]; /* host addr of last user */ + s_char nat_hostname[512]; /* hostname of last user */ + s_char nat_userid[32]; /* userid of last user */ + coord nat_xstart, nat_ystart; /* cap location at start */ + coord nat_xcap, nat_ycap; /* cap location in abs coords */ + coord nat_xorg, nat_yorg; /* origin location in abs coords */ + natid nat_cnum; /* our country number */ + s_char nat_stat; /* inuse, norm, god, abs */ + s_char nat_dayno; /* day of the year mod 128 */ + s_char nat_connected; /* connected or not? */ + s_char nat_update; /* Want an update or not. */ + u_char nat_missed; /* How many updates missed */ + u_short nat_tgms; /* # of telegrams to be announced */ + u_short nat_ann; /* # of annos pending */ + u_short nat_minused; /* number of minutes used today */ + short nat_btu; /* bureaucratic time units */ + long nat_reserve; /* military reserves */ + long nat_money; /* moola */ + time_t nat_last_login; /* time of last login */ + time_t nat_last_logout; /* time of last logout */ + time_t nat_newstim; /* date news last read */ + time_t nat_annotim; /* date annos last read */ + float nat_level[4]; /* technology, etc */ + struct boundstr nat_b[MAXNOR]; /* realm bounds */ + short nat_relate[MAXNOC]; + short nat_contact[MAXNOC]; /* short for everyone */ + short nat_rejects[(MAXNOC+3)/4]; /* four bits for each country */ + s_char nat_priorities[SCT_MAXDEF+8]; /* priority for each SCT_MAXDEF+8*/ + long nat_flags; /* nation flags */ + s_char nat_mission_trigger[MI_MAX]; /* not used -- relation to trig */ +}; + + /* Priorities */ +#define PRI_SMAINT SCT_MAXDEF+2 +#define PRI_PMAINT SCT_MAXDEF+3 +#define PRI_LMAINT SCT_MAXDEF+4 +#define PRI_SBUILD SCT_MAXDEF+5 +#define PRI_PBUILD SCT_MAXDEF+6 +#define PRI_LBUILD SCT_MAXDEF+7 + + /* nation status types */ +#define STAT_INUSE bit(0) /* cnum in use */ +#define STAT_SANCT bit(1) /* country in sanctuary */ +#define STAT_NORM bit(2) /* normal country */ +#define STAT_GOD bit(3) /* deity powers */ +#define STAT_ABS bit(4) /* abs coords */ +#define STAT_NEW bit(5) /* just initialized */ + + /* Update fields. */ +#define WUPD_WANT bit(0) + + /* nstat values */ +#define VIS STAT_INUSE +#define NORM (STAT_INUSE|STAT_NORM) +#define GOD (STAT_INUSE|STAT_GOD) +#define SANCT (STAT_INUSE|STAT_SANCT) +#define CAP bit(6) +#define MONEY bit(7) + + /* nation relation codes */ +#define AT_WAR 0 +#define SITZKRIEG 1 +#define MOBILIZATION 2 +#define HOSTILE 3 +#define NEUTRAL 4 +#define FRIENDLY 5 +#define ALLIED 6 + + /* nation reject codes */ +#define REJ_TELE bit(0) /* dont allow telegrams to be sent */ +#define REJ_TREA bit(1) /* dont allow treaties to be offered */ +#define REJ_ANNO bit(2) /* don't receive announcements */ +#define REJ_LOAN bit(3) /* don't allow loans to be offered */ + +#define NAT_TLEV 0 +#define NAT_RLEV 1 +#define NAT_ELEV 2 +#define NAT_HLEV 3 + +#define NF_CHAR 1 +#define NF_UCHAR 2 +#define NF_SHORT 3 +#define NF_LONG 4 +#define NF_STRING 5 +#define NF_FLOAT 6 +#define NF_DOUBLE 7 +#define NF_BOUND 8 + +#define NF_NOTIFY 1 +#define NF_PRIVATE 2 + +#define NF_NATID NF_UCHAR +#define NF_COORD NF_SHORT + +#define FOUND_FLY 3 /* Number of updates contact lasts */ +#define FOUND_LOOK 5 /* These are only useful with the */ +#define FOUND_SPY 6 /* LOSE_CONTACT option (and HIDDEN) */ +#define FOUND_MAP 6 +#define FOUND_TELE 3 +#define FOUND_COAST 3 + +struct fixnat { + s_char *name; + int type; + int index; + int notify; + int offset; +}; + +/* procedures relating to nation stuff */ + +#define putnat(n) \ + ef_write(EF_NATION, n->nat_cnum, (caddr_t)n) +#define getnatp(n) \ + (struct natstr *) ef_ptr(EF_NATION, (int)n) + +extern double tfact(natid cn, double mult); +extern double tfactfire(natid cn, double mult); +extern double techfact(int level, double mult); +extern double techfactfire(int level, double mult); +extern double reltech(int level1, int level2, double mult); +/* src/lib/subs/comsub.c */ +extern double multread(natid , natid ); +extern int commread(void ); +extern int commwrite(void ); +extern int commlock(void ); +extern int communlock(void ); +extern int commamt(natid , int , float * ); +extern void commset(natid , int , int ); +extern void multset(natid , float ); +extern void commprice(int , float * ); + +extern s_char *cname(natid n); +extern s_char *relatename(struct natstr *np, natid other); +extern s_char *rejectname(struct natstr *np, natid other); +extern s_char *natstate(struct natstr *np); +extern int getrel(struct natstr *np, natid them); +extern int getrejects(natid them, struct natstr *np); +extern int getcontact(struct natstr *np, natid them); +extern void putrel(struct natstr *np, natid them, int relate); +extern void putreject(struct natstr *np, natid them, int how, int what); +extern void putcontact(struct natstr *np, natid them, int contact); +extern void agecontact(struct natstr *np); +extern struct fixnat *natfield(); + +#define NF_INFORM bit(0) /* Inform me of telegrams right away */ +#define NF_FLASH bit(1) /* Allow other players to flash me (sicko :) */ +#define NF_BEEP bit(2) /* Make beeping sounds when appropriate */ +#define NF_COASTWATCH bit(3) /* Turn auto-coastwatch on */ +#define NF_SONAR bit(4) /* Turn auto-sonar on */ +#define NF_TECHLISTS bit(5) /* Sort lists by tech not type */ +#define NF_SACKED bit(6) /* Capital was sacked, and hasn't been reset yet */ + +#endif /* _NAT_H_ */ diff --git a/include/news.h b/include/news.h new file mode 100644 index 00000000..f933e717 --- /dev/null +++ b/include/news.h @@ -0,0 +1,173 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * news.h: Definitions for Empire News + * + * Known contributors to this file: + * Dave Pare + * Thomas Rushack + * Steve McClure + */ + +/* + * News codes for new options are not #ifdefed, since defining maxverb + * would be a pain, and it doesn't hurt to leave them in --ts + */ + +#ifndef _NEWS_H_ +#define _NEWS_H_ + +struct nwsstr { + short ef_type; + natid nws_ano; /* "actor" country # */ + short nws_uid; + s_char nws_vrb; /* action (verb) */ + natid nws_vno; /* "victim" country # */ + s_char nws_ntm; /* number of times */ + time_t nws_when; /* time of action */ +}; + +#define NUM_RPTS 2 /* number of story alternates */ + +struct rptstr { + int r_good_will; /* how "nice" the action is */ + int r_newspage; /* which page this item belongs on */ + s_char *r_newstory[NUM_RPTS]; /* texts for fmt( */ +}; + + /* news verbs */ +#define N_WON_SECT 1 +#define N_SCT_LOSE 2 +#define N_SPY_SHOT 3 +#define N_SENT_TEL 4 +#define N_SIGN_TRE 5 +#define N_MAKE_LOAN 6 +#define N_REPAY_LOAN 7 +#define N_MAKE_SALE 8 +#define N_OVFLY_SECT 9 +#define N_SCT_SHELL 10 +#define N_SHP_SHELL 11 +#define N_TOOK_UNOCC 12 +#define N_TORP_SHIP 13 +#define N_FIRE_BACK 14 +#define N_BROKE_SANCT 15 +#define N_SCT_BOMB 16 +#define N_SHP_BOMB 17 +#define N_BOARD_SHIP 18 +#define N_SHP_LOSE 19 +#define N_FLAK 20 +#define N_SEIZE_SECT 21 +#define N_HONOR_TRE 22 +#define N_VIOL_TRE 23 +#define N_DISS_GOV 24 +#define N_HIT_MINE 25 +#define N_DECL_ALLY 26 +#define N_DECL_NEUT 27 +#define N_DECL_WAR 28 +#define N_DIS_ALLY 29 +#define N_DIS_WAR 30 +#define N_OUT_PLAGUE 31 +#define N_DIE_PLAGUE 32 +#define N_NAME_CHNG 33 +#define N_DIE_FAMINE 34 +#define N_RIOT 35 +#define N_DOWN_PLANE 36 +#define N_NUKE 37 +#define N_FREEDOM_FIGHT 38 +#define N_SHOOT_CIV 39 +#define N_LAUNCH 40 +#define N_SAT_KILL 41 +#define N_GIFT 42 +#define N_AIDS 43 +#define N_HURTS 44 +#define N_TAKE 45 +#define N_NUKE_STOP 46 +#define N_SCT_MISS 47 +#define N_SHP_MISS 48 +#define N_TRADE 49 +#define N_PIRATE_TRADE 50 +#define N_PIRATE_KEEP 51 +#define N_SHIP_TORP 52 +#define N_SUB_BOMB 53 +#define N_ASSAULT_LOSE 54 +#define N_UNIT_BOMB 55 +#define N_LHIT_MINE 56 +#define N_FIRE_F_ATTACK 57 +#define N_FIRE_L_ATTACK 58 +#define N_FIRE_S_ATTACK 59 +#define N_SACK_CAP 60 +#define N_UP_FRIENDLY 61 +#define N_DOWN_FRIENDLY 62 +#define N_UP_NEUTRAL 63 +#define N_DOWN_NEUTRAL 64 +#define N_UP_HOSTILE 65 +#define N_DOWN_HOSTILE 66 +#define N_SCT_SMISS 67 +#define N_SHP_SMISS 68 +#define N_START_COL 69 +#define N_NUKE_SSTOP 70 +#define N_LND_MISS 71 +#define N_LND_SMISS 72 +#define N_AWON_SECT 73 +#define N_PWON_SECT 74 +#define N_PARA_UNOCC 75 +#define N_ALOSE_SCT 76 +#define N_PLOSE_SCT 77 +#define N_FIN_TROUBLE 78 +#define N_CREDIT_JUNK 79 +#define N_WELCH_DEAL 80 +#define N_LND_LOSE 81 +#define N_BOARD_LAND 82 +#define N_MAX_VERB 82 + +#define N_FOR 1 +#define N_FRONT 2 +#define N_SEA 3 +#define N_SKY 4 +#define N_MISS 5 +#define N_ARTY 6 +#define N_ECON 7 +#define N_COLONY 8 +#define N_HOME 9 +#define N_SPY 10 +#define N_TELE 11 +#define N_MAX_PAGE 11 + +#define NEWS_PERIOD days(10) + +#define getnews(n, p) \ + ef_read(EF_NEWS, n, (caddr_t)p) +#define putnews(n, p) \ + ef_write(EF_NEWS, n, (caddr_t)p) +#define getnewsp(n) \ + (struct nwsstr *) ef_ptr(EF_NEWS, n) + +extern struct rptstr rpt[]; + +extern int nws_maxno; + +#endif /* _NEWS_H_ */ diff --git a/include/nsc.h b/include/nsc.h new file mode 100644 index 00000000..d323b794 --- /dev/null +++ b/include/nsc.h @@ -0,0 +1,167 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * nsc.h: Definitions for Empire conditionals + * + * Known contributors to this file: + * Dave Pare, 1989 + */ + +#ifndef _NSC_H_ +#define _NSC_H_ + +#include "prototype.h" +#include "xy.h" + +#define NS_LSIZE 128 +#define NS_NCOND 16 + +struct nscstr { + long fld1; /* first commodity or number */ + long fld2; /* second commodity or number */ + int oper; /* required relationship operator */ +}; + +struct nstr_sect { + coord x, y; /* current x-y */ + coord dx, dy; /* accumlated x,y travel */ + int id; /* return value of sctoff */ + int type; /* type of query */ + int curdist; /* dist query: current range */ + struct range range; /* area of coverage */ + int dist; /* dist query: range */ + coord cx, cy; /* dist query: center x-y */ + int (*read)(); /* read function */ + int ncond; /* # of selection conditions */ + struct nscstr cond[NS_NCOND]; /* selection conditions */ +}; + +struct nstr_item { + int cur; /* current item */ + int sel; /* selection type */ + int type; /* item type being selected */ + int curdist; /* if NS_DIST, current item's dist */ + struct range range; /* NS_AREA/NS_DIST: range selector */ + int dist; /* NS_DIST: distance selector */ + coord cx, cy; /* NS_DIST: center x-y, NS_XY: xy */ + int group; /* NS_GROUP: fleet/wing match */ + int size; /* NS_LIST: size of list */ + int index; /* NS_LIST: index */ + int list[NS_LSIZE]; /* NS_LIST: item list */ + int (*read)(); /* read function */ + int flags; /* EFF_ flags */ + int ncond; /* # of selection conditions */ + struct nscstr cond[NS_NCOND]; /* selection conditions */ +}; + +#define NS_UNDEF 0 +#define NS_LIST 1 +#define NS_DIST 2 +#define NS_AREA 3 +#define NS_ALL 4 +#define NS_XY 5 +#define NS_GROUP 6 + +/* + * looks something like this: + * D: only deity can query on this field + * R: round this value to the nearest 10 if not owner + * T: type of pointer. + * C: catagory of value. + * V: value. + * + * 22 2 1 1 1 + * 32 0 8 6 2 8 4 0 + * xxxx xxxx xxxx xxxx xxxx xxxx + * DRTT TTCC VVVV VVVV VVVV VVVV + */ + +/* + * catagories + */ +#define NSC_VAL (0) /* normal number */ +#define NSC_VAR (1<<16) /* is a vtype */ +#define NSC_OFF (2<<16) /* is an offset */ +#define NSC_CMASK (3<<16) + +/* + * how to interpret "offset" fields + */ +#define NSC_CHAR (1<<18) /* pointer to s_char */ +#define NSC_UCHAR (2<<18) /* pointer to uchar */ +#define NSC_SHORT (3<<18) /* pointer to short */ +#define NSC_USHORT (4<<18) /* pointer to unsigned short */ +#define NSC_INT (5<<18) /* pointer to int */ +#define NSC_LONG (6<<18) /* pointer to long */ +#define NSC_XCOORD (7<<18) /* pointer to short that needs x conversion */ +#define NSC_YCOORD (8<<18) /* pointer to short that needs y conversion */ +#define NSC_FLOAT (9<<18) /* pointer to float */ +#define NSC_CHARP (10<<18) /* pointer to string pointer */ +#define NSC_TIME (11<<18) /* pointer to time_t */ +#define NSC_TMASK (15<<18) + +#define NSC_NATID NSC_UCHAR /* change if natid typedef changes */ + +#define NSC_MASK (0xffff0000) + +#define NSC_ROUND (1<<22) +#define NSC_DEITY (1<<23) + +struct castr { + long ca_code; /* encoded form */ + s_char *ca_name; /* name used for matches */ + u_short ca_len; /* Used for arrays */ + long ca_edv; /* which commands is this field visible to? */ +}; + +/* variables using the above */ + +extern struct castr var_ca[]; +extern struct castr sect_ca[]; +extern struct castr ship_ca[]; +extern struct castr plane_ca[]; +extern struct castr land_ca[]; +extern struct castr nuke_ca[]; +extern struct castr news_ca[]; +extern struct castr nat_ca[]; +extern struct castr treaty_ca[]; +extern struct castr trade_ca[]; +extern struct castr loan_ca[]; +extern struct castr genitem_ca[]; +extern struct castr map_ca[]; +extern struct castr bmp_ca[]; +extern struct castr ca[]; +extern struct castr commodity_ca[]; + +/* src/lib/subs/nstr.c */ +extern s_char * nstr_comp(struct nscstr * , int * , int , s_char * ); +extern int encode(register s_char * , long * , int ); + + +extern s_char *decodep _PROTO((register long code, register void *addr)); + +#endif /* _NSC_H_ */ diff --git a/include/nuke.h b/include/nuke.h new file mode 100644 index 00000000..2c86e085 --- /dev/null +++ b/include/nuke.h @@ -0,0 +1,79 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * nuke.h: Definitions for things having to do with nukes + * + * Known contributors to this file: + * Dave Pare, 1986 + */ + +#ifndef _NUKE_H_ +#define _NUKE_H_ + +#define N_MAXNUKE 15 + +struct nukstr { + short ef_type; + natid nuk_own; + short nuk_uid; + coord nuk_x; /* current loc of device */ + coord nuk_y; + s_char nuk_n; /* number of nukes in list */ + short nuk_ship; /* currently aboard ship */ + short nuk_trade; /* index into trade file */ + short nuk_types[N_MAXNUKE]; /* # of nukes in sector of given type */ + time_t nuk_timestamp; /* Last time this nuke was touched */ +}; + +struct nchrstr { + s_char *n_name; /* warhead unit name */ + int n_lcm; /* costs to build */ + int n_hcm; + int n_oil; + int n_rad; + int n_blast; /* blast radius */ + int n_dam; /* damage at center */ + int n_cost; + int n_tech; /* tech needed to build */ + int n_weight; + int n_flags; /* description of capability */ +}; + +#define N_NEUT bit(0) /* Neutron bomb (low damage, high fallout) */ + +#define getnuke(n, p) \ + ef_read(EF_NUKE, n, (caddr_t)p) +#define putnuke(n, p) \ + ef_write(EF_NUKE, n, (caddr_t)p) +#define getnukep(n) \ + (struct nukstr *) ef_ptr(EF_NUKE, n) + +extern struct nchrstr nchr[]; + +extern int nuk_maxno; + +#endif /* _NUKE_H_ */ diff --git a/include/options.h b/include/options.h new file mode 100644 index 00000000..dc081f93 --- /dev/null +++ b/include/options.h @@ -0,0 +1,127 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * options.h: Define which "optional" features should be enabled. + * + * Known contributors to this file: + * Dave Pare + * Jeff Bailey + * Chad Zabel + * Thomas Rushack, 1992 + * Ken Stevens, 1995 + * Steve McClure, 1998 + */ + +#ifndef _OPTIONS_H_ +#define _OPTIONS_H_ + +#include "gamesdef.h" + +/* #define NO_LCMS */ /* No lcms needed */ +/* #define NO_HCMS */ /* No hcms needed */ + +/* #define NO_FORT_FIRE */ /* Forts cannot fire */ + +#define BRIDGETOWERS /* Bridge towers are enabled */ + +#define GODNEWS /* We inform the world when deities give/take away */ + +#define LANDSPIES /* Enable the land unit type spies */ + +#define START_CASH 25000 /* set starting cash when capitol created */ + + /* Setting BLITZ sets a couple of things. + 1. BTU's always max when you login. + 2. Changing name doesn't take any btus or $$ + enables BLITZ updates, also turns on NOFOOD, below */ + +/*#define START_UNITS 2 *//* How many free start units you get. Types are + specified in src/lib/global/constants.c */ + +/* #define SHIP_DECAY */ /* Allows ships at sea to decay */ +#define PLANENAMES /* Use real names for planes, not the boring ones :) */ + +/* #define GO_RENEW */ /* Gold and Oil are renewable resources */ + +/* #define DEFENSE_INFRA */ /* Allow the improvement of defensive infrastructure */ + +/*#define MOB_ACCESS */ /* Mobility updates real-time */ +/*#define TECH_POP */ /* Technology costs more as population rises */ + +/*#define MARKET */ /* Time-based MARKET and TRADING */ +#define LOANS /* Bail out other countries via S&L scandals */ +#define TREATIES /* Sign treaties with your friends and enemies */ + +/*#define HIDDEN*/ /* Hides information between players */ +/*#define LOSE_CONTACT*/ /* Allows contact to be lost after a few updates */ + +/* Chainsaw Mods */ +/*#define NONUKES*/ /* Eliminates nukes */ +#ifndef NO_OIL /* Can't have fuel with no oil! */ +/*#define FUEL*/ /* Ships use fuel to move */ +#endif +/*#define TRADESHIPS*/ /* Use Tradeships */ +/*#define SLOW_WAR*/ /* Declaring war takes time */ +/*#define SNEAK_ATTACK*/ /* Allows sneak attacks */ +#define ORBIT /* Satalites will orbit each update */ +#define PINPOINTMISSILE /**/ +#define FALLOUT /* Enables secondary effects caused by radiation */ +#define SAIL /* A update routine to move ships */ +#define SHIPNAMES /* Name your ships, removing this option saves space */ +#define NEUTRON /* Enables Neurton Warheads */ +#define NEWPOWER /* Better power formula */ +#define NOMOBCOST /* No mob cost for firing from ships */ +/*#define SUPER_BARS */ /* Bars can't be destroyed by fire */ +#define EASY_BRIDGES /* Bridges can be built anywhere */ +#define ALL_BLEED /* Tech bleeds to everyone */ +/*#define DRNUKE*/ /* Need research to make nukes */ +#define NO_PLAGUE /* Plague is disabled */ +#define NEW_STARVE /* UW's starve, then civs, then mil */ +#define NEW_WORK /* Work is changed in proportion to the # of civs mvd */ +/*#define RES_POP*/ /* population is limited by research */ +/*#define GRAB_THINGS*/ /* units will grab things they need to build */ +/*#define BIG_CITY */ /* allow 10x civs in 'c' sectors */ +#define INTERDICT_ATT /* interdict post-attack move in */ + +#define SHOWPLANE /**/ +#define NUKEFAILDETONATE /**/ +#define MISSINGMISSILES /* Missiles have a change to miss the target */ +#define UPDATESCHED /* Used to controle update times and should always */ +#ifdef UPDATESCHED /* be used */ +#define DEMANDUPDATE /* NOTE! Depends on UPDATESCHED! Don't use without it! */ +#endif /* UPDATESCHED */ + +#ifdef BLITZ +#define NOFOOD /* automatically have no food for blitzes */ +#endif /* BLITZ */ +/*#define NOFOOD*/ /**/ + +#ifndef SLOW_WAR +#undef SNEAK_ATTACK /* SNEAK_ATTACK is only useful with SLOW_WAR */ +#endif /* SLOW_WAR */ + +#endif /* _OPTIONS_H_ */ diff --git a/include/optlist.h b/include/optlist.h new file mode 100644 index 00000000..eff0ad14 --- /dev/null +++ b/include/optlist.h @@ -0,0 +1,128 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * optlist.h: Definitions of option listings + * + * Known contributors to this file: + * Ken Stevens, 1995 + * Steve McClure, 1998 + */ + +#ifndef _OPTLIST_H_ +#define _OPTLIST_H_ + +#include "prototype.h" + +struct option_list { + char *opt_key; + int *opt_valuep; +}; + +extern struct option_list Options[]; + +extern void set_option _PROTO((const char *key)); +extern void delete_option _PROTO((const char *key)); + +extern int WORLD_X; +extern int WORLD_Y; + +extern int opt_NO_FORT_FIRE; +extern int opt_TREATIES; +extern int opt_BRIDGETOWERS; +extern int opt_GODNEWS; +extern int opt_GO_RENEW; +extern int opt_DEFENSE_INFRA; +extern int opt_SHIP_DECAY; +extern int opt_MOB_ACCESS; +extern int opt_MARKET; +extern int opt_LOANS; +extern int opt_LANDSPIES; +extern int opt_PLANENAMES; +extern int opt_NO_LCMS; +extern int opt_NO_HCMS; +extern int opt_NO_OIL; +extern int opt_NOFOOD; +extern int opt_SNEAK_ATTACK; +extern int opt_BLITZ; +extern int opt_HIDDEN; +extern int opt_LOSE_CONTACT; +extern int opt_NONUKES; +extern int opt_FUEL; +extern int opt_TRADESHIPS; +extern int opt_NEWPOWER; +extern int opt_NOMOBCOST; +extern int opt_SUPER_BARS; +extern int opt_EASY_BRIDGES; +extern int opt_ALL_BLEED; +extern int opt_DRNUKE; +extern int opt_SLOW_WAR; +extern int opt_NO_PLAGUE; +extern int opt_NEW_STARVE; +extern int opt_NEW_WORK; +extern int opt_RES_POP; +extern int opt_GRAB_THINGS; +extern int opt_SHOWPLANE; +extern int opt_ORBIT; +extern int opt_PINPOINTMISSILE; +extern int opt_FALLOUT; +extern int opt_SAIL; +extern int opt_NUKEFAILDETONATE; +extern int opt_MISSINGMISSILES; +extern int opt_SHIPNAMES; /* not used currently */ +extern int opt_NEUTRON; +extern int opt_UPDATESCHED; +extern int opt_DEMANDUPDATE; +extern int opt_BIG_CITY; +extern int opt_INTERDICT_ATT; +extern int opt_TECH_POP; + +struct keymatch; /* forward decl */ + +/* function prototype for variable setting routines */ +typedef void KmFunc _PROTO((struct keymatch *kp, s_char **av)); + +/* current known routines */ +#if defined(__cplusplus) || (defined(__STDC__) &&__STDC__) +KmFunc optstrset, intset, floatset, doubleset, longset, + optionset, optiondel, worldxset; +#else +void optstrset(), intset(), floatset(), doubleset(), longset(), + optionset(), optiondel(), worldxset(); +#endif + +struct keymatch { + s_char *km_key; /* the key */ + KmFunc *km_func; /* the function to call if matches */ + caddr_t km_data; /* associated data */ + int km_flags; /* useful flags */ +#define KM_ALLOC 0x01 /* memory allocated */ + s_char *km_comment; /* Comment (hopefully useful) */ +}; + +extern struct keymatch configkeys[]; + +#endif /* _OPTLIST_H_ */ diff --git a/include/path.h b/include/path.h new file mode 100644 index 00000000..1c0e6841 --- /dev/null +++ b/include/path.h @@ -0,0 +1,87 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * path.h: Definitions for directions, paths, etc. + * + * Known contributors to this file: + * + */ + +#ifndef _PATH_H_ +#define _PATH_H_ + +#include "misc.h" /* s_char coord etc. */ +#include "sect.h" /* struct sctstr */ +#include "xy.h" + + /* direction indices */ +#define DIR_STOP 0 +#define DIR_UR 1 +#define DIR_R 2 +#define DIR_DR 3 +#define DIR_DL 4 +#define DIR_L 5 +#define DIR_UL 6 +#define DIR_VIEW 7 +#define DIR_MAP 8 +#define DIR_FIRST 1 +#define DIR_LAST 6 + +#define SELL_NOT_DELIV 7 /* in "_use" field => contract */ + +extern int dirindex[]; +extern int diroff[][2]; +extern s_char dirch[]; + +/* src/lib/subs/paths.c */ +extern s_char * getpath(s_char * , s_char * , coord , coord , int , int, + int , int ); +extern double fcost(struct sctstr * , natid ); +extern double ncost(struct sctstr * , natid ); +extern double pathtoxy(s_char * , coord * , coord * , double (* )(struct sctstr *sp, natid own)); +extern int chkdir(s_char , int , int ); +extern int getdir(s_char * , s_char * , s_char * , s_char * ); +extern void direrr(s_char * , s_char * , s_char * ); +extern double mcost(struct sctstr * , int ); +extern int chkpath(natid , s_char * , coord , coord ); +extern void pathrange(register coord , register coord , register s_char *, + int , struct range * ); + +extern s_char *masktopath(); +extern long pathtomask(); + +extern double sector_mcost(); + +#define P_NONE 0 /* NO destinations allowed */ +#define P_WALKING 1 /* use BestLandPath, only owned */ +#define P_FLYING 2 /* use bestpath, any */ +#define P_SAILING 3 /* use bestpath, any */ +#define P_DISTING 4 /* use BestDistPath, only owned */ + +#define MAX_PATH_LEN 1024 + +#endif /* _PATH_H_ */ diff --git a/include/plane.h b/include/plane.h new file mode 100644 index 00000000..e7bdbc18 --- /dev/null +++ b/include/plane.h @@ -0,0 +1,206 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * plane.h: Definitions for planes and plane types + * + * Known contributors to this file: + * Dave Pare, 1986 + * Ken Stevens, 1995 + * Steve McClure, 1998 + */ + +#ifndef _PLANE_H_ +#define _PLANE_H_ + +#include "queue.h" +#include "sect.h" + +#define PLANE_MINEFF 10 + +/* + * some routines assume that from pln_x to pln_wing remains + * exactly equivalent with shp_x to shp_fleet + */ +struct plnstr { + short ef_type; + natid pln_own; /* owning country */ + short pln_uid; /* plane unit id */ + coord pln_x; /* plane x-y */ + coord pln_y; + s_char pln_type; /* fighter, bomber, etc */ + s_char pln_effic; /* actually "training" */ + s_char pln_mobil; /* plane mobility */ + short pln_sell; /* index into trade file */ + short pln_tech; /* plane's tech level */ + s_char pln_wing; /* like fleet */ + coord pln_opx; /* Op sector coords */ + coord pln_opy; /* Op sector coords */ + short pln_mission; /* mission code */ + short pln_radius; /* mission radius */ + u_char pln_range; /* total distance, not radius */ + u_char pln_range_max; /* max range for this plane */ + short pln_ship; /* pointer to carrier */ + short pln_land; /* pointer to carrier */ + int pln_att; /* plane air-air attack/defense values */ + int pln_def; + int pln_acc; + int pln_load; + int pln_fuel; + s_char pln_harden; /* for missiles */ + s_char pln_nuketype; /* type of nuclear armament (if any) */ + s_char pln_flags; /* State of the plane */ + time_t pln_access; /* Last time mob was updated (MOB_ACCESS) */ + time_t pln_timestamp; /* Last time this plane was touched */ + float pln_theta; /* position in orbital sine wave */ +}; + +#define PLN_LAUNCHED bit(0) /* A satellite that's in orbit */ +#define PLN_SYNCHRONOUS bit(1) /* A satellite in geo-synchronous orbit */ +#define PLN_AIRBURST bit(2) /* Airburst the nuke we're armed with */ + +struct plchrstr { + s_char *pl_name; /* plane vanilla unit name */ + s_char *pl_planename; /* plane real name */ + int pl_lcm; /* costs to build */ + int pl_hcm; + int pl_cost; + int pl_tech; /* tech needed to build */ + int pl_acc; /* bombing accuracy (higher the better) */ + int pl_load; /* bomb load, also for carrying cargo */ + int pl_att; /* air-air attack/defense strengths */ + int pl_def; + int pl_range; /* how many sectors it can fly */ + int pl_crew; /* number of mil to crew it */ + int pl_fuel; /* fuel consumption */ + int pl_stealth; /* how stealthy is it? */ + int pl_flags; /* description of capability */ +}; + +#define P_B bit(0) /* bombing factor only for bombing */ +#define P_T bit(1) /* tactical bombing ability */ +#define P_F bit(2) /* interceptor/escort */ +#define P_C bit(3) /* bombing factor for transport only */ +#define P_V bit(4) /* vtol ability */ +#define P_M bit(5) /* missile, used only once, can't be intercepted */ +#define P_L bit(6) /* light plane, lands on carriers */ +#define P_S bit(7) /* Spy ability */ +#define P_I bit(8) /* Imaging ability (advanced spying) */ +#define P_O bit(9) /* Orbital ability (a satellite) */ +#define P_X bit(10) /* Stealth ability */ +#define P_N bit(11) /* Nuclear RV interceptor (abm) */ +#define P_H bit(12) /* Half stealthy */ +#define P_E bit(13) /* extra light */ +#define P_K bit(14) /* chopper */ +#define P_A bit(15) /* ASW (Anti-Sub Warfare) */ +#define P_P bit(16) /* paradropping */ +#define P_ESC bit(17) /* escort */ +#define P_MINE bit(18) /* can lay mines */ +#define P_SWEEP bit(19) /* can sweep mines */ +#define P_MAR bit(20) /* missile can hit ships */ + +#define PM_R bit(0) /* Recon mission */ +#define PM_S bit(1) /* Mine-sweeping mission */ + +#define PLN_MAXDEF 50 + + /* internal to "fly" module -- really shouldn't be here */ + +struct plist { + struct emp_qelem queue; /* list of planes */ + int state; /* state of plane */ + int bombs; /* bombs carried for bombing mission */ + int misc; /* amount of random item being transported */ + struct plchrstr *pcp; /* pointer to desc of plane */ + struct plnstr plane; /* struct plane */ +}; + +#define P_OK 0 +#define P_FIRED 1 +#define P_DEL 2 + +#define getplane(n, p) \ + ef_read(EF_PLANE, n, (caddr_t)p) +#define putplane(n, p) \ + ef_write(EF_PLANE, n, (caddr_t)p) +#define getplanep(n) \ + (struct plnstr *) ef_ptr(EF_PLANE, n) + +extern struct plchrstr plchr[]; +extern int pln_maxno; + + struct shiplook{ + short uid; + u_char looked; + u_char found; + struct shiplook *next; + }; + +#define PLN_ATTDEF(b, t) (b + ((b?1:0) * ((t/20)>10?10:(t/20)))) +#define PLN_ACC(b, t) (b * (1.0 - (sqrt((double)t) / 50.))) +#define PLN_RAN(b, t) (t ? (b + (logx((double)t, (double)2.0))) : b) +#define PLN_LOAD(b, t) (t ? (b * (logx((double)t, (double)50.0) < 1.0 ? 1.0 : \ + logx((double)t, (double)50.0))) : b) + +double sqrt(); +double logx(); + +float pln_damage_sect(); + +void count_planes(); +double sqrt(); +s_char *prplane(); + + +/* src/lib/subs/aircombat.c */ +extern void ac_planedamage(struct plist * , natid , int , natid , int , + int , s_char * ); +extern void ac_intercept(struct emp_qelem * , struct emp_qelem * , + struct emp_qelem * , natid , coord , coord); +extern void ac_combat_headers(natid , natid ); +extern void ac_airtoair(struct emp_qelem * , struct emp_qelem * , natid ); +extern void ac_doflak(struct emp_qelem * , struct sctstr * ); +extern void ac_shipflak(struct emp_qelem * , coord , coord ); +extern void ac_landflak(struct emp_qelem * , coord , coord ); +extern void ac_fireflak(struct emp_qelem * , natid , natid , int ); +extern void ac_encounter(struct emp_qelem * , struct emp_qelem * , coord , + coord , s_char * , int , int , + struct emp_qelem *, struct emp_qelem *); +extern int ac_isflying(struct plnstr *, struct emp_qelem *); +extern int do_evade(struct emp_qelem * , struct emp_qelem * ); +extern void sam_intercept(struct emp_qelem * , struct emp_qelem * , + natid , natid , coord , coord , int ); +extern int all_missiles(struct emp_qelem * ); +extern int can_fly(int ); + +/* src/lib/subs/aswplnsubs.c */ +extern int have_looked(u_char , struct shiplook * ); +extern int have_found(u_char , struct shiplook * ); +extern void set_have_looked(u_char , struct shiplook * ); +extern void set_have_found(u_char , struct shiplook * ); +extern int print_found(struct shiplook * ); + +#endif /* _PLANE_H_ */ diff --git a/include/player.h b/include/player.h new file mode 100644 index 00000000..cae5093a --- /dev/null +++ b/include/player.h @@ -0,0 +1,106 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * player.h: Definitions for player information (threads) + * + * Known contributors to this file: + * Dave Pare, 1994 + * Doug Hay, 1998 + */ + +#ifndef _PLAYER_H_ +#define _PLAYER_H_ + +#include +#if !defined(_WIN32) +#include +#endif +#include "prototype.h" +#include "queue.h" +#include "misc.h" +#include "com.h" +#include "empthread.h" + +struct player { + struct emp_qelem queue; + empth_t *proc; + s_char hostaddr[32]; + s_char hostname[512]; + s_char client[128]; + s_char userid[32]; + int validated; + natid cnum; + int state; + struct cmndstr *command; + struct iop *iop; + s_char combuf[1024]; + s_char *argp[128]; + s_char *condarg; + time_t lasttime; + int ncomstat; + int minleft; + int btused; + int visitor; + int god; + int owner; + int nstat; + int waiting; + int simulation; /* e.g. budget command */ + double dolcost; + int broke; + time_t curup; /* used in calc of minutes used */ + int aborted; + int curid; /* for pr, cur. line's id, -1 none */ + int blitz_time; + char *map; /* pointer to in-mem map */ + char *bmap; /* pointer to in-mem bmap */ +}; + +#define PS_INIT 0 +#define PS_LOGIN 1 +#define PS_PLAYING 2 +#define PS_SHUTDOWN 3 +#define PS_KILL 4 + +/* thread priorities */ +#define PP_UPDATE 6 +#define PP_SHUTDOWN 5 +#define PP_SCHED 4 +#define PP_TIMESTAMP 2 +#define PP_PLAYER 3 +#define PP_ACCEPT 3 +#define PP_KILLIDLE 2 + +#include "prototypes.h" /* must come at end, after defines and typedefs */ + +#endif /* _PLAYER_H_ */ + + + + + + diff --git a/include/power.h b/include/power.h new file mode 100644 index 00000000..43f41465 --- /dev/null +++ b/include/power.h @@ -0,0 +1,65 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * power.h: Definitions for things having to do with the power report. + * + * Known contributors to this file: + * + */ + +#ifndef _POWER_H_ +#define _POWER_H_ + +struct powstr { + natid p_nation; + float p_sects; + float p_effic; + float p_civil; + float p_milit; + float p_shell; + float p_guns; + float p_petrol; + float p_iron; + float p_dust; + float p_food; + float p_oil; + float p_bars; + float p_planes; + float p_ships; + float p_units; + float p_money; + float p_power; +}; + +#define getpower(n, p) \ + ef_read(EF_POWER, n, (caddr_t)p) +#define putpower(n, p) \ + ef_write(EF_POWER, n, (caddr_t)p) +#define getpowerp(n) \ + (struct powstr *) ef_ptr(EF_POWER, n) + +#endif /* _POWER_H_ */ diff --git a/include/product.h b/include/product.h new file mode 100644 index 00000000..2b1b6ed6 --- /dev/null +++ b/include/product.h @@ -0,0 +1,75 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * product.h: Definitions for things having to do with products + * + * Known contributors to this file: + * + */ + +#ifndef _PRODUCT_H_ +#define _PRODUCT_H_ + +struct pchrstr { + u_char p_nv; /* number of constituents */ + u_char p_vtype[MAXCHRNV];/* constituent types */ + u_short p_vamt[MAXCHRNV]; /* constituent amounts */ + int p_type; /* vtype if product is a variable */ + int p_level; /* index (NAT_?LEV) if product is not a var */ + int p_cost; /* dollars / product unit */ + int p_nrndx; /* index into sect of natural resource */ + int p_nrdep; /* depletion as a % of resource used */ + int p_nlndx; /* index (NAT_?LEV) affecting production */ + int p_nlmin; /* minimum lvl required */ + int p_nllag; /* lag, mul by (lvl-nlmin)/(lvl-nlmin+nllag) */ + int p_effic; /* process efficiency, mult by p_effic/100 */ + s_char *p_name; /* name of product */ + s_char *p_sname; /* short (7char or less) name of product */ +}; + +#define P_SHELL 1 +#define P_GUN 2 +#define P_PETROL 3 +#define P_IRON 4 +#define P_DUST 5 +#define P_BAR 6 +#define P_FOOD 7 +#define P_OIL 8 +#define P_LCM 9 +#define P_HCM 10 +#define P_TLEV 11 +#define P_RLEV 12 +#define P_ELEV 13 +#define P_HLEV 14 +#define P_URAN 15 +#define P_MDUST 16 + +extern struct pchrstr pchr[]; + +extern int prd_maxno; + +#endif /* _PRODUCT_H_ */ diff --git a/include/proto.h b/include/proto.h new file mode 100644 index 00000000..08f24bda --- /dev/null +++ b/include/proto.h @@ -0,0 +1,68 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * proto.h: Protocol for client + * + * Known contributors to this file: + * Dave Pare, 1986 + */ + +#ifndef _PROTO_H_ +#define _PROTO_H_ + +#define CLIENTPROTO 2 /* if new things are added, bump this */ + +#define USER 0 +#define COUN 1 +#define QUIT 2 +#define PASS 3 +#define PLAY 4 +#define LIST 5 +#define CMD 6 +#define CTLD 7 +#define WAT 8 +#define KILL 9 +#define GKILL 10 /* kill even if process stuck --ts */ + +#define C_CMDOK 0x0 +#define C_DATA 0x1 +#define C_INIT 0x2 +#define C_EXIT 0x3 +#define C_FLUSH 0x4 +#define C_NOECHO 0x5 +#define C_PROMPT 0x6 +#define C_ABORT 0x7 +#define C_REDIR 0x8 +#define C_PIPE 0x9 +#define C_CMDERR 0xA +#define C_BADCMD 0xB +#define C_EXECUTE 0xC +#define C_FLASH 0xD +#define C_INFORM 0xE +#define C_LAST 0xE + +#endif /* _PROTO_H_ */ diff --git a/include/prototype.h b/include/prototype.h new file mode 100644 index 00000000..68ec07f5 --- /dev/null +++ b/include/prototype.h @@ -0,0 +1,44 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * prototype.h: Various prototype stuff + * + * Known contributors to this file: + * + */ + +/* this stuff ought to be somewhere general... */ +#ifndef _PROTOTYPE_H_ +#define _PROTOTYPE_H_ +#if defined(__cplusplus) || (defined(__STDC__) &&__STDC__) || defined(_WIN32) +#define _PROTO(x) x +#else +#define _PROTO(x) () +#define const +#define volatile +#endif +#endif /* _PROTOTYPE_H_ */ diff --git a/include/prototypes.h b/include/prototypes.h new file mode 100644 index 00000000..9c1c70b9 --- /dev/null +++ b/include/prototypes.h @@ -0,0 +1,997 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * prototypes.h: Prototypes for server functions + * + * Known contributors to this file: + * Curtis Larsen, 1998 + * Steve McClure, 1998,2000 + */ + +#ifndef _PROTOTYPES_H_ +#define _PROTOTYPES_H_ + +#include "misc.h" +#include "empthread.h" +#include "player.h" +#include "commands.h" +#include "common.h" +#include "gen.h" +#include "global.h" +#include "subs.h" +#include "update.h" +#include "empio.h" +#include "commodity.h" + +/* src/server/main.c */ +extern emp_sig_t panic(int sig); +extern emp_sig_t shutdwn(int sig); + +/***************************************************************************** + * src/lib/ * / *.c + *****************************************************************************/ + +/* src/lib/empthread/lwp.c */ +#ifdef _EMPTH_LWP +extern int empth_init (char **ctx, int flags); +extern empth_t *empth_create (int prio, void (*entry)(), int size, + int flags, char *name, char *desc, void *ud); +#if 0 +extern void empth_setctx(void *ctx); +#endif +extern empth_t *empth_self(void); +extern void empth_exit (void); +extern void empth_yield (void); +extern void empth_terminate(empth_t *a); +extern void empth_select(int fd, int flags); +extern void empth_wakeup(empth_t *a); +extern void empth_sleep(long int until); +extern empth_sem_t *empth_sem_create(char *name, int cnt); +extern void empth_sem_signal(empth_sem_t *sm); +extern void empth_sem_wait (empth_sem_t *sm); +extern emp_sig_t empth_alarm(int sig); +#endif /* _EMPTH_LWP */ + +/* src/lib/empthread/pthread.c */ +#ifdef _EMPTH_POSIX +extern void *empth_start(void *ctx); +extern int empth_init (char **ctx_ptr, int flags); +extern empth_t *empth_create (int prio, void (*entry)(), + int size, int flags, + char *name, char *desc, void *ud); +extern empth_t *empth_self(void); +extern void empth_exit (void); +extern void empth_yield (void); +extern void empth_terminate(empth_t *a); +extern void empth_select(int fd, int flags); +extern emp_sig_t empth_alarm(int sig); +extern void empth_wakeup(empth_t *a); +extern void empth_sleep(long until); +extern empth_sem_t *empth_sem_create(char *name, int cnt); +extern void empth_sem_signal(empth_sem_t *sm); +extern void empth_sem_wait (empth_sem_t *sm); +#endif /* _EMPTH_POSIX */ + +/* + * src/lib/commands/ *.c + */ +extern int acce(void ); +extern int add(void ); +extern int anti(void ); +extern int arm(void ); +extern int army(void ); +extern int assa(void ); +extern int atta(void ); +extern int bdes(void ); +extern int best(void ); +extern int boar(void ); +extern int pinflak_planedamage(struct plnstr * , struct plchrstr * , natid , int ); +extern int bomb(void ); +extern int brea(void ); +extern s_char * dotsprintf(s_char * , s_char * , int ); +extern int goodsect(char ); +extern void prexpense(long , int * , s_char , int ); +extern int budg(void ); +extern int buil(void ); +extern int buy(void ); +extern int check_market(void ); +extern int capi(void ); +extern int carg(void ); +extern int lcarg(void ); +extern int cede_sect(struct nstr_sect * , natid ); +extern void grab_sect(register struct sctstr * , natid ); +extern int cede_ship(struct nstr_item * , natid ); +extern void grab_ship(register struct shpstr * , natid ); +extern int cede(void ); +extern int cens(void ); +extern void set_coastal(struct sctstr * ); +extern int chan(void ); +extern int coas(void ); +extern int coll(void ); +extern int comm(void ); +extern int cons(void ); +extern long do_conv(struct nstr_sect , int , int ); +extern int conv(void ); +extern int coun(void ); +extern int cuto(void ); +extern int decl(void ); +extern int deli(void ); +extern long do_demo(struct natstr * , struct nstr_sect , int , s_char * , int ); +extern int demo(void ); +extern long do_desi(struct natstr * , s_char * , s_char * , long , int ); +extern int desi(void ); +extern int disa(void ); +extern int diss(void ); +extern int dist(void ); +extern int drop(void ); +extern int dump(void ); +extern int echo(void ); +extern int doland(s_char , int , struct sctstr * ); +extern int docountry(s_char , int , s_char * , float , natid , struct natstr * ); +extern int doship(s_char , int , s_char * , struct shpstr * ); +extern int dounit(s_char , int , s_char * , struct lndstr * ); +extern int doplane(s_char , int , s_char * , struct plnstr * ); +extern int edit(void ); +extern int getin(s_char * * , s_char * * , int * , s_char *); +extern int errcheck(int , int , int ); +extern int enab(void ); +extern int enli(void ); +extern int explore(void ); +extern int fina(void ); +extern int flash(void ); +extern int sendmessage(struct natstr * , struct natstr * , char * , int ); +extern int wall(void ); +extern int flee(void ); +extern int fly(void ); +extern int foll(void ); +extern int force(void ); +extern int fort(void ); +extern int is_engineer(int , int ); +extern int fuel(void ); +extern int give(void ); +extern int grin(void ); +extern int hard(void ); +extern int head(void ); +extern int hidd(void ); +extern int improve(void ); +extern int info(void ); +extern int apro(void ); +extern int land(void ); +extern int laun(void ); +extern int ldump(void ); +extern int ledg(void ); +extern int leve(void ); +extern void gift(int , int , s_char * , int , s_char * ); +extern int load(void ); +extern int lload(void ); +extern int look(void ); +extern int llook(void ); +extern int lost(void ); +extern int lstats(void ); +extern int ltend(void ); +extern int map(void ); +extern int march(void ); +extern int mark(void ); +extern int display_mark(s_char * ); +extern int quiet_bigdef(int , struct emp_qelem * , natid , natid , coord , coord , int * ); +extern int multifire(void ); +extern void use_ammo(struct emp_qelem * ); +extern void do_defdam(struct emp_qelem * , double ); +extern void add_to_fired_queue(struct emp_qelem * , struct emp_qelem * ); +extern int mine(void ); +extern int landmine(void ); +extern int mission(void ); +extern int mobq(void ); +extern int mobupdate(void); +extern int morale(void ); +extern int move(void ); +extern int want_to_abandon(struct sctstr * , int , int, struct lndstr * ); +extern int would_abandon(struct sctstr * , int , int, struct lndstr * ); +extern int mult(void ); +extern int name(void ); +extern int nati(void ); +extern int navi(void ); +extern int nav_map(int , int , int ); +extern int ndump(void ); +extern int new(void ); +extern int deity_build_land(int , coord , coord , natid , int ); +extern int newe(void ); +extern int news(void ); +extern int nuke(void ); +extern int offe(void ); +extern int offs(void ); +extern int orde(void ); +extern int qorde(void ); +extern int sorde(void ); +extern int orig(void ); +extern int para(void ); +extern int path(void ); +extern int pdump(void ); +extern int plan(void ); +extern int play(void ); +extern int powe(void ); +extern int set_target(s_char * , int * ); +extern int count_pop(register int ); +extern int prod(void ); +extern int pstat(void ); +extern int rada(void ); +extern int range(void ); +extern int lrange(void ); +extern int rea(void ); +extern int real(void ); +extern int reco(void ); +extern int reje(void ); +extern int rela(void ); +extern int repa(void ); +extern int repo(void ); +extern int rese(void ); +extern int reso(void ); +extern int retr(void ); +extern int lretr(void ); +extern int rout(void ); +extern int sail(void ); +extern int sate(void ); +extern int scra(void ); +extern int scuttle_tradeship(struct shpstr *, int); +extern int scut(void ); +extern void scuttle_ship(struct shpstr * ); +extern void scuttle_land(struct lndstr * ); +extern int sdump(void ); +extern int sct(void ); +extern int sell(void ); +extern int set(void ); +extern int setres(void ); +extern int setsector(void ); +extern void resnoise(struct sctstr *sptr, int public_amt, s_char *name, int old, int new); +extern int shar(void ); +extern int shark(void ); +extern int shi(void ); +extern int shoo(void ); +extern int show(void ); +extern int shut(void ); +extern int sinfra(void ); +extern int skyw(void ); +extern int line_of_sight(s_char **rad, int ax, int ay, int bx, int by); +extern int sona(void ); +extern int blankrow(s_char * ); +extern void plane_sona(struct emp_qelem * , int , int , struct shiplook * ); +extern int spy(void ); +extern int num_units(int , int ); +extern void prunits(int , int ); +extern void prplanes(int , int ); +extern int sstat(void ); +extern int start(void ); +extern int stop(void ); +extern int stre(void ); +extern int starve(void ); +extern int supp(void ); +extern int surv(void ); +extern int swaps(void ); +extern void print_res(struct sctstr * ); +extern int tele(void ); +extern int tend(void ); +extern int tend_nxtitem(struct nstr_item * , caddr_t ); +extern int terr(void ); +extern int thre(void ); +extern int togg(void ); +extern void anti_torp(int , int , int ); +extern void fire_dchrg(struct shpstr * , struct shpstr * , int , int ); +extern s_char * prsub(struct shpstr * ); +extern int torp(void ); +extern int canshoot(struct shpstr * , struct shpstr * ); +extern int cantorp(struct shpstr * , struct shpstr * ); +extern int fire_torp(struct shpstr * , struct shpstr * , int , int ); +extern int candchrg(struct shpstr * , struct shpstr * ); +extern int trad(void ); +extern int check_trade(void ); +extern int ontradingblock(int , int * ); +extern void trdswitchown(int , int * , int ); +extern int tran(void ); +extern int trea(void ); +extern int turn(void ); +extern int upda(void ); +extern int upgr(void ); +extern int supgr(void ); +extern int pupgr(void ); +extern int lupgr(void ); +extern int vers(void ); +extern int wai(void ); +extern int wing(void ); +extern int wipe(void ); +extern int work(void ); +extern int buildeff(struct sctstr * , int , double * ); +extern int zdon(void ); + +/* + * src/lib/common/ *.c + */ +/* bestpath.c */ +extern s_char * bestownedpath(s_char * , s_char * , int , int , int , + int , s_char * , int ); +/* bridgefall.c */ +extern void bridgefall(struct sctstr * , struct emp_qelem *); +extern void knockdown(struct sctstr *, struct emp_qelem *); +/* damage.c */ +extern void landdamage(struct lndstr * , int ); +extern void ship_damage(struct shpstr * , int ); +extern int damage(register int , int ); +extern void shipdamage(struct shpstr * , int ); +extern void land_damage(struct lndstr * , int ); +extern void planedamage(struct plnstr * , int ); +extern int nukedamage(struct nchrstr * , int , int ); +extern int effdamage(register int , int ); +extern int commdamage(register int , int , int ); +/* check.c */ +extern int check_sect_ok(struct sctstr *); +extern int check_ship_ok(struct shpstr *); +extern int check_land_ok(struct lndstr *); +extern int check_nuke_ok(struct nukstr *); +extern int check_plane_ok(struct plnstr *); +extern int check_comm_ok(struct comstr *); +extern int check_loan_ok(struct lonstr *); +/* fsize.c */ +extern int fsize(int ); +extern int blksize(int ); +extern time_t fdate(int ); +extern void filetruncate(s_char * ); +/* getvar.c */ +extern int getvar(int , s_char * , int ); +extern int getvec(int , int * , s_char * , int ); +extern int putvar(int , int , s_char * , int ); +extern int putvec(int , int * , s_char * , int ); +/* hap_fact.c */ +extern double hap_fact(struct natstr * , struct natstr * ); +/* hours.c */ +extern int gamehours(time_t , int * ); +/* land.c */ +extern int has_units(coord , coord , natid, struct lndstr * ); +extern int has_units_with_mob(coord , coord , natid ); +extern int adj_units(coord , coord , natid ); +/* log.c */ +extern void loginit(void ); +extern void logerror(s_char *, ...); +extern void filelogerror(s_char *, ...); +/* maps.c */ +extern int draw_map(int , s_char , int , struct nstr_sect * , int ); +extern int bmnxtsct(register struct nstr_sect * ); +extern void bitinit2(struct nstr_sect * , u_char * , int ); +extern int unit_map(int , int , struct nstr_sect * , s_char * ); +extern int bmaps_intersect(natid , natid ); +extern int share_bmap(natid , natid , struct nstr_sect * , s_char , + s_char * ); +/* move.c */ +extern double sector_mcost(struct sctstr * , int ); +/* nstr_subs.c */ +extern s_char * decodep(long , void * ); +extern int decode(natid , long , void * , int ); +extern int nstr_exec(struct nscstr * , register int , void * , int ); +/* path.c */ +extern s_char * bp_init(void ); +extern int best_path(struct sctstr * , struct sctstr * , s_char * , int); +extern void bp_enable_cachepath(); +extern void bp_disable_cachepath(); +extern void bp_clear_cachepath(); +extern s_char * BestDistPath(s_char * , struct sctstr * , struct sctstr * , + double * , int ); +extern s_char * BestLandPath(s_char * , struct sctstr * , struct sctstr * , + double * , int ); +extern s_char * BestShipPath(s_char *, int, int, int, int, int); +extern s_char * BestAirPath(s_char *, int, int, int, int); +extern double pathcost(struct sctstr * , s_char * , int ); +/* res_pop.c */ +extern int max_pop(float , struct sctstr * ); +/* sectdamage.c */ +extern int sect_damage(struct sctstr * , int, struct emp_qelem * ); +extern int sectdamage(struct sctstr * , int, struct emp_qelem * ); +/* snxtit_subs.c */ +extern void snxtitem_area(register struct nstr_item * , int, struct range *); +extern void snxtitem_dist(register struct nstr_item * , int , int, int, int); +extern void snxtitem_xy(register struct nstr_item * , int , coord , coord ); +extern void snxtitem_all(register struct nstr_item * , int ); +extern void snxtitem_group(register struct nstr_item * , int , s_char ); +extern void snxtitem_rewind(struct nstr_item * ); +extern int snxtitem_list(register struct nstr_item * , int , int * , int ); +/* snxtsect_subs.c */ +extern void snxtsct_area(register struct nstr_sect * , struct range * ); +extern void xydist_range(coord , coord , register int , struct range * ); +extern void xysize_range(register struct range * ); +extern void snxtsct_all(struct nstr_sect * ); +extern void snxtsct_rewind(struct nstr_sect * ); +extern void snxtsct_dist(register struct nstr_sect * , coord , coord , int); +/* stmtch.c */ +extern int stmtch(register s_char * , s_char * , int , int ); +extern int mineq(register s_char * , register s_char * ); +/* type.c */ +extern int typematch(s_char * , int ); +/* vlist.c */ +extern int vl_find(register int , u_char * , u_short * , int ); +extern int vl_set(register int , u_int , u_char * , u_short * , + u_char * , int ); +extern int vl_damage(register int , register u_char * , register u_short *, + register int ); +extern int vl_getvec(register u_char * , register u_short * , register int, + register int , register int * ); +extern int vl_setvec(register u_char * , register u_short * , u_char * , + int , register int , register int * ); +/* wantupd.c */ +extern int demand_update_want(int * , int * , int ); +extern int update_maxmissed(void ); +extern int demandupdatecheck(void ); +extern int update_between(void ); +extern int updatetime(time_t * ); +extern void demand_update_info(int * , int * , int * , int * ); +extern void next_update_time(time_t * , time_t * , time_t * ); +extern void next_update_check_time(time_t * , time_t * , time_t * ); +extern int updates_disabled(void ); + +/* + * src/lib/gen/ *.c + */ +/* emp_config.c */ +extern int emp_config (char *file); +extern void print_config (FILE *fp); + +extern int atoip(s_char * * ); +extern int atopi(s_char * ); +extern int roll(int ); +extern int roundavg(double ); +extern int chance(double ); +extern s_char * copy(register s_char * , register s_char * ); +extern void disassoc(void ); +extern int getfdtablesize(void ); +extern void setfdtablesize(int , int ); +extern s_char * getstarg(s_char * , s_char * , s_char * ); +extern s_char * getstring(s_char * , s_char * ); +extern int ifloor(double ); +extern int iceil(double ); +#if !defined(_WIN32) +extern s_char * inet_ntoa(struct in_addr ); +#endif +extern int file_lock(int ); +extern int file_unlock(int ); +extern int deltax(int , int ); +extern int deltay(int , int ); +extern int mapdist(int , int , int , int ); +extern int mapdsq(int , int , int , int ); +extern double dmin(double , double ); +#if !defined(_WIN32) +extern int max(int , int ); +extern int min(int , int ); +#endif +extern double dmax(double , double ); +extern s_char * numstr(s_char * , int ); +extern s_char * effadv(int ); +extern int onearg(s_char * , s_char * ); +extern int parse(register s_char * , s_char * * , s_char * * , s_char * , + s_char * * ); +extern s_char * esplur(int ); +extern s_char * splur(int ); +extern s_char * iesplur(int ); +extern s_char * plur(int , s_char * , s_char * ); +extern int ldround(double , int ); +extern int roundintby(int , int ); +extern int same(register s_char * , register s_char * ); +extern int scthash(register int , register int , int ); +extern void blocksig(void ); +extern void unblocksig(void ); +extern const s_char * signame(int ); +#ifdef NOSTRDUP +extern char *strdup(char *x); +#endif +extern int strscan(s_char *target, s_char *string); + + +/* + * src/lib/global/ *.c + */ +extern void global_init(void ); +extern void init_pchr(void ); +extern void init_mchr(void ); +extern void init_plchr(void ); + + + +/* + * src/lib/player/ *.c + */ +/* accept.c */ +extern void player_init(void ); +extern struct player * player_new(int , struct sockaddr_in * ); +extern struct player * player_delete(struct player * ); +extern struct player * player_next(struct player * ); +extern struct player * player_prev(struct player * ); +extern struct player * getplayer(natid ); +extern struct player * player_find_other(struct player * , register natid ); +extern void player_wakeup_all(natid ); +extern void player_wakeup(struct player * ); +extern void player_accept(void * ); +/* dispatch.c */ +extern int dispatch(s_char * , s_char * ); +/* empdis.c */ +extern int getcommand(s_char * ); +extern void init_player_commands(void ); +extern void log_last_commands(void ); +extern int explain(void ); +extern int gamedown(void ); +extern void daychange(time_t ); +extern void getconstants(void ); +extern int getminleft(time_t , int * , int * ); +/* empmod.c */ +/* init_nats.c */ +extern int init_nats(void ); +extern int nat_cap(int ); +/* login.c */ +extern void player_login(void * ); +extern int client_cmd(struct player * , int , char * * ); +extern int user_cmd(struct player * , int , char * * ); +extern int sanc_cmd(struct player * , int , char * * ); +extern int coun_cmd(struct player * , int , char * * ); +extern int pass_cmd(struct player * , int , char * * ); +extern int play_cmd(struct player * , int , char * * ); +extern int kill_cmd(struct player * , int , char * * ); +extern int list_cmd(struct player * , int , char * * ); +extern int quit_cmd(struct player * , int , char * * ); +/* nat.c */ +extern int natbyname(s_char * , natid * ); +extern int natpass(int , s_char * ); +/* player.c */ +extern struct player *player; /* current player's context */ +extern s_char * praddr(struct player * ); +extern void player_main(struct player * ); +extern int show_motd(void ); +extern int match_user(char * , struct player * ); +extern int status(void ); +extern int command(void ); +extern int execute(void ); +extern int quit(void ); +/* recvclient.c */ +extern int recvclient(s_char * , int ); + +/* + * src/lib/subs/ *.c + */ +/* askyn.c */ +extern int confirm(s_char * ); +extern int askyn(s_char * ); +/* bsanct.c */ +extern void bsanct(void ); +/* caploss.c */ +extern void caploss(struct sctstr * , natid , s_char * ); +/* chkmoney.c */ +extern int chkmoney(long , long , s_char * ); +extern int check_cost(int , int , long , int * , s_char * ); +/* cnumb.c */ +extern int cnumb(s_char * ); +/* control.c */ +extern int military_control(struct sctstr * ); +/* detonate.c */ +extern int detonate(struct plnstr * , int , int ); +/* disloan.c */ +extern int disloan(int , register struct lonstr * ); +/* distrea.c */ +extern int distrea(int , register struct trtstr * ); +/* fileinit.c */ +extern void ef_init(void ); +/* fortdef.c */ +extern int sd(natid , natid , coord , coord , int , int , int ); +extern int dd(natid , natid , coord , coord , int , int ); +extern int sb(natid , natid , struct sctstr * , coord , coord , int, int); +extern int shipdef(natid , natid , coord , coord ); +/* getbit.c */ +extern int emp_getbit(int , int , u_char * ); +extern void emp_setbit(int , int , u_char * ); +extern void emp_setbitmap(int ,int, u_char *, int *); +extern void emp_bitinit(struct nstr_sect * , u_char * ); +/* getele.c */ +extern int getele(s_char * , s_char * ); +/* land.c */ +extern s_char * prland(struct lndstr * ); +extern int lnd_postread(int, s_char * ); +extern int lnd_prewrite(int , s_char * ); +extern void lnd_init(int , s_char * ); +/* landgun.c */ +extern double seagun(int , int ); +extern double landgun(int , int ); +extern double landunitgun(int, int, int, int, int ); +extern int roundrange(double ); +/* list.c */ +extern int shipsatxy(coord , coord , int , int ); +extern int carriersatxy(coord , coord , int , int , natid ); +extern int unitsatxy(coord , coord , int , int ); +extern int planesatxy(coord , coord , int , int, struct emp_qelem * ); +extern int asw_shipsatxy(coord , coord , int , int , struct plnstr * , + struct shiplook * ); +extern int num_shipsatxy(coord , coord , int , int ); +extern int islist(s_char * ); +/* src/lib/subs/mission.c */ +extern s_char * mission_name(short ); +extern s_char * nameofitem(s_char * , struct genitem * , int ); +extern int collateral_damage(coord , coord , int , struct emp_qelem *); +extern int dosupport(struct genlist * , coord , coord , natid , natid ); +extern void build_mission_list(struct genlist * , coord, coord, int, natid ); +extern void build_mission_list_type(struct genlist *, coord, coord, int, int, + natid); +extern int perform_mission(coord , coord , natid , struct emp_qelem * , + int , s_char * , int ); +extern void mission_pln_sel(struct emp_qelem * , int , int , int ); +extern int mission_pln_arm(struct emp_qelem * , coord , coord , int , + int , struct ichrstr * , int , int , int * ); +extern int mission_pln_equip(struct plist * , struct ichrstr *, int, s_char); +extern int find_airport(struct emp_qelem * , coord , coord ); +extern void add_airport(struct emp_qelem * , coord , coord ); +extern void divide(struct emp_qelem * , struct emp_qelem * , coord , coord); +extern int air_damage(struct emp_qelem * , coord , coord , int , natid , + s_char *, int); +extern int ground_interdict(coord , coord , natid , s_char * ); +extern int unit_interdict(coord , coord , natid , s_char * , int , int ); +extern int off_support(coord , coord , natid , natid ); +extern int def_support(coord , coord , natid , natid ); +extern int oprange(struct genitem * , int , int * ); +extern void find_escorts(coord , coord , natid , struct emp_qelem * ); +extern int cando(int , int ); +extern s_char * mission_short_name(int ); +extern void show_mission(int , struct nstr_item * ); +extern int air_defense(coord , coord , natid , struct emp_qelem * , + struct emp_qelem * ); +/* move.c */ +extern int move_map(s_char * , coord , coord , s_char * ); +extern int check_lmines(coord , coord , double ); +extern int move_ground(s_char * , struct sctstr * , struct sctstr * , + double , double , s_char * , + int (* )(s_char *, coord , coord , s_char *) , + int , int * ); +extern int fly_map(coord , coord ); +/* mslsub.c */ +extern int msl_intercept(coord , coord , natid , int , int , int , int ); +extern int msl_equip(struct plnstr * ); +extern int msl_hit(struct plnstr * , int , int , int , int , s_char * , + coord , coord , int ); +extern void msl_sel(struct emp_qelem * , coord , coord , natid , int , + int , int ); +extern int msl_launch_mindam(struct emp_qelem * , coord , coord , int , + int , int , s_char * , int , int ); +/* mtch.c */ +extern int intmatch(register int , register int * , int ); +extern int comtch(register s_char * , struct cmndstr * , int , int ); +/* natarg.c */ +extern int natarg(s_char * , s_char * ); +/* neigh.c */ +extern int neigh(coord , coord , natid ); +/* nreport.c */ +extern void nreport(natid , int , natid , int ); +extern void filereport(int , int , int , int ); +/* nuke.c */ +extern int nuk_postread(int, s_char * ); +extern int nuk_prewrite(int , s_char * ); +extern void nuk_init(int , s_char * ); +extern void nuk_add(coord , coord , int , int ); +extern void nuk_delete(struct nukstr * , int , int ); +/* nxtitem.c */ +extern int nxtitem(struct nstr_item * , caddr_t ); +/* nxtsct.c */ +extern int nxtsct(register struct nstr_sect * , struct sctstr * ); +/* plane.c */ +extern s_char * prplane(struct plnstr * ); +extern int pln_postread(int, s_char * ); +extern int pln_prewrite(int , s_char * ); +extern void pln_init(int , s_char * ); +/* plnsub.c */ +extern void count_planes(struct shpstr * ); +extern int pln_equip(struct plist * , struct ichrstr * , int , s_char ); +extern int pln_onewaymission(struct sctstr * , int * , int * ); +extern void pln_newlanding(struct emp_qelem * , coord , coord , int ); +extern int can_be_on_ship(int , int ); +extern int put_plane_on_ship(struct plnstr * , struct shpstr * ); +extern void pln_dropoff(struct emp_qelem * , struct ichrstr * , coord , + coord , s_char * , int ); +extern void pln_sel(struct nstr_item * , struct emp_qelem * , + struct sctstr * , int , int , int , int ); +extern int pln_arm(struct emp_qelem * , int , int , struct ichrstr * , + int , int , int * ); +extern int pln_mobcost(int , struct plnstr * , int ); +extern void pln_put(struct emp_qelem * ); +extern void pln_removedupes(struct emp_qelem * , struct emp_qelem * ); +extern int take_plane_off_ship(struct plnstr * , struct shpstr * ); +extern int take_plane_off_land(struct plnstr * , struct lndstr * ); +extern void plane_sweep(struct emp_qelem * , coord , coord ); +extern void count_land_planes(struct lndstr * ); +extern int count_sect_planes(struct sctstr * ); +extern int put_plane_on_land(struct plnstr * , struct lndstr * ); +extern int pln_hitchance(struct plnstr * , int , int ); +extern int pln_damage(struct plnstr * , coord , coord , s_char , int *, int ); +extern int pln_identchance(struct plnstr * , int , int ); +/* pr.c */ +extern void pr(s_char *, ...); +extern void prnf(s_char *buf); +extern void pr_id(struct player *, int, s_char *, ...); +extern void pr_flash(struct player *, s_char *, ...); +extern void pr_inform(struct player *, s_char *, ...); +extern void pr_wall(s_char *, ...); +extern void pr_player(struct player *pl, int id, s_char *buf); +extern void pr_hilite(s_char *buf); +extern void outid(struct player *pl, int n); +extern void prredir(s_char *redir); +extern void prexec(s_char *file); +extern void prprompt(int min, int btu); +extern void showvers(int vers); +extern int prmptrd(s_char *prompt, s_char *str, int size); +extern void prdate(void); +extern void prxy(s_char *format, coord x, coord y, natid country); +extern void PR(int, s_char *, ...); +extern void PRdate(natid cn); +extern void pr_beep(void); +extern void mpr(int, s_char *, ...); + +/* radmap.c */ +extern void radmap2(int, int , int , int , int , double , int ); +extern int deltx(struct range * , coord ); + /* Prototype include a typedef name. + It should be moved after the typedef declaration */ +extern int delty(struct range * , coord ); + /* Prototype include a typedef name. + It should be moved after the typedef declaration */ +extern void radmap(int , int , int , int , double ); +extern void radmapnopr(int , int , int , int , double ); +extern void radmapupd(int, int , int , int , int , double ); +/* rej.c */ +extern int setrel(natid , natid , int ); +extern int setcont(natid , natid , int ); +extern int setrej(natid , natid , int , int ); +/* retreat.c */ +extern void retreat_ship(struct shpstr * , s_char ); +extern int retreat_ship1(struct shpstr * , s_char , int ); +extern int findcondition(s_char ); +extern void retreat_land(struct lndstr * , s_char ); +extern int retreat_land1(struct lndstr * , s_char , int ); +extern int check_retreat_and_do_shipdamage(struct shpstr * , int ); +extern int check_retreat_and_do_landdamage(struct lndstr * , int ); +/* sarg.c */ +extern int sarg_type(s_char * ); +extern int sarg_xy(s_char * , coord * , coord * ); +extern int sarg_getrange(s_char * , register struct range * ); +extern int sarg_area(s_char * , register struct range * ); +extern int sarg_range(s_char * , coord * , coord * , int * ); +extern int sarg_list(s_char * , register int * , int ); +/* satmap.c */ +extern void satdisp(struct sctstr * , int , int ); +extern void satmap(int , int , int , int , int , int ); +extern void sathead(void ); +/* sect.c */ +extern int sct_postread(int, s_char * ); +extern int checksect(struct sctstr * ); +extern int sct_prewrite(int , s_char * ); +extern int issector(s_char * ); +extern void sct_init(coord , coord , s_char * ); +/* ship.c */ +extern s_char * prship(struct shpstr * ); +extern int shp_postread(int, s_char * ); +extern int shp_prewrite(int , s_char * ); +extern void shp_init(int , s_char * ); +/* show.c */ +extern void sort_lookup_list(void ); +extern void show_bridge(int ); +extern void show_tower(int ); +extern void show_nuke_stats(int ); +extern void show_nuke_capab(int ); +extern void show_nuke_build(int ); +extern void show_ship_build(int ); +extern void show_ship_stats(int ); +extern void show_ship_capab(int ); +extern void show_plane_stats(int ); +extern void show_plane_capab(int ); +extern void show_plane_build(int ); +extern void show_land_build(int ); +extern void show_land_capab(int ); +extern void show_land_stats(int ); +extern void show_sect_build(int ); +extern void show_sect_stats(int ); +extern void show_sect_capab(int ); +/* shpsub.c */ +extern void shp_sel(struct nstr_item * , struct emp_qelem * ); +extern void shp_nav(struct emp_qelem * , double * , double * , int * , + natid ); +extern int shp_check_one_mines(struct mlist *); +extern int shp_sweep(struct emp_qelem * , int , natid ); +extern int shp_interdict(struct emp_qelem * , coord , coord , natid ); +extern void shp_mess(s_char * , struct mlist * ); +extern int shp_check_mines(struct emp_qelem * ); +extern int shp_check_nav(struct sctstr * ); +extern s_char * shp_path(int , struct shpstr * , s_char * ); +extern void shp_put(struct emp_qelem * , natid ); +extern int shp_hit_mine(struct shpstr * , struct mchrstr * ); +extern void shp_list(struct emp_qelem * ); +extern int shp_hardtarget(struct shpstr * ); +extern void shp_view(struct emp_qelem * ); +extern int shp_nav_one_sector(struct emp_qelem * , int , natid , int ); +extern int shp_missile_defense(coord , coord , natid , int ); +extern void shp_missdef(struct shpstr * , natid ); +/* snxtitem.c */ +extern int snxtitem(register struct nstr_item * , int , s_char * ); +/* snxtsct.c */ +extern int snxtsct(register struct nstr_sect * , s_char * ); +/* supply.c */ +extern void resupply_all(struct lndstr * ); +extern void resupply_commod(struct lndstr * , int ); +extern int get_minimum(struct lndstr * , int ); +extern int supply_commod(int , int , int , int , int ); +extern int s_commod(int , int , int , int , int , int ); +extern int try_supply_commod(int , int , int , int , int ); +extern s_char * itemname(int ); +extern int at_minimum(struct lndstr * , int ); +extern int has_supply(struct lndstr * ); +extern int use_supply(struct lndstr * ); +/* takeover.c */ +extern void takeover_land(register struct lndstr * , natid , int ); +extern void takeover(register struct sctstr * , natid ); +extern void takeover_ship(register struct shpstr * , natid , int ); +/* trdsub.c */ +extern int trade_check_ok(int, struct trdstr *, union trdgenstr *); +extern s_char * trade_nameof(struct trdstr * , union trdgenstr * ); +extern int trade_desc(struct trdstr * , union trdgenstr * ); +extern int trade_getitem(struct trdstr * , union trdgenstr * ); +extern long get_couval(int ); +extern long get_outstand(int ); +extern struct ichrstr * whichitem(char ); +/* trechk.c */ +extern int trechk(register natid , register natid , int ); +/* whatitem.c */ +extern struct ichrstr * whatitem(s_char * , s_char * ); +/* wire.c */ +extern int typed_wire(natid , natid , s_char * , int ); +/* wu.c */ +extern void clear_telegram_is_new(natid ); +extern int typed_wu(natid , natid , s_char * , int ); +extern int wu(natid, natid, s_char *, ...); + +/* + * src/lib/update/ *.c + */ +/* age.c */ +extern void age_levels(int ); +/* anno.c */ +extern void delete_old_announcements(void ); +/* bp.c */ +extern void fill_update_array(int * , struct sctstr * ); +extern int * get_wp(int * , struct sctstr * , int ); +extern int gt_bg_nmbr(int * , struct sctstr * , int ); +extern void pt_bg_nmbr(int * , struct sctstr * , int , int ); +/* deliver.c */ +extern int deliver(register struct sctstr * , struct ichrstr * , int , int , int , int ); +/* distribute.c */ +extern int dodistribute(struct sctstr * , int , s_char * , double , double ); +/* finish.c */ +extern void finish_sects(int ); +/* human.c */ +extern int do_feed(register struct sctstr * , register struct natstr * , + int * , int * , int * , int ); +extern int growfood(struct sctstr * , register int * , int , int ); +extern int feed_people(register int * , int , int * ); +extern void starvation(struct sctstr * ); +extern int grow_people(struct sctstr * , register int , + register struct natstr * , int * , int , + register int * ); +extern void trunc_people(struct sctstr * , register struct natstr * , + register int * ); +/* land.c */ +extern void upd_land(register struct lndstr * , int , register int , struct natstr * , int * , int ); +extern int prod_land(int , int , int * , int ); +extern int landrepair(register struct lndstr * , int * , struct natstr * , int * , int ); +extern int feed_land(struct lndstr * , register int * , int , int * , int ); +extern int plague_land(struct lndstr * , struct natstr * , register int * , register int * , int ); +/* main.c */ +extern void update_main(void * ); +extern void do_prod(int , int , int , int * , long int (*)[2] , int * , int * , int * , int * , int * , int * ); +/* material.c */ +extern void get_materials(struct sctstr * , int * , int * , int ); +/* mobility.c */ +extern void mob_sect(register int ); +extern void do_mob_sect(register struct sctstr * , register int ); +extern void mob_ship(register int ); +extern void do_mob_ship(register struct shpstr * , register int ); +extern void mob_land(register int ); +extern void do_mob_land(register struct lndstr * , register int ); +extern void mob_plane(register int ); +extern void do_mob_plane(register struct plnstr * , register int ); +extern void do_mob_sect(register struct sctstr *sp, register int etus); +extern void update_all_mob(void); +extern void update_timestamps(time_t offset); +extern void sct_do_upd_mob(register struct sctstr *sp); +extern void shp_do_upd_mob(register struct shpstr *sp); +extern void lnd_do_upd_mob(register struct lndstr *lp); +extern void pln_do_upd_mob(register struct plnstr *pp); +/* move_sat.c */ +extern void move_sat(register struct plnstr * ); +/* nat.c */ +extern double logx(double , double ); +extern double limit_level(double , int , int ); +extern void prod_nat(int ); +extern void share_incr(register double * , register double * ); +/* nav_ship.c */ +extern void scuttle_it(register struct shpstr * ); +extern void swap(register struct shpstr * ); +extern int nav_ship(register struct shpstr * ); +/* nav_util.c */ +extern int check_nav(struct sctstr * ); +extern int load_it(register struct shpstr * , register struct sctstr * , int ); +extern int com_num(s_char * ); +extern void unload_it(register struct shpstr * ); +extern void auto_fuel_ship(register struct shpstr * ); +/* nxtitemp.c */ +extern s_char * nxtitemp(struct nstr_item * , int ); +/* nxtsctp.c */ +extern struct sctstr * nxtsctp(register struct nstr_sect * ); +/* plague.c */ +extern void do_plague(struct sctstr * , struct natstr * , int ); +extern int infect_people(struct natstr * , register int * , u_int , int , struct sctstr *); +extern int plague_people(struct natstr * , register int * , register int * , int ); +/* plane.c */ +extern int prod_plane(int , int , int * , int ); +/* populace.c */ +extern void populace(struct natstr * , register struct sctstr * , register int * , int ); +extern int total_work(register int , register int , register int , register int , register int ); +/* prepare.c */ +extern void tax(struct sctstr * , struct natstr * , int , long * , int * , int * , int * ); +extern int upd_slmilcosts(natid , int ); +extern void prepare_sects(int , int * ); +extern int bank_income(struct sctstr * , int ); +/* produce.c */ +extern int produce(struct natstr * , struct sctstr * , int * , int , int , int , int , int * , int * ); +extern int materials_cost(struct pchrstr * , register int * , int * ); +extern void materials_charge(struct pchrstr * , register int * , register int ); +/* removewants.c */ +extern int update_removewants(void ); +/* revolt.c */ +extern void take_casualties(struct sctstr * , int ); +extern void revolt(struct sctstr * ); +extern void guerrilla(struct sctstr * ); +/* sail.c */ +extern void fltp_to_list(struct fltheadstr * , struct emp_qelem * ); +extern void sail_ship(natid ); +/* sect.c */ +extern int dodeliver(struct sctstr * , int * ); +extern int upd_buildeff(struct natstr * , register struct sctstr * , int * , int * , int , int * , int , int * ); +extern int enlist(register int * , int , int * ); +extern void meltitems(int , int , int , int * , int , int , int , int ); +extern void do_fallout(register struct sctstr * , register int ); +extern void spread_fallout(struct sctstr * , int ); +extern void decay_fallout(struct sctstr * , int ); +extern void produce_sect(int natnum, int etu, int *bp, long int (*p_sect)[2], + int sector_type); +/* ship.c */ +extern void upd_ship(register struct shpstr * , int , register int , struct natstr * , int * , int ); +extern int prod_ship(int , int , int * , int ); +extern int shiprepair(register struct shpstr * , int * , struct natstr * , int * , int ); +extern int feed_ship(struct shpstr * , register int * , int , int * , int ); + +/* + * src/server + */ +/* shutdown.c */ +extern void shutdown_init(void); +extern void shutdown_sequence(int argc, s_char **argv); + +#endif /* _PROTOTYPES_H_ */ diff --git a/include/queue.h b/include/queue.h new file mode 100644 index 00000000..bbc9337f --- /dev/null +++ b/include/queue.h @@ -0,0 +1,48 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * queue.h: Generic vax-like doubly linked list queues + * + * Known contributors to this file: + * + */ + +#ifndef _QUEUE_H_ +#define _QUEUE_H_ + +#define QEMPTY(p) ((p)->q_forw == (p)) + +struct emp_qelem { + struct emp_qelem *q_forw; + struct emp_qelem *q_back; +}; + +extern void emp_remque(struct emp_qelem * ); +extern void emp_initque(struct emp_qelem * ); +extern void emp_insque(struct emp_qelem * , struct emp_qelem * ); + +#endif /* _QUEUE_H_ */ diff --git a/include/retreat.h b/include/retreat.h new file mode 100644 index 00000000..b0c5ac21 --- /dev/null +++ b/include/retreat.h @@ -0,0 +1,50 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * retreat.h: Things having to do with retreating + * + * Known contributors to this file: + * Ken Stevens, 1995 + */ + +#ifndef _RETREAT_H_ +#define _RETREAT_H_ + +#define MAX_RETREAT 2 /* Max number of sectors you can retreat */ +#define RET_LEN 10 + +/* Retreat conditions */ +#define RET_GROUP 1 /* Whole group retreats */ +#define RET_INJURED 2 /* Retreat when damaged at all */ +#define RET_TORPED 4 /* Retreat when torped */ +#define RET_SONARED 8 /* Retreat when sonared */ +#define RET_HELPLESS 16 /* Retreat when fired upon from beyond range */ +#define RET_BOMBED 32 /* Retreat when bombed */ +#define RET_DCHRGED 64 /* Retreat when depth-charged */ +#define RET_BOARDED 128 /* Retreat when unsuccessfully boarded */ + +#endif /* _RETREAT_H_ */ diff --git a/include/sect.h b/include/sect.h new file mode 100644 index 00000000..49d39889 --- /dev/null +++ b/include/sect.h @@ -0,0 +1,202 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * sect.h: Definitions for things having to do with sectors. + * + * Known contributors to this file: + * Dave Pare + * Ken Stevens, 1995 + * Steve McClure, 1998 + */ + + +/* + * each "point" of MAXSCTV costs 32k for 128x128. + * MAXSCTV = 20 ==> 655k for the commodities alone! + * + * If you set this to I_MAX*3, you'll never run ou + * of slots, which is nice. (You'll eat a lot of + * space, tho) + */ + +#ifndef _SECT_H_ +#define _SECT_H_ + +#define MAXSCTV 42 + +/* The order of the following elements is there to match up with genitem */ + +struct sctstr { + short ef_type; + natid sct_own; /* owner's country num */ + short sct_elev; /* elevation/depth */ + coord sct_x; /* x coord of sector */ + coord sct_y; /* y coord of sector */ + u_char sct_type; /* sector type */ + u_char sct_effic; /* 0% to 100% */ + short sct_mobil; /* mobility units */ + u_char sct_loyal; /* updates until civilans "converted" */ + u_char sct_terr; /* territory 0 id # of sector */ + u_char sct_terr1; /* territory 1 id # of sector */ + u_char sct_terr2; /* territory 2 id # of sector */ + u_char sct_terr3; /* territory 3 id # of sector */ + coord sct_dist_x; /* Dist sector */ + coord sct_dist_y; + short sct_avail; /* available workforce for "other things" */ + short sct_flags; /* temporary flags */ + short sct_fill; /* gunk */ + u_char sct_work; /* pct of civ actually working */ + u_char sct_coastal; /* is this a coastal sector? */ + u_char sct_newtype; /* for changing designations */ + u_char sct_min; /* ease of mining ore */ + u_char sct_gmin; /* amount of gold ore */ + u_char sct_fertil; /* fertility of soil */ + u_char sct_oil; /* oil content */ + u_char sct_uran; /* uranium ore content */ + natid sct_oldown; /* old owner of sector (for liberation) */ + u_char sct_updated; /* Has this sect been updated? */ + u_char sct_off; /* Should this sector produce? */ + u_char sct_nv; /* current number of variables */ + u_char sct_vtype[MAXSCTV]; + u_short sct_vamt[MAXSCTV]; + time_t sct_access; /* Last time mob was updated (MOB_ACCESS) */ + u_char sct_road; /* Road value of a sector */ + u_char sct_rail; /* Rail value of a sector */ + u_char sct_defense; /* Defensive value of a sector */ + time_t sct_timestamp; /* Last time this sector was written to */ +}; + +struct dchrstr { + int d_mnem; /* map symbol */ + int d_prd; /* product vtype */ + int d_mcst; /* movement cost */ + int d_flg; /* movement cost */ + int d_pkg; /* type of packaging in these sects */ + float d_ostr; /* offensive strength */ + float d_dstr; /* defensive strength */ + int d_value; /* resale ("collect") value */ + int d_cost; /* cost to designate the sect */ + int d_build; /* cost multiplier for eff */ + int d_lcms; /* lcm's needed per point of eff */ + int d_hcms; /* hcm's needed per point of eff */ + s_char *d_name; /* full name of sector type */ +}; + +#define NPKG 0 /* no special packaging */ +#define WPKG 1 /* "warehouse" packaging */ +#define UPKG 2 /* "urban" packaging */ +#define BPKG 3 /* "bank" packaging */ + +/* for d_flg */ +#define NAVOK 1 /* ships can always navigate */ +#define NAV_02 2 /* requires 2% effic to navigate */ +#define NAV_60 3 /* requires 60% effic to navigate */ + + /* sector types (must agree with order in dchr, empglb.c) */ + +#define SCT_WATER 0 /* basics */ +#define SCT_MOUNT 1 +#define SCT_SANCT 2 +#define SCT_WASTE 3 +#define SCT_RURAL 4 +#define SCT_CAPIT 5 +#define SCT_URAN 6 +#define SCT_PARK 7 +#define SCT_ARMSF 8 /* industries */ +#define SCT_AMMOF 9 +#define SCT_MINE 10 +#define SCT_GMINE 11 +#define SCT_HARBR 12 +#define SCT_WAREH 13 +#define SCT_AIRPT 14 +#define SCT_AGRI 15 +#define SCT_OIL 16 +#define SCT_LIGHT 17 +#define SCT_HEAVY 18 +#define SCT_FORTR 19 /* military/scientific */ +#define SCT_TECH 20 +#define SCT_RSRCH 21 +#define SCT_NUKE 22 +#define SCT_LIBR 23 +#define SCT_HIWAY 24 /* communications */ +#define SCT_RADAR 25 +#define SCT_HEADQ 26 /* headquarters */ +#define SCT_BHEAD 27 /* Bridge head */ +#define SCT_BSPAN 28 /* Bridge span */ +#define SCT_BANK 29 /* financial */ +#define SCT_REFINE 30 /* refinery */ +#define SCT_ENLIST 31 /* enlistment center */ +#define SCT_PLAINS 32 /* plains sector */ +#define SCT_BTOWER 33 /* Bridge tower */ + +#define SCT_EFFIC 34 /* used in update & budget */ +#define SCT_MAXDEF 34 /* highest sector type in header files */ + +#define getsect(x, y, p) \ + ef_read(EF_SECTOR, sctoff((int) x, (int) y), (caddr_t)p) +#define putsect(p) \ + ef_write(EF_SECTOR, sctoff((int) (p)->sct_x, \ + (int) (p)->sct_y), (caddr_t)p) +#define getsectp(x, y) \ + (struct sctstr *) ef_ptr(EF_SECTOR, sctoff((int)x, (int)y)) +#define getsectid(id) \ + (struct sctstr *) ef_ptr(EF_SECTOR, id) + +/* things relating to sectors */ +extern int sctoff(coord x, coord y); +extern double landgun(); + +extern int sct_maxno; +extern struct dchrstr dchr[]; +extern struct dchrstr bigcity_dchr; + +#define MIN_MOBCOST 0.001 /* lowest cost a sector can have to move into */ +#define FORTEFF 5 /* forts must be 5% efficient to fire. */ + +#define MOB_NONE 0 +#define MOB_ROAD 1 +#define MOB_RAIL 2 + +#define INT_ROAD 0 +#define INT_RAIL 1 +#define INT_DEF 2 + +/* Sector flags */ +#define MOVE_IN_PROGRESS bit(0) /* move in progress */ + +/* Each cost is per point of efficency */ +struct sctintrins { + char *in_name; + u_char in_lcms; + u_char in_hcms; + u_char in_dcost; + u_char in_mcost; +}; + +extern struct sctintrins intrchr[]; + +#endif /* _SECT_H_ */ diff --git a/include/ship.h b/include/ship.h new file mode 100644 index 00000000..bebffbbd --- /dev/null +++ b/include/ship.h @@ -0,0 +1,229 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * ship.h: Definitions for things having to do with ships + * + * Known contributors to this file: + * Dave Pare + * Thomas Rushack, 1992 + * Ken Stevens, 1995 + * Steve McClure, 1998 + */ + +#ifndef _SHIP_H_ +#define _SHIP_H_ + +#include "queue.h" +#include "misc.h" +#include "retreat.h" + +#define SHIP_MINEFF 20 + +/* bit masks for the autonav mode flags */ + +/* +#define AN_SAILDIR 1 +#define AN_AUTONAV 2 +#define AN_STANDBY 4 +#define AN_LOADING 8 + */ +#define AN_SAILDIR bit(1) +#define AN_AUTONAV bit(2) +#define AN_STANDBY bit(3) +#define AN_LOADING bit(4) +#define AN_SCUTTLE bit(5) /* Auto-scuttle of trade ships */ + +/* TMAX is the number of cargo holds a ship use in the autonav code. */ +#define TMAX 6 + + +#define MAXSHPV 12 + +#define MAXSHPPATH 28 +#define MAXSHPNAMLEN 24 + +struct shpstr { + short ef_type; + natid shp_own; /* owner's country num */ + short shp_uid; /* unit id (ship #) */ + coord shp_x; /* x location in abs coords */ + coord shp_y; /* y location in abs coords */ + s_char shp_type; /* ship type */ + s_char shp_effic; /* 0% to 100% */ + s_char shp_mobil; /* mobility units */ + short shp_sell; /* pointer to trade file */ + short shp_tech; /* tech level ship was built at */ + s_char shp_fleet; /* group membership */ + coord shp_opx,shp_opy;/* Op sector coords */ + short shp_mission; /* mission code */ + short shp_radius; /* mission radius */ + u_char shp_nplane; /* number of planes on board */ + u_char shp_nland; /* number of land units on board */ + short shp_armor; + short shp_speed; + short shp_visib; + short shp_frnge; + short shp_glim; + coord shp_destx[2]; /* location for ship destination */ + coord shp_desty[2]; + s_char shp_tstart[TMAX]; /* what goods to pick up at start point */ + s_char shp_tend[TMAX]; /* what goods to pick up at end point */ + short shp_lstart[TMAX]; /* How much do we pick up at the start */ + short shp_lend[TMAX]; /* How much do we pick up at the end */ + u_char shp_autonav; /* autonavigation flags */ + s_char shp_nv; /* current number of variables */ + u_char shp_vtype[MAXSHPV]; + u_short shp_vamt[MAXSHPV]; + time_t shp_access; /* Last time mob was updated (MOB_ACCESS) */ + time_t shp_timestamp; /* Last time this ship was touched. */ + u_char shp_mobquota; /* mobility quota */ + s_char shp_path[MAXSHPPATH]; + short shp_follow; + s_char shp_name[MAXSHPNAMLEN]; /* name set with the "name" command */ + u_char shp_fuel; /* How much fuel do we have */ + u_char shp_nchoppers; /* How many choppers on board? */ + u_char shp_nxlight; /* How many xlight planes on board? */ + coord shp_orig_x; + coord shp_orig_y; /* Where we were built */ + natid shp_orig_own; /* Who built us */ + int shp_rflags; /* When do I retreat? */ + s_char shp_rpath[RET_LEN]; /* retreat path */ +}; + +struct fltelemstr { + int num; + int own; + double mobil,mobcost; + struct fltelemstr *next; +}; + +struct fltheadstr { + int leader; + s_char real_q; +/* defines for the real_q member */ +#define LEADER_VIRTUAL 0 +#define LEADER_REAL 1 +#define LEADER_WRONGSECT 2 + coord x,y; + natid own; + unsigned maxmoves; + struct fltelemstr *head; + struct fltheadstr *next; +}; + +struct mchrstr { + u_char m_nv; /* number of variables it can hold */ + u_char m_vtype[MAXCHRNV]; + u_short m_vamt[MAXCHRNV]; + int m_lcm; /* units of lcm to build */ + int m_hcm; /* units of hcm to build */ + int m_armor; /* how well armored it is */ + int m_speed; /* how fast it can go */ + int m_visib; /* how well it can be seen */ + int m_vrnge; /* how well it can see */ + int m_frnge; /* how far it can fire */ + int m_glim; /* how many guns it can fire */ + u_char m_nxlight; /* maximum number of xlight planes */ + u_char m_nchoppers; /* maximum number of choppers */ + u_char m_fuelc; /* fuel capacity */ + u_char m_fuelu; /* fuel used per 10 mob */ + s_char *m_name; /* full name of type of ship */ + int m_tech; /* tech required to build */ + int m_cost; /* how much it costs to build */ + long m_flags; /* what special things can this ship do */ + u_char m_nplanes; /* maximum number of planes this ship holds */ + u_char m_nland; /* maximum number of units this ship holds */ +}; + +#define M_FOOD bit(0) /* catch that fish! */ +#define M_TORP bit(1) /* fire torpedoes */ +#define M_DCH bit(2) /* drop depth charges on subs */ +#define M_FLY bit(3) /* launch and recover planes */ +/* M_MSL will be automatically set in init_global() if m_nplanes > 0 + and M_FLY is not set */ +#define M_MSL bit(4) /* launch missiles */ +#define M_OIL bit(5) /* drill for oil */ +#define M_SONAR bit(6) /* locate submarines */ +#define M_MINE bit(7) /* drop mines */ +#define M_SWEEP bit(8) /* clean up the mines */ +#define M_SUB bit(9) /* a submarine */ +#define M_SPY bit(10) /* gather intelligence info */ +#define M_LAND bit(11) /* allows full landing ability */ +#define M_SUBT bit(12) /* allows torping of other subs */ +#define M_TRADE bit(13) /* is a trade ship */ +#define M_SEMILAND bit(14) /* can land 1/4 */ +/* M_XLIGHT will be automatically set in init_global() if m_nxlight > 0 */ +#define M_XLIGHT bit(15) /* can hold xlight planes */ +/* M_CHOPPER will be automatically set in init_global() if m_nchoppers > 0 */ +#define M_CHOPPER bit(16) /* can hold choppers */ +#define M_OILER bit(17) /* can re-fuel ships */ +#define M_SUPPLY bit(18) /* Can supply units/sects/ships */ +/* M_XUNIT will be automatically set in init_global() if m_nland > 0 */ +#define M_UNIT bit(19) /* Can carry units */ +#define M_ANTIMISSILE bit(20) /* Shoot down missile */ + +#define getship(n, p) \ + ef_read(EF_SHIP, n, (caddr_t)p) +#define putship(n, p) \ + ef_write(EF_SHIP, n, (caddr_t)p) +#define getshipp(n) \ + (struct shpstr *) ef_ptr(EF_SHIP, n) + +extern double seagun(); + +extern struct mchrstr mchr[]; +extern int shp_maxno; + +struct mlist { + struct emp_qelem queue; /* list of ships */ + struct mchrstr *mcp; /* pointer to desc of ship */ + struct shpstr ship; /* struct ship */ + double mobil; /* how much mobility the ship has left */ + int done; /* has this ship been interdicted yet? */ +}; + +#define SHP_DEF(b, t) (t ? (b * (logx((double)t, (double)40.0) < 1.0 ? 1.0 : \ + logx((double)t, (double)40.0))) : b) +#define SHP_SPD(b, t) (t ? (b * (logx((double)t, (double)35.0) < 1.0 ? 1.0 : \ + logx((double)t, (double)35.0))) : b) +#define SHP_VIS(b, t) (b * (1 - (sqrt((double)t) / 50))) +#define SHP_RNG(b, t) (t ? (b * (logx((double)t, (double)35.0) < 1.0 ? 1.0 : \ + logx((double)t, (double)35.0))) : b) +#define SHP_FIR(b, t) (t ? (b * (logx((double)t, (double)60.0) < 1.0 ? 1.0 : \ + logx((double)t, (double)60.0))) : b) + +double sqrt(); +double logx(); + + /* return codes from shp_check_nav */ +#define CN_NAVIGABLE (0) +#define CN_LANDLOCKED (1) +#define CN_CONSTRUCTION (2) +#define CN_ERROR (-1) + +#endif /* _SHIP_H_ */ + diff --git a/include/struct.h b/include/struct.h new file mode 100644 index 00000000..ad0994a4 --- /dev/null +++ b/include/struct.h @@ -0,0 +1,41 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * struct.h: Used to access information relating to the fields of a structure. + * + * Known contributors to this file: + * + */ + +#ifndef _STRUCT_H_ +#define _STRUCT_H_ + +#define fldoff(str, fld) ((int)&(((struct str *)0)->fld)) +#define fldsiz(str, fld) (sizeof(((struct str *)0)->fld)) +#define strbase(str, ptr, fld) ((struct str *)((s_char *)(ptr)-fldoff(str, fld))) + +#endif /* _STRUCT_H_ */ diff --git a/include/subs.h b/include/subs.h new file mode 100644 index 00000000..1a3539f1 --- /dev/null +++ b/include/subs.h @@ -0,0 +1,55 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * subs.h: Headers for things having to do with subs. + * + * Known contributors to this file: + * + */ + +#ifndef _SUBS_H_ +#define _SUBS_H_ + +#include "misc.h" +#include "sect.h" +#include "plane.h" +#include "loan.h" +#include "treaty.h" +#include "nsc.h" +#include "land.h" +#include "com.h" +#include "nuke.h" +#include "item.h" +#include "ship.h" +#include "queue.h" +#include "xy.h" +#include "genitem.h" +#include "trade.h" +#include "player.h" +#include "prototypes.h" /* must come at end, after defines and typedefs */ + +#endif /* _SUBS_H_ */ diff --git a/include/tel.h b/include/tel.h new file mode 100644 index 00000000..91883c7e --- /dev/null +++ b/include/tel.h @@ -0,0 +1,61 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * tel.h: Definitions for things having to do with telegrams + * + * Known contributors to this file: + * + */ + +#ifndef _TEL_H_ +#define _TEL_H_ + +#define MAXTELSIZE 1024 /* doesn't apply to TEL_UPDATE */ + +#define TEL_NORM 0 /* normal */ +#define TEL_ANNOUNCE 1 /* announcement */ +#define TEL_BULLETIN 2 /* bulletin */ +#define TEL_UPDATE 3 /* update message */ +#define TEL_LAST 3 + +#define TEL_SECONDS 5 /* how many seconds before starting a new telegram */ + +struct telstr { + natid tel_from; /* sender */ + s_char tel_type; + long tel_length; /* how long */ + time_t tel_date; /* when sent */ +}; + +extern s_char *mailbox(s_char *buf, natid cn); + +extern s_char *teldir, *telfil; + +extern s_char *annfil; + + +#endif /* _TEL_H_ */ diff --git a/include/trade.h b/include/trade.h new file mode 100644 index 00000000..28be53fe --- /dev/null +++ b/include/trade.h @@ -0,0 +1,88 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * trade.h: Definitions for trading units/ships/planes in a time delay + * system + * + * Known contributors to this file: + * Dave Pare + * Pat Loney, 1992 + * Steve McClure, 1996 + */ + +#ifndef _TRADE_H_ +#define _TRADE_H_ + +#include "genitem.h" +#include "nuke.h" +#include "plane.h" +#include "land.h" +#include "ship.h" + +#include "prototype.h" + +struct trdstr { + short ef_type; + natid trd_owner; + short trd_uid; + char trd_type; + short trd_unitid; + long trd_price; + int trd_maxbidder; + int trd_maxprice; + time_t trd_markettime; + coord trd_x; + coord trd_y; +}; + +struct genstr { + short trg_ef_type; + natid trg_own; + short trg_uid; + coord trg_x; + coord trg_y; + s_char trg_type; +}; + +union trdgenstr { + struct genstr gen; + struct nukstr nuk; + struct plnstr pln; + struct lndstr lnd; + struct shpstr shp; +}; + +s_char *trade_nameof _PROTO((struct trdstr *tp, union trdgenstr *tgp)); + +#define gettrade(n, p) \ + ef_read(EF_TRADE, n, (caddr_t)p) +#define puttrade(n, p) \ + ef_write(EF_TRADE, n, (caddr_t)p) +#define gettradep(n) \ + (struct trdstr *) ef_ptr(EF_TRADE, n) + +#endif /* _TRADE_H_ */ diff --git a/include/treaty.h b/include/treaty.h new file mode 100644 index 00000000..de6dcfc6 --- /dev/null +++ b/include/treaty.h @@ -0,0 +1,84 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * treaty.h: Definitions for treaties + * + * Known contributors to this file: + * Steve McClure, 1998 + * + */ + +#ifndef _TREATY_H_ +#define _TREATY_H_ + +struct trtstr { + natid trt_cna; /* proposer */ + natid trt_cnb; /* acceptor */ + s_char trt_status; /* treaty status */ + s_char trt_fill; + short trt_acond; /* conditions for proposer */ + short trt_bcond; /* conditions for accepter */ + float trt_bond; /* amount of bond involved */ + time_t trt_exp; /* expiration date */ +}; + +struct tchrstr { + int t_cond; /* bit to indicate this clause */ + s_char *t_name; /* description of clause */ +}; + +#define TS_FREE 0 +#define TS_PROPOSED 1 +#define TS_SIGNED 2 + + /* treaty clauses */ +#define LNDATT bit(0) /* no attacks on land units */ +#define SEAATT bit(1) /* no attacks on ships */ +#define SEAFIR bit(2) /* no shelling ships */ +#define LANATT bit(3) /* no attacks on sectors */ +#define LANFIR bit(4) /* no shelling sectors */ +#define NEWSHP bit(5) /* no new ships */ +#define NEWNUK bit(6) /* no new nuclear weapons */ +#define NEWPLN bit(7) /* no new planes */ +#define NEWLND bit(8) /* no new land units */ +#define TRTENL bit(9) /* no enlistment */ +#define SUBFIR bit(10) /* no depth-charging submarines */ + +/* global treaty variables */ + +#define gettre(n, p) \ + ef_read(EF_TREATY, n, (caddr_t)p) +#define puttre(n, p) \ + ef_write(EF_TREATY, n, (caddr_t)p) +#define gettrep(n) \ + (struct trtstr *) ef_ptr(EF_TREATY, n) + +extern struct tchrstr tchr[]; + +extern int trt_maxno; + +#endif /* _TREATY_H_ */ diff --git a/include/update.h b/include/update.h new file mode 100644 index 00000000..4f5634e8 --- /dev/null +++ b/include/update.h @@ -0,0 +1,49 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * update.h: Include headers used for updates + * + * Known contributors to this file: + * + */ + +#ifndef _UPDATE_H_ +#define _UPDATE_H_ + +#include "misc.h" +#include "queue.h" +#include "sect.h" +#include "item.h" +#include "land.h" +#include "plane.h" +#include "ship.h" +#include "nat.h" +#include "nsc.h" +#include "product.h" +#include "prototypes.h" /* must come at end, after defines and typedefs */ + +#endif /* _UPDATE_H_ */ diff --git a/include/user.h b/include/user.h new file mode 100644 index 00000000..f2bb00fa --- /dev/null +++ b/include/user.h @@ -0,0 +1,53 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * user.h: User definitions + * + * Known contributors to this file: + * Dave Pare, 1986 + */ + +#ifndef _USER_H_ +#define _USER_H_ + +#include "queue.h" + +struct user { + struct emp_qelem queue; + struct iop *u_iop; + int u_cnum; + int u_pid; +}; + +/* + * lock commandsx + */ +#define L_UNLOCK bit(0) /* command to unlock */ +#define L_LOCK bit(1) /* command to lock */ +#define L_NOLOCK bit(3) /* allow no new locks */ + +#endif /* _USER_H_ */ diff --git a/include/var.h b/include/var.h new file mode 100644 index 00000000..dd5ddfc1 --- /dev/null +++ b/include/var.h @@ -0,0 +1,148 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * var.h: various variable definitions + * + * Known contributors to this file: + * + */ + +#ifndef _VAR_H_ +#define _VAR_H_ + +#define V_MAX 255 + +#define PLG_HEALTHY 0 +#define PLG_DYING 1 +#define PLG_INFECT 2 +#define PLG_INCUBATE 3 +#define PLG_EXPOSED 4 + +#define VT_ITEM (1<<5) +#define VT_COND (2<<5) +#define VT_DIST (3<<5) +#define VT_DEL (4<<5) +#define VT_SELL (5<<5) +#define VT_SPARE1 (6<<5) +#define VT_SPARE2 (7<<5) +#define VT_TYPE (7<<5) + +#define isitem(x) (((x) & VT_TYPE) == VT_ITEM) +#define iscond(x) (((x) & VT_TYPE) == VT_COND) +#define isdist(x) (((x) & VT_TYPE) == VT_DIST) +#define isdel(x) (((x) & VT_TYPE) == VT_DEL) +#define issell(x) (((x) & VT_TYPE) == VT_SELL) +#define unitem(x) ((x) & (VT_ITEM -1)) + +#define V_ITEM(x) ((x)|VT_ITEM) /* a moveable, sellable(?) commodity */ +#define V_COND(x) ((x)|VT_COND) /* condition (plg time, etc) */ +#define V_DIST(x) ((x)|VT_DIST) /* distribution command */ +#define V_DEL(x) ((x)|VT_DEL) /* delivery command */ +#define V_SELL(x) ((x)|VT_SELL) /* make a sale */ + +#define I_CIVIL 1 +#define I_MILIT 2 +#define I_SHELL 3 +#define I_GUN 4 +#define I_PETROL 5 +#define I_IRON 6 +#define I_DUST 7 +#define I_BAR 8 +#define I_FOOD 9 +#define I_OIL 10 +#define I_LCM 11 +#define I_HCM 12 +#define I_UW 13 +#define I_RAD 14 +#define I_MAX 14 + +#define C_MINE 1 +#define C_PSTAGE 2 +#define C_PTIME 3 +#define C_REM 4 +#define C_CHE 5 +#define C_FALLOUT 6 + +#define V_MINE V_COND(C_MINE) +#define V_PSTAGE V_COND(C_PSTAGE) +#define V_PTIME V_COND(C_PTIME) +#define V_REM V_COND(C_REM) +#define V_CHE V_COND(C_CHE) +#define V_FALLOUT V_COND(C_FALLOUT) + +/* should this be here?? */ +#define get_che_cnum(x) ((x) >> 8) +#define set_che_cnum(x, cn) ((x) = ((x) & 0xff) | ((cn) << 8)) +#define get_che_value(x) ((x) & 0xff) +#define set_che_value(x, n) ((x) = ((x) & 0xff00) | (n)) + +#define V_CIVIL V_ITEM(I_CIVIL) +#define V_MILIT V_ITEM(I_MILIT) +#define V_SHELL V_ITEM(I_SHELL) +#define V_GUN V_ITEM(I_GUN) +#define V_PETROL V_ITEM(I_PETROL) +#define V_IRON V_ITEM(I_IRON) +#define V_DUST V_ITEM(I_DUST) +#define V_BAR V_ITEM(I_BAR) +#define V_FOOD V_ITEM(I_FOOD) +#define V_OIL V_ITEM(I_OIL) +#define V_LCM V_ITEM(I_LCM) +#define V_HCM V_ITEM(I_HCM) +#define V_UW V_ITEM(I_UW) +#define V_RAD V_ITEM(I_RAD) + +#define V_CDEL V_DEL(I_CIVIL) +#define V_MDEL V_DEL(I_MILIT) +#define V_SDEL V_DEL(I_SHELL) +#define V_GDEL V_DEL(I_GUN) +#define V_PDEL V_DEL(I_PETROL) +#define V_IDEL V_DEL(I_IRON) +#define V_DDEL V_DEL(I_DUST) +#define V_BDEL V_DEL(I_BAR) +#define V_FDEL V_DEL(I_FOOD) +#define V_ODEL V_DEL(I_OIL) +#define V_LDEL V_DEL(I_LCM) +#define V_HDEL V_DEL(I_HCM) +#define V_UDEL V_DEL(I_UW) +#define V_RDEL V_DEL(I_RAD) + +#define V_CDIST V_DIST(I_CIVIL) +#define V_MDIST V_DIST(I_MILIT) +#define V_SDIST V_DIST(I_SHELL) +#define V_GDIST V_DIST(I_GUN) +#define V_PDIST V_DIST(I_PETROL) +#define V_IDIST V_DIST(I_IRON) +#define V_DDIST V_DIST(I_DUST) +#define V_BDIST V_DIST(I_BAR) +#define V_FDIST V_DIST(I_FOOD) +#define V_ODIST V_DIST(I_OIL) +#define V_LDIST V_DIST(I_LCM) +#define V_HDIST V_DIST(I_HCM) +#define V_UDIST V_DIST(I_UW) +#define V_RDIST V_DIST(I_RAD) + +#endif /* _VAR_H_ */ diff --git a/include/version.h b/include/version.h new file mode 100644 index 00000000..bb105ea3 --- /dev/null +++ b/include/version.h @@ -0,0 +1,47 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * version.h: describes major, minor and release levels of the software + * + * Known contributors to this file: + * Thomas Rushack, 1992 + * Ken Stevens, 1995 + * Steve McClure, 1998, 1999 + */ + +#ifndef _VERSION_H_ +#define _VERSION_H_ + +#define EMP_VERS_MAJOR 4 +#define EMP_VERS_MINOR 2 +#define EMP_VERS_PATCH 12 + +#define KSU_DIST 1.04 +#define CHAINSAW_DIST 4.00 +#define WOLFPACK_DIST 2.12 + +#endif /* _VERSION_H_ */ diff --git a/include/wantupd.h b/include/wantupd.h new file mode 100644 index 00000000..91336136 --- /dev/null +++ b/include/wantupd.h @@ -0,0 +1,101 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * wantupd.h: Header used to check to see if an update is wanted + * and/or allowed. + * + * Known contributors to this file: + * Doug Hay, 1991 + */ + +/* + * In the "hours" file, + * + * update_policy: N + * 0 - normal policy, update each time. + * 1 - update at times specified by keyword "update_times". + * 2 - blitz updates + * 3 - no regular updates. (Only demand ones.) + * default: 0. + * + * update_times: 1:00 3:00 8:00 + * Sets the times when updates occur under policy #1. + * NOTE that the schedual times should coincide. + * + * update_timeslop: N + * The number of minutes that the update check is allowed to slip + * to match one of the update times shown. + * default 5. + * + * update_wantmin: N + * 0 - disabled, no requests. + * >0 - minimum number of requests before an update. + * Setting it to more than num of coun will max at num of coun. + * defaults to MAXNOC. + * + * update_abswantmin: N + * N - absolute minimum number of requests for an update. + * Prevents quick breaks and updates. + * defaults to 1. + * + * update_demandtimes: 1:00-3:00 5:00-6:00 + * Time intervals when update requests are allowed. + * NOTE that time ranges CANNOT cross midnight. + * They must go like: 20:00-24:00 0:00-3:00 + * + * update_demandpolicy: N + * 0 - demand updates occur only emp_tm checks. + * 1 - demand updates occur right after setting command. + * 2 - demand updates disabled. + * defaults to 0. + * + * update_demandmaxperday: N + * Not implemented yet. + */ + +#ifndef _WANTUPD_H_ +#define _WANTUPD_H_ + +#define UDP_NORMAL 0 +#define UDP_TIMES 1 +#define UDP_NOREG 3 +#define UDP_BLITZ 2 +#define UDP_MAX 3 +#define UDP_DEFAULT UDP_NORMAL + +/* The maximum number of "update_times" allowed */ +#define UDTIMES_MAX 20 + +#define UDDEM_TMCHECK 0 +#define UDDEM_COMSET 1 +#define UDDEM_DISABLE 2 +#define UDDEM_MAX 2 +#define UDDEM_DEFAULT UDDEM_TMCHECK + +#define BLITZTIME 20 + +#endif /* _WANTUPD_H_ */ diff --git a/include/xy.h b/include/xy.h new file mode 100644 index 00000000..81ec32dd --- /dev/null +++ b/include/xy.h @@ -0,0 +1,71 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * xy.h: Constants having to do with world locations. + * + * Known contributors to this file: + * Steve McClure, 1998 + */ + +#ifndef _XY_H_ +#define _XY_H_ + +#include "sect.h" +#include "nat.h" + +/* Used to calculate an offset into an array. Used for + dynamically sizing the world. */ +#define XYOFFSET(x, y) ((y * WORLD_X) + x) + +#define XNORM(x) (((x)<0) ? ((WORLD_X-(-(x)%WORLD_X))%WORLD_X) : ((x)%WORLD_X)) +#define YNORM(y) (((y)<0) ? ((WORLD_Y-(-(y)%WORLD_Y))%WORLD_Y) : ((y)%WORLD_Y)) + +struct range { + coord lx; /* low-range x,y */ + coord ly; + coord hx; /* high-range x,y */ + coord hy; + int width; /* range width, height */ + int height; +}; + +extern s_char *xyfmt(); +extern s_char *xyas(coord x, coord y, natid country); +extern s_char *ownxy(struct sctstr *sp); +extern coord xrel(struct natstr *np, coord absx); +extern coord yrel(struct natstr *np, coord absy); +extern void xyrelrange(struct natstr *np, struct range *src,struct range *dst); +extern void xyabsrange(struct natstr *np, struct range *src,struct range *dst); +extern void inputxy(coord *xp, coord *yp, natid cn); +extern coord xabs(struct natstr *np, coord relx); +extern coord yabs(struct natstr *np, coord rely); +extern coord xnorm(register coord x); +extern coord ynorm(register coord y); +extern int xyinrange(coord x, coord y, struct range *rp); + +#endif /* _XY_H_ */ + diff --git a/info/Blank.awk b/info/Blank.awk new file mode 100644 index 00000000..52cb1bf9 --- /dev/null +++ b/info/Blank.awk @@ -0,0 +1,10 @@ +# Will Edgington, wedgingt@nike.cair.du.edu +/^$/ { if (prev != "") { + print + prev = "" + } + next } + { + print + prev = "a" + } diff --git a/info/CRT.MAC b/info/CRT.MAC new file mode 100644 index 00000000..966ce43c --- /dev/null +++ b/info/CRT.MAC @@ -0,0 +1,27 @@ +.\" EMPIRE MACRO FILE FOR 24-LINE CRT +.\" Normal Font +.rm nF +.\" Example Font +.rm eF +.\" Bold Font +.rm bF +.\" Italic Font +.rm iF +.\" Large Font +.rm lF +.\" Previous Font +.rm pF +.\" Nothing special here +.ds <= <= +.ds >= >= +.ds Q " +.ds U " +.pl 23v \" Page length: 23 lines +.ll 7.8i \" Line length: 7.8 inches +.ev 1 +.ll 7.8i \" Line length: 7.8 inches +.ev +.ev 2 +.ll 7.8i \" Line length: 7.8 inches +.ev +.so ../INFO.MAC \" Read in INFO.MAC macros diff --git a/info/Commands/MakeSrcs b/info/Commands/MakeSrcs new file mode 100644 index 00000000..aa56267d --- /dev/null +++ b/info/Commands/MakeSrcs @@ -0,0 +1 @@ +INFOSRCS=accept.t add.t announce.t anti.t apropos.t arm.t army.t assault.t attack.t bdes.t bestdistpath.t bestpath.t bmap.t board.t bomb.t break.t budget.t build.t buy.t bye.t capital.t cargo.t cede.t census.t change.t coastwatch.t collect.t commodity.t consider.t convert.t country.t cutoff.t declare.t deliver.t demobilize.t designate.t disable.t disarm.t dissolve.t distribute.t drop.t dump.t echo.t edit.t enable.t enlist.t execute.t explore.t financial.t fire.t flash.t fleetadd.t fly.t follow.t force.t fortify.t fuel.t give.t grind.t harden.t headlines.t hidden.t improve.t info.t land.t launch.t lboard.t lcargo.t ldump.t ledger.t level.t list.t lload.t llookout.t lmap.t lmine.t load.t lookout.t lost.t lradar.t lrange.t lretreat.t lstat.t ltend.t lunload.t map.t march.t market.t mine.t mission.t mobupdate.t morale.t motd.t move.t mquota.t mult.t name.t nation.t navigate.t ndump.t newcap.t neweff.t newspaper.t nmap.t nuke.t offer.t offset.t order.t origin.t paradrop.t path.t payoff.t pboard.t pdump.t plane.t players.t pmap.t power.t pray.t production.t pstat.t qorder.t quit.t radar.t range.t read.t realm.t recon.t reject.t relations.t repay.t report.t reset.t resource.t retreat.t route.t sabotage.t sail.t satellite.t scrap.t scuttle.t sdump.t sect.t sell.t set.t setresource.t setsector.t sharebmap.t shark.t ship.t shoot.t show.t shutdown.t sinfrastructure.t skywatch.t smap.t sonar.t sorder.t spy.t sstat.t start.t starvation.t stop.t strength.t supply.t survey.t swapsector.t sweep.t telegram.t tend.t territory.t test.t threshold.t toggle.t torpedo.t trade.t transport.t treaty.t turn.t unload.t unsail.t update.t upgrade.t version.t wait.t wall.t wingadd.t wipe.t wire.t work.t zdone.t diff --git a/info/Commands/Makefile b/info/Commands/Makefile new file mode 100644 index 00000000..d2224a61 --- /dev/null +++ b/info/Commands/Makefile @@ -0,0 +1,62 @@ +# +# Empire - A multi-player, client/server Internet based war game. +# Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, +# Ken Stevens, Steve McClure +# +# 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 2 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, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# --- +# +# See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the +# related information and legal notices. It is expected that any future +# projects/authors will amend these files as needed. +# +SRCDIR = ../.. +NROFF = nroff +TROFF = troff + +INFOSRCS = empty + +INFOOBJS = $(INFOSRCS:.t=) + +HTMLOBJS = $(INFOSRCS:.t=.) + +include MakeSrcs + +.SUFFIXES: .t + +all: + @echo INFOSRCS=`echo *.t` > MakeSrcs + @make nroffs + @echo Done. + +html: + @echo INFOSRCS=`echo *.t` > MakeSrcs + @make htmlfiles + @echo Done. + +htmlfiles: $(HTMLOBJS) + +nroffs: $(INFOOBJS) + +$(INFOOBJS): + @$(NROFF) $(SRCDIR)/info/CRT.MAC $@.t | awk -f $(SRCDIR)/info/Blank.awk > $(SRCDIR)/info.nr/$@ + @echo Created $(SRCDIR)/info.nr/$@ + +$(HTMLOBJS): + @perl $(SRCDIR)/info/emp2html.pl $@t > $(SRCDIR)/info.html/$@html + @echo Created $(SRCDIR)/info.html/$@html + + diff --git a/info/Commands/accept.t b/info/Commands/accept.t new file mode 100644 index 00000000..3c9c0f20 --- /dev/null +++ b/info/Commands/accept.t @@ -0,0 +1,23 @@ +.TH Command ACCEPT +.NA accept "Find out who's accepting what communications from whom" +.LV Expert +.SY "accept [country]" +The accept command allows you to find out the communications status of +a country. With no argument, accept prints your status. With an argument, +it prints the acceptance status of the specified country. +.s1 +.EX "accept 7" +.nf +Temekula Acceptance Status Report Sun Feb 21 20:53:51 1993 + +Acceptance status his theirs + tel trty anno loan tel trty anno loan +1) Gobu YES YES YES YES YES YES YES YES +2) Spectre YES YES YES YES YES YES YES YES +3) Rohan YES YES YES YES YES YES YES YES +4) Sioux YES YES YES YES YES YES YES YES +5) Tom_Servo YES YES YES YES YES YES YES YES +6) Horgoth YES YES YES YES YES YES YES YES +.fi +.s1 +.SA "telegram, announce, read, wire, reject, Diplomacy, Communication" diff --git a/info/Commands/add.t b/info/Commands/add.t new file mode 100644 index 00000000..b036af35 --- /dev/null +++ b/info/Commands/add.t @@ -0,0 +1,17 @@ +.TH Command ADD +.NA add "Add/Remove a country in the game" +.LV Expert +.SY "add " +.EX add 1 bunky mypass n i +This adds a new player to the game. +.EX add 2 visitor visitor v i +This adds a visitor country to the game. +.EX add 1 bunky mypass d w +This removes bunky and all his sectors & units from the game. +.EX add 1 bunky mypass d c +Just to make sure that bunky doesn't still have any stuff in the game. +.EX add 36 martian outerspace a i +This will add a new country which will be able to send/receive +telegrams but won't have any land. For example, you could give a +newbie helper a country like this. +.SA "newcap, Deity" diff --git a/info/Commands/announce.t b/info/Commands/announce.t new file mode 100644 index 00000000..533f0619 --- /dev/null +++ b/info/Commands/announce.t @@ -0,0 +1,34 @@ +.TH Command ANNOUNCE +.NA announce "Send an announcement to all players" +.LV Basic +.SY "announce" +The announce command is a variant of the telegram command. +It sends your message to \fIall\fR of the players in the game. +This convenient service may cost money to provide, depending on +your deity. +.s1 +A banner line saying \*QANNOUNCEMENT\*U is prepended to your message +so that announcements won't be confused with telegrams. In +all other respects, announcements are exactly the same as telegrams. +.s1 +For example: +.EX announce +.NF +Enter telegram for everyone; end with ^D +1024 left: +1023 left: For Immediate Release + 987 left: from + 962 left: Groonland Embassy + 928 left: + 927 left: + 926 left: HELP! Curmudgeon just TRASHED our capital! We had even proposed + 860 left: a very fair treaty, but they did it anyway! People of the World, + 794 left: UNITE! Overthrow the slavemasters of Curmudgeon! + 744 left: +JoeBlowLand is rejecting your announcements +ZappaLand is rejecting your announcements +.FI +.s1 +Note that announcements can be rejected. See info reject for more information. +.s1 +.SA "pray, wire, telegram, read, reject, Communication" diff --git a/info/Commands/anti.t b/info/Commands/anti.t new file mode 100644 index 00000000..4a2bb01a --- /dev/null +++ b/info/Commands/anti.t @@ -0,0 +1,35 @@ +.TH Command ANTI +.NA anti "anti-terrorist actions" +.LV Basic +.SY "anti " +.s1 + The anti-guerrilla command is used to remove che from any sector. +The command take the following form: +.EX anti +.s1 +Once issued, the strength of the che is +compared to the number of mil in the sector. The maximum number of mil +allowed to fight is equal to the mobility in the sector. Che recieve a +combat multiplier which may or may not make +them tougher to kill. There are only +three outcomes for this command. +.s1 +.NF + 1) The mil kill all the che. The sector is cleared (for now). + 2) The che kill the mil. The sector then returns to the old owner with + most or all of the che reverting to mil. The old owner is sent a + telegram informing him of the event. + 3) The battle is suspended when the mobility in the sector is used up. + Each mil or che killed uses one mobility point. +.FI +.s1 +Units do not participate in the anti command. A sector can revert +to the old owner while your units are stuck in it. +.s1 +Note that che are finicky. If you manage to lose a sector fighting them, +they do unpredictable things. +They may all come out of hiding to join the +military. A few may stay in hiding while the majority come out to join +the military. Who knows what else they may do. +.s1 +.SA "census, Guerrilla, Sectors, Populace" diff --git a/info/Commands/apropos.t b/info/Commands/apropos.t new file mode 100644 index 00000000..44fa016e --- /dev/null +++ b/info/Commands/apropos.t @@ -0,0 +1,24 @@ +.TH Command APROPOS +.NA apropos "Searches info pages for information on a topic" +.LV Basic +.SY "apropos [maxhits]" +.s1 +The Empire info pages are organized by subject. It can sometimes be hard to +find the exact page with the information in which you are interested. +To get a list of subjects containing the word you are looking for, type: +.EX apropos +.s1 +without the < and > brackets. +.s1 +You can then type: +.EX apropos bridge +to get a list of Empire commands and info topics which contain the +word bridge, as well as the line that mentions it. +.s1 +Apropos is not case sensitive, thus the above example will find +pages with Bridge or bridge (or even bRiDgE). +.s1 +By default, apropos exits when 100 hits are found. You can change this value +with an optional second parameter. +.s1 +.SA "info, Playing" diff --git a/info/Commands/arm.t b/info/Commands/arm.t new file mode 100644 index 00000000..684892ae --- /dev/null +++ b/info/Commands/arm.t @@ -0,0 +1,21 @@ +.TH Command ARM +.NA arm "Load nuclear weapons onto planes or missiles" +.LV Expert +.SY "arm " +The \*Qarm\*U command loads nuclear devices +aboard delivery systems such as planes or missiles. +.s1 +No nuclear weapons can be delivered unless they are first loaded +aboard delivery vehicles. +However, until they are residing in a plane or missile, they +are considered invulnerable to attack (buried inside of mountains), +and cannot be used by any potential conqueror (they don't know the +fail-safe codes). +.s1 +You decide whether the warhead will airburst or groundburst at the +time you arm it. If you'd like to change airburst/groundburst later +on, just arm the plane/missile again (in this case, the second +argument will be ignored). You can see whether a nuke will air or +ground burst using the "plane" command. +.s1 +.SA "disarm, plane, build, transport, launch, Damage, Planes" diff --git a/info/Commands/army.t b/info/Commands/army.t new file mode 100644 index 00000000..c22d2c0d --- /dev/null +++ b/info/Commands/army.t @@ -0,0 +1,43 @@ +.TH Command ARMY +.NA army "Designate members of an \*Qarmy\*U" +.LV Expert +.SY "army " +The army command is used to specify the army groupings +of your units. +.s1 +.EX army +In the syntax is the alphabetic character to be used as the +army designation. +This character can be chosen from the set of +upper or lower case a-z and tilde (~). +The pseudo-army specification tilde +specifies all units not currently in any army. +.s1 +The specification of units, , +can have one of several syntaxes: +.NF +example meaning +------- ------- +23 unit 23 +2/14/23 units 2, 14, and 23 +c all units currently in army `c' +~ all units currently in the \*Qnull\*U army +2,3 all units in sector 2,3 +-1:3,0:2 all units in the square area bounded by -1,0 & 3,2 +.FI +All armies, (with the exception of the `~' army), +are limited to some maximum size +and you will be informed how many units can be added +when this command is run. +.s1 +Having units organized into armies can be very helpful in +loading, moving, etc., +in that fewer commands are required to perform these commands +on groups of units if they can be specified by army number. +.s1 +Note that you can remove units from a army by adding them to +the `~' army. e.g. +.EX army ~ A +This command would purge all units from army `A'. +.s1 +.SA "load, lookout, navigate, radar, land, unload, LandUnits" diff --git a/info/Commands/assault.t b/info/Commands/assault.t new file mode 100644 index 00000000..4137147a --- /dev/null +++ b/info/Commands/assault.t @@ -0,0 +1,81 @@ +.TH Command ASSAULT +.NA assault "Attack coastal sector from ship" +.LV Basic +.SY "assault [ ]" +.s1 +The assault command allows your marines to \*Qhit the beaches\*U. +It is also the only way to get ashore other than by unloading at a harbor, +thus it is the first step to gaining land on a new continent. +.s1 +Any ship with military can assault a sector containing 0 mil, however +only a landing ship can assault a sector with military in it with +its full complement of troops. +The other ships will only be able to land a fraction of their troops +in any given assault (usually 1/10th). +This represents the use of the Admiral's gig, the Captain's barge, etc. +.s1 +Note that some ships will have the +semi-lander flag, which allows them to land 25% of their troops. +.s1 +If you have land units with the 'assault' ability +aboard the ship assaulting, you will be asked if +you wish them to join in the assault as well. +Assaulting land units go to negative mobility when assaulting. +(by an amount equal to the mobility gain per update) +Marine units go to 0 mobility instead. +If assaulting from a ship with the landing ability, a normal unit +pays only mob equal to 1 update's worth of mobility. A marine unit +pays 1/2 that amount. (Example: in a game where land units gain 32 +mobility per update, a non-marine unit would pay 32 mobility to assault +from a landing ship. A marine unit would pay only 16 mobility) +.s1 +.L NOTE +This mobility loss for units happens whether or not you +own the sector being assaulted. If you wish to land troops +without suffering this penalty, make/capture a harbor! +.s1 +If you have ship #28 bearing 10 military at 31,53 +it can assault land at any of the adjacent sectors, +(32,52; 33,53; 32,54; 30,54; 29,53; or 30,52). + +For example: +.EX assault 32,54 28 +.s1 +This command asks to assault sector 32,54 from ship #28. +If you assault with 9 troops and assuming the sector has no military, +and since there were 10 troops on the ship to begin with, +90% of the food will be taken along by the assaulting troops, +(and each one that makes it will contribute his or her 10% +to the conquered sector). A minimum of 1 food will be left +on the ship. Land units will not take any food from +the ship, and will only have the food they are carrying. +.s1 +You will be asked for any information which was +not included on the command line, +(sector to be assaulted, which ship is doing the assaulting, +number of brave troops to disembark, land units to use). +.s1 +The offensive value of assaulting units is cut in half to represent +the difficulty of getting to shore, except for "marine" units whihc +assault at full strength. +.s1 +Units may not retreat from an assault, and will take extra casualties +instead if they fail a morale check. +.s1 +Other than these factors, assault is the same as normal land combat, with +forts/units/ships/planes firing on both sides to support, etc. Support +arguments are also as in attacking. +.s1 +See info \*QAttack\*U for the exact procedure. The sector being assaulted +will have exactly the same reaction to being conquered as if it were attacked +by land. +.s1 +You may assault your own sectors. In this case, the assaulting mil +are added to the mil in the sector, and assaulting land units simply +come ashore. +.s1 +You may also use assault to sneak spies on land. To do this, you must +assault with spies only, and they will try and sneak on land. See "info Spies" +for more information. +.s1 +.SA "Spies, Attack, LandUnits, Ships, Combat" diff --git a/info/Commands/attack.t b/info/Commands/attack.t new file mode 100644 index 00000000..841d4cc9 --- /dev/null +++ b/info/Commands/attack.t @@ -0,0 +1,9 @@ +.TH Command ATTACK +.NA attack "Sector vs sector combat" +.LV Basic +.SY "attack [ ]" +.s1 +The attack command is used to attack a sector from neighbouring sectors. +For more details, see "info Attack". +.s1 +.SA "Attack, Combat, LandUnits" diff --git a/info/Commands/bdes.t b/info/Commands/bdes.t new file mode 100644 index 00000000..eda649b1 --- /dev/null +++ b/info/Commands/bdes.t @@ -0,0 +1,35 @@ +.TH Command BDES +.NA bdes "Manually change your bmap" +.LV Expert +.SY "bdes " +A bmap gives you a graphic representation of all or part of your country. +Bdes allows you to change a sector of your bmap. +.s1 +Bmap differs from map in that it reflects everything you've learned +about the world. If, for example, you navigate near a sector and find +out that it is as sea, it will show up on your bmap as sea, even if it +doesn't show up on your map. +.s1 +When you get new information, it will overwrite the designation you put in +with bdes, UNLESS you put in an 'x' or an 'X'. These two characters, 'x' +and 'X' are permanent, unless you manually change them with bdes. Once you +change them back, the sector will be updated normally by nav, march, etc. +(The normal use for these is to record minefields, so that you can march +adjacent to the minefield without eliminating the information) +.s1 +Unlike normal designation, with bdes, you may use any character. +If you wish to use a space, surround it with double quotes: +bdes # " " +.s1 +You can't bdesignate something to a ? +.s1 +Conditionals do not work with bdes (i.e. bdes # ?des=c C) unless +you own the sector. +.s1 +Note that the bdes command only changes your 'working' bmap and not +your 'true' bmap. If you make a mistake and bdes a bunch of sectors +where you didn't want them to be, you can always start over by typing +.EX "bmap revert" +which will revert your 'working' bmap back to your 'true' bmap. +.s1 +.SA "bmap, sharebmap, Maps" diff --git a/info/Commands/bestdistpath.t b/info/Commands/bestdistpath.t new file mode 100644 index 00000000..a7781496 --- /dev/null +++ b/info/Commands/bestdistpath.t @@ -0,0 +1,27 @@ +.TH Command BESTDISTPATH +.NA bestdistpath "Show the best distribution path from one sector to another" +.LV Expert +.SY "bestpath " +.SY "bestdistpath " +.s1 +The bestpath & bestdistpath commands show you the best path from any sector +to any sector. You must own both sectors. +.s1 +The path shown by bestpath is the cheapest +owned existing path in terms of mobility. +.s1 +Bestdistpath shows the best distribution path that can be found, which +should be the same as the best path.. +During the update, sectors distribute to +and from their distribution point by means of the best distribution path +they can find at that time. +.s1 +Note that if you give these commands areas, they will show you more paths. +For example, +.s1 +.EX bestpath #1 #2 +.s1 +will show the best paths from all sectors in realm 1 to all the sectors in +realm 2. +.s1 +.SA "distribute, Maps" diff --git a/info/Commands/bestpath.t b/info/Commands/bestpath.t new file mode 100644 index 00000000..68bb384e --- /dev/null +++ b/info/Commands/bestpath.t @@ -0,0 +1,27 @@ +.TH Command BESTPATH +.NA bestpath "Show the best path from one sector to another" +.LV Expert +.SY "bestpath " +.SY "bestdistpath " +.s1 +The bestpath & bestdistpath commands show you the best path from any sector +to any sector. You must own both sectors. +.s1 +The path shown by bestpath is the cheapest +owned existing path in terms of mobility. +.s1 +Bestdistpath shows the best distribution path that can be found, which +should be the same as the best path. +During the update, sectors distribute to +and from their distribution point by means of the best distribution path +they can find at that time. +.s1 +Note that if you give these commands areas, they will show you more paths. +For example, +.s1 +.EX bestpath #1 #2 +.s1 +will show the best paths from all sectors in realm 1 to all the sectors in +realm 2. +.s1 +.SA "distribute, Maps" diff --git a/info/Commands/bmap.t b/info/Commands/bmap.t new file mode 100644 index 00000000..a9f89c6a --- /dev/null +++ b/info/Commands/bmap.t @@ -0,0 +1,94 @@ +.TH Command BMAP +.NA bmap "Big map of all your worldly knowledge" +.LV Basic +.SY "bmap [ | ] " +.SY "lbmap [ | ] " +.SY "pbmap [ | ] " +A bmap gives you a graphic representation of all or part of your country. +.s1 +Bmap differs from map in that it reflects everything you've learned +about the world. If, for example, you navigate near a sector and find +out that it is sea, it will show up on your bmap as sea, even if it +doesn't show up on your map. +.s1 +Note that bmap shows the \*QLAST KNOWN INFORMATION\*U you have about +a sector. It may change, and your bmap will not reflect it. For example, +if you re-designate a sector, it won't show up on your bmap as the +new sector type until you do a map. +.s1 +Commands contributing to bmap include (but are not limited to): +map, nav, fly, bomb, recon, para, drop, lookout, coastwatch, radar. +(probably others) +.s1 +Your own sectors show up as a designation mnemonic +(see \*QSector-types\*U) while sectors held by other countries +appear as question marks (\*Q?\*U). +Mountains, wilderness areas, and seas appear +as '^', '-' and '.' respectively. +.s1 +Note that any sector +marked as 'X' on your bmap will automatically be avoided by +ships when they are trying to calculate the best path between two +points. Whenever you detect a sea mine in a sector, the server will +automatically put an 'X' on your bmap. +.s1 +You can call up a local bmap while navigating or marching by typing 'B' +at the prompt. +.s1 +Examples: +.EX bmap -9:18,-8:5 +generates a 28 x 14 bmap based on data supplied by the sectors +in the area specified. +.NF + ---------0000000000111111111 + 9876543210123456789012345678 + -8 . . . - - -8 + -7 . . . . - ^ -7 + -6 . . . . - - - - -6 + -5 . . - . a a - ^ ? ? - -5 + -4 . . . . k o ! - ^ ? ? ? -4 + -3 . - . a h j a ^ ^ ^ ^ ^ - -3 + -2 . . - . a a a ^ a a - - - -2 + -1 . . . a a a b + + ^ ^ - -1 + 0 . . . m c u a a - ^ - ^ 0 + 1 . - . a a . a a - - ^ 1 + 2 - ^ ^ a a a ^ a - - ^ 2 + 3 - - - - - - - . . - 3 + 4 ^ - - - - - ^ - - 4 + 5 - ^ - - ^ - - - 5 + ---------0000000000111111111 + 9876543210123456789012345678 +.FI +.s1 +.EX bmap # >mapfil +where your \*Qrealm\*U (or '#', +see \*Qinfo realm\*U or \*Qinfo update\*U) +is -5:5,-6:6 will type out a 11 by 13 sector bmap +and also put the bmap in the file called \*Qmapfil\*U. +.s1 +You can also give the number of a ship, and bmap will give you a small +bmap centered on the location of that ship, provided you own it. +If you use lmap, the number of a land unit will give you a map around +that land unit. The pmap command does the same for planes. +.s1 +.L "BMAP FLAGS" +.s1 +If you specify an 's' flag, bmap will put your ships on the map. +If you specify an 'l' flag, bmap will put your land units on the map. +If you specify an 'p' flag, bmap will put your planes on the map. +A '*' will put all on the map. +.s1 +You actually have two bmaps. One which is created by the server; this +one is called your 'true' bmap. You can view your true bmap at any +time using the +.SY "bmap true" +command. However, usually when you view your bmap, you are looking at +your 'working' bmap. The only difference between your working bmap +and your true bmap is that your working bmap also contains +designations put on there by you using the 'bdes' command, and by your +friends using the "sharebmap" command. If somehow your bmap gets +corrupted, you can revert your working bmap back to your true bmap +using the command: +.SY "bmap revert" +.s1 +.SA "bdes, map, navigate, fly, bomb, recon, paradrop, drop, lookout, coastwatch, radar, sharebmap, Maps" diff --git a/info/Commands/board.t b/info/Commands/board.t new file mode 100644 index 00000000..18771f3e --- /dev/null +++ b/info/Commands/board.t @@ -0,0 +1,48 @@ +.TH Command BOARD +.NA board "Board enemy ship" +.LV Basic +.SY "board [] [ | ]" +The board command enables two ships' crews to engage in hand-to-hand +combat. +To board ship #16 from ship #93 you might type: +.EX board 16 +.s1 +The program will ask from which ship or sector you wish to board, +(you may only board from one ship at a time), how many troops to board +with, and which land units (having "assault" capability) to board with. +.s1 +In order to be able to board a ship from a ship, your ship must be as fast +or faster than the defending ship. +If you can't catch him, you can't board him! +.s1 +The attacking ship will use, based upon its speed, an amount of mobility +to overtake and board the target ship. +If the attacking ship has no mobility, it cannot catch anybody! +Ships' speed depends upon the speed of the ship, the technology +of the owner, and the current efficiency of the ship. +A 50% damaged ship moves one-half the speed it does when undamaged. +.s1 +In order to board a ship from a sector, the ship must be in the +sector, and either the sector must have mobility or it must contain +some land units with the "assault" capability. +.s1 +Some things to note: +.s1 +The defense strength is multiplied by 1 + def/100 where def is the +defense strength of the ship (see show ship stats). +.s1 +Other ships belonging to the victim will fire on you when you +try to board, (if you're within range). +.s1 +Any land units in the combat will fight as if they were simply mil, +i.e. they won't get any offensive of defensive multiplier, except for +"marine" units which get their full bonus. Similarly, units +on ships don't have to take morale checks, as they are fighting as mil. +Mil on the victim ship will still die before units take casualties, however. +.s1 +Note that you can only board with as many mil and land units that the +ship you are trying to board can hold. +.s1 +See info \*QAttack\*U for the exact procedure. +.s1 +.SA "Attack, LandUnits, Ships, Combat" diff --git a/info/Commands/bomb.t b/info/Commands/bomb.t new file mode 100644 index 00000000..a5f8ad34 --- /dev/null +++ b/info/Commands/bomb.t @@ -0,0 +1,117 @@ +.TH Command BOMB +.NA bomb "Dispose of inconvenient enemy assets with airpower." +.LV Basic +.SY "bomb mission-type route|destination" +The \*Qbomb\*U command is used to rain destruction upon helpless +enemy ships, planes, and sectors. +It represents a complete mission for one or more bombers and escorts +taking off from one place and returning to base at the end of the mission. +.s1 + represents a list of planes which can carry bombs. +Only planes which have a bomb bay, belong in a sector which is +stocked with gas and shells, and have sufficient mobility will +be successfully selected for the mission. +.s1 + represent a list of fighter planes which are capable of escorting +the bombers all the way to the target. +To be selected, escorts must have fuel and mobility. +.s1 +Mission-type must be one of "pinpoint" or "strategic". +Each mission has different objectives for the planes performing it. +Pinpoint missions allow bombers to attack ships, sector efficiency, +commodities in sectors, and planes on the ground in the target sector. +Strategic missions damage all commodities in the entire target sector, +while not damaging any ships or planes resident (similar to the +ship and sector \*Qfire\*U missions). +If a plane is armed with a nuclear warhead, then it will drop the bomb +rather than using conventional weapons. +Nuclear devices damage everything in the sector; planes, ships, and +commodities. +Only missiles in hardened silos can avoid damage from a nuclear mission. +.s1 + represents an assembly point, where all of the planes in the +mission meet before proceeding on to the target sector. +The assembly point must be owned by you, and must not be more than +four sectors away from any of the planes selected for the mission. +.s1 +Route is a normal empire path specification. You may also give a +destination sector on the command line, or at any time while giving +the route, and empire will use the best path from the current sector +to the desired destination sector. +.s1 +When getting a path interactively, empire will show you a small map +(from your bmap) concerning the current area, to help you plot +your course. +.s1 +Light bombers (with the tactical capability) are used primarily for pinpoint +bombing. They perform as well as fighters do for strategic bombing. +Heavy bombers (with the bomber capability), while they can perform pinpoint +bombing, are notoriously inaccurate and in general miss what they are aiming +at. They are used mainly for strategic bombing. +.s1 +During the course of a mission, +your planes may fly over someone else's land. +If you fly over land owned by another country, +and this country is either hostile or in any war state (see info relation) +with you, fighter planes from the enemy country will scramble +and attempt to intercept your force. +If the country is simply neutral, +he will be notified that his radar tracked your planes +as they flew over his country. +If the country is allied, then nothing will occur. +.s1 +If you manage to fight though the enemy fighters and arrive +at the target sector, your force must still contend with +any flak guns which your enemy has stationed there. +What's more, any enemy ship in the target sector will also +shoot at each of your bombers before any attacks are performed. +Any enemy land units with the 'flak' ability will also fire at +all your planes at this time. +.s1 +A well-equipped fleet of battleships in a heavily-defended harbor +can be very risky to attack, even though hitting ships in harbor is +like shooting fish in a barrel. +.s1 +When bombing ships/planes/units, entering a '~' character will cause a +particular plane not to bomb. Other planes on the mission will still +be asked for their targets. +.s1 +If your plane has anti-submarine +(asw) capabilities, you will be told when you arrive in a sector whether +it has submarines in it. If you then choose to pin-bomb ships, each plane +in turn will attempt to find submarines (this ability varies with the plane's +accuracy rating). Each plane can only bomb the subs it can find. (It +is assumed +that planes on anti-sub missions split up to cover the area) +.s1 +Planes have differing air-to-air combat abilities, differing ranges, +and load-carrying capacities. +Some airplanes don't need runways, but can operate out of any +sector which has fuel in it. +.s1 +ASW capable planes may attempt +to fly pin-bombing missions versus submarines. To do this, the plane +gives a target sector, and flies there. If there are any subs in the +sector, a message will be printed saying that. If the plane then +attempts to bomb ships, it may get the chance to bomb subs in the sector. +.s1 +The chance to detect a sub is the same as the chance of hitting it. +.s1 +If the plane does not detect a particular sub, it may not bomb it on that +mission. On other missions, it could roll again. +.s1 +Trying to pinpoint bomb land units is similar to trying to bomb a sub. +The chance to find the unit to bomb it is based on the unit's +visibility & the type of the sector it is in. +.s1 +When you pin-bomb a land unit, it will fire flak at the plane bombing it, +unless it is an 'flak' unit (in which case it fired earlier), or +it has an AA fire rating of 0. +.s1 +In the case of pinbombing, see \*Qinfo Hitchance\*U for the formula +determining whether a plane hits its target. +.s1 +Note that a plane must be at least 40% efficient before it can leave +the ground. +.s1 +.SA "Plane-types, build, fly, paradrop, drop, recon, relations, Mobility, Damage, Planes" diff --git a/info/Commands/break.t b/info/Commands/break.t new file mode 100644 index 00000000..245772a5 --- /dev/null +++ b/info/Commands/break.t @@ -0,0 +1,14 @@ +.TH Command BREAK +.NA break "Break sanctuary and begin to play" +.LV Basic +.SY "break" +In Empire your sectors are initially sanctuaries. +While in sanctuary your people don't eat, work or reproduce. +They also can't be attacked. +.s1 +Break removes the sanctuary protection from your country and forces +your people to work for a living. +You can't do any country development commands until you break out +of sanctuary. +.s1 +.SA "Sector-types, Nation" diff --git a/info/Commands/budget.t b/info/Commands/budget.t new file mode 100644 index 00000000..ce0572b0 --- /dev/null +++ b/info/Commands/budget.t @@ -0,0 +1,88 @@ +.TH Command BUDGET +.NA budget "Look at a national balance sheet & set priorities" +.LV Basic +.SY "budget [ ]" +budget with no arguments produces: +.EX budget +.NF +Sector Type Abbr Production Priority Cost +park p 850 happy 7650 +defense plant d 115 guns 3600 +shell industry i 679 shells 2097 +technical center t 66 tech 27000 +research lab r 7 medical 900 +library/school l 1616 edu 14544 +refinery % 388 petrol 425 +enlistment center e 930 mil 2790 +Unit building L 6 units 358 +Unit maintenance A 85 units 28992 +Ship building S 2 ships 480 +Ship maintenance M 25 ships 6327 +Plane building P 9 planes 2508 +Plane maintenance N 219 planes 8874 +Sector building 2398 +Military payroll 7648 mil, 338 res 38247 +City maintenance 5 cities 300 +Total expenses....................................................147490 +Income from taxes 320709 civs, 100235 uws +92513 +Income from bars 7986 bars +95832 +Total income.....................................................+188345 +Balance forward 41617 +Estimated delta +40855 +Estimated new treasury.............................................82472 +.FI +.s1 +Budget with an argument sets the priority of the given sector type +(or L for unit building, or A for unit maintenance, or +P for plane building, or S for ship building, or M for ship +maintenance, or N for plane maintenance, or C to clear all) +.s1 +Priorities are a positive number, or 0, or ~. +.s1 +By default, budget lists only items which cost something. Non-producing +items will be listed if they are given a priority. +.s1 +Update order: +.s1 +Please see info \*QUpdate-sequence\*U for more details on the order things +happen in during the update.. +.s1 +.L "Turning sectors off" +.s1 +Sector designations (or ship or plane building) with a 0 priority will not +produce, build efficiency, or gain avail. +.s1 +If a sector of a type with 0 priority has been re-designated, the sector will +be torn down and rebuilt as usual (and may produce as well, depending on the +amount of work available, as normal) +.s1 +If a sector of a type with a non-zero priority has been re-designated to a +type with a 0 priority, the sector will be torn down to 0%, and the designation +changed, but no further work will be done. +.s1 +For other ways to control sector production, see the \*Qstart\*U and \*Qstop\*U +commands. +.s1 +Costs for each sector type include costs for building efficiency in sectors +of that type. (This is true even if the sector will change to a different +type as a result of that work. For example, costs for libraries will include +all costs for work done in library sectors, even if one of the sectors is +being turned into an aggie) +.s1 +Estimated Delta +.s1 +The estimated delta may not be correct, due to events during updates. +(starvation, plague, sector revolts, etc). +.s1 +Budget takes into account avail in headquarters, +harbors and airports, and will +only show you how much you'll pay for work that will actually get done +in cases where your headquarters/airports/harbors will not have enough avail +to work on all units/planes/ships. +.s1 +If a cost is in [ brackets ], then that means that you will not pay it +because you will not have enough money. If a cost is in ( brakets ), +then that means that you will not pay it because you have chosen not +to pay that cost (i.e. you have set the priority of that item to 0). +.s1 +.SA "show, Sector-types, Nation, Update" diff --git a/info/Commands/build.t b/info/Commands/build.t new file mode 100644 index 00000000..7f3169a8 --- /dev/null +++ b/info/Commands/build.t @@ -0,0 +1,303 @@ +.TH Command BUILD +.NA build "Build ships, planes, bridges, land units or nuclear weapons" +.LV Basic +.SY "build [land|ship|plane|nuke|bridge] [unit-type|ship-type|plane-type|nuke-type|direction] [Number to build] [tech] [sure?]" +The build command is used to specify the types of units to be built +at your headquarters, ships +to be built in your harbors, the planes and missiles at your airfields, +the nuclear devices at your nuclear production facilities, +and the directions in which bridge spans are to be built. +.s1 +The ability to produce units, ships, planes, nukes, or bridges, is based on +several factors: +labor force, light production units, heavy production units, +oil units, radioactive material units, available cash, +and technology level. +The quantities or levels required vary with the object being built. +.s1 +In order to build anything, the sector involved needs to have +avail. Avail is work available in the sector after the demands +of the update (building efficiency, working on things, etc) +Avail in the sector is show in the output of the \*Qcensus\*U +command in the 'avail' column. +.s1 +The "Number to build" option may only be given if the command is being +specified totally on the command line. If you give multiple sectors and +a number to build, it will attempt to build that number at EACH sector +specified. If you ask to build more than 20 units, it will ask you +"are you sure you want to build so many?". +.s1 +If you don't specify TECH then it will build the unit at your current +tech level. +.s1 +BUILDING BRIDGES +.s1 +If you type +.EX build b 1,3 +and 1,3 has enough hcm (heavy construction +materials), the workforce in the sector is large enough (as defined above), +you have enough money, and your technology level is high enough, +then the program will respond: +.NF +Bridge head at 1,3 + + k +o a . + . . +build span in what direction? n +.FI +.s1 +With the EASY_BRIDGES option enabled, bridges may be built from any sector +that is at least 60% efficient. Otherwise, bridges may only be built +from bridge-head sectors. The +sector the bridge span is to be built in must be adjacent to +at least 1 non-sea, non-bridge span sector. +.s1 +If everything is correct, you get: +.NF + +Bridge span built over 2,4 +.FI +To find out the required amounts of materials, workforce, and money +use the \*Qshow bridge build\*U command. +.s1 +You may now also build bridges all in one line as in: +.EX build b 1,3 n +.s1 +A sector that has a bridge built in it is automatically cleared +of mines at the time of building. +.s1 +Bridge spans are built at 20%. If the efficiency drops below 20% (due +to bombing, shelling, etc.) the bridge span falls. +.s1 +If a bridge falls, all mines in the sector are likewise cleared. +.s1 +BUILDING BRIDGE TOWERS +.s1 +If you type +.EX build t 1,3 +and 1,3 has enough hcm (heavy construction +materials), the workforce in the sector is large enough (as defined above), +you have enough money, and your technology level is high enough, and the +sector is a bridge span, +then the program will respond: +.NF +Building from 1,3 + + a +o = . + . . +build tower in what direction? n +.FI +.s1 +Bridge towers can only be built if the BRIDGETOWERS option is enabled. +.s1 +In addition, bridge towers can only be built in open water, i.e. not +adjacent to any land or other bridge towers. Bridge towers must be +built from bridge spans that are at least 60% efficient. +.s1 +If everything is correct, you get: +.NF + +Bridge tower built in 2,4 +.FI +To find out the required amounts of materials, workforce, and money +use the \*Qshow tower build\*U command. +.s1 +You may now also build bridge towers all in one line as in: +.EX build t 1,3 n +.s1 +A sector that has a bridge tower built in it is automatically cleared +of mines at the time of building. +.s1 +Once a bridge tower is built, you may build other bridge spans from it. +.s1 +Note that you cannot navigate through a bridge tower like you can through a +bridge span. +.s1 +Bridge towers are built at 20%. If the efficiency drops below 20% (due +to bombing, shelling, etc.) the bridge tower falls. +.s1 +If a bridge tower falls, all mines in the sector are likewise cleared. +In addition, if a bridge tower falls, all bridges around it are +knocked down unless they have another supporting bridgehead (such as +another tower, bridge head or next to land if EASY_BRIDGES is on.) +.s1 +NUCLEAR PLANT SECTORS & BUILDING NUKES +.s1 +If you type +.EX build 6,2 +and 6,2 is a nuclear plant that has enough hcm +(heavy construction materials), +lcm (light construction materials), oil, and radioactive material, +the workforce in the sector is large enough (as defined above), +you have enough money, and your technology level is high enough, +then the program will construct a new nuclear device of the type +requested, and add it to the current stockpile in that sector. +.s1 +Note: If the DRNUKE option is enabled, you will need a certain amount +of research to make nukes. At the present time, it is 1/3 the amount of +tech needed to make the nuke. See the \*Qshow\*U command, which lists +this if applicable. +.s1 +TYPES OF THINGS YOU CAN BUILD (besides bridges) +.s1 +Many different types of units/ships/planes/nukes are available. +For a brief table indicating the production costs of the +different things, respond with \*Q?\*U when asked for the type, +or use the \*Qshow\*U command. +Note that if there are two things in the list of items that are +similar, such as "destroyer 1" and "destroyer 2", you will need +to give the full name, or the program will build the first one +that it encounters. +.s1 +\*QNote:\*U if you wish to give the ship-type argument on the +command line, it may be necessary to quote the ship-type. For +example: build s 0,0 "lander 2" 80 would build a lander 2. Without +the quotes, it might build a lander 1 instead, since the ship-type +is two words. +.s1 +Once built, units/ships/planes grow in efficiency until they reach +100%. This growth is accomplished using the avail left in the sector +at the time of the update, so if you use all the avail building things, +there won't be any left to make them more efficient. The avail there +is divided amongst all things in the sector needing work, so the more +units/ships/planes there, the less each will be worked upon. +Ships/planes/units also require materials be present in the sector to +gain efficiency. In general, for each 1% the ship/plane/unit gains in +efficiency, it will use 1% of the materials listed by \*Qshow\*U. +.s1 +HEADQUARTERS SECTORS & BUILDING LAND UNITS +.s1 +Land units are built in headquarters sectors. (designation !). +In order to build a land unit, you must have 10% of the items +listed by \*Qshow\*U (typically military, lcms, hcms, guns, shells, +petrol, etc) available at the time of building. The land unit will +appear at 10% efficiency (a unit of less than 10% efficiency is +dead). Then, +each update, the unit will grow in efficiency, and use up more +of the required goods until it reaches 100%. +Land units can also gain efficiency in fortress sectors, but cannot +be built there. +.s1 +The work required to add a point of efficiency to a land unit is +.s1 +.NF +(20 + (lcm_to_build + 2 * hcm_to_build))/100 +.FI +.s1 +A land unit will can gain efficiency in any other sector type (assuming +the correct goods are available), but at 1/3rd the normal rate. +.s1 +HARBORS & BUILDING SHIPS +.s1 +Ships are built in harbor sectors. 20% of the materials +listed by \*Qshow\*U must be available at the time of building. +(typically hcms & lcms) +Ships first appear at 20% efficiency and a 19% efficient ship +will not float (i.e., it sinks). Then, each update, the ship will +grow in efficiency, and use up more of the required materials until +it reaches 100%. +.s1 +In addition to the avail in the harbor sector, ships are also +worked on by their crews. So, for fastest efficiency growth, +put full crews on your newly built +ships and leave them in harbor until they reach 100%. +.s1 +The work required to add a point of efficiency to a ship is +.s1 +.NF +(20 + (lcm_to_build + 2 * hcm_to_build))/100 +.FI +.s1 +Ships at sea have only their crews to make repairs. +Crew members each supply the same amount of work, +whether civilian, military, or uncompensated worker. +A small crew on a large ship +may not be able to make any repairs at all. +(Moral: keep your ships fully crewed in anticipation of future damage.) +Repairs at sea do not use any lcms or hcms, but may not push the +efficiency of a ship over 80%. +.s1 +Entropy acts on ships without sufficient crews. In general, if a ship +is at sea, and has less than about 40% of its maximum crew, it +will gradually rust, take on water, and sink. +.s1 +.NF + The amount of efficiency lost depends on the ship size and crew level. + + Figure the following quantities: + + Avail is the work done by the crew: + + On a military ship: work = etus * mil/2 + On a civilian ship: work = etus * (civ/2 + mil/5) + + Crew is the current # of mil (for a military ship), or civs for a +civilian ship. + + Max crew is the max # of mil/civs (depending on ship type) + + W_p_eff is the amount of work per point of efficiency of the ship: + + w_p_eff = 20 + (lcm + 2 * hcm); + + Lcms & hcms are the cms required to build the ship. + + Then, subtract (etus * (100-((crew*100)/max_crew)))/7 from the avail. + + If the result is less than 0, divide it by the w_p_eff, and subtract + that amount from the ship's efficiency. + + avail -= (etus * (100-((amt*100)/abs_max)))/7; + ship->shp_effic += avail/w_p_eff; + Example: A frigate (a military ship) can hold 60 mil. It has only 10. + + w_p_eff = 20 + (lcm + 2*hcm) = 20 + (30 + 2*30) = 110 + Avail = etus * mil/2 = 60 * (10/2) = 300 + + 300 - (60 * (100-((10*100)/(60)))/7) ~= -420 + + Since the result is negative, divide it by w_p_eff: + + 420/110 = 3.8 = 4% loss of efficiency + + Note from this that the frigate would need 24 crew to break even. +.FI +.s1 +AIRPORT SECTORS & BUILDING PLANES +.s1 +The choices range from low tech \*Qfighter 1\*U planes +up to and including super-long range \*Qjet hvy bomber\*Us +and \*Qicbm\*Us. +For a brief table indicating the production costs of the +different plane types respond with \*Q?\*U, or check out +the \*Qshow\*U command. +.s1 +Note that planes first appear at 10% efficiency. +10% of the listed hcms/lcms/crew must be in the airport in order to +build the plane. (typically hcms, lcms, and mil (crew)) +In order for the plane to gain efficiency, it needs +hcms/lcms/mil, as ships and land units do. +As time passes, and as long as there are \*Qavailable work units\*U in the +airport at which the planes reside (to work on the planes), they grow to +100% efficiency. A plane is not capable of leaving the ground until +it has reached 40% efficiency. +.s1 +The work required to add a point of efficiency to a plane is +.s1 +.NF +(20 + (lcm_to_build + 2 * hcm_to_build))/100 +.FI +.s1 +Planes will also gain efficiency in non-airport sectors, but at only 1/3rd +the normal rate. +.s1 +If the CARRIER_WORK option is enabled, planes on carriers will also gain +efficiency. The amount of work available is based on the carrier's crew, +and the rate is the same as a non-airport sector. +Repairs at sea do not use any lcms/hcms/mil, but may not push the +efficiency of a plane over 80%. +.s1 +Once you have reached tech level 290, you are no longer allowed to +build planes that have tech level below 151. +.s1 +.SA "Unit-types, Ship-types, Plane-types, Nuke-types, Bridges, show, upgrade, Maintenance, Ships, Planes, LandUnits, Sectors" diff --git a/info/Commands/buy.t b/info/Commands/buy.t new file mode 100644 index 00000000..2f3745d8 --- /dev/null +++ b/info/Commands/buy.t @@ -0,0 +1,41 @@ +.TH Command BUY +.NA buy "Purchase commodities from the world market" +.LV Expert +.SY "buy " +The buy command allows nations to purchase commodities +on the open market. +Not all commodities can be traded -- notably civilians and military. +.s1 +It is based on a bidding system, and after the bidding time has passed, +the transactions are executed, and the highest bidder gets the goods +(maybe.) If there are no bidders once the time passes, the goods stay +on the market and the first bidder will get them. +.s1 +Typical output looks like: +.EX buy food +.NF + + Empire Market Report + Wed Mar 13 14:26:26 1996 + lot high bid by time left owner item amount sector + --- -------- -- --------- ----- ---- ------ ------ + 0 $ 10.00 1 0.00 hrs ( 1) f 10 + 1 $ 1.00 1 0.00 hrs ( 1) f 10 + +Looks just like Christmas at K-mart, doesn't it! + +Which lot are you bidding on: 1 +WARNING! This market issues credit. If you make more + bids than your treasury can cover at the time of sale, + you can potentially go into financial ruin, and see no + gains. You have been warned. + +How much per unit: 2 +destination sector : 3,1 +Your bid is being considered. +.FI +.s1 +In addition, the \*Qdestination sector\*U must be a warehouse or harbor, +and must be greater than 60% efficient to receive commodities. +.s1 +.SA "reset, sell, market, Market" diff --git a/info/Commands/bye.t b/info/Commands/bye.t new file mode 100644 index 00000000..f1be03a8 --- /dev/null +++ b/info/Commands/bye.t @@ -0,0 +1,15 @@ +.TH Command BYE +.NA bye "Log out of Empire" +.LV Basic +.SY "bye" +The bye command is how you go \*Qbye-bye\*Q to log out of the game. +.s1 +This command costs zero BTU's. You can use it often. +.s1 +If, for some obscure reason, +you would like to end an Empire session +but prefer not to use the \*Qbye\*Q command +you may achieve the same result by typing the +EOT character, (control-D). +.s1 +.SA "Playing" diff --git a/info/Commands/capital.t b/info/Commands/capital.t new file mode 100644 index 00000000..13cc6473 --- /dev/null +++ b/info/Commands/capital.t @@ -0,0 +1,48 @@ +.TH Command CAPITAL +.NA capital "Change the location of your capital" +.LV Basic +.SY "capital " +This command changes the location of your nation's capital. +The new sector must be of type "capital" or "mountain", +and must be owned by you. Your capital produces BTUs. See "info BTU" +for the exact rate of BTU production. +.s1 +This command does not change your coordinate origin +(where 0,0 is located), +so if you prefer your coordinates centered on your nation's capital, +you must use the origin command. +For example: +.EX capit -10,-4 +.NF +Your capital is now at -10,-4. +.FI +.EX orig -10,-4 +.NF +Designation of new origin requires revision of sector numbers. +Origin at -10,-4 (old system) is now at 0,0 (new system). +.FI +.s1 +If the unthinkable should come to pass, and an enemy captures your capital, +bad things happen. Some happen once, immediately: + +.NF +1) You will lose half your cash, or $3K, whichever is more. +2) Your enemy will gain half your cash times (1/5 + 4/5 * sector efficiency) +.FI +.s1 +Re-taking a previously taken capital has no further effect. Once a new capital +has been declared with this command, +you are again in peril of these two awful things. +.s1 +Some effects happen right away, and last until you use +the \*Qcapital\*U command to create a new capital. The effects are: + +.NF +3) You will not be able to use many commands (use the + 'list of commands' command to see the pitiful few you may still use) + +4) The rate at which you gain BTUs will dramatically decrease (see + info BTU). +.FI +.s1 +.SA "origin, designate, BTU, Nation" diff --git a/info/Commands/cargo.t b/info/Commands/cargo.t new file mode 100644 index 00000000..2a357351 --- /dev/null +++ b/info/Commands/cargo.t @@ -0,0 +1,61 @@ +.TH Command CARGO +.NA cargo "List the commodities on board your ships" +.LV Basic +.SY "cargo [ | ]" +.SY "lcargo [ | ]" +The cargo command lists the commodities on board your ships +in readable format. The lcargo command does the same for land units. +.s1 +The , , and arguments are +provided in case you only wish to look at one ship/unit +or one fleet/army or all ships/units within a given area. +.s1 +The report format contains the following fields: +.s1 +.in +1i +.L shp# or # +the ship or unit number +.L shiptype or unit type +the type of ship/unit; \*Qpatrol boat\*U, \*Qsubmarine\*U, etc, +.L x,y +the ship/unit's current location (relative to your capital), +.L flt +the fleet/army designation letter (set by \*Qfleetadd/army\*U command), +.L eff +the ship/unit's efficiency, +.L sh +the number of shells on board, +.L gun +the number of guns on board +.L pet +the amount of petroleum on board +.L irn +the amount of iron on board +.L dst +the amount of gold dust on board +.L bar +the number of gold bars on board +.L oil +the amount of oil on board +.L lcm +the amount of light construction materials on board +.L hcm +the amount of heavy construction materials on board +.L rad +the amount of radioactive material on board +.in +.s1 +For example: +.EX cargo K +.NF +shp# ship type x,y flt eff sh gun pet irn dst bar oil lcm hcm rad + 86 aircraft carrier -29,-51 K 100% 298 4 0 0 0 0 0 0 0 0 + 110 battleship -29,-51 K 100% 100 8 0 0 0 0 0 0 0 0 + 115 battleship -29,-51 K 100% 60 8 0 0 0 0 0 0 0 0 + 181 destroyer -27,-35 K 100% 40 4 0 0 0 0 0 0 0 0 + 182 destroyer -27,-35 K 100% 40 4 0 0 0 0 0 0 0 0 + 183 destroyer -27,-35 K 100% 40 4 0 0 0 0 0 0 0 0 +6 ships +.FI +.s1 +.SA "land, ship, build, march, navigate, load, lload, fleetadd, army, Ships" diff --git a/info/Commands/cede.t b/info/Commands/cede.t new file mode 100644 index 00000000..c3a83d5f --- /dev/null +++ b/info/Commands/cede.t @@ -0,0 +1,47 @@ +.TH Command CEDE +.NA cede "Give a ship or sector to a friend" +.LV Expert +.SY "cede [se|sh]" +This command gives a sector or sectors to the country of your choice, or +a ship or ships. +A sector to be ceded must have mobility, and must be adjacent to a +sector with mobility owned by the country you are cedeing it to, \*QOR\*U +contain a ship owned by the country you are cedeing it to, \*QOR\*U a +sector owned by the recipient that contains a land unit with mobility. +.s1 +A ship to be ceded must either be in a sector owned by the recipient, or +in a sector containing a ship owned by the recipient. +.s1 +You may only cede to nations which consider you a friendly trading partner. +.s1 +All contents of the sector become the property of the new owner, +such as commodities, planes, land units, etc. Ships, however, do +NOT change ownership. +.s1 +All contents of a ceded ship become the property of the new owner, including +planes or land units. Distribution & delivery info of ceded sectors are wiped. +.s1 +The ceded sector has its mobility set to zero. If the owner of the sector +was not the old owner when he ceded it, the old owner is not changed. +The mobility of a ceded ship is not changed. +.s1 +If it is ambiguous whether you wish to cede a sector or a ship, then +you can specify a third argument of either sh or se meaning ship and +sector respectively. +.s1 +For example: +.EX cede 2,2 Rongovia +.NF +Sat Jan 16 22:33:11 1993 + sect eff + 2,2 100% ceded + 1 sector +.FI +.s1 +The recipient gets a telegram telling him of the gift: +.NF +> BULLETIN from POGO, (#0) dated Sat Jan 16 22:33:11 1993 +-11,-3 ceded to you by Groonland +.FI +.s1 +.SA "Sectors" diff --git a/info/Commands/census.t b/info/Commands/census.t new file mode 100644 index 00000000..060ac0ab --- /dev/null +++ b/info/Commands/census.t @@ -0,0 +1,86 @@ +.TH Command CENSUS +.NA census "Report contents of sectors" +.LV Basic +.SY "census " +The census command displays specific information on +some or all of the sectors you occupy. +.s1 +In the syntax of the census command + is the area on which you wish information, +(see \*Qinfo Syntax\*U). +.s1 +A typical usage might be: +.EX census 0:9,0:9 ?des=m +which would list data for mines in an area +to the south-east of the capital. +.s1 +A census lists each of your sectors in the specified area headed by: +.NF +Tue Oct 10 22:24:49 1995 +CENSUS del dst + sect eff prd mob uf uf * civ mil uw food work avail ter coast +.FI +These columns represent: +.s1 +.in \w'gmin\0\0'u +.L sect +the x and y coordinates of the sector +.L eff +the efficiency of the sector (affects all benefits +of a designated sector except mobility units) +.L prd +Will this sector be updated? If not, you will see an 'n'. +This can be controlled with the \*Qstart\*U and \*Qstop\* commands. +.L mob +the number of mobility units, (see \*Qmove\*U) +.L uf +Two delivery columns corresponding to: +uncompensated workers and food. +.L uf +Two \*Qdistribute\*U columns corresponding to: +uncompensated workers and food. +.L * +occupied enemy sector. +.L civ +the number of civilians +.L mil +the number of military troops +.L uw +the number of uncompensated workers +.L food +the amount of food +.L work +the percentage of civilians working in the sector +(based on the local sector happiness). +.L avail +the quantity of workforce available for construction +or maintenance of planes, ships, or nukes. +.L ter +This is a territory for the sector that you can specify using the +\*Qterritory\*U command. +.L coast +Is this a coastal sector? Note that the "coastal flag" gets set for +the sector only when you use the census command, so if you want to +query your sectors depending on whether they're coastal, then you may +need to do a census twice--the first time to set the coastal flags, +and the second time to query them. +.in \\n(in +.s1 +For example: +.EX cens #0 +.NF +Tue Jun 20 00:33:43 1989 +CENSUS del dst + sect eff prd mob uf uf * civ mil uw food work avail ter + 2,-2 f 100% 8 .. .. 0 499 0 0 0% 64 + -1,-1 f 100% 32 .. .. 629 0 0 970 43% 31 3 + 1,-1 n 100% n 31 .. 627 0 0 970 51% 30 + 3,-1 ) 100% 32 .. .. 0 0 0 0 0% 0 + -2,0 h 100% 32 .. .. 629 0 0 970 100% 93 50 + 0,0 * 100% 114 .. .. 906 845 0 729 100% 173 50 + 2,0 c 100% 127 .. .. 154 100 124 71 100% 49 + 1,1 - 0% 32 .. .. 1 0 0 0 0% 0 + 8 sectors +.FI +.s1 +.SA "improve, sinfrastructure, commodity, resource, level, territory, cutoff, map, start, stop, Sectors, Populace, Commodities" diff --git a/info/Commands/change.t b/info/Commands/change.t new file mode 100644 index 00000000..74ee10bd --- /dev/null +++ b/info/Commands/change.t @@ -0,0 +1,29 @@ +.TH Command CHANGE +.NA change "Change country name or representative's name" +.LV Expert +.SY "change [country | representative] Newname" +This simple command enables you +to rename your country, or your representative name +associated with your country. +.s1 +.s1 +COUNTRY NAME +.s1 +.EX change country Hodedo +This will change the name of your country to \*QHodedo\*U. +In order to change your name you must pay 10% of your cash on +hand and 254 btus. +These expenses reflect the trouble of changing all the national +emblems, stationary, flags, etc. +.s1 +.s1 +REPRESENTATIVE NAME +.s1 +.EX change representative ho +Your representative's name will now be \*Qho\*U. +Note that the new name you +type WILL print out, (in case of a typing error). +As a consequence +you won't want to do this while your arch-enemy is watching. +.s1 +.SA "nation, Nation" diff --git a/info/Commands/coastwatch.t b/info/Commands/coastwatch.t new file mode 100644 index 00000000..4de64d91 --- /dev/null +++ b/info/Commands/coastwatch.t @@ -0,0 +1,28 @@ +.TH Command COASTWATCH +.NA coastwatch "Check from sectors for nearby ships" +.LV Basic +.SY "coastwatch []" +The coastwatch command allows coastal sectors to report sightings of ships. +.s1 +Visibility range is equal to +four times the sector efficiency +expressed as a decimal times the technology factor; +e.g. a 100% efficient harbor with a 50% technology factor can +see 2 sectors away. +An exception is radar installations, which have a maximum range +equal to fourteen times the sector efficiency, (i.e. 3.5 times as far). +.s1 +A typical usage might be: +.EX coast #3 ?type=) +.NF + 3,-11 efficiency 100%, range 5.6 +Pandora (#5) oil derrick #74 @3, -9 + -1,4 efficiency 100%, range 5.6 + -3,13 efficiency 100%, range 5.6 +Galexis (#2) destroyer #35 @-3, 11 +.FI +.s1 +Note that subs will NOT show up on coastwatch, unless they are in a +sector you own. +.s1 +.SA "skywatch, lookout, Sector-types, radar, Ships, Detection" diff --git a/info/Commands/collect.t b/info/Commands/collect.t new file mode 100644 index 00000000..665307b9 --- /dev/null +++ b/info/Commands/collect.t @@ -0,0 +1,47 @@ +.TH Command COLLECT +.NA collect "Foreclose an overdue loan" +.LV Expert +.SY "collect " +The collect command is the loan-shark's delight! +Through the collect command overdue loans can be \*Qcleared up\*U. +.s1 +If you should find that you have a problem debtor who refuses +to pay up on your kind loan you can always seize one or more +of his/her sectors. +Perhaps the mere threat of a collection on +someone's capital may do the trick! +.s1 +To settle up accounts on overdue loan #9 you would type: +.EX collect 9 +The program would then ask which sector you would like to claim +as just and rightful compensation for the outstanding debt. +.NF +What sector do you wish to confiscate? +.FI +To which you reply with the coordinates of a sector owned by your +debtor to which you are adjacent. +Any adjacent sector includes any sector you have that borders the +sector you wish to confiscate. +.s1 +The program then paws over the sector and assesses its value: +.NF +That sector (and its contents) is valued at $2345.00 +.FI +If the amount you are owed exceeds this amount the sector +becomes yours! +If the value of the sector is close enough to the +amount you are owed the debt is considered to be repaid. +.s1 +Any che in the area are left alone. Thus, if the original +owner takes the sector back over, the che would continue their +battle against the original owner, not the new owner. +.s1 +In addition, ships, land units, planes and nuclear stockpiles are +not collected. Those remain the property of the owner of the sector. +.s1 +Standing military in the sector are reduced to 1 and he becomes the +latest and greatest addition to your standing army. +.s1 +Mobility of the collected sector remains unchanged. +.s1 +.SA "consider, ledger, offer, shark, Loans" diff --git a/info/Commands/commodity.t b/info/Commands/commodity.t new file mode 100644 index 00000000..6fabb140 --- /dev/null +++ b/info/Commands/commodity.t @@ -0,0 +1,89 @@ +.TH Command COMMODITY +.NA commodity "Report commodities in sectors" +.LV Basic +.SY "commodity " +The commodity report provides information +pertaining to the various commodities +in some or all of the sectors you occupy. +.s1 +In the syntax of the commodity command + is the area on which you wish information, +(see \*Qinfo syntax\*U). +A typical usage might be: +.EX commodity -6:6,-3:3 +which would list data for the area extending +three sectors out from the capital in each direction. +.s1 +The commodity report lists each of your sectors +with the following heading: +.NF + +COMMODITIES deliver-- distribute + sect sgpidbolhr sgpidbolhr sh gun pet iron dust bar oil lcm hcm rad +.FI +These columns represent: +.s1 +.in \w'sgpidbolhr\0\0'u +.L sect +the x and y coordinates of the sector +.L sgpidbolhr +Ten delivery columns corresponding to: +shells, guns, petroleum (refined), iron, dust (gold), +bars of gold, oil, light construction materials, +heavy construction materials, and radioactive materials. +.L sgpidbolhr +Ten distribute columns corresponding to: +shells, guns, petroleum (refined), iron, dust (gold), +bars of gold, oil, light construction materials, +heavy construction materials, and radioactive materials. +.L sh +the number of shells in storage +.L gun +the number of guns in storage +.L pet +the number of units of refined petroleum +.L iron +the number of units of iron ore +.L dust +the number of units of gold dust +.L bar +the number of gold bars +.L oil +the amount of crude oil +.L lcm +the number of units of light construction materials +.L hcm +the number of units of heavy construction materials +.L rad +the number of units of radioactive materials +.in \\n(in +.s1 +For example: +.EX commodity -3:3,-2:2 +.NF +.ps -1 +COMMODITIES deliver-- distribute + sect sgpidbolhr sgpidbolhr sh gun pet iron dust bar oil lcm hcm rad + 6,0 k .......... ...1....0. 0 0 0 100 0 0 0 0 1 0 + -1,1 j .......... .......0.. 0 0 0 95 0 0 0 1 0 0 + 1,1 t .......... .......1.. 0 0 0 0 50 0 54 100 0 0 + -3,3 g ....g..... .......... 0 0 0 0 43 0 0 0 0 0 + -6,4 m ...j...... .......... 0 0 0 65 0 0 0 0 0 0 + -4,4 m ...u...... ...0...... 0 0 0 144 0 0 0 0 0 0 + -2,4 g .......... .......... 0 0 0 0 23 0 0 0 0 0 + 2,6 t .......... .......1.. 0 0 0 0 38 0 53 130 0 0 + 4,6 l .......... .......... 0 0 0 0 0 0 0 100 0 0 + 4,8 t .......... .......1.. 0 0 0 0 37 0 53 20 0 0 + 6,8 h .......... .......... 0 0 0 0 0 0 0 35 15 0 +11 sectors. +.ps +1 +.FI +The direction of delivery is indicated by the same characters +that are used in the \*Qmove\*U, \*Qnavigate\*U, +and other commands to indicate direction. +The presence of a distribution threshold for a particular commodity +is indicated by a digit in the appropriate column +under \*Qdistribute\*U, +representing the hundreds digit of the threshold value. +.s1 +.SA "census, Commodities, Sectors" diff --git a/info/Commands/consider.t b/info/Commands/consider.t new file mode 100644 index 00000000..cf50c854 --- /dev/null +++ b/info/Commands/consider.t @@ -0,0 +1,37 @@ +.TH Command CONSIDER +.NA consider "Accept, decline or postpone consideration of a loan or treaty" +.LV Expert +.SY "consider loan accept|decline|postpone" +.SY "consider treaty accept|decline|postpone" +This command allows you to consider accepting a loan or treaty +offered by another country. +.s1 +The program will list the various terms of the loan or treaty +under consideration and ask for your decision +as to whether to accept the terms, decline them, +or postpone making a decision. +.s1 +If you accept a loan, +the money is immediately credited to your account +and the time period of the loan starts. +If at the time of your acceptance, +the lender does not have sufficient funds the size of the loan +will be diminished to fit the lender's cash on hand. +.s1 +If you accept a treaty, +it goes into effect immediately but the time period of the treaty +is calculated based on the offer date +rather than the acceptance date. +.s1 +Loan offers are withdrawn if not accepted within a number +of days equal to the proposed loan's duration. +.s1 +Treaty offers expire at the time the proposed treaty would expire. +.s1 +Warning: When the terms of a loan are printed out, +take note of the due date; +if you do not pay by the due date the interest will double +and you will be subject to \*Qcollection\*U, +(see \*Qinfo collect\*U). +.s1 +.SA "collect, ledger, offer, treaty, Loans" diff --git a/info/Commands/convert.t b/info/Commands/convert.t new file mode 100644 index 00000000..1a891451 --- /dev/null +++ b/info/Commands/convert.t @@ -0,0 +1,40 @@ +.TH Command CONVERT +.NA convert "Change conquered civilians into uncompensated workers" +.LV Basic +.SY "convert " +The convert command converts \*Qenemy\*U (captured) populace into +uncompensated workers. +If the sector is not actually conquered, no civilians will be +converted. If you convert all the civs in a sector, then the sector +is no longer occupied (i.e. you become the "oldowner" of the sector). +.s1 +After the program has collected any necessary information +it will list each sector where civilians are converted. +.s1 +Note: you must have enough military in the sectors to force the +populace to become uncompensated workers -- about 10%. Land units +count toward this at a value equal to the number of mil required +to build them. Security units are even more efficient, counting for +more than their base value, and increase the number converted. +.s1 +There must also be mobility in the sector to be converted (see \*Qinfo +Mobility\*U for the exact formula). +.s1 +.s1 +.EX conv -3:3,-1:2 10 +.NF +Number to convert : 22 + 22 conquered populace converted in -1,-1 (30) + 13 conquered populace converted in 1,-1 (13) + 22 conquered populace converted in 3,-1 (30) + 17 conquered populace converted in -2,0 (17) + 22 conquered populace converted in 0,0 (36) + 22 conquered populace converted in -1,1 (34) + 22 conquered populace converted in 1,1 (34) + 18 conquered populace converted in 0,2 (18) + 22 conquered populace converted in 2,2 (45) +Total new uw : 180 +.FI +Note that there is a cost of 0.01 BTU's per civilian converted +in addition to the registration fee of $1.5 per conversion. +.SA "Populace, Mobility, Occupation" diff --git a/info/Commands/country.t b/info/Commands/country.t new file mode 100644 index 00000000..9d35f7c7 --- /dev/null +++ b/info/Commands/country.t @@ -0,0 +1,26 @@ +.TH Command COUNTRY +.NA country "Find out information about deity countries" +.LV Expert +.SY "country " + +The country command is temporarily out of order. +Please use the 'players' command instead. + +The country command displays a list of the countries you specify, +their numb, their last access time, their btu's, and their status. +.s1 +If you are \*QNOT\*U a deity, the country command will report on only +deity countries. (So that you can see if a deity is logged on) +Deity countries get the full report. Note that "Now logged on" is +often incorrect, and deities are recommended to use the new command +"players" to list players currently logged on. +.s1 +.EX country * +.NF +Thu Jan 21 07:14:12 1993 + # last access time status country name + 0 Now logged on [512] DEITY The_Scum + 1 Wed Jan 20 23:07 [512] Active Khazad'ur + 2 Thu Jan 21 07:00 [511] Active Spectre +.FI +.SA "players, Communication, Playing" diff --git a/info/Commands/cutoff.t b/info/Commands/cutoff.t new file mode 100644 index 00000000..ec9ee2a7 --- /dev/null +++ b/info/Commands/cutoff.t @@ -0,0 +1,83 @@ +.TH Command CUTOFF +.NA cutoff "List delivery thresholds" +.LV Expert +.SY "cutoff " +The cutoff report provides information about the various +delivery cutoff levels in some or all of the sectors that +you occupy. +.s1 +In the syntax of the level command + is the area on which you wish information, +(see \*Qinfo syntax\*U). +A typical usage might be: +.EX cutoff -6:6,-3:3 +which would list data for the area extending three sectors +out from the capital in each direction. +.s1 +The cutoff report lists each of your sectors with the following heading: +.NF +DELIVERY CUTOFF LEVELS + sect ufsgpidbolhr uw food sh gun pet iron dust bar oil lcm hcm rad +.FI +These columns represent: +.s1 +.in \w'ufsgpidbolh\0\0'u +.L sect +the x and y coordinates of the sector +.L ufsgpidbolhr +the twelve delivery direction columns correspond to the delivery +direction for food, guns, petroleum (refined), iron ore, dust (gold), +bars (dust), oil, lcm, and hcm. +.L uw +the delivery cutoff threshold for uncompensated workers in that sector +.L food +the delivery cutoff threshold for food in that sector +.L gun +the delivery cutoff threshold for guns in that sector +.L sh +the delivery cutoff threshold for shells in that sector +.L pet +the delivery cutoff threshold for petroleum in that sector +.L iron +the delivery cutoff threshold for iron ore in that sector +.L dust +the delivery cutoff threshold for gold dust in that sector +.L bar +the delivery cutoff threshold for gold bars in that sector +.L oil +the delivery cutoff threshold for oil in that sector +.L lcm +the delivery cutoff threshold for light construction materials +in that sector +.L hcm +the delivery cutoff threshold for heavy construction materials +in that sector +.L rad +the delivery cutoff threshold for radioactive materials in that sector +.in \\n(in +.s1 +For example: +.EX cutoff -3:3,-2:0 +.NF +.ps -1 +Wed Nov 12 00:15:51 1986 +DELIVERY CUTOFF LEVELS + sect ufsgpidbolhr uw food sh gun pet iron dust bar oil lcm hcm rad + 0,0 c ............ 0 0 0 0 0 0 0 0 0 0 0 0 + -5,-3 a n........... 0 400 0 0 0 0 0 0 0 0 0 0 + -6,-2 k j........... 0 400 0 0 0 0 0 0 0 0 0 0 + -4,-2 + j........... 0 400 0 0 0 0 0 0 0 0 0 0 + -2,-2 m ....n....... 0 0 0 0 0 0 0 0 0 0 0 0 + -5,-1 t ............ 0 0 0 0 0 0 0 0 0 0 0 0 + -1,-1 w ....j....... 0 0 0 0 0 800 0 0 0 0 0 0 + 1,-1 m ....j...b... 0 0 0 0 0 40 0 0 0 0 0 0 + 3,-1 j .....j...... 0 0 0 0 0 0 104 0 0 0 0 0 + 5,-1 b ............ 0 0 0 0 0 0 0 0 0 0 0 0 + 0,0 c y........... 0 200 0 0 0 0 0 0 0 0 0 0 + 2,0 + g.......j... 0 200 0 0 0 0 0 0 0 80 0 0 + -5,1 l ........j... 0 0 0 0 0 0 0 0 0 0 0 0 + 12 sectors +.ps +1 +.FI +.s1 +.SA "deliver, commodity, census, Distribution" diff --git a/info/Commands/declare.t b/info/Commands/declare.t new file mode 100644 index 00000000..9f50fb24 --- /dev/null +++ b/info/Commands/declare.t @@ -0,0 +1,54 @@ +.TH Command DECLARE +.NA declare "Formally declare alliance, friendly, neutrality, hostile or war" +.LV Basic +.SY "declare " +The declare command allows you to officially declare +your diplomatic relations with other countries. +.s1 + may be \*Qalliance\*U, \*Qfriendly\*U, \*Qneutrality\*U, +\*Qhostile\*U, or \*Qwar\*U; +.s1 + can be the name or number of +a country you want to declare relations towards, or it can be * in +which case you will declare towards all nations. +.s1 +For a complete list of the meanings of all the different types of +relations, see "info relations". +.s1 +GOING TO WAR +.s1 +(Note: the following stuff is only in effect if the SLOW_WAR option is selected) +With the SLOW_WAR option in use, you cannot attack the land of someone you are +not at war with. When you declare war on +someone, your relation goes to \*Qmobilizing\*U. You still can't attack them. +After the next update, your relation goes to \*Qsitzkrieg\*U, and you still +can't attack them. After the NEXT update, you're at war with them, and anything +goes. +.s1 +If someone is \*Qmobilizing\*U or in \*Qsitzkrieg\*U, or at war with you, +and you +declare war against them, your relation is set to be the same as theirs, so +there is no way to gain any advantage through this stuff. It just means that +you can't sneak-attack people. +.s1 +The first person who declares war pays $1000. Return declarations are +free. +.s1 +There is an exception to the SLOW_WAR restrictions. If you are listed as +the old owner of a sector, you are still allowed to attack it. This is to +prevent someone from declaring war with you, taking some sectors, then +declaring neutrality before you declare war. (Assuming you didn't notice +their declaration of war) +.s1 +Also, if the SNEAK_ATTACK option is enabled, you make make one attack upon +someone you're not at war with. You'll pay $5K for the privilege, however. +Once the sneak attack is over (win or lose), war is automatically declare. +(The normal $1K cost is waived in this case) +.s1 +The newspaper is very interested in declarations of war or alliance -- +don't expect to keep such declarations secret. +.s1 +Deities can will be prompted for a third parameter, the country to make +the declaration for. The default is to make it for the deity's country. +.s1 +.SA "fly, nation, spy, relations, Diplomacy" diff --git a/info/Commands/deliver.t b/info/Commands/deliver.t new file mode 100644 index 00000000..1149ed9d --- /dev/null +++ b/info/Commands/deliver.t @@ -0,0 +1,51 @@ +.TH Command DELIVER +.NA deliver "Establish delivery routes for shells, ore, etc" +.LV Expert +.SY "deliver [q|] []" +.s1 +An example of using deliver in addition to distribute is where +you may have a mine which uses distribute to get its food +from a warehouse, but uses deliver to export its iron to the adjacent +hcm factory. +.s1 +Deliver may be used to extra-fine tune a distribution network. In +fact, deliver can greatly improve the performance of a distribution +network if used properly. +.s1 +If 'q' is specified rather than a threshold, then the delivery +directions and thresholds will simply be listed. You can also use the +"cutoff" command to list delivery thresholds. +.s1 +The number specifies how much of that commodity you would +like to be kept in the sector. If you do not want to change the +direction that a sector delivers to, then put a '+' before the number +. +.s1 +Note that delivery thresholds are stored as multiples of 8. If you +specify a threshold that is not a multiple of 8, it will be rounded down. +.s1 +The direction must be specified as one of the six direction characters, +(usually `y' `u' `j' `n' `b' or `g'), the \*Qno-direction\*U character, +(usually `h'). If no direction is specified, then the direction will +not be changed for that sector. +.s1 +.EX "deli f 0,0 0 j" +Will deliver all food from 0,0 to 2,0. +.EX "deli i * ?des=m +87" +Will set iron delivery threshold to 80 in all mines. +.EX "deli l * q" +Will list all lcm delivery specifications. (Sectors with no delivery +threshold or direction will not be listed). +.s1 +The census and commodity reports will indicate deliveries by the +same characters used to specify them in this command. +.s1 +If, during an update, the destination sector is not owned by you, +the message \*Qdelivery walkout between x,y & x,y\*U will be printed +and nothing will be delivered. +.s1 +Delivery routes may also be mapped out with the \*Qroute\*U command. +.s1 +See "info Mobility" for an explanation of mobility costs. +.s1 +.SA "cutoff, census, commodity, route, distribute, Distribution" diff --git a/info/Commands/demobilize.t b/info/Commands/demobilize.t new file mode 100644 index 00000000..a4469d29 --- /dev/null +++ b/info/Commands/demobilize.t @@ -0,0 +1,57 @@ +.TH Command DEMOBILIZE +.NA demobilize "Change military into civilians" +.LV Basic +.SY "demobilize " +The demob command returns soldiers from the military +back to civilian life. +In addition, +you have the option of placing the returning GI's +into the nation's active reserve. +The active reserve provides a pool of available military +for a small salary (usually the same amount generated by a civilian) +and provides for quick mobilization of military +during a threat to national security. +.s1 +If is a positive number, that many military will be +demobilized in each sector, regardless of any military already there. +.s1 +If is a negative number, military beyond - will be +demobilized in each sector. +.s1 +As a result of demobilization, +and as a \*Qthank you\*U for serving their country in its time of need, +a \*QGI Bill\*U is given to each soldier to the tune of $5 each. +.s1 +Troops can only be demobilized in sectors which have greater than +60% efficiency, and only in \*Qhome sectors\*U +(that is, not in occupied territory). +.s1 +When troops are successfully demobilized in a given sector, +the number of new civilians is printed, +and the number in parentheses shows the total +number of military left in that sector. +.s1 +You have the option of placing civilians on active reserve. +Civilians on active reserve can later be enlisted +but you must pay them to stay on. +Generally civilian on active reserve costs one tenth of what +a military costs. +.s1 +.EX demob -2:0,0 1 +.NF +New civilians on active reserve? (y/n) y +1 demobilized in -2,0 (19 mil left) +1 demobilized in 0,0 (9 mil left) +Total new civilians : 2 +Military reserve stands at 2 (up 2) +.FI +.s1 +.EX demob -2:0,0 1 y +.NF +1 demobilized in -2,0 (18 mil left) +1 demobilized in 0,0 (8 mil left) +Total new civilians : 2 +Military reserve stands at 4 (up 2) +.FI +.s1 +.SA "enlist, Populace" diff --git a/info/Commands/designate.t b/info/Commands/designate.t new file mode 100644 index 00000000..2f23cb94 --- /dev/null +++ b/info/Commands/designate.t @@ -0,0 +1,40 @@ +.TH Command DESIGNATE +.NA designate "Specify sector utilization" +.LV Basic +.SY "designate " +In Empire all sectors have a \*Qdesignation\*U. +The \*Qdesignation\*U represents the principal industry or activity +taking place in that area. +When a sector is designated a harbor, for example, +the civilians in the sector start building shipyards and docks, +(with a little help from any military present). +.s1 +If the redesignated sector is already declared to be something else, +and is efficient, then the workers will have to tear down the existing +construction and then build the new sector. +The workers dismantle existing sectors four times faster than they +can build. +.s1 +As work progresses the efficiency will climb toward a maximum of 100%. +.s1 +If you don't specify the argument +in the command line as in: +.EX designate 1:3,2:5 +The program will ask for each sector specified +what you want the new sector designation to be. +.s1 +However, if you wish to designate one or several +sectors to be one particular thing and don't want to +be asked on each one you can type something like: +.EX designate -6:6,-3:3 ?type=f + +This will designate all fortresses that you own within +three sectors of your capital to be highways. +.s1 +Note that you cannot re-designate bridge spans. +.s1 +Normally, each point of efficiency added costs you $1. Some sectors +may cost more, and some may also require the expenditure of lcms and/or +hcms from the sector. In addition, some sectors may cost money merely +to designate. (see the \*Qshow\*U command and \*Qinfo show\*U for details) +.s1 +.SA "Sector-types, Sectors" diff --git a/info/Commands/disable.t b/info/Commands/disable.t new file mode 100644 index 00000000..169374aa --- /dev/null +++ b/info/Commands/disable.t @@ -0,0 +1,7 @@ +.TH Command DISABLE +.NA disable "Disable Updates" +.LV Expert +.SY "disable" +No updates will fire if you disable them. "UPDATES ARE DISABLED" will +show up in the output of the "update" command. +.SA "update, enable, Deity" diff --git a/info/Commands/disarm.t b/info/Commands/disarm.t new file mode 100644 index 00000000..7b0b383a --- /dev/null +++ b/info/Commands/disarm.t @@ -0,0 +1,9 @@ +.TH Command DISARM +.NA disarm "Remove a nuclear warhead from a plane or missile" +.LV Expert +.SY "disarm " +The \*Qdisarm\*U command removes nuclear warheads from +delivery systems such as planes or missiles. +.s1 +.s1 +.SA "arm, transport, Planes" diff --git a/info/Commands/dissolve.t b/info/Commands/dissolve.t new file mode 100644 index 00000000..d40ab5dc --- /dev/null +++ b/info/Commands/dissolve.t @@ -0,0 +1,21 @@ +.TH Command DISSOLVE +.NA dissolve "Dissolve your government and country (suicide)" +.LV Expert +.SY "dissolve" +The dissolve command is the coward's way out of Empire. +It does several things: +it gives all your sectors back to The Deity, +pays off any debts that it can, +voids any treaties in which you were involved, +and allows your ships to decide their own fate. +Some ships riot, some go up for sale, and some are scuttled. +.s1 +Using the dissolve command is simplicity itself: +.EX dissolve +You will be given one last chance to change your mind: +.NF +Are you SURE you want to do this? +.FI +And then it's curtains... +.s1 +.SA "pray, Nation" diff --git a/info/Commands/distribute.t b/info/Commands/distribute.t new file mode 100644 index 00000000..fc3d5510 --- /dev/null +++ b/info/Commands/distribute.t @@ -0,0 +1,98 @@ +.TH Command DISTRIBUTE +.NA distribute "Establish distribution destination sector" +.LV Basic +.SY "distribute " +The distribute command is used to specify the way that goods will +travel during an update. +Each sector is allowed to have one and only one +\*Qdistribution sector\*U (a warehouse or road, typically). +Subsequent distribute commands +will replace the existing distribution sector. +.s1 +For example, +.EX distribute 2,0 8,4 +.NF +highway at 2,0 delivers to 8,4. +Distribution sector? 7,-1 +highway 2,0 new path distributes to 7,-1 (cost 0.200) + Current best path is 'gguh' +.FI +This command changed the distribution path for sector 2,0 from +a warehouse at 8,4 to a warehouse at 7,-1. The cost is the mobility cost +to move 1 normal-weight unit from the sector to the warehouse. +.s1 +DISTSECT is a normal empire sector specification. During the update, +empire will determine the cheapest existing path to the distribution +sector, and use that. (Note that the mobility cost for the path used +during the update could +be different than the cost reported to you when you use the distribute command, +if you have re-designated sectors, or sectors were captured, etc) +Again, it will use the cheapest path available AT THE TIME OF THE UPDATE. +.s1 +You may also use '.' or 'h' to specify no distribution sector. +.s1 +.EX dist 2,0 . +.NF +Distribution to and from 2,0 halted. +.FI +.s1 +The command will warn you if there is no existing path completely +owned by you, and also if the path does not end at a warehouse. +It is not required that the distribution path end at a warehouse, +but it is required that you own all the sectors that the goods +will travel along. +.s1 +.L "Distribution & the Update" +.s1 +One of the last things that takes place during the update, after all growth, +production, delivery, etc, distribution takes place. (The only thing that +really happens after that is mobility increases) Each sector may have +product +thresholds and a distribution sector. A threshold is a target level for a +particular commodity, like food. So, if the food threshold for a sector is +100, it will try to maintain 100 food there. If it has more than 100 food, +it will export it to its distribution point. If it has less than 100, it +will try to import food from the distribution point to reach 100. +.s1 +During the distribution phase of the update, all sectors (going left to +right, top to bottom) first export excess +commodities, and then (again left to right, top to bottom) +import needed commodities. +.s1 +In order to either send things to or get things from a distribution sector, +you must own the distribution sector, and there must be a path of owned +sectors to it. In order to export something from a sector, you must have +military control of the sector. In order to import something from a +distribution sector, you must have military control of the distribution +sector. (Military control is defined as having mil in the sector equal +to at least 1/10th the number of unconverted civilians there. Units count +as if they were straight mil, i.e. a 100% unit that contained 50 mil would +count as 50 mil for the purposes of control) +.s1 +Mobility is used from the sector when sending \*Qto\*U the distribution sector. +When getting something \*Qfrom\*U the distribution sector, mobility is paid +by the distribution sector. See \*Qinfo Mobility\*U for an +explanation of mobility costs. +.s1 +.L Amount +.s1 +The amount is determined by the threshold, as explained above. +Use the \*Qthreshold\*U command to specify what goods +will flow to and from the warehouse. +.s1 +.L "Finding sectors with not dist point set" +.s1 +If you want to find sectors with no distribution point set, use the +xdist and ydist selectors: +.s1 +.EX level # ?xdist=xloc&ydist=yloc +.s1 +This finds all sectors that have themselves as a distribution point. +.s1 +.L "Distributing civilians" +.s1 +When distributing civilians, no distribution point will ship out its +last civilian, regardless of thresholds set in sectors using it as a +distribution point. +.s1 +.SA "deliver, threshold, level, Distribution" diff --git a/info/Commands/drop.t b/info/Commands/drop.t new file mode 100644 index 00000000..56837b52 --- /dev/null +++ b/info/Commands/drop.t @@ -0,0 +1,44 @@ +.TH Command DROP +.NA drop "Use planes to drop commodities in your own sectors" +.LV Expert +.SY "dropoff " +The \*Qdropoff\*U command is used to resupply beleaguered friendly +troops with food, shells, reinforcements, and other necessities of +battle. +.s1 + represents a list of planes which are to travel +to the target sector. +Only planes which are provided with gas, and have sufficient mobility will +be successfully selected for the mission. +.s1 + represent a list of fighter planes which are capable of escorting +the transports all the way to the target. +To be selected, escorts must have fuel and mobility. +.s1 + represents an assembly point, where all of the planes in the +mission meet before proceeding on to the target sector. +The assembly point must be owned by you, and must not be more than +four sectors away from any of the planes selected for the mission. +.s1 + is the name of a commodity which is to be carried along +on all of the planes which have a transport capacity. +.s1 +Route is a normal empire path specification. You may also give a +destination sector on the command line, or at any time while giving +the route, and empire will use the best path from the current sector +to the desired destination sector. +.s1 +When getting a path interactively, empire will show you the information +you have (from your bmap) concerning the current area, to help you plot +your course. +.s1 +Planes which arrive safely at the target sector will drop the goodies off +to the waiting people below. +.s1 +Any plane with the \*Qmine\*U ability can +mine a sector by dropping shells in a sea sector. +.s1 +Note that a plane must be at least 40% efficient before it can leave +the ground. +.s1 +.SA "Plane-types, bomb, fly, paradrop, recon, Mobility, Planes, Commodities" diff --git a/info/Commands/dump.t b/info/Commands/dump.t new file mode 100644 index 00000000..bd88392f --- /dev/null +++ b/info/Commands/dump.t @@ -0,0 +1,125 @@ +.TH Command DUMP +.NA dump "Dump raw sector information" +.LV Expert +.SY "dump []" +The dump command displays all information on +some or all of the sectors you occupy. +dump is a combination of census, commodity, cutoff and level. +Each sector's information is printed on one very long line. +Fields are separated by a single space. +If no fields are specified, all fields are printed. +.s1 +This command is designed to be used for input to an empire tool +such as \*Qve\*U. +.s1 +In the syntax of the dump command + is the area on which you wish information, +[] are the fields you wish to dump. +If no fields are specified, all fields are printed. +(see \*Qinfo Syntax\*U). +.s1 +A dump command lists all selected sectors headed by: +.NF +Sun Feb 9 22:16:37 1997 +DUMP SECTOR 855544597 + +.FI +The first line is the date. The second line is the +"DUMP SECTOR " where the field is the current +timestamp. The third line is the columns which are output. +.s1 +The following may be used as fields. They must be entered EXACTLY as +shown here (no partial pattern matching is done.) +.s1 +.NF + des + sdes + eff + mob + * + off + min + gold + fert + ocontent + uran + work + avail + terr + civ + mil + uw + food + shell + gun + pet + iron + dust + bar + oil + lcm + hcm + rad + u_del + f_del + s_del + g_del + p_del + i_del + b_del + o_del + l_del + h_del + r_del + u_cut + f_cut + s_cut + g_cut + p_cut + i_cut + d_cut + b_cut + o_cut + l_cut + h_cut + r_cut + dist_x + dist_y + c_dist + m_dist + u_dist + f_dist + s_dist + g_dist + p_dist + i_dist + d_dist + b_dist + o_dist + l_dist + h_dist + r_dist + road + rail + defense + fallout + coast + c_del + m_del + c_cut + m_cut + terr1 + terr2 + terr3 +.FI +.s1 +A typical usage might be: +.EX dump #5 +which would list data for all sectors in realm #5. +.s1 +A dump lists each of your sectors in the specified area. +The header line is a list of fields that correspond +to the order that dump prints the sector info. +.FI +.s1 +.SA "census, commodity, cutoff, level, Clients, Sectors" diff --git a/info/Commands/echo.t b/info/Commands/echo.t new file mode 100644 index 00000000..e56d7ab9 --- /dev/null +++ b/info/Commands/echo.t @@ -0,0 +1,24 @@ +.TH Command ECHO +.NA echo "Echo a string back to the client" +.LV Expert +.SY "echo []" +The echo command echos its arguments. +It is designed to help clients synchronize their commands +with the server when operating asynchronously. Note that if there are +any spaces in your string, then you will need to include the string in +quotes. +.s1 +For example: +.EX echo SN#123456 +.nf +SN#123456 +.fi +.EX echo hi mom +.nf +hi +.fi +.EX echo \Q*hi mom\U* +.nf +hi mom +.fi +.SA "toggle, Communication" diff --git a/info/Commands/edit.t b/info/Commands/edit.t new file mode 100644 index 00000000..b0a36870 --- /dev/null +++ b/info/Commands/edit.t @@ -0,0 +1,7 @@ +.TH Command EDIT +.NA edit "Change stats of country, ship, land unit, or plane" +.LV Expert +.SY "edit " +Once you specify what you want to edit, the server will tell you what +to do. Hit return to get out of the prompter. +.SA "setsector, setresource, give, Deity" diff --git a/info/Commands/enable.t b/info/Commands/enable.t new file mode 100644 index 00000000..7c672d39 --- /dev/null +++ b/info/Commands/enable.t @@ -0,0 +1,6 @@ +.TH Command ENABLE +.NA enable "Enable updates" +.LV Expert +.SY "enable" +If updates have been disabled, then this will enable them again. +.SA "update, enable, force, Deity" diff --git a/info/Commands/enlist.t b/info/Commands/enlist.t new file mode 100644 index 00000000..fd2202e7 --- /dev/null +++ b/info/Commands/enlist.t @@ -0,0 +1,52 @@ +.TH Command ENLIST +.NA enlist "Turn civilians into military" +.LV Basic +.SY "enlist " +The enlist command converts civilians into military +in the sectors specified. +Military \*Qcreated\*U by the enlist command are actually reserves +called up from your country's military reserve. +If your country has no military reserves +(created by \*Qdemobilize\*U) +then no civilians will be converted and no military will be generated. +.s1 +After the program has collected any necessary information, +it will list each sector where civilians answer the call +and the number who showed up followed by +the total number of military resulting (in parentheses). +.s1 +If is a positive number that many draftees will be sought in +each sector regardless of any military already in the sector. +.s1 +If is a negative number of the form -\fBxxx\fP, +then an enlistment quota is established +and the draft board will attempt to enlist enough in each sector +to bring the total number of military up to \fBxxx\fP in each sector. +.s1 +Although the program tries to draft the specified number of +civilians in each sector only one-half of the civilians +in a sector can be called upon at any one time. +.s1 +Civilians in conquered sectors (the conquered populace) +will not serve in your armed forces. +.s1 +.EX enl -3:3,-1:2 10 +.NF +Number to enlist (max 397) : 22 + 22 enlisted in -1,-1 (30) + 13 enlisted in 1,-1 (13) + 22 enlisted in 3,-1 (30) + 17 enlisted in -2,0 (17) + 22 enlisted in 0,0 (36) + 22 enlisted in -1,1 (34) + 22 enlisted in 1,1 (34) + 18 enlisted in 0,2 (18) + 22 enlisted in 2,2 (45) +Total new enlistment : 180 +Paperwork at recruiting stations ... 3.6 +.FI +Note that there is a cost of 0.2 BTU's per draftee in addition to the +basic cost of the command and enlistees use up some mobility in the +enlistment process (see \*Qinfo Mobility\*U for the exact formula). +.s1 +.SA "demobilize, Mobility, Populace" diff --git a/info/Commands/execute.t b/info/Commands/execute.t new file mode 100644 index 00000000..803fc670 --- /dev/null +++ b/info/Commands/execute.t @@ -0,0 +1,8 @@ +.TH Command EXECUTE +.NA execute "Execute a batch file" +.LV Expert +.SY "execute " +This command reads Empire commands from and executes them. +.s1 +Note: Not all clients support the execute protocol. +.SA "Playing" diff --git a/info/Commands/explore.t b/info/Commands/explore.t new file mode 100644 index 00000000..98186dd8 --- /dev/null +++ b/info/Commands/explore.t @@ -0,0 +1,93 @@ +.TH Command EXPLORE +.NA explore "Claim unowned land" +.LV Basic +.SY "explore " +The explore command takes over part of the functionality of move. +Explore is used to stake your claim to unowned sectors. +Only civilians and military can be used to explore. +.s1 + can be any one of: +.NF +c civilians +m military +.FI +.s1 +If is not provided in the command line, +the program will request the starting sector +then display the resources of that sector and a map of the +adjoining sectors. +The prompt consists of the number of mobility units in that sector, +its designation, and its coordinates in the form: +.s1 +.NF +<97.0: a -6,4> +.FI +.s1 +which indicates 97 mobility units in agribusiness sector -6,4. +You may respond with any combination of: +.s1 +.NF +y for up-left +u for up-right y u +g for left \\\\ / +j for right g -- -- j +b for down-left / \\\\ +n for down-right b n +v for view +m for map +h for end of movement +.FI +.s1 +The \*Qview\*U command shows the sector efficiency +and some of the contents of the sector you are currently occupying. +.s1 +Since the can be specified in the command line, +simple movements are often typed as a single line, such as: +.EX explore m 2,0 20 jjjh +Or some movements may be done partly on the command line and partly +interactively: +.EX explore c 2,0 1 gg +.NF + - ^ min gold fert oil uran + - - + 67 0 0 0 82 + - ^ +<125.4: - -4,0> v +0% wilderness with 0 civilians. + - ^ min gold fert oil uran + - - + 67 0 0 0 82 + - ^ +<125.4: - -4,0> h +Sector -4,0 is now yours. +.FI +.s1 +You may also simply specify the destination sector on the +command line. In this case, +empire will set the path to be the cheapest path (in terms of +mobility) from the current sector to the destination sector, +if such a path exists. However, the best path cannot extend out +of your owned sectors, so the best use for this feature is to use +it to get to the edge of your owned territory, and then explore +manually from there. +.s1 +For example, +.EX explore 2,0 1 -2,0 +.NF + ^ - min gold fert oil uran + - + c 67 0 0 0 82 + ^ - +<126.2: - -2,0> g + - ^ min gold fert oil uran + - - + 67 0 0 0 82 + - ^ +<125.4: - -4,0> h +Sector -4,0 is now yours. +.FI +.s1 +See 'info Mobility' for a description of how much mobility it costs to +explore into sectors. +.s1 +Note that while exploring, you might hit mines. The more civs or +mil you explore with, the greater the chance of setting off any +mines in the sectors you move through. See info lmine for details. +.s1 +.SA "move, test, navigate, transport, lmine, Populace, Sectors" diff --git a/info/Commands/financial.t b/info/Commands/financial.t new file mode 100644 index 00000000..07a78460 --- /dev/null +++ b/info/Commands/financial.t @@ -0,0 +1,26 @@ +.TH Command FINANCIAL +.NA financial "Show all the outstanding loans in the world" +.LV Expert +.SY "financial" +The financial report shows all of the outstanding loans in the world, +so that the loan sharks can better calculate +the ability of a prospective client to pay. +.s1 +It does not show loan offers pending, however, +just those loans which have been accepted. +.s1 +If a loan is past due (i.e. the loanee has defaulted on the loan) the +"(in arreras)" is printed after the line of that loan. Loans in default +may be "sharked" up and collected upon. +.s1 +.EX financial +.NF + -= Empire Financial Status Report =- + Mon Oct 6 11:12:30 1986 +Loan From To Rate Dur Paid Total + 6 ( 2) Domino ( 3) Oz 0% 10 0 5000 + 8 ( 4) Zyf (14) Id 0% 30 0 2000 (in arreras) + 11 ( 2) Hodedo ( 3) Oz 13% 15 18000 25000 +.FI +.s1 +.SA "offer, ledger, shark, Loans" diff --git a/info/Commands/fire.t b/info/Commands/fire.t new file mode 100644 index 00000000..2aec09e9 --- /dev/null +++ b/info/Commands/fire.t @@ -0,0 +1,158 @@ +.TH Command FIRE +.NA fire "Fire artillery from sector/ship/unit on sector/ship" +.LV Basic +.SY "fire [sect | ship | land] [ | | ] [ | ] +When the multi-fire option is enabled, the syntax of the fire command +changes. It is still used to shoot up land sectors or ships. However, +you may now use multiple ships, units, sectors to fire from. Return +fire is spread amongst all the firing things. +.s1 +If the SLOW_WAR option is in use, you cannot fire on the +land of any nation you are not at war with. (see info relations) +.s1 +The general form for shooting at land from a sector is: +.EX fire sect +Where is the victim sector, +(the sector AT which you are shooting, +not the sector FROM which you are shooting). +ASECTS is a sector or sectors. +.s1 +The general form for shooting at land from ships is: +.EX fire ship +.s1 +The general form for shooting at land from units is: +.EX fire land +.s1 +The general form for firing at ships from land is: +.EX fire sect +Again, is the victim ship number. +.s1 +The general form for firing at ships from ships is: +.EX fire ship +.s1 +The general form for firing at ships from units is: +.EX fire land +.s1 +If not specified on the command line +the program will ask for the sector(s), land unit(s), +or ship(s) FROM which you are firing, (, , or ). +It will also prompt you for targets for each sector/unit/ship firing, if you +did not specify the target on the command line. +.s1 +The only sector that may fire is a fortress, +which must be at least 5% efficient, have at least two military for a +firing crew, +at least one shell to fire, +and a gun big enough to reach the victim location; +range is equal to (7 * ((tech+50)/(tech+200)). If the +fortress is at least 60% efficient, it gets a +1 range bonus. +A fortress firing uses 1 shell. +.s1 +Note that forts cannot fire if the NO_FORT_FIRE option is enabled. +See info \*QOptions\*U for more info. +.s1 +Any military ship may fire as long as it has +at least one crew (which must be military, not civilians), +at least one gun, +at least one shell (or shells within supply range), +and has at least 60% efficiency. +A ship's gun range is its firing range, as shown by +the show command, divided by two, times ((tech+50)/(tech+200). +A ship uses one shell per two guns firing. +.s1 +Any land unit may fire as long as it has +at least one military, +at least one shell (or shells within supply range), +and has at least 40% efficiency. +A land unit's gun range is its firing range, as shown by the show +command, divided by two, times ((50+tech)/(200+tech)). A land unit +uses the amount of ammo, as shown by the lstat command, each time +it fires. +A unit with less shells than its ammo requirement will do +proportionately +less damage. +(See \*Qshow\*U for firing ranges) +.s1 +Forts, land units, and non-depth-charge-equipped ships + cannot hit submarines on the high seas. +The only way to fire on a submarine is to have a depth-charge-equipped +ship drop a depth charge on it, costing two shells. (Note you can +also hit subs using ASW planes or subs which have sub-torp capability.) +.s1 +The program then prints a satisfying \*QKaboom!!!\*U and, +assuming you were in range, inflicts damage. +.s1 +Ships lose mobility points equal to 1/2 the cost they would +pay to move 1 sector for each shot fired. (If the NOMOBCOST +option is in use, ships pay no mobility for firing.) +.s1 +The damages inflicted vary with efficiency of the attacker, +the size of the guns +(battleship guns are four times as big as patrol boat guns), +the number of guns fired (7 being the useful max for forts), +and the armor of the victim. +Land sectors take damage depending on their defensive strength. +Use the command 'show sector stats' to show defensive strengths. +The higher the defensive strength, the less damage the sector +will take. +.s1 +An illustrative example of shelling land: +.EX fir sect 36,18 34,18 +.NF +Kaboom!!! +13% damage done to sector 34,18 +.FI +Meanwhile, the owner of sector 34,18 might be logged on and would +perhaps see the following: +.NF +[15:98] Command: cen 34,18 +Sat Jul 30 16:18:01 1984 +CENSUS del cnt + sect eff mob cmf cmf % * civ mil food min gmin fert oil + 34,18 i 100% 127 ... ... 200 100 23 23 31 73 18 + 1 sector +You have a telegram waiting ... +.FI +.NF +[15:98] Command: read +BULLETIN! dated Sat Jul 30 16:18:02 1984 +Country #9 shelled 34,18 +Shall I burn it? y +.FI +.NF +[15:98] Command: cen 34,18 +Sat Jul 30 16:18:26 1984 +CENSUS del cnt + sect eff mob cmf cmf % * civ mil food min gmin fert oil + 34,18 i 87% 110 ... ... 175 83 20 23 31 73 18 + 1 sector +.FI +Note that the shell did about 13% damage in the sector. + +The player could have typed: +.EX fir sect #0 ?des=f 34,18 + +In that case, ALL forts in realm 0 would have fired on sector 34,18. +.s1 +If the sector fired on is a fort with guns and shells it will fire back +with approximately the same damages (assuming it has the range). +.s1 +Also, any friendly forts, units, or ships within range of the attacker +will return fire, including those belonging to allies, if the allies +are at war with the attacker as well. +.s1 +If a ship fired on has guns and shells it will fire back AND +any other ships, units, or forts of the same nationality that are in range +will also fire on you. +.s1 +All return fire is split evenly over all attacking sectors/units/ships, and is +adjust by the ratio of defending things to attacking things. +.s1 +As a change from the original fire command, with multi-fire enabled, +you will not return fire on yourself. +.s1 +IMPORTANT NOTE: Gun ranges, both on offense AND defense, are somewhat random. +If you have a range of 4.16, you can always shoot to 4, and have a 16% chance +of being able to fire at range 5... +.s1 +.SA "attack, assault, torpedo, Technology, relations, Damage, Combat, Ships" diff --git a/info/Commands/flash.t b/info/Commands/flash.t new file mode 100644 index 00000000..ba21d1e5 --- /dev/null +++ b/info/Commands/flash.t @@ -0,0 +1,33 @@ +.TH Command FLASH +.NA flash "Send a message directly to a friend's terminal" +.LV Expert +.SY "flash []" +.s1 +The argument is either the number or name of +the recipient nation. +.s1 +flash allows instant communication between friendly nations. +flash has two different syntaxes. You can either send your friend a one +line message as in: +.EX flash Foobots Hi there, I'm back from lunch +.s1 +Or you can send a multi-line message: +.EX flash Foobots +.NF +> Hi there. +> I ate Fodderland for lunch. +> . +.FI +Note that you can end a multi-line flash with either a '.' (period) +on a line all by itself, or by hitting ^D on a line by itself. +Note also that all messages are truncated to 60 characters long! +.s1 +If you do not wish to receive any flash messages from your friends, +then you can temporarily turn the feature off by typing "toggle flash". +.s1 +Note that if the person you are flashing is allied to you, you will +be informed if they are not logged in or not accepting flashes when you attempt +to flash them. This only works when *they* are allied with you, since +you would normally see them logged in or not using "players" +.s1 +.SA "toggle, wall, declare, players, telegram, Communication" diff --git a/info/Commands/fleetadd.t b/info/Commands/fleetadd.t new file mode 100644 index 00000000..eaf92327 --- /dev/null +++ b/info/Commands/fleetadd.t @@ -0,0 +1,43 @@ +.TH Command FLEETADD +.NA fleetadd "Designate members of a \*Qfleet\*U" +.LV Expert +.SY "fleetadd " +The fleetadd command is used to specify the fleet groupings +of your ships. +.s1 +.EX fleetadd +In the syntax is the alphabetic character to be used as the +fleet designation. +This character can be chosen from the set of +upper or lower case a-z and tilde (~). +The pseudo-fleet specification tilde +specifies all ships not currently in any fleet. +.s1 +The specification of ships, , +can have one of several syntaxes: +.NF +example meaning +------- ------- +23 ship 23 +2/14/23 ships 2, 14, and 23 +c all ships currently in fleet `c' +~ all ships currently in the \*Qnull\*U fleet +2,3 all ships in sector 2,3 +-1:3,0:2 all ships in the square area bounded by -1,0 & 3,2 +.FI +All fleets, (with the exception of the `~' fleet), +are limited to some maximum size +and you will be informed how many ships can be added +when this command is run. +.s1 +Having ships organized into fleets can be very helpful in +loading, moving, etc., +in that fewer commands are required to perform these commands +on groups of ships if they can be specified by fleet number. +.s1 +Note that you can remove ships from a fleet by adding them to +the `~' fleet. e.g. +.EX fleetadd ~ A +This command would purge all ships from fleet `A'. +.s1 +.SA "load, lookout, navigate, radar, ship, unload, Ships" diff --git a/info/Commands/fly.t b/info/Commands/fly.t new file mode 100644 index 00000000..82d41725 --- /dev/null +++ b/info/Commands/fly.t @@ -0,0 +1,43 @@ +.TH Command FLY +.NA fly "Fly planes from sector/ship to sector/ship and bomb or snoop" +.LV Basic +.SY "fly " +The \*Qfly\*U command is used to move planes and commodities from +the starting sector(s), and ending up in the target sector. +.s1 + represents a list of planes which are to travel +to the target sector. +Only planes which are provided with gas, and have sufficient mobility will +be successfully selected for the mission. +.s1 + represent a list of fighter planes which are capable of escorting +the transports all the way to the target. +To be selected, escorts must have fuel and mobility. +.s1 + represents an assembly point, where all of the planes in the +mission meet before proceeding on to the target sector. +The assembly point must be owned by you, and must not be more than +four sectors away from any of the planes selected for the mission. +.s1 + is the name of a commodity which is to be carried along +on all of the planes which have a transport capacity. +If nothing is specified, then nothing will be carried. +.s1 +Route is a normal empire path specification. You may also give a +destination sector on the command line, or at any time while giving +the route, and empire will use the best path from the current sector +to the desired destination sector. +.s1 +When getting a path interactively, empire will show you the information +you have (from your bmap) concerning the current area, to help you plot +your course. +.s1 +If the transports stray over enemy territory, then they will be +intercepted and shot at just like any other mission. +If the destination sector is not an airport, then all planes in +the mission must have VTOL capability. +.s1 +Note that a plane must be at least 40% efficient before it can leave +the ground. +.s1 +.SA "Plane-types, bomb, paradrop, drop, recon, Mobility, Planes, Moving" diff --git a/info/Commands/follow.t b/info/Commands/follow.t new file mode 100644 index 00000000..4a885719 --- /dev/null +++ b/info/Commands/follow.t @@ -0,0 +1,23 @@ +.TH Command FOLLOW +.NA follow "Cause one ship to automatically follow another" +.LV Expert +.SY "follow " +You use the \*Qfollow\*U command to get a ship to use the same +sailing path as another ship. +At each update, ships with a sailing path \*Qautonavigate\*U along +the path that was set for them, and ships that are set +to follow that ship will also be navigated along the same +path. Telegrams notify you of arrivals +or problems encountered while attempting to follow the path. +.s1 +Radar operates continuously as the ship moves along the path, constantly +adding sector information to the known world map. +.s1 +Ship movement is performed before mobility is increased. +This insures that after the update, ships with a sailing path will still +have some mobility so that you can always manually navigate +to some extent. +.s1 +You may follow any ship which is owned by you or a friendly country. +.s1 +.SA "sail, unsail, mquota, Ships" diff --git a/info/Commands/force.t b/info/Commands/force.t new file mode 100644 index 00000000..3be565ae --- /dev/null +++ b/info/Commands/force.t @@ -0,0 +1,6 @@ +.TH Command FORCE +.NA force "Force an update" +.LV Expert +.SY "force " +Force an update in seconds. +.SA "enable, disable, shutdown, Deity" diff --git a/info/Commands/fortify.t b/info/Commands/fortify.t new file mode 100644 index 00000000..9a1e59c5 --- /dev/null +++ b/info/Commands/fortify.t @@ -0,0 +1,33 @@ +.TH Command FORTIFY +.NA fortify "Fortify a land unit" +.LV Basic +.SY "fortify " +The \*Qfortify\*U command is used to make units dig in and +make themselves harder to damage. The maximum amount of +fortification is the same as the maximum amount of mobility +a unit can have. (The version command will print this info). +Each point of mobility used increases the fortification value by one. +.s1 +If is a positive number, at most that much mobility will be +used. +.s1 +If is a negative number, at least - will be left +in each unit. +.s1 +A fully fortified unit is twice as hard to hurt as it normally +would be, and is twice as strong on the defense. +.s1 +Units fortifying in a sector containing an engineering unit +are better at it. Experiment and find out. +.s1 +If a unit moves or retreats, it loses all fortification value. +A unit that reacts to defend a sector, on the other hand, does NOT +lose its fortification unless it is forced to retreat. It receives +the fortification bonus in combat, and is still fortified when it +returns to its original sector after the battle. +.s1 +Note that fortification will not help a unit fight Guerrillas in +an occupied sector (see info Guerrilla). Also note that fortifying +a unit does not affect it's mission status. +.s1 +.SA "bomb, Unit-types, LandUnits" diff --git a/info/Commands/fuel.t b/info/Commands/fuel.t new file mode 100644 index 00000000..c0e09c5a --- /dev/null +++ b/info/Commands/fuel.t @@ -0,0 +1,41 @@ +.TH Command FUEL +.NA fuel "Give fuel to a ship/unit" +.LV Basic +.SY "fuel []" +The fuel command carries out the fueling of ships and units. +The ship(s) must be in a harbor and +the harbor must be at least 2% efficient. +Land units may be in any sector. +Alternatively, you can fuel at sea using an oiler, which is +any ship with the oiler ability. (Note: if you are in a harbor, +you can't fuel from an oiler, you must use the harbor) +.s1 +Ships and units can be fueled by either petrol or oil, with petrol being +used first. 1 unit of petrol = 5 fuel units. 1 unit of oil = 50 +fuel units. Each ship or unit, in turn, will attempt to take on the +specified amount of fuel. Petrol/oil will be used for each ship or unit, +the amount being rounded up individually. For example, if you have +a harbor with 50 fuel in it, and you tell a ship with a 50 fuel +capacity to load 50 fuel, it'll use 1 oil. If you tell it to load +*1* fuel 50 times, it'll use *50* oil, with the round-up making +it use 1 oil each time. The solution, of course, is to not load +fuel in tiny, wasteful amounts. +.s1 +Each update, ships and units use fuel to make mobility points. To produce +10 mobility points requires the number of units of fuel listed +for the ship or unit in the capability list. (see info show) +(This number is usually 1, but may be more). If the number is a 0, +the unit does not use fuel. +.s1 +If the ship or unit has no fuel, +it will attempt to get fuel using the supply procedure (see +info supply). It will try to use first petrol, then oil, until it has enough +fuel to get full mobility. +If it can't get fuel by using the supply system, it won't get mobility. +.s1 +See \*Qshow\*U for a table of the maximum amounts of +fuel that can be carried on each type of unit or ship. +.s1 +You can fuel friendly ships, but must fuel them one at a time, by number. +.s1 +.SA "Ship-types, Unit-types, Ships, LandUnits" diff --git a/info/Commands/give.t b/info/Commands/give.t new file mode 100644 index 00000000..f391243a --- /dev/null +++ b/info/Commands/give.t @@ -0,0 +1,6 @@ +.TH Command GIVE +.NA give "Give(take) Commodities" +.LV Expert +.SY "give " +To get a list of which commodities you can change, type "give" with no arguments. +.SA "setsector, setresource, edit, Deity" diff --git a/info/Commands/grind.t b/info/Commands/grind.t new file mode 100644 index 00000000..32a9f85a --- /dev/null +++ b/info/Commands/grind.t @@ -0,0 +1,10 @@ +.TH Command GRIND +.NA grind "Grind bars back into dust" +.LV Expert +.SY "grind " +The \*Qgrind\*U command converts gold bars back into dust. +This costs 1 BTU plus 5 \*Qavailable work units\*U per bar and can be +done in any sector which is at least 60% efficient. +Due to inefficiencies in the conversion process, only 80% of +the dust can be recovered. +.SA "Commodities" diff --git a/info/Commands/harden.t b/info/Commands/harden.t new file mode 100644 index 00000000..813e805a --- /dev/null +++ b/info/Commands/harden.t @@ -0,0 +1,19 @@ +.TH Command HARDEN +.NA harden "Place missiles into protective silos" +.LV Expert +.SY "harden " +The \*Qharden\*U command is used to install missiles +into protective silos which can prevent their destruction +during a nuclear or non-nuclear +attack. +Each successive \*Qharden\*U command +will add to the current hardness level of the missile in question. +.s1 +Each point of hardening uses one unit of heavy construction materials, +and costs $5. +.s1 +Once a missile has been placed in a silo +(hardened to a level greater than 0) +it can no longer be moved. +.s1 +.SA "launch, Nuke-types, Plane-types, Planes" diff --git a/info/Commands/headlines.t b/info/Commands/headlines.t new file mode 100644 index 00000000..77fa474f --- /dev/null +++ b/info/Commands/headlines.t @@ -0,0 +1,19 @@ +.TH Command HEADLINES +.NA headlines "Summarize the weeks events (part of \*Qnews\*U)" +.LV Expert +.SY "headlines [days]" +The headlines command lets you read just the important, +subjective, summary part of the news +without boring you with the confusing details. +.s1 +If you include a number in the command, +it will print headlines based on the news from that many previous days. +.s1 +The headline \*QRelative Calm Prevails\*U appears +whenever the reporters haven't been able to dig up +any interesting tidbits to give the news analysts. +.s1 +The headlines are produced by the editorial staff of the +Empire News who are solely responsible for their lack of content. +.s1 +.SA "newspaper, Communication" diff --git a/info/Commands/hidden.t b/info/Commands/hidden.t new file mode 100644 index 00000000..41edd3c9 --- /dev/null +++ b/info/Commands/hidden.t @@ -0,0 +1,5 @@ +.TH Command HIDDEN +.NA hidden "Display some deity-only statistics for sectors" +.LV Expert +.SY "hidden " +.SA "Deity" diff --git a/info/Commands/improve.t b/info/Commands/improve.t new file mode 100644 index 00000000..3b470507 --- /dev/null +++ b/info/Commands/improve.t @@ -0,0 +1,19 @@ +.TH Command IMPROVE +.NA improve "Improve the infrastructure of a sector" +.LV Basic +.SY "improve " +.s1 +The improve command allows you to improve the efficiency of the infrastructure +of your sectors. +.s1 +The infrastructure of your sectors affects how well they defend, and how easy +it is for you to move various commodities/vehicles (land units) thorough +them. +.s1 +To improve a sector, you need (most likely) lcms, hcms, mobility and money. +See "info show" for the various costs. +.s1 +Whenever you tear down a sector, the infrastructure is left in tact. The only +way that infrastructure goes down is when the sector takes damage. +.s1 +.SA "sinfrastructure, census, commodity, resource, Sectors, Infrastructure, Mobility, Commodities" diff --git a/info/Commands/info.t b/info/Commands/info.t new file mode 100644 index 00000000..d5d157c1 --- /dev/null +++ b/info/Commands/info.t @@ -0,0 +1,30 @@ +.TH Command INFO +.NA info "Provide information on various topics" +.LV Basic +.SY "info []" +The Empire info pages are organized by subject. To get a list of +subjects, type: +.EX info +You can then type: +.EX info Subject +to get a list of Empire commands and info topics which are related +to the Subject that you chose. Note that Subjects always start with a +capital letter (this is to distinguish them from commands which are +always lowercase). +.s1 +To get info on the syntax of an Empire command, type: +.EX info command +where "command" is the command you're interested in. Note that info +about Empire command syntax is always specified lower-case. +.s1 +To get info about some Empire topic, type: +.EX info Topic +Where Topic is the name of some Empire topic that you're interested in. +.s1 +Every Empire command and topic belongs to at least one subject, and in +some cases more than one. +.s1 +.EX info all +This will list all info pages. Warning: this list is long! +.s1 +.SA "Bugs, Playing" diff --git a/info/Commands/land.t b/info/Commands/land.t new file mode 100644 index 00000000..4ebaabc0 --- /dev/null +++ b/info/Commands/land.t @@ -0,0 +1,61 @@ +.TH Command LAND +.NA land "Report status of unit, army or units in a given area" +.LV Basic +.SY "land [ | ]" +The unit report command is a census of your units and lists all the +info available in readable format. +.s1 +The and arguments are provided in case you only +wish to look at one unit or one army or all units within a given area. +.s1 +Land expects an argument. To see every unit you own, give it +the argument '*', i.e. type "land *". +.s1 +The report format contains the following fields: +.s1 +.in \w'unit-type\0\0'u +.L # +the unit number +.L unit type +the type of unit; \*Qwar band\*U, \*Qengineer\*U, etc, +.L x,y +the unit's current location (relative to your capital), +.L a +the army designation letter (set by \*Qarmy\*U command), +.L eff +the unit's efficiency, +.L mil +the number of mil currently in the land unit +.L frt +the unit's fortification level (0-127) +.L mu +the mobility of the unit +.L fd +the amount of food on board +.L fuel +the amount of fuel on board (if the FUEL option is enabled) +.L tch +the tech level of the unit +.L retr +the retreat percentage of the unit (see info attack) +.L rd +the unit's reaction radius (see info attack) +.L xl +the number of extra-light planes on board (if the XLIGHT option is enabled) +.L ln +the number of land units on board +.L l/s +the ship or land unit the unit is on, if any +.in +.s1 +For example: +.EX land * +.NF + # unit type x,y a eff mil frt mu fd fl tch retr rd xl ln l/s + 0 cav cavalry 1,-1 100% 10 0 127 12 0 992 75% 3 0 0 + 1 cav cavalry 0,0 100% 0 0 127 12 0 968 75% 3 0 0 + 2 cav cavalry 0,0 100% 10 0 127 12 0 40 75% 3 0 0 +3 units +.FI +.s1 +.SA "lstat, upgrade, build, cargo, army, march, attack, assault, lload, llookout, scrap, lmine, LandUnits" diff --git a/info/Commands/launch.t b/info/Commands/launch.t new file mode 100644 index 00000000..a697158f --- /dev/null +++ b/info/Commands/launch.t @@ -0,0 +1,127 @@ +.TH Command LAUNCH +.NA launch "Launch missiles or satellites" +.LV Expert +.SY "launch " +The launch command is used to launch missiles (or satellites) +from sectors or submarines owned by you. +.s1 +There are 5 classes of missiles: +.NF +1. "marine" missiles may only be fired at ships. They may be given + "interdiction" mission. When interdicting ships, "marine" missiles + will keep launching until the entire enemy fleet is sunk. +2. "tactical" missiles (without "marine" capability) may only be fired + against sectors. They may be given missions. If they fire on a + mission, then only enough missiles will fire to cause 100 damage. +3. "intercept" missiles can not be launched. They automatically + intercept planes. You can increase their reaction radius by giving + them an "air" defense mission. +4. "a-sat" missiles will automatically attempt to intercept AT_WAR + satellites which are launched into orbit within range. +5. "abm" (anti-ballistic-missiles) will automatically attempt to + intercept incoming "tactical" (non-"marine") missiles. + +As well, there are "satellites" which are like missiles in that they +can be launched, but unlike missiles in that they don't get destroyed +as soon as they are launched. +.FI +.s1 +In certain cases, a missile will require petrol or shells to be in the +sector before it can be launched. See 'show plane stats' to find out +how much fuel the missile requires. The 'load' value in 'show plane +stats' specifies how many shells the missile requires. Note that if +the missile is armed with a nucelar warhead, then it does not require +any shells. +.s1 +Once a satellite has been launched, it can not be moved again. +.s1 +Note here that it is much safer to use 100% missiles than those which +are less efficient, +and missiles below 60% cannot be launched. +.s1 +The formula for the chance that a missile hits its target is in +\*Uinfo Hitchance\*U. +.s1 +Of course, things don't always go as planned! +.s1 +Note that when you are first asked for the target sector +you can chicken out by hitting ^C +(or your favorite abort character). +.s1 +In the case of non-marine tactical missiles, if there are any HOSTILE +abm's within range of the target sector, then two of them will fire in +an attempt to intercept the incoming missile. +.s1 +Similarly, two AT_WAR a-sat's will attempt to intercept any satellites +you attempt to launch within their range. Also, if the sector you are +launching your satellite at is owned by a non-allied country, then +they will get a telegram informing them of the positioning of the +satellite. See below for details of a satellite's orbit path. +.s1 +When launching missiles, there is a +% chance equal to (5 + 100 - efficiency) * (1 - techfactor) that the +missile will blow up on +the launching pad instead of launching. If that happens, then there is +a further 33% chance that the warhead it is carrying (whether it be +conventional or nuclear) will detonate. (Note that nuclear warheads +will only detonate in this way if the option NUKEFAILDETONATE is enabled). +A nuclear warhead exploding on the launch pad will do the normal +amount of damage, but a conventional missile will only do half damage +to the sector or ship it is being launched from. +.s1 +Missiles launched from submarines are anonymous. The victim +is not notified of the identity of the launching country. +.s1 +Missiles on interdiction mission have the same chance of hitting and +do the same damage as if they were launched by hand. Also, any +nuclear armed missiles will detonate if they launch on an interdiction +mission. You specify whether the nuclear warhead will airburst or +groundburst when you arm the missiles (see info arm). +In order to better destroy missiles on the ground (or in their silos), +the ground-burst technique is used. +Ground-bursts are much less effective against large area targets, +but do massive damage to the sector it impacts, +possibly knocking out hardened missiles +before they can be used against you. +In the parlance of nuclear targeting doctrine, +this is known as \*Qcounter-force\*U targeting. +Air-bursts are used in order to kill large numbers of civilians, +to knock out industry (by flattening the factories), +to take out lightly armored military targets in a large area, +and to generally wreak havoc. +Nuclear strategists call this a \*Qcounter-value\*U technique. +.s1 +See Also \*QOn Thermonuclear War\*U by Herman Kahn. +.s1 +If the ORBIT option is enabled, then when you launch a satellite, you +will be asked "Geostationary orbit?". If you answer "y", then your +satellite will stay where you launch it. If, however, you answer +"n", then your satellite will orbit the planet. When a satellite is +"orbiting", it moves along 5% of a geodesic path every +update. The path the satellite follows looks like this: +.NF ++----+ +| / | +|/ | +| /| +| / | +| / | +|/ | +| /| +| / | ++----+ +.FI + +That is, start in the middle, move northeast until you hit the edge, +then continue from the west edge near the top and go northeast until +you go off the top of the map, then continue at the bottom going +northeast until you go off the eastern edge again, and continue from +the western edge near the bottom until you get back to the centre. +That is the path of satellites which are _not_ in geostationary orbit +(geo-stationary means stay in the same spot over the planet). +.s1 +If a foreign satellite moves over your territory durring an update, then you +will get a message like "Fodderland satellite spotted over 12,24" as a +part of your update BULLETIN. +.s1 +.SA "build, plane, satellite, Nuke-types, relations, Planes" diff --git a/info/Commands/lboard.t b/info/Commands/lboard.t new file mode 100644 index 00000000..cf816521 --- /dev/null +++ b/info/Commands/lboard.t @@ -0,0 +1,30 @@ +.TH Command LBOARD +.NA lboard "Board enemy land unit" +.LV Basic +.SY "lboard [] []" +The lboard command enables the owner of a sector to engage in hand-to-hand +combat with a land unit in that sector. +To board unit #5 from sector 1,-1 you might type: +.EX lboard 5 +.s1 +The program will ask from which sector you wish to board and +how many troops to board with. +.s1 +.s1 +In order to board a land unit from a sector, the land unit must be in the +sector, and the sector must have mobility. +.s1 +Some things to note: +.s1 +Any land units in the combat will fight as if they were simply mil, +i.e. they won't get any offensive of defensive multiplier, except for +"marine" units which get their full bonus. Similarly, units +on land units don't have to take morale checks, as they are fighting as mil. +Mil on the victim unit will still die before units take casualties, however. +.s1 +Note that you can only board with as many mil that the +unit you are trying to board can hold. +.s1 +See info \*QAttack\*U for the exact procedure. +.s1 +.SA "Attack, LandUnits, Combat" diff --git a/info/Commands/lcargo.t b/info/Commands/lcargo.t new file mode 100644 index 00000000..31772e33 --- /dev/null +++ b/info/Commands/lcargo.t @@ -0,0 +1,61 @@ +.TH Command LCARGO +.NA lcargo "List the commodities on board your units" +.LV Basic +.SY "cargo [ | ]" +.SY "lcargo [ | ]" +The cargo command lists the commodities on board your ships +in readable format. The lcargo command does the same for land units. +.s1 +The , , and arguments are +provided in case you only wish to look at one ship/unit +or one fleet/army or all ships/units within a given area. +.s1 +The report format contains the following fields: +.s1 +.in +1i +.L shp# or # +the ship or unit number +.L shiptype or unit type +the type of ship/unit; \*Qpatrol boat\*U, \*Qsubmarine\*U, etc, +.L x,y +the ship/unit's current location (relative to your capital), +.L flt +the fleet/army designation letter (set by \*Qfleetadd/army\*U command), +.L eff +the ship/unit's efficiency, +.L sh +the number of shells on board, +.L gun +the number of guns on board +.L pet +the amount of petroleum on board +.L irn +the amount of iron on board +.L dst +the amount of gold dust on board +.L bar +the number of gold bars on board +.L oil +the amount of oil on board +.L lcm +the amount of light construction materials on board +.L hcm +the amount of heavy construction materials on board +.L rad +the amount of radioactive material on board +.in +.s1 +For example: +.EX cargo K +.NF +shp# ship type x,y flt eff sh gun pet irn dst bar oil lcm hcm rad + 86 aircraft carrier -29,-51 K 100% 298 4 0 0 0 0 0 0 0 0 + 110 battleship -29,-51 K 100% 100 8 0 0 0 0 0 0 0 0 + 115 battleship -29,-51 K 100% 60 8 0 0 0 0 0 0 0 0 + 181 destroyer -27,-35 K 100% 40 4 0 0 0 0 0 0 0 0 + 182 destroyer -27,-35 K 100% 40 4 0 0 0 0 0 0 0 0 + 183 destroyer -27,-35 K 100% 40 4 0 0 0 0 0 0 0 0 +6 ships +.FI +.s1 +.SA "land, ship, build, march, navigate, load, lload, fleetadd, army, LandUnits" diff --git a/info/Commands/ldump.t b/info/Commands/ldump.t new file mode 100644 index 00000000..ebb711ea --- /dev/null +++ b/info/Commands/ldump.t @@ -0,0 +1,85 @@ +.TH Command LDUMP +.NA ldump "Dump raw land unit information" +.LV Expert +.SY "ldump []" +The ldump command displays all information on +some or all of your land units. +ldump is a combination of land, lcargo, and lstat. +Each ship's information is printed on one very long line. +Fields are separated by a single space. +.s1 +This command is designed to be used for input to an empire tool +such as \*Qve\*U. +.s1 +In the syntax of the ldump command + are the land units on which you wish information, +[] are the fields you wish to dump. +If no fields are specified, all fields are printed. +(see \*Qinfo Syntax\*U). +.s1 +An ldump command lists all selected land units headed by: +.NF +Sun Feb 9 22:16:37 1997 +DUMP LAND UNITS 855544597 + +.FI +The first line is the date. The second line is the +"DUMP LAND UNITS " where the field is the current +timestamp. The third line is the columns which are output. +.s1 +These columns represent the following fields which are also the +selection criteria for the command. +.s1 +The following may be used as fields. They must be entered EXACTLY as +shown here (no partial pattern matching is done.) +.NF + type type of land unit + x x location + y y location + army army + eff efficiency + mil # of mil loaded + fort fortification level + mob mobility + food # of food loaded + fuel # of fuel loaded + tech technology of unit + retr retreat %age of unit + react current reaction radius + xl # of x-light planes loaded onto unit + nland # of land units loaded onto unit + land land unit # this unit is loaded on + ship ship # this unit is loaded on + shell # of shells loaded + gun # of guns loaded + petrol # of petrol loaded + iron # of iron loaded + dust # of dust loaded + bar # of bars loaded + oil # of oil loaded + lcm # of lcms loaded + hcm # of hcms loaded + rad # of rads loaded + att attack value of unit + def defense value of unit + vul vulnerability of unit + spd speed of unit + vis visibility of unit + spy spy ability of unit + radius maximum reaction radius + frg firing range of unit + acc accuracy of unit + dam damage unit does when firing + amm amount of ammo used when firing + aaf anti-aircraft fire provided +.FI +.s1 +A typical usage might be: +.EX ldump #5 +which would list data for all land units in realm #5. +.s1 +A ldump lists each of your land units in the specified area. +The header line is a list of fields that correspond +to the order that ldump prints the land unit info. +.s1 +.SA "land, lcargo, lstat, Clients, LandUnits" diff --git a/info/Commands/ledger.t b/info/Commands/ledger.t new file mode 100644 index 00000000..68fb58a6 --- /dev/null +++ b/info/Commands/ledger.t @@ -0,0 +1,26 @@ +.TH Command LEDGER +.NA ledger "Report on outstanding loans" +.LV Expert +.SY "ledger" +The ledger command prints the information on all outstanding loans +in which you are involved. +.s1 +The loan number, lender's name, loanee's name, principal, interest rate, +expiration date, amount due, etc. will be printed for each loan. +.s1 +For example: +.EX ledger +.NF + \&... Groonland Ledger \&... + +Loan #0 from Groonland to Dog Dish +Amount paid to date $0 +Amount due (if paid now) $5046 (if paid on due date) $5250 +Due date is Thu Mar 19 16:44:35 1981 + +Loan #1 from Doctor Fate to Groonland +(proposed) principal=$3000 interest rate=10% duration(days)=30 +Loan must be accepted by Tue Feb 17 16:43:27 1981 +.FI +.s1 +.SA "consider, financial, offer, Loans" diff --git a/info/Commands/level.t b/info/Commands/level.t new file mode 100644 index 00000000..2ab35fff --- /dev/null +++ b/info/Commands/level.t @@ -0,0 +1,75 @@ +.TH Command LEVEL +.NA level "List distribution thresholds" +.LV Basic +.SY "level " +The level report provides information about the various +distribution thresholds in some or all of the sectors that +you occupy. +.s1 +In the syntax of the level command + is the area on which you wish information, +(see \*Qinfo syntax\*U). +A typical usage might be: +.EX level -6:6,-3:3 +which would list data for the area extending three sectors +out from the capital in each direction. +.s1 +The level report lists each of your sectors with the following heading: +.NF +DISTRIBUTION LEVELS + sect dst civ mil uw food sh gun pet iron dust bar oil lcm hcm rad +.FI +These columns represent: +.s1 +.in \w'path------\0\0'u +.L sect +the x and y coordinates of the sector +.L path------ +the route that goods travel to and from the distribution sector +.L dst +the distribution destination for the sector +.L civ +the distribution threshold for civilians in that sector +.L mil +the distribution threshold for military in that sector +.L uw +the distribution threshold for uncompensated workers in that sector +.L food +the distribution threshold for food in that sector +.L gun +the distribution threshold for guns in that sector +.L sh +the distribution threshold for shells in that sector +.L pet +the distribution threshold for petroleum in that sector +.L iron +the distribution threshold for iron ore in that sector +.L dust +the distribution threshold for gold dust in that sector +.L bar +the distribution threshold for gold bars in that sector +.L oil +the distribution threshold for oil in that sector +.L lcm +the distribution threshold for light construction materials +in that sector +.L hcm +the distribution threshold for heavy construction materials +in that sector +.L rad +the distribution threshold for radioactive materials in that sector +.in \\n(in +.s1 +For example: +.EX level -2,2 +.NF +.ps -1 +Fri Oct 31 16:58:34 1986 +DISTRIBUTION LEVELS + sect dst civ mil uw food sh gun pet iron dust bar oil lcm hcm rad +-2,-2 + -2,-2 0 0 201 0 0 0 0 0 0 0 0 0 0 0 + 1 sector +.ps +1 +.FI +.s1 +.SA "distribute, threshold, commodity, census, Distribution" diff --git a/info/Commands/list.t b/info/Commands/list.t new file mode 100644 index 00000000..01790ef5 --- /dev/null +++ b/info/Commands/list.t @@ -0,0 +1,34 @@ +.TH Command LIST +.NA list "List commands which are currently legal" +.LV Expert +.SY list +.SY list of commands +The list command gets you a list of currently legal commands +with their associated BTU costs, +(see \*Qinfo time\*U for description of BTU's). +This should not be confused with \*Qinfo {commands}\*U +which generates a brief summary of each command. +.s1 +.EX list +.NF + Current EMPIRE Command List + ------- ------ ------- ---- +Initial number is cost in BTU's. +The next 2 character (if present) +Next 2 chars (if present) are: +$ - must be non-broke c -- must have capital +Text enclosed in {braces} is comment rather than part of the command. +Args in [brackets] are optional, but can only appear on the command line. +Args in have the following meanings: + :: a country number or name + :: commodity such as `ore', `guns', etc + :: loan number + :: sector coordinates in the form: x,y + :: sector(s) in the form: lox:hix,loy:hiy/d ?cond&cond&... + :: one ship number + :: fleet designation, or area +2 announce 2 arm +2 $c assault {from ship} 2 attack {from sect} + etc. +.FI +.SA "Syntax, Time, Bugs, Playing" diff --git a/info/Commands/lload.t b/info/Commands/lload.t new file mode 100644 index 00000000..9a0d6c12 --- /dev/null +++ b/info/Commands/lload.t @@ -0,0 +1,46 @@ +.TH Command LLOAD +.NA lload "Load things onto land units" +.LV Basic +.SY "lload " +.SY "lload plane " +.SY "lload land " +The load command carries out the loading of units. +Commodities (like guns, civs, food) can be loaded onto any unit capable +of carrying them (to see what cargos a unit can carry, use the show command). +.s1 +Some land units can carry extra-light +planes (typically these are SAM's) +.s1 +Some land units can carry other units +.s1 +.SY "lload " +In the first form, +the amount argument specifies the amount of the given commodity +you wish to load on each unit specified. +Amounts greater than that allowed will be truncated to the +maximum possible. Amounts less than 0 indicate that you want to +make the unit/army have that amount. If the unit/army has less +than that amount, more will be loaded. If the unit/army has more +than that amount, the commodity will be unloaded. For example, +.s1 +.EX load food 3 -100 +.s1 +will cause unit 3 to load or unload food so that it has 100. +If it had 120 food, 20 would be unloaded. If it had 50 food, +50 would be loaded. +.s1 +.SY "lload plane " +In the second form, +where you say \*Qplane\*U instead of say \*Qciv\*U a plane/missile +is loaded onto a unit. +.s1 +See the \*Qshow\*U command for a table of the maximum amounts of +each items that can be carried on each unit type. +.s1 +Note that if either or does not start with a +number (e.g. it is of the form "a" or "*" or "#1" and not of the form +123 or 12,14) then you will not be given any error messages. This is +so that you can type something like "lload plane * *" without getting a +hundred error messages. +.s1 +.SA "lunload, Unit-types, Plane-types, LandUnits" diff --git a/info/Commands/llookout.t b/info/Commands/llookout.t new file mode 100644 index 00000000..5bb0fe1a --- /dev/null +++ b/info/Commands/llookout.t @@ -0,0 +1,35 @@ +.TH Command LLOOKOUT +.NA llookout "Check from units for other units, planes and/or sector types" +.LV Basic +.SY "lookout " +The lookout command allows units to report sightings +of other units, planes, and land sectors. +.s1 +Note that non-spy units require military on-board in order to be able +to see anything. +.s1 +The various ranges over which lookout is effective +break down into two groups: +.s1 +UNIT to UNIT +.s1 +.in +0.2i +This range is dependent on both the visibility of the unit +being observed and the visual range of the observing unit. +(see \*Qinfo Unit-types\*U) +.in \\n(in +.s1 +UNIT to PLANE +.s1 +Planes are treated as if they had a visibility of 10. +.in +0.2i +For example: +.EX lookout 24 +.NF +Groonland (#2) jf4 jet fighter 4 #3 @2,-2 +Groonland (#2) airfield 100% efficient with approx 50 civ @ 2,-2 +Groonland (#2) highway 20% efficient with approx 20 civ @ 3,-1 +Groonland (#2) highway 0% efficient with approx 0 civ @ 0,-2 +.FI +.s1 +.SA "lookout, coastwatch, Unit-types, Sector-types, radar, sonar, LandUnits, Detection" diff --git a/info/Commands/lmap.t b/info/Commands/lmap.t new file mode 100644 index 00000000..b39d53ad --- /dev/null +++ b/info/Commands/lmap.t @@ -0,0 +1,67 @@ +.TH Command LMAP +.NA lmap "Map around a land unit" +.LV Expert +.SY "map " +.SY "nmap " +.SY "smap " +.SY "lmap " +.SY "pmap " +A map gives you a graphic representation of all or part of your country. +.s1 +Your own sectors show up as a designation mnemonic +(see \*QSector-types\*U) while sectors held by other countries +appear as question marks (\*Q?\*U). +Mountains, wilderness areas, and seas appear +as '^', '-' and '.' respectively. +.s1 +You can also get an lmap by typing 'M' at the march prompt. +.s1 +Examples: +.EX map -9:18,-8:5 +generates a 28 x 14 map based on data supplied by the sectors +in the area specified. +.NF + ---------0000000000111111111 + 9876543210123456789012345678 + -8 . . . - - -8 + -7 . . . . - ^ -7 + -6 . . . . - - - - -6 + -5 . . - . a a - ^ ? ? - -5 + -4 . . . . k o ! - ^ ? ? ? -4 + -3 . - . a h j a ^ ^ ^ ^ ^ - -3 + -2 . . - . a a a ^ a a - - - -2 + -1 . . . a a a b + + ^ ^ - -1 + 0 . . . m c u a a - ^ - ^ 0 + 1 . - . a a . a a - - ^ 1 + 2 - ^ ^ a a a ^ a - - ^ 2 + 3 - - - - - - - . . - 3 + 4 ^ - - - - - ^ - - 4 + 5 - ^ - - ^ - - - 5 + ---------0000000000111111111 + 9876543210123456789012345678 +.FI +.s1 +.EX map # >mapfil +where your \*Qrealm\*U (or '#', +see \*Qinfo realm\*U or \*Qinfo update\*U) +is -5:5,-6:6 will type out a 11 by 13 sector map +and also put the map in the file called \*Qmapfil\*U. +.s1 +Also, if you give a ship # instead of coordinates or a realm, map +will show you a small realm around the given ship (assuming you +own it). +.s1 +If you use nmap, you can get a map that shows new sector designations +instead of old sector designations of your own country. +.s1 +If you use lmap, you can get a map around a land unit, +instead. Pmap does the same for a plane. Smap does +the same for a ship. +.s1 +.L "MAP FLAGS" +.s1 +If you give an 's' flag, all your ships will be shown on the map. +An 'l' flag does the same for land units, and a 'p' for planes. +'*' gives all of the above. +.s1 +.SA "census, commodity, radar, realm, route, update, LandUnits, Maps" diff --git a/info/Commands/lmine.t b/info/Commands/lmine.t new file mode 100644 index 00000000..9527c7ff --- /dev/null +++ b/info/Commands/lmine.t @@ -0,0 +1,46 @@ +.TH Command LMINE +.NA lmine "Mine a sector with an engineering unit" +.LV Expert +.SY "lmine " +This command causes a unit with the engineering ability +to lay mines in a sector. (see \*Qinfo Unit-types\*U). If you ask to +lay more mines than the unit is carrying, then it will attempt to keep +resupplying itself until all of the mines have been laid. It costs +1 mobility point per mine laid, so an engineer with 20 mobility can +lay a maximum of 20 mines. The 'strength' command will list how many +mines you have put in each sector. +.s1 +See \*Qinfo Hitchance\*U for the chance of something hitting a land mine. +.s1 +If a defender in land combat has land-mines in the sector, he +receives a bonus to his defense. See info \*Qattack\*U for more information. +If the attacker has engineering units with him, the bonus is less. +.s1 +In the command syntax + is the number of one of your units and is +the number of mines you wish to lay. +That number of shells, (assuming you've got them), +will be dropped in the sector that unit occupies, +magically becoming mines. +.s1 +You need not fear mines in sectors that you are the old owner of. This +is normally all your sectors. When you capture a mined sector, however, +you will need to worry about those mines until you become the old owner +of that sector. Once you are the old owner of a sector (i.e when you +get the message "Sector x,y is now fully yours."), you have the mines located, +and will no longer hit them. +.s1 +If you are in a captured sector, and the original owner attacks, you will not +get the mine bonus (as he knows where all the mines are) +.s1 +Mines can only be removed safely by a unit with the engineering ability. +(Other units can remove them by hitting them, but...) +Engineering units moving through a sector with unlocated mines will +attempt to remove them. The number of times each engineer sweeps for +mines is equal to 2 times the number of mines it can carry. The +chance of the engineer finding a mine on each sweep is equal to 50% +times its 'att' value (see show land stats). If an engineer sweeps +more mines than it can carry, then it will drop the rest as shells +into the sector. +.s1 +.SA "march, strength, move, explore, transport, Hitchance, Damage, Attack, LandUnits" diff --git a/info/Commands/load.t b/info/Commands/load.t new file mode 100644 index 00000000..5cdd29db --- /dev/null +++ b/info/Commands/load.t @@ -0,0 +1,73 @@ +.TH Command LOAD +.NA load "Load goods, people, etc onto a ship" +.LV Basic +.SY "load " +.SY "load plane " +.SY "load land " +The load command carries out the loading of ships. +Commodities (like guns, civs, food) can be loaded onto any ship. +Missiles can be loaded onto nuke subs +and planes can be loaded onto carriers. +Land units may be loaded onto many ships. +.s1 +The ship(s) must be in a harbor and +the harbor must be at least 2% efficient. +.s1 +.SY "load " +In the first form, +the amount argument specifies the amount of the given commodity +you wish to load on each ship specified. +Amounts greater than that allowed will be truncated to the +maximum possible. Amounts less than 0 indicate that you want to +make the ships have that amount. If the ships have less +than that amount, more will be loaded. If the ships have more +than that amount, the commodity will be unloaded. For example, +.s1 +.EX load food 3 -100 +.s1 +will cause ship 3 to load or unload food so that it has 100. +If it had 120 food, 20 would be unloaded. If it had 50 food, +50 would be loaded. +.s1 +.SY "load plane " +In the second form, +where you say \*Qplane\*U instead of say \*Qciv\*U planes are +loaded onto ships. Multiple planes may be given. Some +may not be loaded, if there is not enough room. +.s1 +.SY "load land " +In the third form, +where you say \*Qland\*U instead of say \*Qciv\*U, a unit +is loaded onto a ship. Multiple units may be given. Some may +not be loaded, if there is not enough room. (Note that planes on +land units on ships can't be used, and units on ships generally can't +do much, like firing, marching, etc). When loading a land unit onto a +ship, the unit will check to see that it is in supply before stepping +on deck. If it isn't, then it will try to resupply itself (see info +supply) and if it is not able to do that, then you are issued a +warning. Sailors don't like to go to sea without supplies. +.s1 +See \*Qinfo Ship-types\*U for a table of the maximum amounts of +each items that can be carried on each ship type. +.s1 +If you are loading things onto FRIENDLY ships, you need to type the +numbers of the ships, fleets or realms +will not work. I.e. if you do "load f s 999", it'll load 999 food onto +all your ships in fleet s. If you do "load 1/2/3/4 999 f", it'll try to +load food onto ships 1, 2, 3, and 4, regardless of whether they're yours +or they belong to a friendly trading partner. +.s1 +If you load something onto a friendly nation's ship, it becomes +his and he gets a telegram. If you load a unit, he gets any planes it +may be carrying. +.s1 +If you unload a plane or unit in a friendly nation's harbor, it +becomes his. If you unload a unit, he gets any planes it may be carrying. +.s1 +Note that if any of , or does not start with a +number (e.g. it is of the form "s" or "*" or "#1" and not of the form +123 or 12,14) then you will not be given any error messages. This is +so that you can type something like "load land * *" without getting a +hundred error messages. +.s1 +.SA "unload, navigate, Ship-types, Unit-types, Plane-types, Ships" diff --git a/info/Commands/lookout.t b/info/Commands/lookout.t new file mode 100644 index 00000000..eaaa0005 --- /dev/null +++ b/info/Commands/lookout.t @@ -0,0 +1,41 @@ +.TH Command LOOKOUT +.NA lookout "Check from ships for other ships and/or sector types" +.LV Basic +.SY "lookout " +The lookout command allows ships to report sightings +of other ships and land sectors. +.s1 +The various ranges over which lookout is effective +break down into two groups: +.s1 +SHIP to SHIP +.s1 +.in +0.2i +This range is dependent on both the visibility of the ship +being observed and the visual range of the observing ship. +(see \*Qinfo Ship-types\*U) +Submarines at sea are a special case - they cannot be seen by simply looking +out from a ship! In order to detect subs at sea, you need to use sonar. +Submarines have a very limited range for what ships they +can see using their periscope--they can usually only see ships in the +same sector. However, all ships (including subs) which are docked in +a harbour are visible to all ships (including subs) in adjacent sectors. +(see also \*Qinfo sonar\*U) +.in \\n(in +.s1 +SHIP to SHIP +.s1 +This range is effectively 1.0. +.in +0.2i +For example: +.EX lookout 24 +.NF +Groonland (#1) patrol boat #10 @-13,7 +Curmudgeon (#4) heavy cruiser #36 @-14,6 +Groonland (#1) oil derrick #41 @-14,6 +Groonland (#1) tender #53 @-14,6 +Groonland (#1) mine 100% eff with approx. 300 civilians @-12,6 +Groonland (#1) heavy manufacturing 23% eff with approx. 10 civilians @-11,7 +.FI +.s1 +.SA "coastwatch, Ship-types, Sector-types, radar, sonar, Ships" diff --git a/info/Commands/lost.t b/info/Commands/lost.t new file mode 100644 index 00000000..23cd5c5f --- /dev/null +++ b/info/Commands/lost.t @@ -0,0 +1,62 @@ +.TH Command LOST +.NA lost "Report lost items" +.LV Basic +.SY "lost" +The lost command displays all lost items currently in the +database for your country. +.s1 +All lost items are timestamped at the time they were lost. If +you had a previously lost item in the database, and then build a +new item of the same type with the same id, or regain an item of the +same type with the same +id, it is removed from the database. This is done because the new item +will now show up in the other dump commands, and is no longer lost. +.s1 +Lost items are kept in the database for 48 hours (default) but may +be kept longer at the deity's discretion. Also, issuing the lost +command does not remove items from the database. That is where the +timestamp functionality becomes important. +.s1 +While the lost command does not take any arguments, it does +take the standard syntax for selecting information. +(see \*Qinfo Selector\*U). +.s1 +A typical usage might be: +.EX lost ?timestamp>854954677 +which would list data for all lost items timestamped after +854954677. (Timestamps are kept in system seconds.) +.s1 +A lost command lists all the lost items headed by: +.NF +Sun Feb 9 22:16:37 1997 +DUMP LOST ITEMS 855544597 +type id x y timestamp +.FI +The first line is the date. The second line is the +"DUMP LOST ITEMS " where the field is the current +timestamp. The third line is the columns which are output. +.s1 +These columns represent: +.s1 +.in \w'gtimestamp\0\0'u +.L type +The type of lost item. They are as follows: +.NF + 0 - Sector + 1 - Ship + 2 - Plane + 3 - Land unit + 4 - Nuclear stockpile +.FI +.L id +The # of the ship, plane, land unit or nuke. All of these items +are identified by id. Sectors are identified by x and y. +.L x +The x coordinate of the lost item when it was lost. +.L y +The y coordinate of the lost item when it was lost. +.L timestamp +The timestamp of when the item was lost. +.in \\n(in +.s1 +.SA "dump, ldump, sdump, ndump, pdump, Ships, Planes, LandUnits, Sectors, Clients" diff --git a/info/Commands/lradar.t b/info/Commands/lradar.t new file mode 100644 index 00000000..33a316e3 --- /dev/null +++ b/info/Commands/lradar.t @@ -0,0 +1,28 @@ +.TH Command LRADAR +.NA lradar "Use a radar unit's radar" +.LV Expert +.SY "lradar [ | ]" +The radar command bears some resemblance +to modern high-resolution radar. +It has a circular range dependent upon its efficiency. +.s1 +An example of radar: +.EX lradar 5 +.NF +radar truck #5 efficiency 100%, max range 6 + . a a - ^ ? ? + T k o ! - ^ ? ? + a h j a ^ ^ ^ ^ ^ + h . a w a ^ - ? a ? + . . a m a b f a ^ ^ - + . . m c * a a - ^ - ^ - + . - . a + . 0 a - - ^ - . + - ^ ^ a + ) ^ a - - ^ . + - - a m + a f . . - ^ + ^ a - a + a ^ - - - + - ^ - - ^ - - - - + - ^ - - - - - - + - - - - - - - +.FI +.s1 +.SA "census, map, nation, Ship-types, Technology, radar, LandUnits, Detection" diff --git a/info/Commands/lrange.t b/info/Commands/lrange.t new file mode 100644 index 00000000..a8c475a5 --- /dev/null +++ b/info/Commands/lrange.t @@ -0,0 +1,11 @@ +.TH Command LRANGE +.NA lrange "Edit the reaction range of a unit" +.LV Expert +.SY "lrange " +The \*Qlrange\*U command is used to limit the maximum reaction radius of +land units. This can be useful in restricting the area which a unit will +attempt to defend. (see info attack for details of the reaction process) +.s1 +A unit with a radius of 0 will not react. +.s1 +.SA "attack, LandUnits" diff --git a/info/Commands/lretreat.t b/info/Commands/lretreat.t new file mode 100644 index 00000000..2011c6ee --- /dev/null +++ b/info/Commands/lretreat.t @@ -0,0 +1,90 @@ +.TH Command LRETREAT +.NA lretreat "Set retreat conditions/paths for units or armies" +.LV Expert +.SY "retreat [ | ] [] []" +.SY "lretreat [ | ] [] []" +The retreat command allows you to examine or modify the retreat +paths and conditions of your ships or units. The following description +is for ships. Land units are exactly the same, except of course that +some of the retreat conditions (being sonared, depth charged, etc) don't apply. +.s1 +The and arguments are provided to specify which +ships to view or give orders for. If a fleet designation is given when +specifying orders, the orders apply to all ships within that fleet. +.s1 +Retreat expects an argument. To see every ship you own, give it +the argument '*', or type "retreat *". +.s1 +The report format contains the following fields: +.s1 +.in \w'shiptype\0\0'u +.L shp# +the ship number +.L shiptype +the type of ship; \*Qpatrol boat\*U, \*Qsubmarine\*U, etc, +.L x,y +the ship's current location (relative to your capital), +.L flt +the fleet designation letter (set by \*Qfleetadd\*U command), +.L path +the ship's current retreat path. +.L as_flt? +whether or not the ship's retreat path is a fleet retreat path +.L flags +what conditions the ship will retreat under +.in +.s1 +For example: +.EX retreat * +.NF +shp# ship type x,y fl path as flt? flags + 0 battleship 4 2,0 jjuuj I +1 ship +.FI +.s1 +.L Overview +.s1 +A player may give retreat orders for a ship or a fleet. Retreat +orders include a set of conditions that determine when the fleet/ship +will retreat, and a path that the fleet/ship will follow. When a condition +is met for a particular ship, the \*Qas flt?\*U field is checked. If it +is Yes, then every ship in that fleet with fleet retreat orders retreats +along the specified path. If it is no, then the retreat orders apply to +that ship only, and only that ship retreats. +.s1 +When a ship is added to a fleet, it is given the retreat orders of that +fleet, if any exist. +.s1 +Retreat orders are wiped when a ship navigates. +.s1 +Retreat conditions at present include: +.nf + + Condition Meaning + I Retreat when the ship is injured, + i.e. whenever the ship is damaged + by fire, bombs, or torping. + T Retreat when a sub torpedos or tries + to torpedo the ship. + B Retreat when a plane bombs or tries + to bomb the ship. + S Retreat when the ship detects a sonar + ping. + D Retreat when the ship is depth-charged. + H Retreat when helpless. A ship is helpless + when it is fired upon, and no friendly + ships/sectors (including the ship itself) + are able to fire back at the aggressor. + C Clear the flags +.fi +.s1 +For example, if the battleship above was fired at, it would attempt to +retreat 2 sectors, jj, using the normal amount of mobility for moving +2 sectors. It would then look like: +.NF +shp# ship type x,y fl path as flt? flags + 0 battleship 4 2,0 uuj I +1 ship +.FI +.s1 +.SA "ship, fleetadd, LandUnits" diff --git a/info/Commands/lstat.t b/info/Commands/lstat.t new file mode 100644 index 00000000..d728137c --- /dev/null +++ b/info/Commands/lstat.t @@ -0,0 +1,68 @@ +.TH Command LSTAT +.NA lstat "Report statistics of unit, army or units in a given area" +.LV Basic +.SY "lstat [ | ]" +The lstat command is a report of the varying statistics of your units and +lists the info in a readable format. Since your units' statistics vary by +tech level, this is a very useful way to see what the attack, defense, etc. +modifiers are on a per-unit basis. +.s1 +The and arguments are provided in case you only +wish to look at one unit or one army or all units within a given area. +.s1 +Lstat expects an argument. To see every unit you own, give it +the argument '*', i.e. type "lstat *". +.s1 +The report format contains the following fields: +.s1 +.in \w'unit-type\0\0'u +.L lnd# +the unit number +.L unit type +the type of unit +.L x,y +the unit's current location (relative to your origin), +.L eff +the unit's efficiency, +.L tech +the tech level of the unit +.L att +the attack multiplier of the unit +.L def +the defense multiplier of the unit +.L vul +the vulnerablilty of the unit (see "info Damage") +.L spd +the speed of the unit (see "info Mobility") +.L vis +the visibility of the unit +.L spy +the distance a unit can see +.L rad +the maximum reaction radius of the unit +.L rng +twice the distance the guns can fire, +The range formula is (rng/2) * ((tech + 50) / (tech + 200)) +.L acc +the firing accuracy of the unit +.L fir +the number of guns that fire when the unit fires +.L amm +the amount of ammunition the unit uses per shot fired +.L aaf +the amount of anti-aircraft fire the unit produces +.in +.s1 +For example: +.EX lstat * +.NF + s v s r r a f a a + p i p a n c i m a +lnd# unit-type x,y eff tech att def vul d s y d g c r m f + 0 cav cavalry 1,-1 100% 992 3.4 1.6 54 52 18 4 3 0 0 0 0 0 + 1 cav cavalry 0,0 100% 968 3.4 1.6 55 51 18 4 3 0 0 0 0 0 + 2 cav cavalry 0,0 100% 40 1.9 0.9 74 36 18 4 3 0 0 0 0 0 +3 units +.FI +.s1 +.SA "land, upgrade, build, cargo, army, march, attack, assault, lload, llookout, scrap, lmine, LandUnits" diff --git a/info/Commands/ltend.t b/info/Commands/ltend.t new file mode 100644 index 00000000..440c4ff6 --- /dev/null +++ b/info/Commands/ltend.t @@ -0,0 +1,8 @@ +.TH Command LTEND +.NA ltend "Transfer things between a unit and the ship carrying it" +.LV Expert +.SY "ltend " +The ltend command allows transfer of commodities +from a particular (supply) ship to a land unit it is carrying. +.s1 +.SA "load, unload, lload, lunload, tend, Ships, LandUnits" diff --git a/info/Commands/lunload.t b/info/Commands/lunload.t new file mode 100644 index 00000000..f808fe6e --- /dev/null +++ b/info/Commands/lunload.t @@ -0,0 +1,14 @@ +.TH Command LUNLOAD +.NA lunload "Unload things from land units" +.LV Basic +.SY "lunload " +.SY "lunload plane " +The lunload command is the opposite of lload and follows the +exact same syntax ... +so why look here for documentation? +.s1 +The only thing to know is that lunload won't unload more of a thing if the +sector already has 999. For example, if a unit has 10 food, and the sector +has 994, you can only unload 5 of the 10 food. +.s1 +.SA "lload, LandUnits" diff --git a/info/Commands/map.t b/info/Commands/map.t new file mode 100644 index 00000000..54011d70 --- /dev/null +++ b/info/Commands/map.t @@ -0,0 +1,65 @@ +.TH Command MAP +.NA map "Generate a map showing sector types, seas, etc" +.LV Basic +.SY "map " +.SY "nmap " +.SY "smap " +.SY "lmap " +.SY "pmap " +A map gives you a graphic representation of all or part of your country. +.s1 +Your own sectors show up as a designation mnemonic +(see \*QSector-types\*U) while sectors held by other countries +appear as question marks (\*Q?\*U). +Mountains, wilderness areas, and seas appear +as '^', '-' and '.' respectively. +.s1 +Examples: +.EX map -9:18,-8:5 +generates a 28 x 14 map based on data supplied by the sectors +in the area specified. +.NF + ---------0000000000111111111 + 9876543210123456789012345678 + -8 . . . - - -8 + -7 . . . . - ^ -7 + -6 . . . . - - - - -6 + -5 . . - . a a - ^ ? ? - -5 + -4 . . . . k o ! - ^ ? ? ? -4 + -3 . - . a h j a ^ ^ ^ ^ ^ - -3 + -2 . . - . a a a ^ a a - - - -2 + -1 . . . a a a b + + ^ ^ - -1 + 0 . . . m c u a a - ^ - ^ 0 + 1 . - . a a . a a - - ^ 1 + 2 - ^ ^ a a a ^ a - - ^ 2 + 3 - - - - - - - . . - 3 + 4 ^ - - - - - ^ - - 4 + 5 - ^ - - ^ - - - 5 + ---------0000000000111111111 + 9876543210123456789012345678 +.FI +.s1 +.EX map # >mapfil +where your \*Qrealm\*U (or '#', +see \*Qinfo realm\*U or \*Qinfo update\*U) +is -5:5,-6:6 will type out a 11 by 13 sector map +and also put the map in the file called \*Qmapfil\*U. +.s1 +Also, if you give a ship # instead of coordinates or a realm, map +will show you a small realm around the given ship (assuming you +own it). +.s1 +If you use nmap, you can get a map that shows new sector designations +instead of old sector designations of your own country. +.s1 +If you use lmap, you can get a map around a land unit, +instead. Pmap does the same for a plane. Smap does +the same for a ship. +.s1 +.L "MAP FLAGS" +.s1 +If you give an 's' flag, all your ships will be shown on the map. +An 'l' flag does the same for land units, and a 'p' for planes. +'*' gives all of the above. +.s1 +.SA "census, commodity, radar, realm, route, update, Maps" diff --git a/info/Commands/march.t b/info/Commands/march.t new file mode 100644 index 00000000..d1703571 --- /dev/null +++ b/info/Commands/march.t @@ -0,0 +1,110 @@ +.TH Command MARCH +.NA march "Move a land unit or units" +.LV Basic +.SY "march " +The march command is the \*Qmove\*U command applied to land units. +You can control one unit or an entire army with it. +.s1 +Land units may only move into sectors you own, sectors of countries +you are allied with or deity-owned sectors with 1 exception. Spies. Spies +may move anywhere, with a chance of getting caught. See "info Spies" for +more information. +.s1 +If you are moving an army and the lead unit stops, the army stops; +(the lowest numbered unit is always considered the lead unit). +.s1 +The program will prompt with the mobility of the lead unit, +the minimum mobility value for the army, and the current sector +coordinates in the form: +.NF +<57.0:23.5: -6,4> +.FI +which means the lead unit has 57 mobility units, +some other unit in the army has 23.5 mobility units and +the lead unit is in sector -6,4. +You may indicate the direction you would like the army to move +by typing a string of letters consisting of any combination of the +following: +.NF +y for up-left +u for up-right y u +g for left \\\\ / +j for right g -- -- j +b for down-left / \\\\ +n for down-right b n +r for radar +l for lookout +m to sweep landmines +h for end of movement +.FI +.s1 +The radar option will cause the lead unit to use it's radar, if any. +You may also give a unit number or army or group of units on the same +line: "r 12/13/14/73" +.s1 +The lookout option works in the same way as radar, i.e. it will cause the +lead unit to do a lookout. +.s1 +Note: the lookout and radar commands use BTU's, just as if you'd typed them +separately from the command line. +.s1 +You may also use the 'm' command to have engineers in the marching +group search for mines in the current sector. Example: "m 12" +.s1 +Since the can be specified in the command line, +simple unit movements are often typed as a single line, such as: +.EX march 19 jjjh +.s1 +Or some movements may be done partly on the command line and partly +interactively: + +.EX march 18 yy +.NF +<112.7:112.7: -4, -2> l +Your capital 100% efficient with 549 civ with 10 mil @ -5,-3 +Your highway 100% efficient with 549 civ with 0 mil @ -4,-2 +Your harbor 100% efficient with 549 civ with 109 mil @ -3,-1 +<112.7:112.7: -4, -2> yh +war band #18 stopped at -5,-3 +.FI +.s1 +You may also simply specify the destination sector +on the command line. In this case, +empire will set the path to be the cheapest path (in terms of +mobility) that currently exists. The unit(s) will move to the +destination sector, and then ask for more input. +.s1 +For example, +.EX march 18 -6,-2 +.NF +<104.2:104.2: -6,-2> h +war band #18 stopped at -5,-3 +.FI +.s1 +Note that if you are marching multiple units, you may only specify a +destination sector on the command line if all the units start in the +same sector. +.s1 +See "info Mobility" for the mobility cost to march land units. +.s1 +At the update, units with negative mobility have their mobility halved +before new mob is added. For example, in a game where units got 32 mob +per update, a unit with -100 mobility would have -18 after an update. +(-100/2 = -50 + 32 = -18) This helps inefficient units be not quite as +slow. +.s1 +Moving a unit through a sector that has been mined +introduces a chance of mines/(mines + 50) that you will be damaged. +Units with engineering capabilities can remove up to five mines per +pass through a sector (indicated by the message \*QSweep...\*U). +Such units also take 1/2 normal damage from mines. +See info lmine for more details. +.s1 +Hostile land/sea/air units may fire at/bomb your units, if they're +on interdiction missions (see info mission). If your enemy has a +stack of missiles on interdiction mission, then they will +automatically fire one after another until 100 damage has been done. +Missiles and pinbombers have a 100% chance of hitting their target +(provided they make it through plane/missile defenses). Collateral +damage will be done to the sector that the units were marching into. +.SA "Unit-types, lmine, LandUnits, Moving, Spies" diff --git a/info/Commands/market.t b/info/Commands/market.t new file mode 100644 index 00000000..60fe957b --- /dev/null +++ b/info/Commands/market.t @@ -0,0 +1,52 @@ +.TH Command MARKET +.NA market "Report current selling prices in the world market" +.LV Expert +.SY "market " +The market report displays the lowest price commodity of each type +currently on the market. +.s1 +If you specify "all" for the item, all commodities on the market +are displayed. +.s1 +If you specify a specific item, all lots of that item are displayed. +.s1 +.EX market +.NF + Empire Market Report + Sun Dec 27 12:42:59 1998 + lot high bid/unit by time left owner item amount sector + --- ------------- -- --------- ----- ---- ------ ------ + 1 $ 0.50 1 1.50 hrs ( 1) f 100 -1,1 + 3 $ 0.50 1 1.52 hrs ( 1) o 100 -1,1 + +Looks just like Christmas at K-mart, doesn't it! +.FI +.EX market oil +.NF + + Empire Market Report + Sun Dec 27 12:43:08 1998 + lot high bid/unit by time left owner item amount sector + --- ------------- -- --------- ----- ---- ------ ------ + 2 $ 1.00 1 1.52 hrs ( 1) o 100 -1,1 + 3 $ 0.50 1 1.52 hrs ( 1) o 100 -1,1 + 4 $ 0.50 1 1.52 hrs ( 1) o 100 -1,1 + +Looks just like Christmas at K-mart, doesn't it! +.FI +.EX market all +.NF + Empire Market Report + Sun Dec 27 12:43:09 1998 + lot high bid/unit by time left owner item amount sector + --- ------------- -- --------- ----- ---- ------ ------ + 0 $ 1.00 1 1.50 hrs ( 1) f 100 -1,1 + 1 $ 0.50 1 1.50 hrs ( 1) f 100 -1,1 + 2 $ 1.00 1 1.52 hrs ( 1) o 100 -1,1 + 3 $ 0.50 1 1.52 hrs ( 1) o 100 -1,1 + 4 $ 0.50 1 1.52 hrs ( 1) o 100 -1,1 + +Looks just like Christmas at K-mart, doesn't it! +.FI +.s1 +.SA "buy, sell, reset, Market" diff --git a/info/Commands/mine.t b/info/Commands/mine.t new file mode 100644 index 00000000..32c35857 --- /dev/null +++ b/info/Commands/mine.t @@ -0,0 +1,40 @@ +.TH Command MINE +.NA mine "Drop sea mines from a ship" +.LV Basic +.SY "mine " +This command drops mines in the sea and is functional +from ships with mine-laying capability (see \*Qinfo Ship-types\*U). +.s1 +See \*Qinfo Hitchance\*U for the chance of a ship hitting a mine. +.s1 +In the command syntax + is the number of one of your ships and is +the number of mines you wish to drop. +That number of shells, (assuming you've got them), +will be dropped in the sector that ship occupies, +magically becoming mines as they hit the water. +.s1 +Mines can only be removed safely by a minesweeper. +(Other ships can remove them by hitting them, but...) +Planes with the 'sweep' +ability can clear mines by flying recon missions through +mined sectors, with each passage through the sector possibly +removing some mines. +.s1 +Ships of tech 310 or higher can detect mines with their sonar. +See \*Qinfo sonar\*U for more information. +.s1 +Harbors and sea sectors under bridge spans can be mined. +Your ships will automatically avoid these mines when passing through, +(and your minesweepers will not not pick them up). +.s1 +Note that the sector is checked for possible mine hits +only when a ship moves into it; +thus, a ship may safely drop mines in a sector and then move out. +On the other hand, the mines know no allegiance, +so moving back into a mined sector is foolish at best +unless it is a harbor or under a bridge span. +.s1 +Mines in the same sector as a bridge that collapses are cleared. +.s1 +.SA "navigate, Hitchance, Damage, Ships" diff --git a/info/Commands/mission.t b/info/Commands/mission.t new file mode 100644 index 00000000..85c16359 --- /dev/null +++ b/info/Commands/mission.t @@ -0,0 +1,315 @@ +.TH Command MISSION +.NA mission "Assign a mission to a ship/plane/unit" +.LV Basic +.SY "mission [] []" +.s1 +The mission command is used to assign ships, planes, or land units to +missions. The available missions are: +.s1 +Here is a summary of which units can be put on which missions: +.NF +Mission Op-sect Radius Ships Land-Units Planes +interdiction no yes yes yes only "tactical" + support no yes no no only "tactical" + off support no yes no no only "tactical" + def support no yes no no only "tactical" + reserve yes no no yes no + escort yes no no no only "intercept" or "escort" + air defense no yes no no only "intercept" +.FI +You may also use 'q' (query) to check on +the mission of something, or 'c' (clear) to wipe the mission of a land +unit/plane/ship. +.s1 +GENERAL CONCEPT +.s1 +Missions are things that your planes/land units/ships can do automatically, such +as bombing/shelling. You assign a unit to a mission, and whenever the right +conditions occur, the unit attempts to perform its mission. Note that missions +don't allow a unit to do anything it normally could not do, they simply allow +them to do it in an automatic fashion. In some cases, units performing missions +might not be as 'smart' as they would be if you were operating them personally. +That's the price you pay for having automatic defenses. +.s1 +.L "IMPORTANT NOTES" +.s1 +Missions can occur during updates. (Interdicting ships using "sail" +or "order"). +.s1 +Artillery units less than 20% efficient will not fire. +.s1 +Planes flying missions will be intercepted normally. (i.e. if you fly +over enemy territory, you'll get intercepted. Any mission except air +missions may also be intercepted by planes on air defense missions) +.s1 +Planes of less than 40% efficiency will not fly missions. +.s1 +Planes assigned to missions are \*QNOT\*U eligible to intercept +normally. For example, if a fighter is assigned to an escort or air-defense +or interdiction or support mission, it will \*QNOT\*U rise to intercept +an intruding enemy plane. (planes on air-defense missions will intercept +planes flying in their op-area, in accordance with the air-defense mission, +but will not intercept one outside their op-area, even if it is within +their normal range. Be sure you understand this before using plane missions.) +.s1 +Nukes on missiles or planes flying missions DO detonate. +.s1 +"marine" missiles will keep launching to interdict ships until all of +the valuable ships in the fleet are sunk. A "valuable" ship is one +which cost at least $1000 to build or can carry land units or planes. +For each new missile launched, the most valuable ship according to +(cost to build) * efficiency is targeted. +.s1 +Non-marine missiles will keep firing +on a sector until 100 damage is done. +.s1 +OPERATIONS SECTORS +.s1 +Some missions require the designation of an 'op sector', short for operations +sector. This is the center of an area that the mission is focussed on. +The op sector may be any sector that is within the unit's range. +(Firing range, +for ships & land units, flying range for planes, changeable with rangeedit). +The unit will exert influence in a radius around the op sector. +By default, the radius will be as large as possible, i.e. the biggest range +so that the unit/ship/plane could legally act there.) +For example, a ship with a range of 4 could designate any sector up +to 4 away from it as it's op sector, and would affect anything within +4 of it's op-sector, provided it was also within 4 of the ship. +.s1 +If a smaller radius is desired, it may be specified on +the command line. If it is not specified, it will not be prompted for. +.s1 +The area affected by a unit is known as that unit's op-area. +.s1 +If a '.' is given as the op-sector, the op sector will be the location +of the unit. +.s1 +Additionally, if the unit's op-sector is the sector the unit is in, and +the unit moves without losing its mission +status, the operation sector will move with it. (Normally, of course, the +only way for a unit on a mission to move is to be carried on a ship, so +this mostly applies to planes on carriers) Thus, a tactical bomber on a ship +could have an op-area centered on the carrier that moved with the carrier. +.s1 +Otherwise, if the unit moves without losing its mission status, the +op sector will stay where it was designated. +.s1 +For example, suppose that land unit 4 is an artillery unit, range 5, +located at 0,0. +.s1 +.EX "mission land 4 int ." +.s1 +This would make the unit interdict anything passing within 5 sectors of +its location. +.s1 +.EX "mission land 4 int 4,0" +.s1 +This would make the unit interdict anything passing within 5 sectors of +4,0, provided it was also within 5 sectors (the unit's range) of 0,0. +.s1 +.EX "mission land 4 int 4,0 2" +.s1 +This would make the unit interdict anything passing within 2 sectors of +4,0, provided it was also within 5 sectors (the unit's range) of 0,0. +.s1 +The op-sector/op-range concept allows you to restrict a unit's area of +interest to a small, important area, or just let it shoot at anything within +range. +.s1 +MOBILITY USE +.s1 +When a unit is given a mission, it costs no mobility. When a unit performs +its mission, it uses the normal mobility costs that it would use to +perform that mission if done by the player. +.s1 +A unit stays on its mission until you cancel it, OR the unit acts. Any type +of action not a part of a mission +is sufficient, so marching, navigating, transporting, flying, reconing, +bombing, mining, paratrooping, being attacked, being +paratrooped on, retreating, etc, will all cause a unit to lose its +mission status, but the unit could bomb/shell/etc AS PART OF A MISSION, and +still retain its mission status. +Also, land units with a reserve +mission can react to a threatened sector and fight, and (assuming they win) +return to their original sector without losing their reserve status. +.s1 +Note that fortifying a unit does not affect it's mission status. +.s1 +DEFENDERS +.s1 +The defender's planes will intercept planes flying missions. +His ships/forts/units, however, will \*QNOT\*U fire at ships/forts/units +firing on a mission. +.s1 +INTERDICTION MISSIONS (ships, planes, land units) +.s1 +When giving a unit a interdiction mission, you designate an op sector. From +then on, whenever an enemy (defined as something belonging to a nation which +you are at war with) moves in a sector in that unit's op-area, +the unit will try to shell or bomb it (as appropriate). Almost any kind of +movement, except for distribution movement during an update, and the tiny +amounts moved by the supply routines is enough. +.s1 +For example, an enemy land unit marching up to the front would be +shelled/bombed. +An enemy moving commodities around would have the commodities automatically +shelled/bombed. A ship navigating into a sea sector would be shelled or bombed, +depending on it's type (obviously, only depth-charge or ASW capable units would +affect a submarine, and a submarine would only affect things it could torpedo) +In general, units can only affect things they could normally affect. For +example, if the enemy was transporting a plane along a highway, and you had an +artillery unit and a light bomber interdicting the highway sector, the land +unit would fire and the bomber would fly there and bomb, and the total damage +would be applied to the plane being transported. If it was still alive, it +might be moved to another sector, there to be bombed/shelled again (assuming the +new sector was also in both units' op-areas) If a different unit later moved +in, it would be shelled/bombed. This happens as long as the interdicting units +have mobility left. +.s1 +Damage done is divided amongst all units/ships/commodities moving. For +example, if 6 ships were moving, and the interdiction mission did 18 pts of +damage, each ship would take 3. +.s1 +Note that only ships with sonar and ASW planes can interdict subs. Also, the +units may or may not detect the subs, so it's kind of random. The sub also +has a chance of escaping the damage, depending on the visibility of the sub. +.s1 +Only planes with the 'tactical' ability can fly interdiction missions. +Only planes with 'ASW' ability will fly vs. subs. Planes with 'ASW' +ability will not fly interdiction vs. other types of +ships/planes/units/commods. Subs have a chance of sneaking through +ASW aircover unnoticed, and ASW planes will respond to any +non-Friendly sub movement. Depending on the visibility of the sub, +the ASW plane may or may not identify the type and/or owner of the +sub. + +Interdiction has no effect on flying planes. Interdiction does not +affect loading/unloading. It will also cause some damage to the +sector that the commodities were moving into. +.s1 +Note also that forts will fire at enemy ships coming within +range. You don't have to set anything for this, it +happens automatically. (Forts firing at enemy ships naving happens before +ships/planes/units interdicting ships, so if the enemy is using an area a +lot, a fort will hurt him without costing you mob from planes) +.s1 +SUPPORT MISSIONS (planes only) +.s1 +A support mission allows your planes to automatically bomb the enemy. +Planes with offensive support missions will bomb enemy sectors that you +attack. Planes with defensive support missions will bomb enemy troops +attacking your sector, adding to your defensive strength. Planes with +support orders will do both. +.s1 +When giving a plane a support mission, you designate an op sector. From then on, +whenever a sector owned by the plane's owner (or by an ally of the plane-owner, +if the ally is also at war with the attacker) +in that plane's op-area is +attacked, the plane will attempt to fly to that sector and give ground support, +if it has support or defensive support orders. +.s1 +If the plane's owner (or an ally of the plane's owner, if the ally is +also at war with the country attacked) +attacks a sector in that plane's op-area belonging to a +country that the plane owner is at war with, the plane will +also attempt to fly there and give offensive support if it has +support or offensive support orders. +.s1 +(see info attack for more information on how support works in land combat) +.s1 +Only planes with the 'tactical' ability can fly support missions. +.s1 +ESCORT MISSIONS (planes only) +.s1 +When given an escort mission, an escort or intercept capable plane will attempt +to escort any plane flying a support or interdict mission from the same airport. +If even 1 plane flies a support or interdiction mission from an airport, all +planes on escort duty at that airport will attempt to escort. Planes with escort +duty will NOT attempt to escort planes taking off from other airports, so it +pays to put your bombing planes and escorting planes together. +.s1 +Only planes with the 'escort' or 'intercept' abilities can fly escort missions. +.s1 +AIR DEFENSE MISSIONS (planes only) +When given an air defense mission, an intercept capable plane will attempt +to intercept any enemy plane (defined as any plane belonging to a country +you re at war with) flying into its operations area, irregardless +of whether the enemy planes are flying over owned sectors. For example, if +a plane is given an air defense mission with an op area covering some +owned sectors, some sea, some allied sectors, and some enemy sectors, it +would try to intercept over any of them. +.s1 +When a plane enters a sector, any planes with air defense missions that are +at war with the owner of the plane will fly there to fight it. +The air defense planes +encounter normal interception along the way (but do \*QNOT\*U trigger +more air defense missions, but \*QMAY\*U be intercepted normally). +Once the air defense planes get to the sector, +they fight the plane. Then, if the owner of the sector +is hostile to the plane, still more planes may intercept it. +.s1 +.L Example +Groonland wants to run a recon flight over Bannannarama. Joeland has a +jet fighter with an air defense mission and an op-area covering part of +Bannannarama. The 'j' sector belongs to Joeland, and is the base for the +fighter. The 'b' sectors belong to Bannannarama, which has 1 fighter +in the center sector. The 'g' sector belongs to Groonland. Assume that +all countries are mutually at war. +.s1 +The Joeland fighter's op area is centered on the 'B', radius 2. +.NF + . . . . . . . . . . . . . . . . . + . . . . . j . . . . . b b . . . . + . . . . . . . . . . . b B b . . . + . . . . . . . . . . . b b . . . . + . . . . . . . . . g . . . . . . . +.FI +.s1 +The Groonland player enters a path of 'uujjjbgbggh'. +The first sectors entered is sea, and is not in the Joeland +aircraft's op-area, so nothing happens. +.s1 +Next, the Groonland plane enters the sector adjacent to Bannannarama. +This is within the Joeland aircraft's op-area, so it flies to intercept. +It takes the shortest path there, and fights the Groonland plane. +Let's say that both take 20 points of damage, and neither aborts. +.s1 +Next, the Groonland plane overflies a Bannannarama sector. The Joeland +plane flies there, and is intercepted by the Bannannarama plane. Let's +say that it comes through the fight without being aborted. It then fights +the Groonland plane. After this combat, if the Groonland plane is not +aborted, it may be intercepted again by the busy Bannannarama fighter, +assuming that that plane is still efficient enough, has mob enough, etc. +.s1 +A good use of this mission is to provide a wider CAP around a carrier, +so that enemy planes get intercepted several times on the way to the +carrier, rather than just once, in the carrier's sector. +.s1 +Another use is to provide air-cover for an ally who has temporarily +lost his planes. +.s1 +RESERVE MISSIONS (land units only) +.s1 +A land unit given reserve orders has an increased ability to react to enemy +attacks. A reserve unit has its reaction radius increased by 2. +(Note: this is cumulative with the +1 modifier for being at an +efficient headquarters, so a reserve unit at an HQ would have a +3). +In addition, a reserve unit pays 1/2 the normal cost for fighting a battle. +(It still pays the normal cost for moving to the threatened sector) +See info attack for more details on reaction. +.s1 +Note that units with a reserve mission retain this status, even though they +move to the threatened sector and return. This is an exception to the normal +rules on losing your mission status. If, however, the land unit is forced to +retreat from the combat (see land combat for details), it WOULD lose its status. +.s1 +When a unit with a reserve mission is listed, the op sector is the sector +the unit is in, and the radius is the units maximum reaction radius, including +the bonus for the reserve mission and HQ (if applicable). Note that the unit's +actual radius might be different if it was changed by lrangeedit. +.s1 +Note: information gained from planes flying missions is automatically +added to your bmap. +.s1 +.SA "Ship-types, Plane-types, Unit-types, attack, bomb, Ships, Planes, LandUnits" diff --git a/info/Commands/mobupdate.t b/info/Commands/mobupdate.t new file mode 100644 index 00000000..b8c50772 --- /dev/null +++ b/info/Commands/mobupdate.t @@ -0,0 +1,14 @@ +.TH Command MOBUPDATE +.NA mobupdate "turn on/off mobility updating" +.LV Expert +.SY "mobupdate " +The mobupdate command will disable mobility updating for 'X' minutes. +Note that this only works if the MOB_ACCESS option has been enabled. +.s1 +Using this command with 0 minutes will turn mobility updating back on. +.s1 +Using this command with 'check' or a negative amount of minutes will +tell you when the mobility updating will be turned back on if it is +off, or that it is on if it is on. +.s1 +.SA "update, Deity" diff --git a/info/Commands/morale.t b/info/Commands/morale.t new file mode 100644 index 00000000..60cf29cc --- /dev/null +++ b/info/Commands/morale.t @@ -0,0 +1,30 @@ +.TH Command MORALE +.NA morale "Change the retreat percentage of a unit" +.LV Expert +.SY "morale " +The \*Qmorale\*U command is used to set the retreat percentage of land +units. +.s1 +Normally, a land unit must start making morale checks during combat +when its efficiency is less than or equal to its retreat percentage. +(The chance of failing a morale check is: sqrt(100-effic)%/(men in unit). +Example: a 25 man unit is at 75% efficiency. It's chance of failing is +sqrt(100-75)%/25 = sqrt(25)%/25 = 20%) +.s1 +The morale command +allows you to adjust this percentage within a range. If, for example, you +wish only to trade space for time, you could set the retreat percentage +to 100%, meaning that your units would retreat often, but would still slow +the enemy down a bit. Or, you could set your retreat percentage to the minimum, +and make the unit stick around and fight more, but at the cost of more +casualties. +.s1 +The maximum allowed value is 100% (i.e. start making morale checks after +any casualties) The minimum values is based on happiness: +.ti 3 +(morale_base) - happiness +.s1 +"morale_base" is a deity settable variable, which defaults to 42. When +a unit is first built, it's retreat percentage is set to "morale_base". +.s1 +.SA "attack, assault, LandUnits" diff --git a/info/Commands/motd.t b/info/Commands/motd.t new file mode 100644 index 00000000..b0368b00 --- /dev/null +++ b/info/Commands/motd.t @@ -0,0 +1,9 @@ +.TH Command MOTD +.NA motd "Print the message of the day" +.LV Expert +.SY "motd" +This command will print out the login message (what gets printed to +your screen when you login to the game). It is +here so that you don't have to logout and in again if you want to read +the login message again. +.SA "Communication" diff --git a/info/Commands/move.t b/info/Commands/move.t new file mode 100644 index 00000000..0f3f6b41 --- /dev/null +++ b/info/Commands/move.t @@ -0,0 +1,120 @@ +.TH Command MOVE +.NA move "Transport ore, civilians, guns, etc" +.LV Basic +.SY "move " +The move command is crucial to Empire; it carries out the movement +of civilians, military, ore, guns, shells, food, planes, etc. on land. +Note that you can only move into sectors that you own, so you cannot +take sectors via move. To take sectors, use the "explore" command, +which uses the same syntax as move. +.s1 + can be any one of: +.NF +c civilians +m military +u uncompensated workers +f food +g guns +s shells +p petrol +i iron ore +d gold dust +b bars of gold +l light construction materials +h heavy construction materials +r radioactive materials +.FI +.s1 +If is not provided in the command line, +the program will request the starting sector +then display the number of mobility units in that sector, +its designation, and its coordinates in the form: +.s1 +.NF +<97.0: a -6,4> +.FI +.s1 +which indicates 97 mobility units in agribusiness sector -6,4. +You may respond with any combination of: +.s1 +.NF +y for up-left +u for up-right y u +g for left \\\\ / +j for right g -- -- j +b for down-left / \\\\ +n for down-right b n +v for view +m for map +h for end of movement +.FI +.s1 +The \*Qview\*U command shows the sector efficiency +and some of the contents of the sector you are currently occupying. +.s1 +Since the can be specified in the command line, +simple movements are often typed as a single line, such as: +.EX move m 2,0 20 jjjh +Or some movements may be done partly on the command line and partly +interactively: +.EX move c 2,2 18 jj +.NF +<32.3: g 6,2> v +10% gold mine with 3 civilians. +<32.3: 6,2> h +.FI +.s1 +You may also simply specify the destination sector. +In this case, +empire will set the path to be the cheapest path (in terms of +mobility) from the current sector to the destination sector, +if such a path exists. +.s1 +For example, +.EX move c 2,2 18 6,2 +.s1 +.L "Military control" +.s1 +In order to move something (other than mil) out of a sector, you must have +military control of the sector. Military control is defined as having mil in +the sector equal to at least 1/10th the number of unconverted civilians there. +Units count as if they were straight mil, i.e. a 100% unit that contained 50 +mil would count as 50 mil for the purposes of control) +.s1 +.L Mobility +See 'info Mobility' for a description of how much mobility it costs to +move something. +.s1 +.L Mines +Note that while moving, you might hit mines. The more stuff you're +moving, the greater the chance of setting off any +mines in the sectors you move through. See info lmine for more details. +.s1 +.L Interdiction +Any enemy units on interdiction mission may be triggered by the move +(the more you move, the bigger the chance they interdict). The +interdiction will damage the goods you are moving, and will also cause +some damage to the sector you were moving into. +.s1 +.L "Unhappy civilians" +.s1 +Also, when moving unhappy civilians (work percentage less than 100%), +unhappiness is contagious. If you move even 1 unhappy civilian into a +sector, the new sector's work percentage is set to the level of the +civilian being moved, if that is less than the existing level. +.s1 +However, if the NEW_WORK option is enabled, the work percentage of the +destination sector is computed by averaging the incoming civ's happiness +with the happiness of the civs already there. For example, say you move +100 civs with work percentage of 0% into a sector with 100 fully happy +civilians (100% work). If NEW_WORK is enabled, the work would be: +.ti 3 +((migrants * their work) + (people at dest * their work) / (total civs) +((100 * 0%) + (100 * 100%)) / (100+100) = 100/200 = 50% +.s1 +.L "Plague" +If a sector is infected with the plague, then anything moved out of +the sector will infect the sector that it moves into. Note that +sectors moved through will not catch the plague. +.s1 +.SA "navigate, transport, test, explore, Plague, Mobility, Commodities, Moving" diff --git a/info/Commands/mquota.t b/info/Commands/mquota.t new file mode 100644 index 00000000..92abe930 --- /dev/null +++ b/info/Commands/mquota.t @@ -0,0 +1,8 @@ +.TH Command MQUOTA +.NA mquota "Change the mobility quota of a ship with SAIL orders" +.LV Expert +.SY "mquota " +You use the \*Qmquota\*U command to limit the amount of mobility +that a ship a sailing path will use during an update. +.s1 +.SA "sail, unsail, follow, Ships" diff --git a/info/Commands/mult.t b/info/Commands/mult.t new file mode 100644 index 00000000..f2048c9f --- /dev/null +++ b/info/Commands/mult.t @@ -0,0 +1,47 @@ +.TH Command MULT +.NA mult "Set price multipliers of goods" +.LV Expert +.SY "mult " +The mult command allows a nation to set price multipliers +of the goods they are selling. +.sp +The argument is the number or name of the nation +for which you want to reset the multiplier, and is +the new multiplier (a floating-point number). If no +arguments are given, you are prompted for them. A carriage return +or incorrect nation at this prompt allows the changing +of all the price multipliers. +.sp +For example, if one nation is a \*Qnice\*U nation, +and another is particularly unfriendly, +the price multiplier for the nice one might be 0.75, +while the \*Qnasty\*U nation might have one around 5. +.s1 +The price multiplier affects the price of a nation's goods +to other nations. +Final item price is determined by multiplying the price +of the item at the time of the sale by the individual price multiplier +for the nation buying the item. +You cannot have a price multiplier below 0.05. +.s1 +Typical output looks like: +.EX mult +.NF +for which country? bar +bar ( 1.000) : 3.00 +.FI +.s1 +.EX mult +.NF +for which country? +Editing nation price multipliers... +MGM (1.00) : +hodedo (2.55) : 100 +bar (1.00) : ^C +Aborted +.FI +.s1 +The second editing session left unchanged all price multipliers except the +one for country \*Qhodedo\*U, which was set to 100. +.s1 +.SA "buy, sell, Obsolete" diff --git a/info/Commands/name.t b/info/Commands/name.t new file mode 100644 index 00000000..bcc1500a --- /dev/null +++ b/info/Commands/name.t @@ -0,0 +1,7 @@ +.TH Command NAME +.NA name "Give a name to a ship" +.LV Expert +.SY "name " +The \*Qname\*U command allows individual ships to be give +names. A name of \*Q~\*U is used to remove the name. +.SA "Ships" diff --git a/info/Commands/nation.t b/info/Commands/nation.t new file mode 100644 index 00000000..4eb826fa --- /dev/null +++ b/info/Commands/nation.t @@ -0,0 +1,50 @@ +.TH Command NATION +.NA nation "The state of your nation" +.LV Basic +.SY "nation" +The nation report command displays various data about your country. +.s1 +The data displayed by the nation command is formatted as a single page +report and should be self explanatory. +For example: +.EX nation +.NF + MGM Nation Report Sat Nov 4 15:01:52 1986 +Nation status is ACTIVE Bureaucratic Time Units: 250 +Capital is 100% efficient and has 87 civilians and 80 military +#0 -10:10,-5:5 #1 -10:0,-64:64 #2 -10:64,-64:64 #3 -10:64,-64:64 +#4 -10:20,-10:10 #5 -10:10,-5:5 #6 -10:20,-25:25 #7 -10:30,-20:0 + The treasury has $16800.00 Military reserves: 152 +Education.......... 9.20 Happiness....... 2.01 +Technology......... 16.81 Research........ 19.82 +Technology factor : 30.81% Max population : 556 + +Plague factor : 1.05% +Max safe population for civs/uws: 427/483 +Happiness needed is 4.385283 +.FI +.s1 +If the RES_POP option is in use, there will be a line that +tells you the maximum number of civs you can have in a sector +without losing them (999 without this option), and the maximum +number of civs you can have in a sector without losing population +growth. +.s1 +If the NO_PLAGUE option is not used, you'll also see a line +that has the plague chance for your nation. +.s1 +The max safe population is the highest population in a sector +that will NOT forfeit some population growth during an update. +In the example above, if you have 427 civs in a sector, you are +guaranteed not to have more than 556 after population growth. +If you have more than 427, population growth would make you go +over 556, and the excess babies would be eliminated when the +population was reduced to 556. +.s1 +If you have at least the happiness mentioned in the last line, +your sector's loyalty won't have a chance to go down. Otherwise, +each update, the chance is the number above - your happiness / 5.0. +For the country above, the chance would be (4.385283-2.01)/5.0 = .475 = 47% +chance that any individual sector's loyalty would go down. +.s1 +.SA "power, Nation" diff --git a/info/Commands/navigate.t b/info/Commands/navigate.t new file mode 100644 index 00000000..30030ce7 --- /dev/null +++ b/info/Commands/navigate.t @@ -0,0 +1,119 @@ +.TH Command NAVIGATE +.NA navigate "Move ship or fleet around" +.LV Basic +.SY "navigate " +The navigate command is the \*Qmove\*U command applied to the sea. +You can control one ship or an entire fleet with it. +.s1 +A ship must have at least one crew +(which may be civilian or military, +but not an uncompensated worker) +to be navigated. +When you navigate, you see the hex of sectors around the flagship. +(The lowest numbered ship is always considered the flagship). +.s1 +The program will prompt with the maximum and minimum mobility of the +ships in the fleet, and the current sector of the flagship in the form: +.NF +<57.0:23.5: -6,4> +.FI +which means one ship has 57 mobility units, +some other ship in the fleet has 23.5 mobility units and +the flagship is in sector -6,4. +You may indicate the direction you would like the fleet to move +by typing a string of letters consisting of any combination of the +following: +.NF +y for up-left +u for up-right y u +g for left \\\\ / +j for right g -- -- j +b for down-left / \\\\ +n for down-right b n +.FI +Other commands you may type while navigating are: +.NF +M for map +B for bmap +f to change flagship +i to list ships you are navigating +v to view oil content and fish +r for radar +l to look at land and nearby ships +s for sonar +m to sweep mines +h for end of movement +.FI +.s1 +While navigating you may also use radar, sonar, or lookout. +(by entering r, s, or l) By default it will radar, sonar, or +lookout from the flagship. You may also +give a ship number or fleet or group of ships on the same +line: "r 12/13/14/73" +.s1 +You may also use minesweepers in the currently navigating group to +sweep mines. This costs them the equivalent of 1 sector's mobility. +For example: "m 12/13" +.s1 +Since the can be specified in the command line, +simple ship movements are often typed as a single line, such as: +.EX nav 19 jjjh +.s1 +Or some movements may be done partly on the command line and partly +interactively: + +.EX nav 18 jj +.NF +<112.7:112.7: -4, -2> v +patrol boat #18 on open sea @ -3,-2 +<112.7:112.7: -4, -2> gh +patrol boat #18 stopped at -6,-2 +.FI +.s1 +You may also simply specify the destination sector +on the command line. In this case, +empire will set the path to be the cheapest path (in terms of +length) that currently exists. The unit(s) will move to the +destination sector, and then ask for more input. +.s1 +For example, +.EX nav 18 -6,-2 +.NF +<104.2:104.2: -6, -2> h +patrol boat #18 stopped at -6,-2 +.FI +.s1 +Note that if you are naving multiple ships, you may only specify a +destination sector on the command line if all the ships start in the +same sector. +.s1 +The formula for the movement cost for 1 sector is: +.NF + + 480 / (( speed + speed * (50+tech)/(200+tech) ) * Efficiency/100) + +.FI +.s1 +Moving a ship through a sector that has been mined +introduces a chance of mines/(mines + 50) of hitting a mine. +Minesweeps can remove up to five mines per pass through a +sector (indicated by the message \*QSweep...\*U). +Minesweeps also take 1/2 normal damage from mines. +.s1 +Also, note that some things may affect you while you are moving. Forts +belonging to hostile countries will fire at you when you come within +range. Hostile land/sea/air units may fire at/bomb your ships, if they're +on interdiction missions (see info mission). If your enemy has a +stack of missiles on interdiction mission, then they will +automatically fire one after another until all of your ships are sunk. +The chance of missiles and planes hitting your ships is determined by +the "worst" ship in your fleet (see \*Qbomb\*U for the chance of +hitting). Any damage incurred by the fleet is divided evenly among +all the ships in the fleet which are in the same sector. +.s1 +.L NOTE +.s1 +While navigating, you cannot enter a sector that belongs to another +country unless they have FRIENDLY relations with you. This includes bridges, and harbors. +.s1 +.SA "mine, Ship-types, mission, order, sail, Ships, Moving" diff --git a/info/Commands/ndump.t b/info/Commands/ndump.t new file mode 100644 index 00000000..a2b2adb6 --- /dev/null +++ b/info/Commands/ndump.t @@ -0,0 +1,44 @@ +.TH Command NDUMP +.NA ndump "Dump raw nuke information" +.LV Expert +.SY "ndump " +The ndump command displays all information on +some or all of the sectors you occupy. +Each nuke's information is printed on one very long line. +Fields are separated by a single space. +.s1 +This command is designed to be used for input to an empire tool +such as \*Qve\*U. +.s1 +In the syntax of the ndump command + is the area on which you wish information, +(see \*Qinfo Syntax\*U). +.s1 +An ndump command lists all selected nuclear stockpiles headed by: +.NF +Sun Feb 9 22:16:37 1997 +DUMP NUKES 855544597 +id x y num type +.FI +The first line is the date. The second line is the +"DUMP NUKES " where the field is the current +timestamp. The third line is the columns which are output. +.s1 +id - The id of the stockpile the nuke is in. +.s1 +x and y - The x and y coordinates of the stockpile +.s1 +num - The number of this type of nuke +.s1 +type - This type of nuke (100kt, 5mt, etc.) +.s1 +A typical usage might be: +.EX ndump #5 +which would list data for all nukes in realm #5. +.s1 +A ndump lists each of your sectors in the specified area. +The header line is a list of fields that correspond +to the order that ndump prints the nuke info. +.FI +.s1 +.SA "nuke, Clients, Planes" diff --git a/info/Commands/newcap.t b/info/Commands/newcap.t new file mode 100644 index 00000000..d3bf3b17 --- /dev/null +++ b/info/Commands/newcap.t @@ -0,0 +1,7 @@ +.TH Command NEWCAP +.NA newcap "Place a pair of sanctuaries" +.LV Expert +.SY "newcap []" +If you don't specify , then the server will try to find one +for you. +.SA "add, Deity" diff --git a/info/Commands/neweff.t b/info/Commands/neweff.t new file mode 100644 index 00000000..20ffb481 --- /dev/null +++ b/info/Commands/neweff.t @@ -0,0 +1,21 @@ +.TH Command NEWEFF +.NA neweff "Find out what the efficiency of a sector will be after the next update" +.LV Expert +.SY "neweff " +Neweff predicts how efficient a sector or sectors will be after the +next update. +.s1 +In the syntax of the neweff command + is the area on which you wish information, +(see \*Qinfo syntax\*U). +.s1 +A typical usage might be: +.EX neweff 2,0 +.NF +EFFICIENCY SIMULATION + sect des projected eff + 2,0 + 18% + 1 sector +.FI +.s1 +.SA "Innards, Sectors, Update" diff --git a/info/Commands/newspaper.t b/info/Commands/newspaper.t new file mode 100644 index 00000000..cef7361d --- /dev/null +++ b/info/Commands/newspaper.t @@ -0,0 +1,110 @@ +.TH Command NEWSPAPER +.NA newspaper "The yellow press" +.LV Basic +.SY "newspaper " +The news command prints a copy of the local newspaper published by +The Empire News. +.s1 +This \*Qmorning after\*U daily recounts financial exploits, +the telegram traffic between countries, +and political maneuvering +in addition to the chronicling of such mundanities as shelling, +attacking, and nuclear testing. +.s1 +It's great breakfast reading! +.s1 +Normally your edition of the news will only contain events that have +occurred since you last read the news. +You can specify what time period you'd like it to cover +with the optional argument in the command line as in: +.s1 +.EX news 2 +Which will print the news for the last two days. +.s1 +You can select whose news to see with the ?actor or ?victim selectors, +and what news to see with the ?action selector. Actions are: +.nf + 1) Successful Sector attack + 2) Unsuccessful attack + 3) Spy shot + 4) Telegram sent + 5) Treaty signing + 6) Loan made + 7) Loan repaid + 8) Goods sold + 9) Airspace violated + 10) Artillery fire on sectors + 11) Artillery fire on ships + 12) Attacking unowned land + 13) Ship torpedoed + 14) Gunners firing in self-defense + 15) Breaking sanctuary + 16) Planes bombing sectors + 17) Planes bombing ships + 18) Successful boarding actions + 19) Unsuccessful boarding actions + 20) AA fire + 21) Collecting on loans + 22) Considering treaty violation + 23) Actual treaty violation + 24) Country dissolving + 25) Ships hitting mines + 26) Alliance declaration + 27) Neutrality declaration + 28) War declarations + 29) Alliance dissolving + 30) War ending + 31) Plague outbreaks + 32) Plague deaths + 33) Name changes + 34) Starvation + 35) Rioting (from dissolving) + 36) Air to air combat + 37) Nukes going off + 38) Terrorists + 39) Shooting civs & uw's + 40) Satellite launches + 41) ASAT attacks + 42) Deity giving things + 43) Deity aids country + 44) Deity hurts country + 45) Deity taking things + 46) ABM interceptions + 47) Missile firing on sectors + 48) Missile firing on ships + 49) Trade between countries + 50) Pirates fence loot + 51) Pirates keep loot + 52) Ship torps ship + 53) Sub bombed by ASW plane + 54) Assault defeated + 55) Unit bombed + 56) Unit hits land mine + 57) Fortress artillery supports attack + 58) Land unit artillery supports attack + 59) Naval artillery supports attack + 60) Capital sacking + 61) Upgrades relations to friendly + 62) Downgrades relations to friendly + 63) Upgrades relations to neutral + 64) Downgrades relations to friendly + 65) Upgrades relations to hostile + 66) Downgrades relations to friendly + 67) Missile hits sector + 68) Missile hits ship + 69) Settles on a new island + 70) ABM interception + 71) Missile hits units + 72) Sub-launched missile hits units + 73) Successful assault + 74) Successful paradrop + 75) Paradrop into unoccuppied land + 76) Failed assault + 77) Failed paradrop + 78) Forced loan taken out (by the market) + 79) Forced loan denied (by the market) + 80) Failed boarding of a land unit + 81) Successful boarding of a land unit +.fi +.s1 +.SA "headlines, Communication" diff --git a/info/Commands/nmap.t b/info/Commands/nmap.t new file mode 100644 index 00000000..151bde1c --- /dev/null +++ b/info/Commands/nmap.t @@ -0,0 +1,65 @@ +.TH Command NMAP +.NA nmap "Generate a map showing new sector types, seas, etc" +.LV Basic +.SY "map " +.SY "nmap " +.SY "smap " +.SY "lmap " +.SY "pmap " +A map gives you a graphic representation of all or part of your country. +.s1 +Your own sectors show up as a designation mnemonic +(see \*QSector-types\*U) while sectors held by other countries +appear as question marks (\*Q?\*U). +Mountains, wilderness areas, and seas appear +as '^', '-' and '.' respectively. +.s1 +Examples: +.EX map -9:18,-8:5 +generates a 28 x 14 map based on data supplied by the sectors +in the area specified. +.NF + ---------0000000000111111111 + 9876543210123456789012345678 + -8 . . . - - -8 + -7 . . . . - ^ -7 + -6 . . . . - - - - -6 + -5 . . - . a a - ^ ? ? - -5 + -4 . . . . k o ! - ^ ? ? ? -4 + -3 . - . a h j a ^ ^ ^ ^ ^ - -3 + -2 . . - . a a a ^ a a - - - -2 + -1 . . . a a a b + + ^ ^ - -1 + 0 . . . m c u a a - ^ - ^ 0 + 1 . - . a a . a a - - ^ 1 + 2 - ^ ^ a a a ^ a - - ^ 2 + 3 - - - - - - - . . - 3 + 4 ^ - - - - - ^ - - 4 + 5 - ^ - - ^ - - - 5 + ---------0000000000111111111 + 9876543210123456789012345678 +.FI +.s1 +.EX map # >mapfil +where your \*Qrealm\*U (or '#', +see \*Qinfo realm\*U or \*Qinfo update\*U) +is -5:5,-6:6 will type out a 11 by 13 sector map +and also put the map in the file called \*Qmapfil\*U. +.s1 +Also, if you give a ship # instead of coordinates or a realm, map +will show you a small realm around the given ship (assuming you +own it). +.s1 +If you use nmap, you can get a map that shows new sector designations +instead of old sector designations of your own country. +.s1 +If you use lmap, you can get a map around a land unit, +instead. Pmap does the same for a plane. Smap does +the same for a ship. +.s1 +.L "MAP FLAGS" +.s1 +If you give an 's' flag, all your ships will be shown on the map. +An 'l' flag does the same for land units, and a 'p' for planes. +'*' gives all of the above. +.s1 +.SA "census, commodity, radar, realm, route, update, Maps" diff --git a/info/Commands/nuke.t b/info/Commands/nuke.t new file mode 100644 index 00000000..a7b24ca9 --- /dev/null +++ b/info/Commands/nuke.t @@ -0,0 +1,23 @@ +.TH Command NUKE +.NA nuke "List all nuclear \*Qdevices\*U in a given area" +.LV Expert +.SY "nuke " +For each sector in , this command prints the number of each +type of nuclear device in that sector. If the sector is a nuclear +plant whose efficiency is at least 60% (i.e. a sector where you can +build nuclear warheads), then you will be given additional information +about the sector relevant to the building of nukes. +.s1 +.EX nuke #1 +.NF +0.3i + sect eff num nuke-type lcm hcm oil rad avail + 21,-3 n 100% 2 5mt fusion 499 499 1498 783 549 + 21 100kt fission + 1 250kt fusion + 19,-3 + 100% 12 5mt fusion + 3 50kt neutron +.FI +Note that the sector information is printed only once, and all nukes +in that sector are listed below it. +.s1 +.SA "build, launch, transport, Planes" diff --git a/info/Commands/offer.t b/info/Commands/offer.t new file mode 100644 index 00000000..49f8b0ae --- /dev/null +++ b/info/Commands/offer.t @@ -0,0 +1,74 @@ +.TH Command OFFER +.NA offer "Offer a loan or treaty to another country" +.LV Expert +.SY "offer loan " +.SY "offer treaty " +The offer command is used to offer either a loan or a treaty +to another country. +.s1 +In the case of a loan: +.in +4 +.s1 + is the number or name of the country to whom +you are offering the loan, +.s1 + is the size of the loan. +(NOTE: do not use a dollar sign), +.s1 + is the length of the loan in days, +.s1 + is the interest rate, (per ), on the loan. +.s1 +The program prompts with various questions concerning any +terms of the loan not provided on the command line +and sends a telegram to announcing the loan offer. +.s1 +If the other country accepts the loan, +(using the \*Qconsider\*U command), +the money will be transferred from your account +and you will be notified that the loan duration has started. +.s1 +Note that the dependence of rate on the duration makes a 30 day loan +at 10% a worse deal than a 60 day loan at 15%. +.s1 +.in -4 +In the case of a treaty: +.s1 +.in +4 + is the name or number of the country to whom +you wish to offer the treaty. +.s1 +You will be asked to set both the conditions for yourself +and for the other country. +.s1 +The conditions from which you may choose are: +.s1 +.NF +Condition Command(s) affected +no attacks on land units lboard +no attacks on ships board +no sector attacks assault, attack, paradrop +no shelling ships fire +no depth-charging subs fire +no shelling land fire +no enlistments enlist +no building build +.FI +.s1 +Note that the first six terms apply to interactions +between the two parties to the treaty while the last two apply +to ANY actions of the specified type. +.s1 +Once you have offered the treaty, +a telegram will be sent to the other country indicating the offer. +If the other country accepts the treaty, +(using the \*Qconsider\*U command), +you will be notified that it has gone into effect. +.s1 +Once signed, the treaty is not binding! +However, any violation of the treaty will be pointed out +to the violator in time for him/her to reconsider the action and will +find its way into the news. +.in -4 +.s1 +.SA "collect, consider, ledger, repay, treaty, Loans" diff --git a/info/Commands/offset.t b/info/Commands/offset.t new file mode 100644 index 00000000..c6326e7f --- /dev/null +++ b/info/Commands/offset.t @@ -0,0 +1,6 @@ +.TH Command OFFSET +.NA offset "Temporarily change coordinate system" +.LV Expert +.SY "offset " +This should affect your maps. +.SA "Deity" diff --git a/info/Commands/order.t b/info/Commands/order.t new file mode 100644 index 00000000..4c985a30 --- /dev/null +++ b/info/Commands/order.t @@ -0,0 +1,167 @@ +.TH Command ORDER +.NA order "Order a ship to auto-navigate" +.LV Expert +.SY "order [c|r|s|d|l] +You use the \*Qorder\*U command to give sailing orders to ships. +At each update, ships sailing under orders \*Qautonavigate\*U toward a +specific destination sector. Telegrams notify you of arrivals. +.s1 +ONLY merchant ship may be given orders, but in order to move during the +update a ship must have at least one crew (which may be civilian or military, +but not an uncompensated worker). Merchant ships are those that +have 0 for their firing range and gun limit values. +.s1 +Note that your ships sailing on orders will be interdicted just as if +you were navigating them by hand. +.s1 +.EX order c Clear Orders +.s1 + Use the clear option to wipe out any orders the ship +currently has. This will remove all starting and ending +points and clear all the cargo levels for the ship. +.s1 +.EX order s Suspend Orders +.s1 + If you want to keep orders but don't want the ship +to move during the update use the suspend option. +A quick look at 'sorder' +will display the eta time as suspended. +As long as a ship is suspended it will be unable to move +during the update. +.s1 +.EX order r Resume Orders + Resume will allow ships that have a suspended order to move +again. +.s1 +.EX order d [dest2|scuttle|-] Declare Orders +.s1 +To declare an order you have 3 options. +.NF + 1) Order a ship to any sector on the map. + When it arrives it will clear its orders. + + 2) Order a ship to any sector, load goods, + move to a second sector and unload goods. + Continue to loop between the 2 points. + + 3) Order a ship to any sector on the map. + When it arrives, it will scuttle itself if it is in a harbor that + is at least 2% efficient. This is useful for tradeships. + +Example: You have a cargo ship (#6) in your harbor at sector 6,0 +You want to move good between that harbor and another harbor at +sector 14,0. + + order 6 d 6,0 14,0 + +This reads: + Cargo Ship #6, move to sector 6,0 load goods, sail to sector 14,0 + unload cargo then load again and sail back to 6,0. + +Example: You have a tradeship (#666) at sea in sector -10,0 and you +want to move it to a friendly harbor at 20,4. + + order 666 d 20,4 - + +The ship will now move to sector 20,4 with the most efficient path. + +Example: You have a tradeship (#666) at sea in sector -10,0 and you +want to move it to a friendly harbor at 20,4, and then scuttle itself. + + order 666 d 20,4 scuttle + +The ship will now move to sector 20,4 with the most efficient path, +and scuttle itself when done. + +Note that only trade ships can be given auto-scuttle orders, and won't +scuttle themselves at sea. +.FI +.s1 +.EX order l +.s1 +Set cargo Levels. +.NF +Example: Cargo ship #109 is at your harbor in sector 10,0. +You have agreed to trade 200 lcm and 100 hcm to your friend and +he will give you 100 shells each update. His harbor is at -10,2. +Using 'order declare' you set up your start point 10,0 and end point -10,2 + +order 109 l 1 start lcm 200 +order 109 l 2 start hcm 100 +order 109 l 1 end shell 100 + +When your finished the output would look like this. + +sorder 109 +shp # type x,y start end len eta + 109 cargo ship 2 10,0 10,0 -10,2 11 1 + +qorder 109 +shp # type [Starting] (Ending) + 109 cargo ship 2 [1-l:200 2-h:100 ] , (1-s:100 ) + +.FI +.s1 +AutoNav Features. +.s1 +Whenever a ship is autoloading cargo, it will always wait until it loads +to capacity. If a ship does not load fully it will not move!!! +Remember 'ships need food!!' unless the NOFOOD option is enabled. +Set one of your cargo holds to load food or your ship will starve at sea. +When unloading cargo, the ship will unload all goods +listed in the cargo holds ONLY! It will not unload any extra good +manually placed on the ship. +.s1 +If you are dealing with civilians 1 will be left in either the +sector or the harbor depending if your loading or unloading. +In either case when you arrive at the other harbor all but 1 civ +will be dumped into the harbor. Be careful if you set civilians +as one of your cargo levels. +.s1 +If the FUEL option is enabled ships will try and fuel when they load +cargo in the starting or ending point and they currently have a fuel +level less then half of their max fuel level. +Auto fueling is not foolproof. If you declare a +long path and the ship does not pass through any harbors it might +run out of fuel and mobility. Remember ships can only autofuel +in harbors. +.s1 +You can set any commodity in the game to be loaded on the ship. +However if you tell a ship to load a commodity it can not hold it +will be ignored. Example: If you tell a battleship to load +Lcm, and of course it does not have that capability, see 'show ship +capability' that level will be ignored at the update. +Planes and Units are not commodities so they can not be loaded this way. +.s1 +At update time, the most direct path from the ship to destination +is calculated. Each ship is then autonavigated along that path to +the best of its mobility. The path is calculated from what the player +knows of the world (what you can see using the \*Qbmap\*U command). +Open sea, bridges, harbors, and unexplored regions of the world +are considered to be navigable. Your friend's harbors and bridges +may be uses as long as the harbor >= 2% and the bridge >= 60%. +Your ships will also try to avoid any mines you have declared on your +bmap. 'x' or 'X' characters. Should your ship hit a mine the ship +will stop moving and its orders suspended. You bmap will also be updated +with a 'x' marking the sector for you. +.s1 +If a ship sails in range of enemy forts they will be fired upon. +Setting your ship to autonavigate into an area with good fort +cover could result in many ships getting sunk fast. +However you could put an invasion fleet off someone's coast in a hurry. +.s1 +If the ship has a 'sweep' flag +ships will try and sweep any mines if any are present as they move. +.s1 +Radar operates continuously as the ship moves along the path, constantly +adding sector information to the known world map. +.s1 +The autonav code will try and use as much mobility as possible and this +is all done before mobility is gained from the update. +After an update has completed +your ship will have mobility so it can be moved by hand if needed. +.s1 +For information on setting up ships to feed your country see +'info autofeed' for details. +.s1 +.SA "sorder, qorder, bmap, navigate, ship, Autofeed, Autonav, Ships" diff --git a/info/Commands/origin.t b/info/Commands/origin.t new file mode 100644 index 00000000..3300d08a --- /dev/null +++ b/info/Commands/origin.t @@ -0,0 +1,15 @@ +.TH Command ORIGIN +.NA origin "Change the origin of your country's coordinate system" +.LV Expert +.SY "origin " +This command changes the origin of your coordinate system +(where 0,0 is located.) +.s1 +This command does not change the location of your nation's capital, +though its coordinates, like the coordinates of all other sectors, +will be different after using the origin command. +.s1 +Your \*Qrealms\*U will be automatically recalculated +to point to the same area on the map. +.s1 +.SA "capital, Maps" diff --git a/info/Commands/paradrop.t b/info/Commands/paradrop.t new file mode 100644 index 00000000..49ff2833 --- /dev/null +++ b/info/Commands/paradrop.t @@ -0,0 +1,43 @@ +.TH Command PARADROP +.NA paradrop "Attack a sector from the air" +.LV Expert +.SY "paradrop route|destination" +The \*Qparadrop\*U command is used to sneak troops behind enemy lines, +or to drop in unawares on lightly-defended enemy islands or outposts. +It represents a complete mission for one or more transports and escorts +taking off from one place and returning to base at the end of the mission. +.s1 + represents a list of planes which can carry commodities. +Only planes which have a transport capacity, belong in a sector which is +stocked with gas and military, and have sufficient mobility will +be successfully selected for the mission. Only planes with the para ability +may be used for paratroop missions. +.s1 + represent a list of fighter planes which are capable of escorting +the transports all the way to the target. +To be selected, escorts must have fuel and mobility. +.s1 + represents an assembly point, where all of the planes in the +mission meet before proceeding on to the target sector. +The assembly point must be owned by you, and must not be more than +four sectors away from any of the planes selected for the mission. +.s1 +Route is a normal empire path specification. You may also give a +destination sector on the command line, or at any time while giving +the route, and empire will use the best path from the current sector +to the desired destination sector. +.s1 +If the planes manage to fight through enemy air defenses and arrive +on-target, each transport in the mission will be shot at by any +guns present on the ground. +Surviving transports will drop the paratroops they carry, which will +attack any enemy military occupying the target sector. +.s1 +See info \*QAttack\*U for the exact procedure. The sector being air-assaulted +will have exactly the same reaction to being conquered as if it were attacked +by land. +.s1 +Note that a plane must be at least 40% efficient before it can leave +the ground. +.s1 +.SA "bomb, fly, drop, recon, Attack, Mobility, Combat, Planes" diff --git a/info/Commands/path.t b/info/Commands/path.t new file mode 100644 index 00000000..6a7fc550 --- /dev/null +++ b/info/Commands/path.t @@ -0,0 +1,42 @@ +.TH Command PATH +.NA path "Show the distribution path of a sector" +.LV Expert +.SY "path " +The path command generates a map +of the distribution path for a specific sector. +.s1 +The argument is a single sector, as described in \*Qinfo syntax\*U. + +The distribution paths are indicated with \*Qgo-to\*Us +exactly as for the "route" command: +.NF +.sp + m/ up-right (u in level) + m> right (j in level) + m\\\\ down-right (n in level) +/m down-left (b in level) + t> i/ . . 0 + 1 . a> l/ ^ a a . . 1 + 2 . a a a . a . 2 + - - - 0 0 0 0 0 0 0 0 0 0 1 1 + 3 2 1 0 1 2 3 4 5 6 7 8 9 0 1 +.FI +.sp +where -2,0 distributes to 10,-4 along the path shown. +.sp +.SA "distribute, census, Syntax, route, map, Distribution" diff --git a/info/Commands/payoff.t b/info/Commands/payoff.t new file mode 100644 index 00000000..134371c8 --- /dev/null +++ b/info/Commands/payoff.t @@ -0,0 +1,37 @@ +.TH Command PAYOFF +.NA payoff "Find out the current payoff of a trade ship" +.LV Expert +.SY "payoff [ | ]" +The payoff command gives a census of your trade ships, and lists +the payoff they would give if scuttled at the current sector. +.s1 +The and arguments are provided in case you only +wish to look at one ship +or one fleet or all ships within a given area. +.s1 +Payoff expects an argument. To see every trade ship you own, give it +the argument '*', or type "ship *". +.s1 +The report format contains the following fields: +.s1 +.in \w'shiptype\0\0'u +.L shp# +the ship number +.L shiptype +the type of ship; \*Qpatrol boat\*U, \*Qsubmarine\*U, etc, +.L x,y +the ship's current location (relative to your capital), +.L $$ +the money you would get if you scuttled this ship +.s1 +For example: +.EX payoff * +.NF +shp# ship type orig x,y x,y dist $$ + 5 ts2 trade ship 2 2,2 21,-13 17 $5050.00 +1 ship +.FI +.s1 +Note that this command is only enabled if the TRADESHIPS option is in use. +.s1 +.SA "Trade-ships, sonar, torpedo, upgrade, Ships" diff --git a/info/Commands/pboard.t b/info/Commands/pboard.t new file mode 100644 index 00000000..48638e79 --- /dev/null +++ b/info/Commands/pboard.t @@ -0,0 +1,19 @@ +.TH Command PBOARD +.NA pboard "Board enemy plane" +.LV Basic +.SY "pboard []" +The pboard command enables the owner of a sector to capture any planes +another player has trapped in that sector. +To board plane #6 you might type: +.EX pboard 6 +.s1 +In order to board a plane, the plane must be on the ground in a sector +that you own. +.s1 +Some things to note: +.s1 +The crew of the plane will attempt to blow up or disable the plane to +avoid capture. +.s1 +The boarding parties do not recognize relations. Thus "pboard *" will +board all planes in your territory whether owned by allies or enemies. diff --git a/info/Commands/pdump.t b/info/Commands/pdump.t new file mode 100644 index 00000000..94dd5671 --- /dev/null +++ b/info/Commands/pdump.t @@ -0,0 +1,67 @@ +.TH Command PDUMP +.NA pdump "Dump raw plane information" +.LV Expert +.SY "pdump []" +The pdump command displays all information on +some or all of your planes. +pdump is a combination of plane and pstat. +Each plane's information is printed on one very long line. +Fields are separated by a single space. +.s1 +This command is designed to be used for input to an empire tool +such as \*Qve\*U. +.s1 +In the syntax of the pdump command + are the planes on which you wish information, +[] are the fields you wish to dump. +If no fields are specified, all fields are printed. +(see \*Qinfo Syntax\*U). +.s1 +A pdump command lists all selected planes headed by: +.NF +Sun Feb 9 22:16:37 1997 +DUMP PLANES 855544597 + +.FI +The first line is the date. The second line is the +"DUMP PLANES " where the field is the current +timestamp. The third line is the columns which are output. +.s1 +These columns represent the following fields which are also the +selection criteria for the command. +.s1 +The following may be used as fields. They must be entered EXACTLY as +shown here (no partial pattern matching is done.) +.NF + type type of plane + x x location + y y location + wing wing + eff efficiency + mob mobility + tech technology level + att attack value + def defense value + acc accuracy + react current reaction range + range maximum range + load load rating + fuel amount of fuel used in one flight + hard hardness + ship ship number the plane is on + land land unit number the plane is on + laun launchable? + orb orbiting synchronously? + nuke nuke name (if armed) + grd groundburst? (if armed) +.FI +.s1 +A typical usage might be: +.EX pdump #5 +which would list data for all planes in realm #5. +.s1 +A pdump lists each of your planes in the specified area. +The header line is a list of fields that correspond +to the order that pdump prints the plane info. +.s1 +.SA "plane, pstat, Clients, Planes" diff --git a/info/Commands/plane.t b/info/Commands/plane.t new file mode 100644 index 00000000..7f6e7deb --- /dev/null +++ b/info/Commands/plane.t @@ -0,0 +1,54 @@ +.TH Command PLANE +.NA plane "Report status of plane, wing or planes in a give area" +.LV Basic +.SY "plane [ | ]" +The plane report command is a census of your planes +and lists all the information available in readable format. +.s1 +The and arguments are provided in case you only +wish to look at one plane +or all planes within a given area. +.s1 +Plane expects some argument. To see all planes, use the +argument '*', or enter "plane *". +.EX plane * +.NF + # type x,y w eff mu def tech ran hard s/l LSB nuke + 0 f2 P-51 Mustang 1,-1 100% 90 5 110 11 0 + 1 f2 P-51 Mustang 1,-1 100% 90 5 110 11 0 + 3 lb TBD-1 Devastato 1,-1 100% 90 4 120 11 0 +3 planes +.FI +.s1 +The report format contains the following fields: +.s1 +.in +1i +.L # +the plane number +.L type +the type of plane; \*Qfighter 1\*U, \*Qjet hvy bomber\*U, etc, +.L x,y +the plane's current location (relative to your capital), +.L w +the \*Qair wing\*U designation letter, +.L eff +the plane's efficiency, +.L mu +the number of mobility points the plane has, +.L att +the attack value of the plane (for air-to-air combat) +.L tech +the tech level at which it was created, +.L range +and the range (in sectors) it can fly on a given mission. +.L s/l +the ship or land unit the plane is on +.L LSB +For satellites, LS stands for "launched?" and "Geo-synchroneous orbit?". +For planes or missiles armed with nukes, B will either have the value +"A" for airburst, or "G" for groundburst (see info arm). +.L nuke +the type of nuke carried +.in +.s1 +.SA "pstat, upgrade, arm, bomb, build, drop, fly, launch, paradrop, recon, satellite, scrap, wingadd, Planes" diff --git a/info/Commands/players.t b/info/Commands/players.t new file mode 100644 index 00000000..900ff2ca --- /dev/null +++ b/info/Commands/players.t @@ -0,0 +1,27 @@ +.TH Command PLAYERS +.NA players "List players currently connected to the game" +.LV Expert +.SY "players" +.EX players +.NF +Fri Sep 29 17:27:42 1995 + # time idle last command +Khazad'ur 34 tetherow@nol.nol.org 0:38 32s cen 0,0 +children 0 children@RedDragon.Empire.Net 0:16 7s play +2 players +.FI +.L "#" +the country number of the player. +.L time +the total number of hours:minutes the player has been connected today +.L idle +the number of seconds since the player has typed their last command +.L "last command" +the last command that the player typed +.s1 +If you are not a deity, then the "players" command will only list +your allies (and omit userid@host.name). Also, +non-deity players will only be given an estimate (based on a secret +random formula) of the total number of players currently logged on. +.s1 +.SA "country, Nation, Communication, Deity, Playing" diff --git a/info/Commands/pmap.t b/info/Commands/pmap.t new file mode 100644 index 00000000..70adc4c2 --- /dev/null +++ b/info/Commands/pmap.t @@ -0,0 +1,65 @@ +.TH Command PMAP +.NA pmap "Get a map around a plane" +.LV Expert +.SY "map " +.SY "nmap " +.SY "smap " +.SY "lmap " +.SY "pmap " +A map gives you a graphic representation of all or part of your country. +.s1 +Your own sectors show up as a designation mnemonic +(see \*QSector-types\*U) while sectors held by other countries +appear as question marks (\*Q?\*U). +Mountains, wilderness areas, and seas appear +as '^', '-' and '.' respectively. +.s1 +Examples: +.EX map -9:18,-8:5 +generates a 28 x 14 map based on data supplied by the sectors +in the area specified. +.NF + ---------0000000000111111111 + 9876543210123456789012345678 + -8 . . . - - -8 + -7 . . . . - ^ -7 + -6 . . . . - - - - -6 + -5 . . - . a a - ^ ? ? - -5 + -4 . . . . k o ! - ^ ? ? ? -4 + -3 . - . a h j a ^ ^ ^ ^ ^ - -3 + -2 . . - . a a a ^ a a - - - -2 + -1 . . . a a a b + + ^ ^ - -1 + 0 . . . m c u a a - ^ - ^ 0 + 1 . - . a a . a a - - ^ 1 + 2 - ^ ^ a a a ^ a - - ^ 2 + 3 - - - - - - - . . - 3 + 4 ^ - - - - - ^ - - 4 + 5 - ^ - - ^ - - - 5 + ---------0000000000111111111 + 9876543210123456789012345678 +.FI +.s1 +.EX map # >mapfil +where your \*Qrealm\*U (or '#', +see \*Qinfo realm\*U or \*Qinfo update\*U) +is -5:5,-6:6 will type out a 11 by 13 sector map +and also put the map in the file called \*Qmapfil\*U. +.s1 +Also, if you give a ship # instead of coordinates or a realm, map +will show you a small realm around the given ship (assuming you +own it). +.s1 +If you use nmap, you can get a map that shows new sector designations +instead of old sector designations of your own country. +.s1 +If you use lmap, you can get a map around a land unit, +instead. Pmap does the same for a plane. Smap does +the same for a ship. +.s1 +.L "MAP FLAGS" +.s1 +If you give an 's' flag, all your ships will be shown on the map. +An 'l' flag does the same for land units, and a 'p' for planes. +'*' gives all of the above. +.s1 +.SA "census, commodity, radar, realm, route, update, Planes, Maps" diff --git a/info/Commands/power.t b/info/Commands/power.t new file mode 100644 index 00000000..bee2b58d --- /dev/null +++ b/info/Commands/power.t @@ -0,0 +1,101 @@ +.TH Command POWER +.NA power "Display arbitrarily measured strengths of all countries" +.LV Basic +.SY "power [num]" +.SY "power new [num]" +.SY "power country " +The power report provides one view of national strengths. +It can be particularly helpful in planning defense strategies +and treaty voting. +.s1 +If the optional \*Qnum\*U argument is given, only the +top num entries in the power chart will be displayed. Note that for +deities, if you give a negative number, only the top num entries in +the power chart will be displayed, and the power number rating will +not be displayed. +.s1 +If the optional \*Qnew\*U argument is given, +the program will take several minutes to gather information +and generate a power report based on that up-to-date information. +This costs several BTU's (typically 10). +.s1 +If the optional \*Qnew\*U argument is not given, +the program will shown you the report generated +the last time someone asked for new data. +.s1 +If the optional \*Qcountry\*U argument is given, then the information +is only given for those particular countries. Countries are +separated by the "/" character as in: +.EX power c Fodder/19/Mirky +Note that countries may be specified as either names or numbers. +.s1 +In the power report the countries are listed +in order of decreasing \*Qpower factor\*U, +each being represented by a line in the following format: +.s1 +.NF +sects eff civ mil shell gun pet iron dust oil pln ship unit money +.FI + +Each column represents a different commodity or aspect for that country. +The columns and values used in computing the \*Qpower factor\*U are: +.NF +a # of sectors +b average sector efficiency +c # of civilians +d # of military +e # of shells +f # of guns +h tons of iron ore (not displayed) +i tons of gold dust +j # of gold bars +k tons of food (not displayed) +l tanks of oil +g # of planes +m # of ships +mm tons of ships (not displayed) +r # of land units +n # of dollars +oo units of light construction materials (not displayed) +pp units of heavy construction materials (not displayed) +qq megatons of nuclear weaponry (not displayed) +bb gold bars +.FI +.s1 +The \*Qpower factor\*U is determined by the following equation: +.s1 +.NF +power factor = n / 100 + + (c + d + e + h + i + k + l + mm + oo) / 10 + + pp / 5 + + (f + a * b) / 3 + + g + m + j + r + + a * 3 + + qq * 100 +.FI +.s1 +However, if the NEWPOWER option is in effect, the formula becomes: + +.NF +power factor = for each land unit calculate and add the following + ((((land unit lcm cost / 10) * (land unit effic / 100)) + + ((land unit hcm cost / 10) * (land unit effic / 100))) * 2) +power factor += for each ship calculate and add the following: + ((((ship lcm cost / 10) * (ship effic / 100)) + + ((ship hcm cost / 10) * (ship effic / 100))) * 2) +power factor += for each plane calculate and add the following: + (20 * (plane effic / 100) * (nation tech level / 500)) +power factor += ((nation money / 100) + (petrol / 500) + + ((civilians + military) / 10) + (shells / 12.5) + + (iron / 100) + (dust / 5) + (oil / 10) + bars + + (guns / 2.5) + (lcms / 10) + (hcms / 5)) +power factor += ((number of sectors * (average sector effic / 100)) * 10) +power factor = ((power factor) * (nation tech level / 500)) +power factor = ((power factor) * (research factor)) + +.FI +.s1 +The research factor is either 1, if RES_POP is not being used, or 1+(max +pop in a sector)/10000, if it is being used. +.s1 +.SA "census, nation, Communication, Nation, Diplomacy" diff --git a/info/Commands/pray.t b/info/Commands/pray.t new file mode 100644 index 00000000..ea873f9d --- /dev/null +++ b/info/Commands/pray.t @@ -0,0 +1,45 @@ +.TH Command PRAY +.NA pray "Interacting with the Deity" +.LV Basic +.s1 +There is one country in the game that has no material possessions yet +owns everything... +That country is country #0 (often called \*QThe Deity\*U). +The power of this ethereal country is unbounded -- +it can do anything from creating a civilian +(as was the case with the first civilian), +to literally moving mountains. +.s1 +Despite this great power The Deity keeps his hands out of the game +and country #0 only gets involved when there is a problem with +the source code, or prohibited activity is suspected. +The most common form of prayer +is the telegram; if you should be in need of aid type: + +.EX pray + +When the program requests your message for The Deity, +state it simply: +.NF +Enter telegram for your Gracious Deity; end with ^D +<512> I can't do anything!!!! +<488> HELP!! +<481> . +.FI +If this doesn't get helpful results then you should send a +second prayer with more specific details. e.g. +.NF +<512> Every time I type any command which requires a BTU +<461> I get dumped out of the game. Can you help me? +<413> . +.FI +.s1 +This last message is sure to move the compassionate Deity to +provide help. +.s1 +In general, when you encounter problems, be as specific about them +as possible. Include a transcript of the output of the problem, +if available. The more information you provide, the easier it is +for the deity to give you a quick & fair fix for the problem. +.s1 +.SA "telegram, Communication, Playing" diff --git a/info/Commands/production.t b/info/Commands/production.t new file mode 100644 index 00000000..d74d03fa --- /dev/null +++ b/info/Commands/production.t @@ -0,0 +1,90 @@ +.TH Command PRODUCTION +.NA production "Predicts production of sectors at the next update" +.LV Basic +.SY "production " +Produce predicts how much is going to be produced at the next update. +It also shows you how much could be produced if more materials were +available in the sector. +.s1 +Note that due to random rounding factors in the update, prod is not +totally accurate -- it may be off by a little bit. +.s1 +In the syntax of the produce command + is the area on which you wish information, +(see \*Qinfo syntax\*U). +Produce reports on any sector that would produce goods, +sectors that don't produce anything +or are less than 60% efficient are ignored. +.s1 +A typical usage might be: +.EX produce 0:9,0:9 ?type=m +which would list data for mines +in an area to the south-east of the capital. +.s1 +The production report is headed by the lines: +.NF +PRODUCTION SIMULATION + sect des eff wkfc will make--- p.e. cost use1 use2 use3 max1 max2 max3 max +.FI +These columns represent: +.s1 +.in \w'will make---\0\0'u +.L sect +the x and y coordinates of the sector +.L des +The sectors designation +.L eff +the efficiency of the sector in doing its task. +Note that some sectors although working at 100% +may show up less as the natural resources influence this figure. +.L wkfc +the number of active workers in the sector (in units of civilians). +.L will make--- +How much of what product will be made at the next update. +.L p.e. +Production efficiency \- the efficiency with which the product is made +(i.e. how much benefit education or technology gives). +.L cost +The cost of the product in dollars +.L use[123] +The three use fields show how much of what product are consumed in +producing the given number of products produced. +.L max[123] +The three max fields show what would be used if it were available in +the sector (i.e. this is what the workforce is capable of using if it +was available). +.L max +This field gives the maximum output for the workforce if all the raw +materials were present. +.in \\n(in +.s1 +For example: +.EX prod #4 ?civ>100 +.NF +prod # +Wed Aug 17 08:28:21 1988 +PRODUCTION SIMULATION + sect des eff wkfc will make--- p.e. cost use1 use2 use3 max1 max2 max3 max + 1,-3 m 56% 1003 22 iron 1.00 $0 22 + 5,-3 a 46% 1006 171 food 0.87 $0 171 + 9,-3 l 100% 1003 0 edu 1.00 $0 0l 40l 40 +-14,-2 r 100% 999 0.00 medical 0.06 $0 0d 0o 0l 2d 10o 20l 0.12 + -8,-2 j 100% 798 32 lcm 0.87 $0 32i 32i 32 + -6,-2 o 1% 182 0 oil 0.87 $0 0 + -4,-2 a 100% 1003 360 food 0.87 $0 360 + 0,-2 m 60% 1003 24 iron 1.00 $0 24 + 4,-2 m 54% 999 22 iron 1.00 $0 22 + 8,-2 % 100% 999 0 petrol 0.78 $0 0o 40o 400 +-15,-1 l 100% 1003 26 edu 1.00 $234 26l 40l 40 +-13,-1 o 28% 968 11 oil 0.87 $0 11 + -3,-1 m 51% 1003 20 iron 1.00 $0 20 + 5,-1 k 100% 1998 40 hcm 0.87 $0 78i 78i 40 +-28,0 a 53% 1003 19 food 0.87 $0 19 +-16,0 m 62% 1003 25 iron 1.00 $0 25 +-12,0 j 100% 999 40 lcm 0.87 $0 39i 39i 40 + -6,0 m 50% 964 19 iron 1.00 $0 19 + -4,0 m 59% 935 22 iron 1.00 $0 22 + 19 sectors +.FI +.s1 +.SA "Products, Update, Production" diff --git a/info/Commands/pstat.t b/info/Commands/pstat.t new file mode 100644 index 00000000..371eea2d --- /dev/null +++ b/info/Commands/pstat.t @@ -0,0 +1,52 @@ +.TH Command PSTAT +.NA pstat "Report statistics of plane, wing or planes in a give area" +.LV Basic +.SY "pstat [ | ]" +The pstat command is a report of the varying statistics of your planes and +lists the info in a readable format. Since your planes' statistics vary by +tech level, this is a very useful way to see what the attack, defense, etc. +modifiers are on a per-plane basis. +.s1 +The and arguments are provided in case you only +wish to look at one plane +or all planes within a given area. +.s1 +pstat expects some argument. To see all planes, use the +argument '*', or enter "pstat *". +.EX pstat * +.NF +pln# plane-type x,y eff tech att def acc ran load fuel + 0 f2 P-51 Mustang 1,-1 100% 110 5 5 72 11 1 1 + 1 f2 P-51 Mustang 1,-1 100% 110 5 5 72 11 1 1 + 3 lb TBD-1 Devastator 1,-1 100% 120 0 4 45 11 2 1 +3 planes +.FI +.s1 +The report format contains the following fields: +.s1 +.in +1i +.L pln# +the plane number +.L type +the type of plane; \*Qfighter 1\*U, \*Qjet hvy bomber\*U, etc, +.L x,y +the plane's current location (relative to your capital), +.L eff +the plane's efficiency, +.L tech +the tech level at which it was created, +.L att +the attack value of the plane (for air-to-air combat) +.L def +the defensive value of the plane (for air-to-air combat) +.L acc +the accuracy of the plane (for bombing) +.L ran +and the range (in sectors) it can fly on a given mission. +.L load +the carrying capacity of the plane +.L fuel +the amount of fuel the plane takes per flight +.in +.s1 +.SA "plane, upgrade, arm, bomb, build, drop, fly, launch, paradrop, recon, satellite, scrap, wingadd, Planes" diff --git a/info/Commands/qorder.t b/info/Commands/qorder.t new file mode 100644 index 00000000..31111f27 --- /dev/null +++ b/info/Commands/qorder.t @@ -0,0 +1,27 @@ +.TH Command QORDER +.NA qorder "Query the auto-navigation orders of a ship" +.LV Expert +.SY "qorder " +.s1 +\*Qqorder\*U shows current commodity levels on a ship. +Ships with no orders are not listed. +The report indicates: +.NF + shp# ship number + ship type type of ship (cargo ship, destroyer, etc) + Starting The first sector to move and cargo hold levels. + Ending The destination sector to and cargo hold levels. + +shp# ship type [Starting] , (Ending) + 6 cargo ship 1 [1-s:50 2-l:500] , ( 1-g:50 ) + 54 cargo ship 1 [ ] , (1-h:1000) +1003 destroyer 2 [1-s:40] , ( ) +.FI +This report reads. +Cargo Ship #6 will sail to its starting sector, displayed +in the sorder, and load cargo hold 1 with 50 shells and cargo hold 2 with 500 +light construction materials. Then sail to the ending sector, again +displayed in the sorder command, unload the cargo and load cargo hold +1 with 50 guns. +.s1 +.SA "order, sorder, bmap, navigate, ship, Ships, Autonav, Autofeed" diff --git a/info/Commands/quit.t b/info/Commands/quit.t new file mode 100644 index 00000000..e0ba41aa --- /dev/null +++ b/info/Commands/quit.t @@ -0,0 +1,8 @@ +.TH Command QUIT +.NA quit "Log out of Empire" +.LV Basic +.SY "quit" +You use the \*Qquit\*U command to close your connection to the Empire +Server. In some clients, pressing control-D will do the same thing. + +.SA "Playing" diff --git a/info/Commands/radar.t b/info/Commands/radar.t new file mode 100644 index 00000000..51fe71af --- /dev/null +++ b/info/Commands/radar.t @@ -0,0 +1,124 @@ +.TH Command RADAR +.NA radar "Perform radar scan from ship or sector" +.LV Basic +.SY "radar [ | ]" +The radar command bears some resemblance +to modern high-resolution radar. +It has a circular range dependent upon its efficiency. +.s1 +To run land radar type: +.EX radar +where must be the sector where the radar station resides, +or an area that contains one or more radar stations. +.s1 +The program will respond with the station's efficiency and range +and then display the area. +.s1 +What is displayed is dependent upon the range. +Sectors and ships within 1/3 of the range +are displayed with their sector or ship designations. +Sectors at greater distances are indicated by a '?' +if they are inhabited by another country. +.s1 +A 100% radar station in a country with infinite technology +on a clear day has a range of 16. +The range is linearly related to efficiency; +thus a 50% radar station can see half as far +as a 100% radar station. +The range is related to technology level in the \*Qusual\*U way, +i.e., it varies linearly with \*Qtechnology factor\*U +as indicated in the nation report; +see \*Qinfo nation\*U and \*Qinfo technology\*U for details. +.s1 +Satellites will appear on the map as a '$'. +.s1 +WARNING! +Land radar cannot spot submarines. +.s1 +FURTHER WARNING! +Even worse, should your cunning enemy move troops right to your +doorstep and leave the sector designated a wilderness it would +show up on your very efficient radar as '-'. +Thus you would never know he was there.... +Well, almost never. +.s1 +An example of land radar: +.EX radar 5,1 +.NF +5,1 efficiency 100%, max range 6 + . a a - ^ ? ? + T k o ! - ^ ? ? + a h j a ^ ^ ^ ^ ^ + h . a w a ^ - ? a ? + . . a m a b f a ^ ^ - + . . m c * a a - ^ - ^ - + . - . a + . 0 a - - ^ - . + - ^ ^ a + ) ^ a - - ^ . + - - a m + a f . . - ^ + ^ a - a + a ^ - - - + - ^ - - ^ - - - - + - ^ - - - - - - + - - - - - - - +.FI +.s1 +To run unit radar type: +.EX lradar +where is the number of a unit or an army designation. +.s1 +To run naval radar type: +.EX radar +where is the number of a ship or a fleet designation. +.s1 +Sea radar is highly dependent upon what kind of ship you +have and what kind the opponent has. +(e.g., Battleships can see battleships far away +but fishing boats must be close together to see each other). +.s1 +The maximum distance at which ship A can see ship B +is dependent on two factors: +the \*Qspying\*U ability of ship A, +and the \*Qvisibility\*U of ship B. +Battleships have sophisticated communications equipment +which give them a maximum spying range of 6 while fishing boats, +having little such equipment, +have a maximum range of 2. +This factor is shown in a table in \*Qinfo Ship-types\*U +under the heading \*Qspy\*U. +On the other hand, the ships vary in size and consequently, +vary in visibility. +Battleships, oil derricks, and carriers are the easiest to see; +next come cargo ships, heavy cruisers and tenders, and so on. +See \*Qinfo Ship-types\*U for a chart. +.s1 +Ship A will see ship B if the distance between them is less than: +.NF + 0.3i + spy factor of ship A * visibility of ship B +efficiency * ------------------------------------------- * technology factor + 20 +.FI +.s1 +Note that, although subs can not be found via radar, +destroyers automatically use sonar so they can see subs. +Destroyer A will see submarine B if the distance between them is less than: +.NF + 0.3i + spy factor of ship A * visibility of ship B +efficiency * ------------------------------------------- * technology factor + 20 +.FI +.s1 +An example of ship radar: +.EX radar 50 +.NF +patrol boat #50 at -1, -3 efficiency 100%, max range 4 + . . . . . + . . . . - - + . . - . a a - + . . . T k o ! - + . - F a P j a ^ ^ + . . - . a w a ^ + . . . a m a b + . . m c * a + - . a + . +.FI +.s1 +.SA "skywatch, coastwatch, census, map, nation, Ship-types, Technology, lradar, Detection, Ships, Sectors" diff --git a/info/Commands/range.t b/info/Commands/range.t new file mode 100644 index 00000000..e4d78e2d --- /dev/null +++ b/info/Commands/range.t @@ -0,0 +1,21 @@ +.TH Command RANGE +.NA range "Edit the range of a plane" +.LV Expert +.SY "range " +The \*Qrange\*U command is used to limit the maximum range of +individual planes. This can be useful in setting up high tech +interceptors (planes, ABMs, SAMs, etc.) to cover only a small +limited area. +.s1 +Note that missiles always fly at double range (since they don't need +to fly back), so you should cut the desired range in half before using +the range command. +.s1 +For example, if plane 1 were a plane and you wanted to limit its +reaction radius to 6, then you would type: +.EX "range 1 6" +and if plane 2 were a missile and you wanted to limit its reaction +radius to 6, then you would type: +.EX "range 2 3" + +.SA "Planes" diff --git a/info/Commands/read.t b/info/Commands/read.t new file mode 100644 index 00000000..5167ba8b --- /dev/null +++ b/info/Commands/read.t @@ -0,0 +1,22 @@ +.TH Command READ +.NA read "Read your telegrams" +.LV Basic +.SY "read" +The read command is used to read the telegrams sent you +by other countries and by the game, +(e.g. when you make a sale or are attacked). +.sp +When telegrams arrive you are informed with: +.NF +\*QYou have a new telegram waiting ...\*U if there is just one new one, or +\*QYou have ten new telegrams waiting ...\*U if there are ten of them, or +\*QYou have several new telegrams waiting ...\*U if there are very many. +.FI +After reading all your telegrams you may discard them by answering \*Qyes\*U to +the question posed. If you answer \*Qno\*U the telegrams will remain +pending but you will not be reminded of them. +.s1 +This command reads only +telegrams & bulletins, use the 'wire' command to read announcements. +.s1 +.SA "toggle, telegram, wire, flash, accept, reject, Communication" diff --git a/info/Commands/realm.t b/info/Commands/realm.t new file mode 100644 index 00000000..178749bc --- /dev/null +++ b/info/Commands/realm.t @@ -0,0 +1,36 @@ +.TH Command REALM +.NA realm "Print out or modify one of your \*Qrealms\*U" +.LV Basic +.SY "realm " +The realm command allows you to manipulate the contents of the +\*Qrealm\*Us associated with your country +which provide a convenient way to save coordinates that are +frequently used +(see \*Qinfo syntax\*U for use of realm arguments). +.s1 +In the syntax of the realm command + is the number of the realm to be set. +.s1 +The argument is optional; +if included, the specified realm will be set to ; +if omitted the coordinates of the specified realm will be printed. +.sp +.EX realm 1 +.NF +Realm 1 is -3:3,3:3 +.FI +.EX realm 1 -3:2,4 +.EX realm 1 +.NF +Realm 1 is now set to -3:2,4:4 +.FI +.s1 +If the argument is omitted, +the coordinates of all realms will be printed. +.s1 +Also note that the argument may use the \*Q#\*U form of realm +specification. +.EX realm 0 #1 +Now realm 0 is set to -3:2,4:4. +.s1 +.SA "Syntax, nation, Maps" diff --git a/info/Commands/recon.t b/info/Commands/recon.t new file mode 100644 index 00000000..95029df3 --- /dev/null +++ b/info/Commands/recon.t @@ -0,0 +1,51 @@ +.TH Command RECON +.NA recon "Use planes to take a look around" +.LV Expert +.SY "recon route|destination" +The \*Qrecon\*U command is used to gather intelligence about sectors +that the spy mission overflies. +The planes take off from their respective airports, assemble, and +then fly the mission and land in the destination sector. +.s1 + represents a list of planes which are to be performing the +intelligence gathering operation. +Only planes which are provided with gas, and have sufficient mobility will +be successfully selected for the mission. +.s1 + represent a list of fighter planes which are capable of escorting +the transports all the way to the target. +To be selected, escorts must have fuel and mobility. +.s1 + represents an assembly point, where all of the planes in the +mission meet before proceeding on to the target sector. +The assembly point must be owned by you, and must not be more than +four sectors away from any of the planes selected for the mission. +.s1 +Route is a normal empire path specification. You may also give a +destination sector on the command line, or at any time while giving +the route, and empire will use the best path from the current sector +to the desired destination sector. +.s1 +When getting a path interactively, empire will show you the information +you have (from your bmap) concerning the current area, to help plot +your course. +.s1 +Information given by recon is not totally accurate. +.s1 +Recon missions can be intercepted just like any other mission. +If the destination sector is not an airport, then all planes in +the mission must have V/STOL capability. +.s1 +Planes with the ASW ability will +perform a sonar search on each sector as they fly through it. +Each sub contact will be reported only once, giving the sector and number +of the sub, from the sector in which it +is first detected (which may not be the sector the sub is in, as plane +sonar has a range dependent on acc, and a chance of finding a sub of +((100-acc)-(4-sub visib)*10))+((100-effic)/5) percent. +The sub being sonared may detect the sonar ping. +.s1 +Note that a plane must be at least 40% efficient before it can leave +the ground. +.s1 +.SA "Plane-types, bomb, fly, paradrop, drop, sweep, Mobility, Planes, Detection" diff --git a/info/Commands/reject.t b/info/Commands/reject.t new file mode 100644 index 00000000..425b3aa6 --- /dev/null +++ b/info/Commands/reject.t @@ -0,0 +1,25 @@ +.TH Command REJECT +.NA reject "Stop/start listening to other countries" +.LV Expert +.SY "reject " +The reject command allows you to either accept or reject announcements, +mail, treaties, or loans from a country. +.s1 +.EX "reject" +.nf +reject or accept? reject +mail, treaties, loans, or announcements? anno +nat(s)? 0 +Rejecting annos from The_Scum +.fi +.EX "reject" +.nf +reject or accept? accept +mail, treaties, loans, or announcements? anno +nat(s)? 0 +Accepting annos from The_Scum +.fi +.s1 +The accept command can be used to see the communications status of a country. +.s1 +.SA "telegram, announce, read, wire, reject, accept, Communication, Diplomacy" diff --git a/info/Commands/relations.t b/info/Commands/relations.t new file mode 100644 index 00000000..a30643d3 --- /dev/null +++ b/info/Commands/relations.t @@ -0,0 +1,109 @@ +.TH Command RELATIONS +.NA relations "Shows diplomatic relations between countries" +.LV Basic +.SY "relations" +The relations command displays your diplomatic status with other nations. +If the optional argument is specified, the command displays that country's +diplomatic status with other nations. +.s1 +The data displayed by the nation command is formatted as a single page +report. +.EX relations +.NF + + MGM Diplomatic Relations Report Sat Jun 17 23:24:46 1989 + + 0) POGO Allied Allied + 1) 1 Neutral Neutral + 2) Groonland At War Hostile + +.FI +.EX relations 2 +.NF + + Groonland Diplomatic Relations Report Sat Jun 17 23:24:46 1989 + + 0) POGO Neutral Neutral + 1) 1 Allied Neutral + 3) MGM Hostile At War + +.FI +.s1 +Relations are: \*QAllied\*U, \*QFriendly\*U, \*QNeutral\*U, +\*QHostile\*U, \*QMobilizing\*U, \*QSitzkrieg\*U, and \*QAt +War\*U. Each has certain ramifications. +.s1 +.L Allied +Your ally is someone you trust deeply, and are willing to make +sacrifices for. If you are allied with someone, then your forts, +ships, planes, & artillery will support them in battle. Also, they +can over-fly you, and you will not be told. (I.e. an ally can map you +out easily). When you use the "wall" command, it sends a flash +message to all of your allies (see info wall). Unless the ALL_BLEED +option is in effect, you will benefit from tech produced by your +allies, but not by others . Allied nations are assumed to have +"friendly" trade relations. +.s1 +.L Friendly +When you accept a country as a trustworthy trading partner, then you +establish friendly relations towards them. This allows them to sail +ships into your harbours, load and unload goods, fuel, and have their +ships repaired there. You are allowed to "tend" and "follow" friendly +ships. You are allowed to cede sectors to a friendly +nation, and may send them "flash" messages (see info flash). You will +be warned, however, if they overfly +your territory. And if they do it enough times, your diplomatic +relations towards them will be automatically downgraded. You may +"spy" on a friendly nation with no consequences. +.s1 +.L Neutral +You start out neutral towards all countries. It simply means that you +are ambivalent towards them. If they overfly your territory, you will +be warned and your relations will automatically downgrade. Caught +spies will be deported. +.s1 +.L Hostile +If you are suspicious that a nation may be planning to attack you, +but you are not committed to an all out war against them, then you +should declare hostile relations towards them. This will ensure that +your planes will intercept theirs if they +try to over-fly you, and your forts will fire on their ships when they +sail within range. Also, your a-sat's and abm's will attempt +to intercept their satellites and missiles independent of the target +sector they have launched them at, and your ships with anti-missile +capability will attempt to intercept any incoming marine missiles +within range. Caught spies will be shot. +.s1 +.L War +If you are committed to expending major resources against a nation, +then you should declare war on them. This will cause all of your +ships, artillery, planes and missiles which have been put on a mission +to react to enemy movement. +.s1 +The following paragraphs apply only if the SLOW_WAR option is used. +.s1 +.L Mobilizing +If you are Mobilizing, it means that you have declared war, and are getting +ready to attack. You cannot attack someone's land until you are actually +\*QAt War\*U. At the next update, you will automatically move to +\*QSitzkrieg\*U. Your interdiction of the enemy will be the same as +if you were hostile towards them. +.s1 +.L Sitzkrieg +Sitzkrieg is the same as \*QMobilizing\*U. You still are unable to attack +their land. At the next update, you will automatically move to \*QAt War\*. +.s1 +When you are At War with someone, you may attack them willy-nilly. +.s1 +Note that if the SNEAK_ATTACK option is enabled, you can make an attack +on someone you're not at war with (not shelling or anything else, just an +attack or assault). For this privilege, you are charged $5K. Once your +attack is over, whether successful or not, you automatically declare war +on them and must wait through the normal SLOW_WAR procedure to attack again. +(In this case, the $1K fee for declaring war is waived) +.s1 +Also, there is an automatic progression. If someone you are allied with +attacks you, you become hostile towards them. If someone you are neutral +to over-flies or attacks you, you become hostile towards them. Neither of +these progressions can lead to war, however, they both stop at hostility. +.SA "Diplomacy" diff --git a/info/Commands/repay.t b/info/Commands/repay.t new file mode 100644 index 00000000..319b0c6d --- /dev/null +++ b/info/Commands/repay.t @@ -0,0 +1,30 @@ +.TH Command REPAY +.NA repay "Repay a loan (all or part)" +.LV Expert +.SY "repay " +The repay command is used to repay loans from other countries. +.s1 +The argument is the number of the loan you are repaying +and if not included on the command line +it will be solicited by the program. +.s1 +You can repay all or part of the loan with this command; +however beware of letting the loan become overdue -- +the lender may decide to force collection +(see \*Qinfo collect\*U). +.s1 +When you repay on a loan a telegram is sent to the lender +informing her/him of the amount repaid. +.s1 +.EX repay 12 +.NF +You presently owe $4515 payment : $2000 +.FI +or, +.EX repay 12 +.NF +You presently owe $4515 payment : $4515 +Congratulations, you've paid off the loan! +.FI +.s1 +.SA "collect, consider, ledger, offer, Loans" diff --git a/info/Commands/report.t b/info/Commands/report.t new file mode 100644 index 00000000..5db5fc30 --- /dev/null +++ b/info/Commands/report.t @@ -0,0 +1,59 @@ +.TH Command REPORT +.NA report "List all countries and their status" +.LV Basic +.SY "report " +The report command displays a list of nations in . It shows +their status (in-flux, visitor, active, etc), and their estimated tech, +education, research and happiness levels. +.s1 +If is a country name or number, it will only display information +on that country; if is * then information on all countries will +be listed. +.s1 +An example of a report command for the country \*QFroom 93\*U would +look something like this: +.EX report * +.NF +Thu Sep 14 16:10:40 1995 + # name tech research education happiness status + 2 Artifax 0 - 147 79 - 99 0 - 23 0 - 9 In flux + 3 Billy 0 - 137 79 - 99 0 - 23 0 - 9 In flux + 4 CCCP 150 - 200 120 - 150 23 - 30 20 - 25 Active + 8 Khazad'ur 86 - 108 120 - 150 23 - 30 12 - 17 Active + 9 Lorphos 96 - 121 120 - 150 0 - 23 12 - 17 Active + +This is how the ranges are determined. +(1) If your value of the statistic is 0, then n/a (not applicable) + will be printed in that column. + +(2) If the value for both countries is > 100, then shift them down so + the lowest one is at 100. + +(3) Each of the following tests is made in order. As soon as one of them + is true, then that will be the range for that statistic: + 2.0 * yours < theirs + 1.5 * yours < theirs < 2.0 * yours + 1.2 * yours < theirs < 1.5 * yours + 1.1 * yours < theirs < 1.2 * yours + yours / 1.1 < theirs < 1.1 * yours + yours / 1.2 < theirs < yours / 1.1 + yours / 1.5 < theirs < yours / 1.2 + yours / 2.0 < theirs < yours / 1.5 + theirs < yours / 2.0 + +(4) Once the range has been determined, it is shifted back up to where + it should be. + +(5) There is a "minimum range" for the different characteristics: + tech: 20 + res: 10 + edu: 5 + hap: 5 + If the distance between the high and low end of the range is smaller + than the "minimum range", then the range is expanded (equally in both + directions but never crossing zero) to be equal to the minimum range. + However, it will never be expanded beyond twice your value of that + statistic. +.FI +.s1 +.SA "country, Diplomacy, Nation" diff --git a/info/Commands/reset.t b/info/Commands/reset.t new file mode 100644 index 00000000..cdbb6317 --- /dev/null +++ b/info/Commands/reset.t @@ -0,0 +1,13 @@ +.TH Command RESET +.NA reset "Reset the price of a product on the market" +.LV Expert +.SY "reset " +The reset price command allows you to reset the prices of your +commodities that are on the market. +.s1 + is the lot # shown by the 'market' command. + is the new asking price. An asking price of 0 will take +your goods off the market and return them to your harbor or warehouse. +.sp +.SA "buy, sell, Market" + diff --git a/info/Commands/resource.t b/info/Commands/resource.t new file mode 100644 index 00000000..f7305dfa --- /dev/null +++ b/info/Commands/resource.t @@ -0,0 +1,68 @@ +.TH Command RESOURCE +.NA resource "Show the resources of sectors" +.LV Basic +.SY "resource " +The resource command displays specific information on +some or all of the sectors you occupy. +.s1 +In the syntax of the resource command + is the area on which you wish information, +(see \*Qinfo syntax\*U). +.s1 +A typical usage might be: +.EX resource 0:9,0:9 ?des=m +which would list data for mines in an area +to the south-east of the capital. +.s1 +A resource report lists each of your sectors in the specified area +headed by: +.NF +RESOURCE + sect eff min gold fert oil uran ter +.FI +These columns represent: +.s1 +.in \w'gmin\0\0'u +.L sect +the x and y coordinates of the sector +.L eff +the efficiency of the sector (affects all benefits +of a designated sector except mobility units) +.L min +the percentage richness of non-gold minerals, +(range is 0-100, not used up, i.e. a renewable resource) +.L gold +the amount of gold ore, +(range is 0-100, in absolute tons, i.e. non-renewable) +.L fert +the fertility of the soil in relative terms, +(range is 0-100, not used up, i.e. a renewable resource) +.L oil +the petroleum content of the soil in relative terms, +(range is 0-100, in absolute tons, i.e. non-renewable) +.L uran +the uranium (radioactive materials) content in relative terms, +(non-renewable) +.L ter +the territory number. +.in \\n(in +.s1 +For example: +.EX reso #0 +.NF +Sat Sep 2 03:20:00 1989 +RESOURCE + sect eff min gold fert oil uran ter + 3,-5 ^ 40% 38 0 64 0 44 + 5,-5 ) 100% 75 0 41 0 36 90 + 7,-5 t 100% 65 0 38 0 72 + 9,-5 h 100% 48 0 42 0 45 5 + 0,-4 j 100% 0 0 112 40 0 + 2,-4 j 100% 32 0 69 0 36 + 4,-4 l 100% 60 0 53 0 37 22 + 6,-4 + 100% 52 0 14 0 78 + 10,-4 ^ 20% 100 0 0 0 79 + 9 sectors +.FI +.s1 +.SA "commodity, census, Products, Sectors" diff --git a/info/Commands/retreat.t b/info/Commands/retreat.t new file mode 100644 index 00000000..0e57fda6 --- /dev/null +++ b/info/Commands/retreat.t @@ -0,0 +1,91 @@ +.TH Command RETREAT +.NA retreat "Set retreat conditions/paths for ships or fleets" +.LV Expert +.SY "retreat [ | ] [] []" +.SY "lretreat [ | ] [] []" +The retreat command allows you to examine or modify the retreat +paths and conditions of your ships or units. The following description +is for ships. Land units are exactly the same, except of course that +some of the retreat conditions (being sonared, depth charged, etc) don't apply. +.s1 +The and arguments are provided to specify which +ships to view or give orders for. If a fleet designation is given when +specifying orders, the orders apply to all ships within that fleet. +.s1 +Retreat expects an argument. To see every ship you own, give it +the argument '*', or type "retreat *". +.s1 +The report format contains the following fields: +.s1 +.in \w'shiptype\0\0'u +.L shp# +the ship number +.L shiptype +the type of ship; \*Qpatrol boat\*U, \*Qsubmarine\*U, etc, +.L x,y +the ship's current location (relative to your capital), +.L flt +the fleet designation letter (set by \*Qfleetadd\*U command), +.L path +the ship's current retreat path. +.L as_flt? +whether or not the ship's retreat path is a fleet retreat path +.L flags +what conditions the ship will retreat under +.in +.s1 +For example: +.EX retreat * +.NF +shp# ship type x,y fl path as flt? flags + 0 battleship 4 2,0 jjuuj I +1 ship +.FI +.s1 +.L Overview +.s1 +A player may give retreat orders for a ship or a fleet. Retreat +orders include a set of conditions that determine when the fleet/ship +will retreat, and a path that the fleet/ship will follow. When a condition +is met for a particular ship, the \*Qas flt?\*U field is checked. If it +is Yes, then every ship in that fleet with fleet retreat orders retreats +along the specified path. If it is no, then the retreat orders apply to +that ship only, and only that ship retreats. +.s1 +When a ship is added to a fleet, it is given the retreat orders of that +fleet, if any exist. +.s1 +Retreat orders are wiped when a ship navigates. +.s1 +Retreat conditions at present include: +.nf + + Condition Meaning + I Retreat when the ship is injured, + i.e. whenever the ship is damaged + by fire, bombs, or torping. + T Retreat when a sub torpedos or tries + to torpedo the ship. + B Retreat when a plane bombs or tries + to bomb the ship. + S Retreat when the ship detects a sonar + ping. + D Retreat when the ship is depth-charged. + H Retreat when helpless. A ship is helpless + when it is fired upon, and no friendly + ships/sectors (including the ship itself) + are able to fire back at the aggressor. + U Retreat upon a failed boarding attempt. + C Clear the flags +.fi +.s1 +For example, if the battleship above was fired at, it would attempt to +retreat 2 sectors, jj, using the normal amount of mobility for moving +2 sectors. It would then look like: +.NF +shp# ship type x,y fl path as flt? flags + 0 battleship 4 2,0 uuj I +1 ship +.FI +.s1 +.SA "ship, fleetadd, Ships" diff --git a/info/Commands/route.t b/info/Commands/route.t new file mode 100644 index 00000000..d317a020 --- /dev/null +++ b/info/Commands/route.t @@ -0,0 +1,61 @@ +.TH Command ROUTE +.NA route "Display delivery routes" +.LV Expert +.SY "route " +The route command generates a graphic display +of the delivery arrangement +for a specific deliverable item +in a given sector area. +.s1 +The argument is as described in \*Qinfo syntax\*U. + is one of the following: +.NF +u uncompensated workers +f food +s shells +g guns (not gold) +p planes +i iron ore +d dust, (gold) +b bars of gold +o oil +l light construction materials +h heavy construction materials +r radioactive materials +.FI + +The delivery routes are indicated with \*Qgo-to\*Us +using the following codes, (assuming the sector in question is a mine): +.NF +.sp + m/ up-right (u in census) + m> right (j in census) + m\\\\ down-right (n in census) +/m down-left (b in census) + h> \\\\j \\\\a$ + -3 + -2 \\\\a$ \\\\a$ $a\\\\ /a$ /a$ -2 + -1 /a$ $a\\\\ /a$ b /+ + -1 + 0 m c u t \\\\i 0 + 1 \\\\a$ \\\\l \\\\a \\\\a 1 + 2 a/ \\\\a a/ $a$ 2 + - - - 0 0 0 0 0 0 0 0 0 0 1 1 1 + 3 2 1 0 1 2 3 4 5 6 7 8 9 0 1 2 +.FI +.sp +.s1 +.SA "deliver, census, Syntax, Distribution" diff --git a/info/Commands/sabotage.t b/info/Commands/sabotage.t new file mode 100644 index 00000000..7feb5d5b --- /dev/null +++ b/info/Commands/sabotage.t @@ -0,0 +1,17 @@ +.TH Command SABOTAGE +.NA sabotage "Damage enemy territory with spy unit" +.LV Basic +.SY "sabotage " +The \*Qsabotage\*U command is used to blow up commodities +and cause havoc in the sector the spy is in. Spies don't +check relations and can cause damage to enemies and allies. +Sabotage can only be done by spy units. The spy must have +a shell to make an attempt. +.s1 +Terrorizing your neighbors is dangerous work. Spies can be +caught or die during a sabotage attempt. +.s1 +Sabotage can be more effective against enemy warehouses filled +with explosive or flammable materials. +.s1 +.SA "Spies, Unit-types, LandUnits" diff --git a/info/Commands/sail.t b/info/Commands/sail.t new file mode 100644 index 00000000..f4bf98df --- /dev/null +++ b/info/Commands/sail.t @@ -0,0 +1,55 @@ +.TH Command SAIL +.NA sail "Give sailing orders to a ship" +.LV Expert +.SY "sail [|q[uery]|-]" +You use the \*Qsail\*U command to give a sailing path to ships. +At each update, ships with a sailing path \*Qautonavigate\*U along +the path that was set for them. Telegrams notify you of arrivals +or problems encountered while attempting to follow the path. +.s1 +Radar operates continuously as the ship moves along the path, constantly +adding sector information to the known world map. +.s1 +Ship movement is performed before mobility is increased. +This insures that after the update, ships with a sailing path will still +have some mobility so that you can always manually navigate +to some extent. +.s1 +Note that ships sailing can encounter exactly the same interdiction as +ships navigating. +.s1 +.EX sail \*Qq[uery]\*U +.s1 +\*Qsail\*U, with the \*Qquery\*U parameter, shows the current sailing path. +The report indicates: +.NF + shp# ship number + ship type type of ship (cargo ship, destroyer, etc) + x,y ship's current position + mobil ship's current mobility + mobquota mobility available per update to sail + follows ship that is being followed + path the current sailing path + +shp# ship type x,y mobil mobquota follows path + 1 cargo ship -27,19 44 32 1 jjjuujj + 12 cargo ship -27,19 40 32 1 + 34 fishing boat 15,32 58 32 3 ggbbgyyg + 58 cargo ship 18,34 62 0 4 +4 ship(s) +.FI +.s1 +.EX sail \*Q-\*U +.s1 +\*Qsail\*U, with the \*Q-\*U parameter, causes the sailing path +for the ships specified to be removed. +.s1 +The PATH is a normal empire path specification. You may *not* give a +destination sector on the command line, or at any time while giving +the route. Use the \*Qorder\*U command if you wish this functionality. +.s1 +When getting a path interactively, empire will show you the information +you have (from your bmap) concerning the current area, to help you plot +your course. +.s1 +.SA "follow, unsail, mquota, Ships" diff --git a/info/Commands/satellite.t b/info/Commands/satellite.t new file mode 100644 index 00000000..df8589c6 --- /dev/null +++ b/info/Commands/satellite.t @@ -0,0 +1,58 @@ +.TH Command SATELLITE +.NA satellite "Download data from a reconnaissance satellite" +.LV Expert +.SY "satellite [ [?cond&cond&...]]" +The satellite command is how you get information from your satellites. +A satellite must be in orbit (launched) +before it will begin transmitting. +The type of information you get from a satellite +depends on what type of satellite it is. +.s1 +An ordinary satellite will return data that looks remarkably like +\*Qradar\*U output. +If the satellite has \*Qimaging\*U capabilities +you will see the sector designations. +If not then you will see a '?' for inhabited sectors. +.s1 +A satellite with imaging capabilities +will also show ships and land units. +.s1 +Spy satellites provide much more information. +Their output is a table that looks remarkably like \*Qspy\*U output +followed by another table listing all the ships in the area with +their owner, ship type, and efficiency. +.s1 +Spy satellites with \*Qimaging\*U capabilities can also see subs! +.s1 +After launching, a satellite will take a while to come \*Qon line\*U. +During this period, +(shown by mobility being < 127), +you cannot use the satellite. +.s1 +If a satellite has been damaged, then it will only transmit partial +data. For example, a 75% satellite will only display three out of +every four sectors. Note that it will always be the same 75% of +sectors which are displayed (i.e. it is not random), so you will gain +nothing by repeatedly downloading data from the satellite. +.s1 +You may also filter the information you receive from the satellite +using conditionals. Here are some examples to show you how +conditionals work. In all of the following examples, we will assume +that we are using satellite #28. +.s1 +To list all airports: +.EX "sat 28 se ?des=*" +To list all airports owned by country #7: +.EX "sat 28 se ?des=*&own=7" +To list all ships in 12,14: +.EX "sat 28 sh ?xloc=12&yloc=14" +To list all land units: +.Ex "sat 28 l" +To list all cavalry units: +.EX "sat 28 l ?type=cavalry". +.s1 +For a complete list of conditionals you can use, see info Syntax. +Note that the large radar map is only drawn when the output is not filtered: +.EX "sat 28" +.s1 +.SA "launch, radar, spy, census, map, Syntax, Ship-types, Planes, Detection" diff --git a/info/Commands/scrap.t b/info/Commands/scrap.t new file mode 100644 index 00000000..da8a2f95 --- /dev/null +++ b/info/Commands/scrap.t @@ -0,0 +1,24 @@ +.TH Command SCRAP +.NA scrap "Scrap a ship, plane, or unit" +.LV Basic +.SY "scrap " +This command allows you to scrap planes/units/ships when you no longer +need them. +.s1 +Ships may only be scrapped friendly 60% harbours. +Planes may only be scrapped in 60% airfields. +Units may be scrapped in any sector. +.s1 +When scrapping a unit, plane or ship, you receive materials equal to 2/3 +the amount used to build it. The materials are put in the sector where +the scrapping occurs. +.s1 +When scrapping a unit, you also get the military that the unit represents +as mil in the sector. (Example: a unit that takes 100 mil to build is +at 50%, and is scrapped. 50 mil will be added to the sector) Units on +ships cannot be scrapped. +.s1 +If you scrap a ship or unit that has planes on board, the planes will +be transferred to the sector. +.s1 +.SA "scuttle, build, ship, land, plane, Ships, Planes, LandUnits" diff --git a/info/Commands/scuttle.t b/info/Commands/scuttle.t new file mode 100644 index 00000000..7c1d7a63 --- /dev/null +++ b/info/Commands/scuttle.t @@ -0,0 +1,19 @@ +.TH Command SCUTTLE +.NA scuttle "Destroy a ship, plane, or unit" +.LV Basic +.SY "scuttle " +This command allows you to destroy planes/units/ships when you no longer +need them. +.s1 +Planes, units, and ships may be scuttled in any sector. +.s1 +If you scuttle a ship or unit that has planes on board, the planes will either +be transferred to land (if a unit, or if the ship is in a harbor), or will die +(if the ship is elsewhere) +.s1 +Units on ships may not be scuttled. +.s1 +Scuttling trade-ships (if the TRADESHIPS option is enabled) has other effects. +See info Trade-ships. +.s1 +.SA "scrap, Trade-ships, build, ship, plane, land, Ships, Planes, LandUnits" diff --git a/info/Commands/sdump.t b/info/Commands/sdump.t new file mode 100644 index 00000000..a6b31f1d --- /dev/null +++ b/info/Commands/sdump.t @@ -0,0 +1,80 @@ +.TH Command SDUMP +.NA sdump "Dump raw ship information" +.LV Expert +.SY "sdump []" +The sdump command displays all information on +some or all of your ships. +sdump is a combination of ship, cargo, and sstat. +Each ship's information is printed on one very long line. +Fields are separated by a single space. +.s1 +This command is designed to be used for input to an empire tool +such as \*Qve\*U. +.s1 +In the syntax of the sdump command + are the ships on which you wish information, +[] are the fields you wish to dump. +If no fields are specified, all fields are printed. +(see \*Qinfo Syntax\*U). +.s1 +An sdump command lists all selected ships headed by: +.NF +Sun Feb 9 22:16:37 1997 +DUMP SHIPS 855544597 + +.FI +The first line is the date. The second line is the +"DUMP SHIPS " where the field is the current +timestamp. The third line is the columns which are output. +.s1 +These columns represent the following fields which are also the +selection criteria for the command. +.s1 +The following may be used as fields. They must be entered EXACTLY as +shown here (no partial pattern matching is done.) +.NF + type type of ship + x x location + y y location + flt fleet + eff efficiency + civ # of civilians on board + mil # of mil on board + uw # of uw on board + food # of food on board + pln # of planes on board + he # of helicopters on board + xl # of x-light planes on board + land # of land units on board + mob mobility + fuel fuel on board + tech technology of ship + shell # of shells on board + gun # of guns on board + petrol # of petrol on board + iron # of iron on board + dust # of dust on board + bar # of bars on board + oil # of oil on board + lcm # of lcms on board + hcm # of hcms on board + rad # or rads on board + def defense of ship + spd speed of ship + vis visibility of ship + rng firing range of ship + fir max # of guns fired by each volley + name ship name + origx x origin where trade ship was built + origy y origin where trade ship was built +.FI +.s1 +A typical usage might be: +.EX sdump #5 +which would list data for all ships in realm #5. +.s1 +A sdump lists each of your ships in the specified area. +The header line is a list of fields that correspond +to the order that sdump prints the ship info. +.s1 +.SA "ship, cargo, sstat, Clients, Ships" diff --git a/info/Commands/sect.t b/info/Commands/sect.t new file mode 100644 index 00000000..bdddd730 --- /dev/null +++ b/info/Commands/sect.t @@ -0,0 +1,40 @@ +.TH Command SECT +.NA sect "Show only sectors owned by you in map form" +.LV Expert +.SY "sect " +The sect report gives you a graphic representation of all or part +of your country, similar to map. +Only sectors owned by you show up, however. +The rest of the world is simply blank. +.s1 +If your terminal is of the proper type, +any sectors selected by the \*Q?cond\*U operator +will show up in reverse video. +.s1 +Examples: +.EX sect -9:18,-8:5 +generates a 28 x 14 map based on data supplied by the sectors +in the area specified. +.NF + ---------0000000000111111111 + 9876543210123456789012345678 + -8 -8 + -7 -7 + -6 -6 + -5 a a -5 + -4 k o ! -4 + -3 a h j a -3 + -2 a a a a a -2 + -1 a a a b + + -1 + 0 m c u a a 0 + 1 a a a a 1 + 2 a a a a 2 + 3 3 + 4 4 + 5 5 + ---------0000000000111111111 + 9876543210123456789012345678 +.FI +.s1 +.s1 +.SA "census, commodity, radar, realm, route, update, map, Maps" diff --git a/info/Commands/sell.t b/info/Commands/sell.t new file mode 100644 index 00000000..6cda4067 --- /dev/null +++ b/info/Commands/sell.t @@ -0,0 +1,42 @@ +.TH Command SELL +.NA sell "Sell commodities on the world market" +.LV Expert +.SY "sell " +The sell command allows nations to sell commodities on the open market. +Not all commodities can be traded -- +notably civilians and military. +.s1 +The is the type of commodity you are selling, + represents the range of sectors which will be selling items. +Only harbors and warehouses +which are at least 60% efficient may sell goods. +.s1 +, if positive, +reflects the amount of food to be taken from each sector. +If negative, +the amount shows the \*Qlower limit\*U of food required to be +present in that sector and will only sell food in excess of that limit. + is the base price of the commodity per unit to the world. +.s1 +In addition, the sector selling needs to have at least 1 mobility to +sell goods. +.s1 +Typical output looks like: +.NF +[7:640] Command : sell food 4,-2 10 5 +Sold 10 food at 4,-2 (206 left) + +[7:639] Command : sell food 4,-2 -100 5 +Sold 106 food at 4,-2 (100 left) +.FI +.s1 +Only harbors and warehouses +may sell items. Also, note that due to the +time delay market, you don't get any money until the goods are actually +bidded upon and paid for once the bidding time is up. +.s1 +There is a certain overhead on selling items, based on the difficulty +of moving the items in question. This is based on the tax you pay +which is set by the deity (see \*Qinfo version\*U). +.s1 +.SA "buy, reset, Market" diff --git a/info/Commands/set.t b/info/Commands/set.t new file mode 100644 index 00000000..a1dbc6f6 --- /dev/null +++ b/info/Commands/set.t @@ -0,0 +1,24 @@ +.TH Command SET +.NA set "Establish price for a ship, plane or land unit" +.LV Expert +.SY "set " +The set price command allows you to set the prices on ships/units/planes +for sale. +.s1 + is the type of unit you are putting on sale, +either ship, plane, or land. + is(are) the unit #(s), and + is the cost per item. +.s1 +If you don't supply the price on the command line the program +will ask the selling price. +.s1 +Negative prices can't be used (no more Crazy Eddie). +.s1 +You may withdraw an offer by setting the price to zero. +.s1 +Note that ships are not \*Qdelivered\*U to the purchaser, +but planes and units are. +.sp +.SA "trade, Market" + diff --git a/info/Commands/setresource.t b/info/Commands/setresource.t new file mode 100644 index 00000000..37e1755a --- /dev/null +++ b/info/Commands/setresource.t @@ -0,0 +1,5 @@ +.TH Command SETRESOURCE +.NA setresource "Change resources of a sector" +.LV Expert +.SY "setresource " +.SA "swapsector, give, setsector, Deity" diff --git a/info/Commands/setsector.t b/info/Commands/setsector.t new file mode 100644 index 00000000..744fa7b5 --- /dev/null +++ b/info/Commands/setsector.t @@ -0,0 +1,6 @@ +.TH Command SETSECTOR +.NA setsector "Change stats of a sector" +.LV Expert +.SY "setsector " +You can change anything that appears in dump or hidden (I think). +.SA "give, setresource, edit, Deity" diff --git a/info/Commands/sharebmap.t b/info/Commands/sharebmap.t new file mode 100644 index 00000000..dc0c42e7 --- /dev/null +++ b/info/Commands/sharebmap.t @@ -0,0 +1,35 @@ +.TH Command SHAREBMAP +.NA sharebmap "Share parts of your bmap with another country" +.LV Expert +.SY "sharebmap []" +This command will share all of the information on your bmap with the +country . In order for it to work, they must be friendly +towards you and your bmaps must already overlap to some extent. Note +that your 'working' bmaps are not compared for this, but rather your 'true' bmaps. In particular, you can not fool the game into thinking +that your bmaps overlap through using the 'bdes' command. See the +bottom of 'info bmap' for an explanation of the difference between +your 'working' and your 'true' bmap. +.s1 +When sectors owned by you get transferred to your friend's bmap, they +will be replaced with the first letter of your country name +(capitalized), the only exception being harbors and bridges which will +always be transmitted. Also, if you want to send them the location of +owned sectors having a certain designation you can specify that using +the optional argument. For example if your country name was +"TheScum" and you typed: +.EX "sharebmap Fodderland #1 j" +then all of your bmap would be added to Fodderland's bmap, with sectors +owned by you replaced with 'T', except for your '=', 'h', and 'j' +sectors which would be sent as is. +.s1 +Note that the destination bmap will only be changed if in that +location there was a '?', a '.', a ' ', or the first letter +of your country name (capitalized). Thus, the receiving country will +not loose any information in this exchange. +.s1 +Note that the sharebmap command only changes your 'working' bmap and +so you can delete sharebmap information from your bmap by typing: +.EX "bmap revert" +See 'info bmap' for more details. +.s1 +.SA "bdes, bmap, Communication, Maps" diff --git a/info/Commands/shark.t b/info/Commands/shark.t new file mode 100644 index 00000000..662e390f --- /dev/null +++ b/info/Commands/shark.t @@ -0,0 +1,15 @@ +.TH Command SHARK +.NA shark "Purchase defaulted loan" +.LV Expert +.SY "shark " +The shark command is used to buy out an overdue loan from another +owner. The is the number of the loan you wish to buy. +.s1 + The loan must be in arrears. The holder of the note will recieve +the value of the loan plus one periods worth of interest from your +treasury. The player who owes the money on the loan will be notified +of the switch. After the loan is transfered you may collect on it as +normal. +.sp +.SA "offer, consider, collect, financial, Loans" + diff --git a/info/Commands/ship.t b/info/Commands/ship.t new file mode 100644 index 00000000..8c5aea68 --- /dev/null +++ b/info/Commands/ship.t @@ -0,0 +1,61 @@ +.TH Command SHIP +.NA ship "Report status of ship, fleet or ships in a given area" +.LV Basic +.SY "ship [ | ]" +The ship report command is a census of your ships and lists all the +info available in readable format. +.s1 +The and arguments are provided in case you only +wish to look at one ship +or one fleet or all ships within a given area. +.s1 +Ship expects an argument. To see every ship you own, give it +the argument '*', or type "ship *". +.s1 +The report format contains the following fields: +.s1 +.in \w'shiptype\0\0'u +.L shp# +the ship number +.L shiptype +the type of ship; \*Qpatrol boat\*U, \*Qsubmarine\*U, etc, +.L x,y +the ship's current location (relative to your capital), +.L flt +the fleet designation letter (set by \*Qfleetadd\*U command), +.L eff +the ship's efficiency, +.L civ +the number of civilians on board +.L mil +mil is the number of military on board +.L uw +the number of uncompensated workers on board, +.L fd +the amount of food on board +.L pn +the number of planes on the ship +.L he +the number of helicopters on board (if the SHIPCHOPPERS option is enabled) +.L xl +the number of extra-light planes on board (if the XLIGHT option is enabled) +.L ln +the number of land units on board +.L fuel +the amount of fuel on board (if the FUEL option is enabled) +.L mu +the mobility of the ship +.L tech +the tech level of the ship +.in +.s1 +For example: +.EX ship * +.NF +shp# ship type x,y fl eff civ mil uw fd pn he xl ln mob fuel tech + 0 dd destroyer 1,1 100% 0 0 0 0 0 0 0 0 127 30 140 + 1 bb battleship 1,1 100% 0 0 0 0 0 0 0 0 120 50 200 +2 ships +.FI +.s1 +.SA "sstat, build, cargo, fleetadd, navigate, load, lookout, scrap, sonar, torpedo, upgrade, land, Ships" diff --git a/info/Commands/shoot.t b/info/Commands/shoot.t new file mode 100644 index 00000000..b4ec55dc --- /dev/null +++ b/info/Commands/shoot.t @@ -0,0 +1,36 @@ +.TH Command SHOOT +.NA shoot "Dispose of enemy civilians or uncompensated workers" +.LV Basic +.SY "shoot c " +.SY "shoot u " +The shoot command allows you to shoot \*Qenemy\*U civilians +or recalcitrant uncompensated workers. +In order to be able to keep the populace under control +(i.e., not have them rebel), +you must have one military for every ten civilians. +Any land units in the sector count towards the mil necessary for control. +Also, security units in the sector will make shooting more efficient, +.s1 +Each civ or uw shot uses mobility (see \*Qinfo Mobility\*U for the +exact formula). +.s1 +Fractions are rounded randomly up or down, depending on size. For example, +a 0.8 cost has an 80% chance of being 1, and a 20% chance of being 0. +.s1 + is a positive number +that is the number of people shot per sector. +.s1 +After the program has collected any necessary information +it will list each sector where your troops shoot down the poor +helpless people along with the number of people murdered. +.s1 +If all the civilians in the sector are removed, +and it was a conquered sector, +it will become completely controlled by you, +and you will be notified of this fact. +.s1 +Having security troops in the sector will increase the efficiency +of the firing squads, +resulting in more dead than you asked for. (They're enthusiastic) +.s1 +.SA "convert, Mobility, Citizens, Populace, Occupation" diff --git a/info/Commands/show.t b/info/Commands/show.t new file mode 100644 index 00000000..4e9853d8 --- /dev/null +++ b/info/Commands/show.t @@ -0,0 +1,41 @@ +.TH Command SHOW +.NA show "Stats for building ships, planes, units, or bridges" +.LV Basic +.SY "show [build|stats|capabilities] [tech]" +The show command either gives information on the indicated unit types. +This information is gleaned directly from the current Empire +data structures so is always up to date. +The format of each output is more fully described +in the relevant info pages +(Ship-types, Nuke-types etc.). +.s1 +Describe currently knows about bridges, planes, ships, land units, nukes, +and sectors at a given tech (up to 1.25 times your current tech.) +.s1 +To get information on a particular topic type: +.EX show unit-type +Unless the unit is a bridge, a further parameter is needed to indicate +whether you wish information about construction of units, the statistics +of units or the capabilities & abilities of units. +So, for example +.EX show nuke capabilities +will give something like +.NF + blst dam lbs tech $ +10kt fission 3 80 4 200 $7500 +50kt fission 3 100 6 225 $9000 +100kt fission 4 120 8 250 $12000 +250kt fusion 4 150 4 280 $7500 +500kt fusion 5 170 6 295 $9000 +1mt fusion 6 190 8 310 $12000 +3mt fusion 7 210 10 325 $19000 +.s1 +Note that you can only get information on items that you are actually +technologically capable of building (within 1.25 times of your current +tech.) +.FI +.s1 +To learn about the various build costs, stats, capabilities, and their +meanings, see the info files below. +.s1 +.SA "Ship-types, Nuke-types, Plane-types, Unit-types, Sector-types, Ships, Planes, LandUnits" diff --git a/info/Commands/shutdown.t b/info/Commands/shutdown.t new file mode 100644 index 00000000..f9f5129e --- /dev/null +++ b/info/Commands/shutdown.t @@ -0,0 +1,17 @@ +.TH Command SHUTDOWN +.NA shutdown "Shut down the server" +.LV Expert +.SY "shutdown [] " +Shutdown the server in minutes. If is 0 or not +specified, then any previous shutdown request will be canceled. If +the second argument is a "n" then updates will not be disabled +(otherwise they will be). +.s1 +All players currently logged on will be sent flash messages when the +shutdown is started, every hour the day of the shutdown, every 10 +minutes the hour of the shutdown, and every minute for the last five +minutes of the shutdown. When the shutdown actually +happens, the server will abort player commands in the same way that +the update does. The players connection is closed in the same way +that idle connections are closed. +.SA "enable, disable, force, turn, Deity" diff --git a/info/Commands/sinfrastructure.t b/info/Commands/sinfrastructure.t new file mode 100644 index 00000000..d176f35a --- /dev/null +++ b/info/Commands/sinfrastructure.t @@ -0,0 +1,62 @@ +.TH Command SINFRASTRUCTURE +.NA sinfrastructure "Report infrastructure of sectors" +.LV Basic +.SY "sinfrastructure " +The sinfrastructure command displays specific infrastructure information on +some or all of the sectors you occupy. +.s1 +In the syntax of the census command + is the area on which you wish information, +(see \*Qinfo syntax\*U). +.s1 +A typical usage might be: +.EX sinfrastructure 0:9,0:9 ?des=m +which would list data for mines in an area +to the south-east of the capital. +.s1 +A sinfrastructure lists each of your sectors in the specified area headed by: +.NF +Thu Aug 8 08:37:03 1996 + road rail defense + sect eff eff mcost eff mcost eff fact +.FI +These columns represent: +.s1 +.in \w'defense fact\0\0'u +.L sect +the x and y coordinates of the sector +.L eff +the efficiency of the sector (affects all benefits +of a designated sector except mobility and defense) +.L road eff +the road efficiency of the sector +.L road mcost +the mcost used to determine the mobility cost of moving things and marching +non-train units through the sector +.L rail eff +the rail efficiency of the sector +.L rail mcost +the mcost used to determine the mobility cost of moving trains through the +sector. If the rail eff is 0, trains cannot move through this sector. +.L defense eff +the defense efficiency of the sector. +.L defense fact +the defense factor of the sector. This is how well the sector defends. +All sectors start at 1, and improve (see "improve") from there to the maximum +shown in "show sect stats" +.FI +.in \w' 'u +.s1 +For example: +.EX sinf #0 +.NF +Thu Aug 8 08:37:03 1996 + road rail defense + sect eff eff mcost eff mcost eff fact + 1,-1 f 0% 0% 0.400 0% 0.400 6% 1.18 + 0,0 c 100% 2% 0.192 28% 0.113 8% 1.08 + 2,0 m 100% 0% 0.200 0% 0.200 100% 2.00 +3 sectors +.FI +.s1 +.SA "improve, census, commodity, resource, Sectors, Infrastructure, Mobility, Commodities" diff --git a/info/Commands/skywatch.t b/info/Commands/skywatch.t new file mode 100644 index 00000000..3ce26a7c --- /dev/null +++ b/info/Commands/skywatch.t @@ -0,0 +1,18 @@ +.TH Command SKYWATCH +.NA skywatch "Check from sectors for nearby satellites" +.LV Expert +.SY "skywatch []" +The skywatch command allows sectors to report sightings of satellites. +.s1 +The visibility range is equal to +four times the sector efficiency +expressed as a decimal times the technology factor; +e.g. a 100% efficient mine with a 50% technology factor can +see 2 sectors away. +An exception is radar installations, which have a maximum range +equal to fourteen times the sector efficiency, (i.e. 3.5 times as far). +.s1 +A typical usage might be: +.EX sky #3 ?type=) +.s1 +.SA "coastwatch, radar, Detection" diff --git a/info/Commands/smap.t b/info/Commands/smap.t new file mode 100644 index 00000000..74afc8e5 --- /dev/null +++ b/info/Commands/smap.t @@ -0,0 +1,67 @@ +.TH Command SMAP +.NA smap "Get a map around a ship" +.LV Basic +.SY "map " +.SY "nmap " +.SY "smap " +.SY "lmap " +.SY "pmap " +A map gives you a graphic representation of all or part of your country. +.s1 +Your own sectors show up as a designation mnemonic +(see \*QSector-types\*U) while sectors held by other countries +appear as question marks (\*Q?\*U). +Mountains, wilderness aresa, and seas appear +as '^', '-' and '.' respectively. +.s1 +You can also get this by typing 'M' at the navigation prompt. +.s1 +Examples: +.EX map -9:18,-8:5 +generates a 28 x 14 map based on data supplied by the sectors +in the area specified. +.NF + ---------0000000000111111111 + 9876543210123456789012345678 + -8 . . . - - -8 + -7 . . . . - ^ -7 + -6 . . . . - - - - -6 + -5 . . - . a a - ^ ? ? - -5 + -4 . . . . k o ! - ^ ? ? ? -4 + -3 . - . a h j a ^ ^ ^ ^ ^ - -3 + -2 . . - . a a a ^ a a - - - -2 + -1 . . . a a a b + + ^ ^ - -1 + 0 . . . m c u a a - ^ - ^ 0 + 1 . - . a a . a a - - ^ 1 + 2 - ^ ^ a a a ^ a - - ^ 2 + 3 - - - - - - - . . - 3 + 4 ^ - - - - - ^ - - 4 + 5 - ^ - - ^ - - - 5 + ---------0000000000111111111 + 9876543210123456789012345678 +.FI +.s1 +.EX map # >mapfil +where your \*Qrealm\*U (or '#', +see \*Qinfo realm\*U or \*Qinfo update\*U) +is -5:5,-6:6 will type out a 11 by 13 sector map +and also put the map in the file called \*Qmapfil\*U. +.s1 +If you use nmap, you can get a map that shows new sector designations +instead of old sector designations of your own country. +.s1 +Also, if you give a ship # instead of coordinates or a realm, map +will show you a small realm around the given ship (assuming you +own it). +.s1 +If you use lmap, you can get a map around a land unit, +instead. Pmap does the same for a plane. Smap does +the same for a ship. +.s1 +.L "MAP FLAGS" +.s1 +If you give an 's' flag, all your ships will be shown on the map. +An 'l' flag does the same for land units, and a 'p' for planes. +'*' gives all of the above. +.s1 +.SA "census, commodity, radar, realm, route, update, Ships, Maps" diff --git a/info/Commands/sonar.t b/info/Commands/sonar.t new file mode 100644 index 00000000..644c2352 --- /dev/null +++ b/info/Commands/sonar.t @@ -0,0 +1,98 @@ +.TH Command SONAR +.NA sonar "Use sonar to look for ships" +.LV Basic +.SY "sonar " +The sonar command allows ships to look for submarines +and submarines to look for ships. +.s1 +If the argument is +specified then the sonar map will not be drawn. This is useful if you +just need to see the list of ships you can detect. Whether or not a +map is printed, the sonar information will be added to your bmap. +.s1 +Only ships at sea may use sonar and sonar only detects ships +which are at sea. Furthermore, there must be a straight line of water +between the detector and the detected (sonar doesn't work around corners). +.s1 +In the current implementation, sonar works similar to +lookout. The major difference is that a submarines cannot use +lookout to sight ships. Likewise, submarines cannot be sighted +by ships via lookout. +.s1 +There are two aspects to sonar - passive and active sonar. +.s1 +ACTIVE SONAR +.s1 +This is the most visible form of sonar. It is simply a +ship's ability to use sonar pings to detect other ships. +The range of a ship's active sonar is identical to the +range that it can sight ships via lookout. +(see \*Qinfo lookout\*U) +When you type "sonar 25", you are using active sonar. +.s1 +PASSIVE SONAR +.s1 +This is more subtle. Passive sonar is a ship's ability +to hear sounds, mainly active sonar pings. When a ship +pings you with active sonar, you can detect that ping. +If a ship with sonar gets pinged, that country receives +a telegram saying "Sonar ping from x,y detected by ship Z!" +In its current implementation, passive sonar is the ability +to detect a ping. +.s1 +When a ship emits a ping, that ping has to travel out to a +target ship, reflect off of it, and then return to its source. +So, in order to detect a ship X sectors away, a sonar ping +must be able to travel 2X sectors - from the source to the +target, and back to the source. So, if a ship can use active +sonar to detect ships X sectors away, passive sonar can detect +active sonars from 2X sectors away. So the range at which you +can detect sonar pings is twice the range at which you can use +sonar. +.s1 +The active and passive sonar modes means that you want to be +careful when you use sonar, because you will tell others where +you are long before you actually detect them. This also gives +you some warning before you get your submarine attacked, as +enemy ships have to use sonar to find you. The key to submarine +warfare is "run silent", meaning use your sonar only when you +have to. +.s1 +On the other hand, destroyers are designed to hunt subs. A +destroyer guarding a player's coast should use sonar often, +especially if it has other destroyers nearby to support him if +he gets in trouble. +.s1 +For example: +.EX sonar 3 +.NF +sb2 submarine 2 (#3) at 24,0 efficiency 76%, max range 2 +Sonar detects TheBorg (#5) bb4 battleship 4 (#1) @ 23,-1 + . + . B ? +. . 0 ? + . . . + . . . +.FI +.s1 +Sonar-capable ships of tech 310 or better can also detect mines with +their sonar, although at only half their normal sonar range. Mines +will show up on the sonar map as 'X' and this 'X' will be added to +your bmap. +.s1 +In the case of using sonar to detect subs, detection = (sub visibility + ship +spy value). If detection is less than 8, then the sonar will just +print you something like: +.NF + Sonar detects sub #12 +.FI +If detection is above 7, then you will be told the ship type, and if +it is above 9, you will also be told the owner of the sub. Note that +type and owner will always be shown for Friendly subs. +.s1 +.TH Concept plane-sonar +.s1 +Planes with the ASW ability can use +sonar while on recon missions. See info recon for more details. +.s1 +.SA "coastwatch, Ship-types, Sector-types, radar, recon, Ships, Detection" diff --git a/info/Commands/sorder.t b/info/Commands/sorder.t new file mode 100644 index 00000000..aa7d5256 --- /dev/null +++ b/info/Commands/sorder.t @@ -0,0 +1,35 @@ +.TH Command SORDER +.NA sorder "Show ship order statistical information" +.LV Expert +.SY "sorder " +.s1 +\*Qsorder\*U shows some statistical information on ships that +have been given orders. +The report indicates: +.NF + shp# ship number. + ship type type of ship (cargo ship, destroyer, etc) + x,y ships current position + start The first destination for the ship. + end The second destination for the ship. + len The number of sector required to get from its + current position to the start sector. + eta The estimated number of updates required to + reach the start sector. + +shp # ship type x,y start end len eta + #6 cargo ship 1 6,0 2,0 20,0 2 1 + #10 destroyer 1 -10,0 20,2 17 2 +.FI +This report reads: +Cargo ship #6 is currently at sector 6,0 and has orders to sail to +sector 2,0. It will arrive and load any cargo set for that ship, +see qorder, and then sail to sector 20,0. It currently needs to +sail 2 sectors and will arrive in 1 update at sector 2,0. + +Destroyer 1 is at sector -10,0 and only has orders to sail to sector +20,2. It needs to move 17 sectors and will arrive at 20,2 in 2 updates. +When it arrives order will be cleared since only one destination +order was given to it. +.s1 +.SA "order, qorder, bmap, navigate, ship, Ships, Autonav, Autofeed" diff --git a/info/Commands/spy.t b/info/Commands/spy.t new file mode 100644 index 00000000..b4833f9e --- /dev/null +++ b/info/Commands/spy.t @@ -0,0 +1,60 @@ +.TH Command SPY +.NA spy "Snoop on adjacent enemy sectors" +.LV Basic +.SY "spy " +The spy command allows reconnaissance operations to enforce +an oral treaty or as preparation for an attack +(or even for a prayer to the Deity). +.s1 +The spy report will reveal, (in round figures), the numbers of troops, +civilians, guns, shells, iron, and planes and the sector designation and +efficiency in neighboring sectors. +.s1 +The sectors denoted by +are those from which you are spying, +(see \*Qinfo syntax\*U for format). +Note: you can only spy from sectors that have military or land units in them. +.s1 +Note that the number of BTU's consumed +is dependent upon the number of sectors into which you spy, +e.g., a 5x8 area costs one full BTU. +.s1 +If you are spying on an unallied country your spy could be apprehended... +his/her chances are dependent upon the number +of patrolling military in the sector. +.s1 +However, having a recon unit in the sector the spy is coming from +enhances your chances of succeeding even if the spy is caught. +.s1 +If the other country has declared itself at war with you the spy +will be shot and the other country, (and the rest of the world, +through the news), will be warned that you tried to spy on him... +.s1 +If the other country is neutral towards you the spy will be deported. +.s1 +.EX "spy 29,3" +.NF +SPY report +Thu Aug 8 10:48:18 1996 + old sct rd rl def + sect de own own eff eff eff eff civ mil shl gun pet food bars lnd pln + 28,4 bf 2 2 100 90 0 50 100 30 90 100 0 40 0 0 0 + 29,5 e 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 +Neutral unit in 29,5: cavalry #6 (efficiency 98, tech 18) +Neutral unit in 29,5: if1 infantry 1 #7 (efficiency 98, tech 15) +.FI +.s1 +Spies will also report all non-owned planes and land units that exist in +the sector you are spying from, such as allied land units that have been +marched there, allied planes that have been landed there, spy units that have +marched there and non-allied units that have been trapped there. +.s1 +Note that spy units are not always seen. There is a 10-100% chance of a spy +unit being seen by the spy command. See "info Spies" for more information. +.s1 +.L NOTE +.s1 +Spies reporting on the tech level of enemy units are pretty inaccurate. +They can vary by +/- 20 tech or so... +.s1 +.SA "census, read, declare, Sectors, Combat, Detection" diff --git a/info/Commands/sstat.t b/info/Commands/sstat.t new file mode 100644 index 00000000..877f9fcd --- /dev/null +++ b/info/Commands/sstat.t @@ -0,0 +1,52 @@ +.TH Command SSTAT +.NA sstat "Report statistics of ship, fleet or ships in a given area" +.LV Basic +.SY "sstat [ | ]" +The sstat command is a report of the varying statistics of your ships and +lists the info in a readable format. Since your ships' statistics vary by +tech level, this is a very useful way to see what the attack, defense, etc. +modifiers are on a per-ship basis. +.s1 +The and arguments are provided in case you only +wish to look at one ship +or one fleet or all ships within a given area. +.s1 +Sstat expects an argument. To see every ship you own, give it +the argument '*', or type "sstat *". +.s1 +The report format contains the following fields: +.s1 +.in \w'shiptype\0\0'u +.L shp# +the ship number +.L ship-type +the type of ship; \*Qpatrol boat\*U, \*Qsubmarine\*U, etc, +.L x,y +the ship's current location (relative to your capital), +.L eff +the ship's efficiency, +.L tech +the tech level of the ship +.L def +the armor value of the ship (i.e. how strong is the hull) +.L spd +the speed of the ship +.L vis +the visibility of the ship (i.e. how easy is it to see) +.L rng +twice the distance the guns can fire, +The range formula is (rng/2) * ((tech + 50) / (tech + 200)) +.L fir +the number of guns the ship can fire at once +.in +.s1 +For example: +.EX ship * +.NF +shp# ship-type x,y eff tech def spd vis rng fir + 0 dd destroyer 1,1 100% 140 51 41 19 9 2 + 1 bb battleship 1,1 100% 200 129 35 34 17 7 +2 ships +.FI +.s1 +.SA "ship, build, cargo, fleetadd, navigate, load, lookout, scrap, sonar, torpedo, upgrade, land, Ships" diff --git a/info/Commands/start.t b/info/Commands/start.t new file mode 100644 index 00000000..4b4814ae --- /dev/null +++ b/info/Commands/start.t @@ -0,0 +1,17 @@ +.TH Command START +.NA start "Turn sector production on" +.LV Basic +.SY "start " +The start command orders a sector to start producing for an update. +This counteracts the stop command. +.s1 +.EX start 2,0 +.NF +Wed Jan 20 21:37:22 1993 +PRODUCTION STARTING + sect eff + 2,0 c 100% will be updated normally. + 1 sector +.FI +.s1 +.SA "stop, census, Production, Update" diff --git a/info/Commands/starvation.t b/info/Commands/starvation.t new file mode 100644 index 00000000..2159309a --- /dev/null +++ b/info/Commands/starvation.t @@ -0,0 +1,59 @@ +.TH Command STARVATION +.NA starvation "Find out who's going to starve" +.LV Basic +.SY "starvation [|l |s ]" +The starvation command warns you of possible starvation in your +sectors, land units, and ships. +.SY starv +With no arguments, the starvation command will list all of your +sectors, land units, and ships that will starve at the update. +.SY "starv " +.s1 +With this syntax, the starvation command displays all sectors in + that currently do not have enough food. It does not take into account +emergency food growing & supplying (see info supply) +It also does not worry about feeding babies... it merely +check for starvation. If you want population increase, +you'll need to chuck in some extra food... +.s1 +For example: +.EX starv #0 +.NF +Mon Aug 28 04:53:38 1995 +Starvation + sect eff + 4,0 + 100% will starve 125 people. 15 more food needed +1 sector +.FI +.s1 +.SY "starv l " +With this syntax, the starvation command will list which of your units +are currently not carrying enough food (see "info lload" and "info +supply"). For example: +.EX starv l * +.NF +Mon Aug 28 04:53:05 1995 +Starvation + lnd# unit type + 6 cavalry will starve 9 mil. 1 more food needed + 7 cavalry will starve 13 mil. 2 more food needed +2 units +.FI +.s1 +.SY "starv s " +With this syntax, the starvation command will list which of your ships +are currently not carrying enough food to feed the people on them. +For example: +.EX starv s * ?type=frigate +.NF +Mon Aug 28 04:53:29 1995 +Starvation + shp# ship type + 0 frigate will starve 10 people. 2 more food needed +1 ship +.FI +.s1 +To see how much food your people need to eat, check the output +of the version command. +.s1 +.SA "census, version, Populace" diff --git a/info/Commands/stop.t b/info/Commands/stop.t new file mode 100644 index 00000000..721f5732 --- /dev/null +++ b/info/Commands/stop.t @@ -0,0 +1,21 @@ +.TH Command STOP +.NA stop "Stop sector production" +.LV Expert +.SY "stop " +The stop command orders a sector to stop producing for an update. +After the update, the sector will return to normal. +.s1 +The sector will still distribute, etc, but will not gain in efficiency or +produce anything. Ships, planes, and units in the sector will +not gain efficiency. +.s1 +.EX stop 2,0 +.NF +Wed Jan 20 21:35:34 1993 +PRODUCTION STOPPAGE + sect eff + 2,0 c 100% will not produce or gain efficiency. + 1 sector +.FI +.s1 +.SA "start, census, Production, Update" diff --git a/info/Commands/strength.t b/info/Commands/strength.t new file mode 100644 index 00000000..cb424685 --- /dev/null +++ b/info/Commands/strength.t @@ -0,0 +1,51 @@ +.TH Command STRENGTH +.NA strength "Report defensive strengths of sectors" +.LV Expert +.SY "strength " +.s1 +A strength lists each of your sectors in the specified area headed by: +.NF +DEFENSE STRENGTH land sect sector reacting total + sect eff mil units mines mult defense units defense +.FI +These columns represent: +.s1 +.in \w'reacting\0\0'u +.L sect +the x and y coordinates of the sector +.L eff +the efficiency of the sector (affects all benefits +of a designated sector except mobility units) +.L mil +the number of military troops +.L units +the total defensive strength of units in the sector +.L land mines +the number of land mines in the sector. If you do not completely own +the sector, then a '?' will appear here. +.L sect mult +the defensive multiplier of the sector including the land mine bonus +.L sector defense +(mil + units) * mult +.L reacting units +the total strengths of all supplied mobile reacting units in range +.L total defense +(sector defense) + (reacting units) +.in \\n(in +.s1 +For example: +.EX str #1 +.NF +Mon Oct 23 22:44:16 1995 +DEFENSE STRENGTH land sect sector reacting total + sect eff mil units mines mult defense units defense + 5,-5 * 100% 95 1.00 95 48 143 + 4,-4 c 100% 4.00 0 192 192 + 6,-4 f 0% 78 48 2.00 252 252 + -1,-3 c 100% 4.00 0 80 80 + 1,-3 c 100% 4.00 0 80 80 + 3,-3 c 100% 4.00 0 80 80 + 7,-3 ! 100% 53 90 2.80 148 134 282 +7 sectors +.FI +.SA "attack, assault, Land-units, Combat" diff --git a/info/Commands/supply.t b/info/Commands/supply.t new file mode 100644 index 00000000..7c492e74 --- /dev/null +++ b/info/Commands/supply.t @@ -0,0 +1,98 @@ +.TH Command SUPPLY +.NA supply "Cause a unit to draw supplies" +.LV Basic +.SY "supply " +The supply command causes a unit to draw enough supplies from its +supply sources to make sure that it has its basic load of supplies. +Supply tells you which units have enough supplies. +.s1 +A basic load of supplies for a unit consists of: +.nf + 1) enough food to eat for one update + + 2) enough shells to fire once + A unit uses shells equal to its ammo stat to fire once. + Use the \*Qshow\*U command to find out how much ammo + the unit uses per shot. + + 3) petrol equal to its fuel use number, if the unit uses fuel + (show land stats will show the fuel use number) +.fi + +.s1 +If the unit has enough of all these things, it is said to be 'in supply'. +A lack of any of these things is enough to make the unit 'out of supply'. +.s1 +.L "When supplies are drawn & used" +.s1 +A unit that fights may use a basic load of supplies +to attack with. (depending on the intensity of combat. The more intense the +combat, the more chance the unit will use a basic load of supplies) +.s1 +During the update, each unit will attempt to draw food supplies just before +starvation is calculated. +.s1 +When a unit needs to draw supplies, such as when you use the supply command, +or the unit wishes to attack, or is attacked, etc, it must attempt to get +them from supply sources. Other things may use the same routines, such as +loyal sectors, which will draw food from supply sources when in danger of +starvation, and ships/forts/sectors, which will draw shells when they need +them to fire defensively or fire AA at planes. +.s1 +.L "Supply Sources" +.s1 +There are four sources of supply. In each case, the +unit must be within supply range of the source. Supply range is: +.s1 +.ti 3 +10 * ((tech+50)/(tech+200) sectors. +.s1 +In addition there must be a valid supply path to the source. A supply path +is a path of sectors owned by the owner of the unit that leads to the +supply source. (Note that the path may be of any length.. only the supply +source itself must be within supply range.. this is to make the coding +simpler, and may change in the future) The best path (in terms of mobility +use) will be used. +.s1 +In each case, mobility is used to move the supplies. +.s1 +The first source of supply checked is the sector the unit is in. +This is foraging, and uses some mobility from the unit itself. +.s1 +If the unit's needs can't be satisfied by forging, it look for an owned +warehouse or headquarters that is at least 60% efficient. Drawing +from these sources uses mobility from +the warehouse or headquarters. (A headquarters will NOT supply a unit if it +has no distribution path) +.s1 +If still in need, the unit will look for an owned supply ship (one that has +the supply ability) in an owned harbor. +The harbor must be at least 2% +efficient. This uses mobility from the harbor. +.s1 +If it still can't find enough supplies, the unit will look for an owned +unit with the 'supply' ability. (see info show for information on how to +find out about abilities of units) In this case, the supply unit uses its +mobility to use the supplies. After it supplies the unit, the supply unit +will then itself try to re-supply, so that it is possible to form a chain +of supply units reaching back to a headquarters or supply ship. +.s1 +If after all this the unit can't get enough, it is out of supplies. +.s1 +Note that no supply source will give up enough food to make it starve. In +addition, no supply source will go below 1 of any commodity. +.s1 +.EX supply * +War band #2 has supplies +.ti 3 +4 units +.s1 +OTHER USES OF SUPPLY +.s1 +In general, when any land unit/ship/fort needs shells, it will attempt to +draw them before use, if it does not already have them. +.s1 +Also, units/ships/sectors will use supply sources to get enough food during +the update so that they do not starve. +.s1 +.SA "lload, LandUnits" diff --git a/info/Commands/survey.t b/info/Commands/survey.t new file mode 100644 index 00000000..063c8fc9 --- /dev/null +++ b/info/Commands/survey.t @@ -0,0 +1,37 @@ +.TH Command SURVEY +.NA survey "Show distributions in map form" +.LV Expert +.SY "survey ?condcond" +The survey command shows the distribution +of a commodity or resource in map form. +Sectors which are owned by you, +but do not match the conditional +have their current designation displayed much as in a map. +Sectors matching the conditional are shown in one of several ways. +.s1 +Sectors which have none (or a level of zero) of the item being +surveyed show up as a blank. +.s1 +If is a commodity, +then sectors having the commodity present +will be shown as a digit from 0 to 9, +the digit representing the number +of hundreds of the commodity present in the sector. +Sectors with more than 999 of a given commodity will be seen as a '$'. +.s1 +If is a sector resource, +then the 0 to 9 digits will represent +the number of tens of the resource present in the sector. +Sectors with more than 99 of a given resource will show up as a $. +.s1 +If your terminal can support standout mode, +then sectors selected will be highlighted. +.s1 +Sectors not owned by you will show up as blanks. +.s1 +NOTE: the syntax of this command is somewhat bizarre, +as the conditional \*Qcondcond\*U +is for all practical purposes NOT optional +if the survey is to display any values. +.s1 +.SA "sect, map, Maps" diff --git a/info/Commands/swapsector.t b/info/Commands/swapsector.t new file mode 100644 index 00000000..f68aac3e --- /dev/null +++ b/info/Commands/swapsector.t @@ -0,0 +1,15 @@ +.TH Command SWAPSECTOR +.NA swapsector "Swap two sectors" +.LV Expert +.SY "swapsector " + +This command allows the deity to pick up two sectors and then put them +back down in each-other's location. It is particularly handy for +changing the shape of start islands when setting up a game. For +example, a piece of an island may be cut off by a mountain, and so to +fix it you could just swap the mountain over to some other part of the +island. All aspects of the sector (e.g. resources, commodities) get +transferred to the new location. The only change that is made is that +dist paths are wiped. + +.SA "give, setsector, setresource, Deity" diff --git a/info/Commands/sweep.t b/info/Commands/sweep.t new file mode 100644 index 00000000..3da46222 --- /dev/null +++ b/info/Commands/sweep.t @@ -0,0 +1,55 @@ +.TH Command SWEEP +.NA sweep "Use planes to remove mines from sea sectors" +.LV Expert +.SY "sweep route|destination" +The \*Qsweep\*U command is identical to the recon command, except +that if you use planes capable of minesweeping, they will sweep +mines from sectors along their route. +.s1 + represents a list of planes which are to be performing the +intelligence gathering operation. +Only planes which are provided with gas, and have sufficient mobility will +be successfully selected for the mission. +.s1 + represent a list of fighter planes which are capable of escorting +the transports all the way to the target. +To be selected, escorts must have fuel and mobility. +.s1 + represents an assembly point, where all of the planes in the +mission meet before proceeding on to the target sector. +The assembly point must be owned by you, and must not be more than +four sectors away from any of the planes selected for the mission. +.s1 +Route is a normal empire path specification. You may also give a +destination sector on the command line, or at any time while giving +the route, and empire will use the best path from the current sector +to the desired destination sector. +.s1 +When getting a path interactively, empire will show you the information +you have (from your bmap) concerning the current area, to help plot +your course. +.s1 +Information given by sweep/recon is not totally accurate. +.s1 +Sweep/recon missions can be intercepted just like any other mission. +If the destination sector is not an airport, then all planes in +the mission must have V/STOL capability. +.s1 +Planes with the ASW ability will +perform a sonar search on each sector as they fly through it. +Each sub contact will be reported only once, giving the sector and number +of the sub, from the sector in which it +is first detected (which may not be the sector the sub is in, as plane +sonar has a range dependent on acc, and a chance of finding a sub of +((100-acc)-(4-sub visib)*10))+((100-effic)/5) percent. +The sub being sonared may detect the sonar ping. +.s1 +Planes with the sweep ability will +automatically attempt to sweep mines in sea or harbor sectors they overfly. +Their chance of sweeping is (100-acc), and they can only sweep 1 mine per +overflight of the sector. +.s1 +Note that a plane must be at least 40% efficient before it can leave +the ground. +.s1 +.SA "Plane-types, bomb, fly, paradrop, drop, Planes" diff --git a/info/Commands/telegram.t b/info/Commands/telegram.t new file mode 100644 index 00000000..be05ebcc --- /dev/null +++ b/info/Commands/telegram.t @@ -0,0 +1,45 @@ +.TH Command TELEGRAM +.NA telegram "Send \*Qdiplomatic\*U communique to another country" +.LV Basic +.SY "telegram [] [[]]" +The telegram command allows non-treaty communication +to take place between representatives. Currently you +are given only 1024 characters per telegram. +.s1 +The argument is either the number or name of +the recipient nation. You may specify as many recipients on the +command line as you wish. +Telegrams sent to country #0 appear as prayers, +(favors are best obtained in this manner.) +.s1 +While entering your telegram the system tells you how many characters +you have left. You end the telegram by typing ^D on a line by itself, +or by entering a line with a '.' on a line by itself. A line containing +only a '~' will abort the telegram. +.s1 +For example: +.EX tel 7 8 +.NF +Enter telegram for multiple recipients; end with ^D + 1024 left: + 1023 left: B.F.D. Pouncetrifle + 1003 left: Groonland Embassy + 984 left: + 983 left: Dear Ambassador Pouncetrifle, + 953 left: + 952 left: Just a little note to express the friendly wishes that all of us + 887 left: in Curmudgeon feel toward you backward savages in Groonland. As + 822 left: to the matter of the treaty you've proposed please remember that + 757 left: if we wished we could TRASH your capital. + 715 left: + 714 left: As always I remain, + 688 left: Your humble and obedient servant, etc, etc + 638 left: E. D. Amen Dada + 616 left: Under Asst. West Coast Promo. + 580 left: the Sovereign State of Curmudgeon + 540 left: +.FI +.s1 +Note that others can reject your telegrams, using \*Qreject\*U. +.s1 +.SA "flash, toggle, announce, read, reject, Communication, Diplomacy" diff --git a/info/Commands/tend.t b/info/Commands/tend.t new file mode 100644 index 00000000..26fde1c4 --- /dev/null +++ b/info/Commands/tend.t @@ -0,0 +1,30 @@ +.TH Command TEND +.NA tend "Transfer commodities between ships" +.LV Basic +.SY "tend " +The tend command allows transfer of commodities +from a particular (supply) ship to patrol boats, +submarines, battleships, etc. while at sea. +.s1 +If you had cargo ship #16 which had food, and your fleet S needed food, +you could resupply the entire fleet with 20 units of food by typing +.EX tend food 16 20 S +.s1 +Requirements are that the tending ship must be in the same sector +as the tended ships, and it must be yours, or belong to a country that +considers you a friendly trading partner. +A positive indicates the amount the tender will give away, +while a negative amount indicates the amount that the tender +will try to extract from each ship. (However, you cannot take goods +from a friendly ship by giving a negative amount) +.s1 +Only land units with the "assault" capability may be tended between +ships. If you wanted to tend land unit #23 from ship #8 to ship #17, +then you would type: +.EX tend land 8 23 17 +Besides the "assault" capability restriction, tending land units has +the same effect as though you were simply loading the unit onto a +ship. In particular, you may tend land units to "friendly" ships in +the same sector. +.s1 +.SA "load, unload, lload, lunload, ltend, Ships" diff --git a/info/Commands/territory.t b/info/Commands/territory.t new file mode 100644 index 00000000..1a5f0e77 --- /dev/null +++ b/info/Commands/territory.t @@ -0,0 +1,38 @@ +.TH Command TERRITORY +.NA territory "Assign various sectors to a specific territory" +.LV Expert +.SY "territory []" +In Empire, sectors may be given a territory id number. +This number may be used in conditional statements as in: +.EX census # ?terr=27 +The program will then give you a census report for all the +sectors that have been assigned the territory number \*Q27\*U. +.s1 +In this sense it is essentially an extended \*Qrealm\*U. +However, you are not limited to rectangular regions and you have +99 values to choose from. +.s1 +There are four independent territory fields. If the optional field +argument is empty, field 0 is used. +.s1 +.EX territory #1 5 1 +.s1 +Would set terr1 field to 5 for all sectors in realm 1. +.s1 +.EX sect * ?terr1=6&terr2=12 +.s1 +If terr1 was used to mark different islands and terr2=12 indicated +productive sectors, this would highlight all the productive sectors +on island number 6. +.s1 +Some possible uses include; +all sectors distributing to a particular sector; +all coastal sectors; +all sectors that have armed missiles in them. +And probably thousands that I haven't thought of. ;-) +.s1 +To \*Qunset\*U a territory, set its value to zero. +.s1 +Note: terr and terr0 are the same. +.s1 +.SA "realm, distribute, Sectors" diff --git a/info/Commands/test.t b/info/Commands/test.t new file mode 100644 index 00000000..bca4161a --- /dev/null +++ b/info/Commands/test.t @@ -0,0 +1,23 @@ +.TH Command TEST +.NA test "Check the effect of a proposed move" +.LV Expert +.SY "test " +The test command lets you check the effect of a proposed move. +This can be helpful when you're not sure whether you have enough +mobility to reach a certain location or you wish to compare two +possible routes for a move. +.s1 +The test command has exactly the same arguments as the move command +and acts almost the same. +There are two important differences: +.in +0.3i +.s1 +Nothing is actually moved and no mobility is used. +.s1 +The move is tested for irrespective of how much + is actually in the sector. This is useful for testing a sector +which will be used as a temporary stopover in a multi-step move to +make sure the stuff won't get stranded there. +.in -0.3i +.s1 +.SA "move, Commodities" diff --git a/info/Commands/threshold.t b/info/Commands/threshold.t new file mode 100644 index 00000000..2af069cb --- /dev/null +++ b/info/Commands/threshold.t @@ -0,0 +1,46 @@ +.TH Command THRESHOLD +.NA threshold "Set commodity distribution thresholds" +.LV Basic +.SY "threshold " +The threshold command is used to specify the level +of a given commodity which is to be maintained +by the sector's distribution sector. +These levels are maintained by either importing or exporting +commodities. +This importation and exportation is done automatically during +an update. +Both imports and exports from distribution sectors cost only +one-half normal mobility. +.s1 +In the syntax, + is the sector or sectors from which the deliveries are made, + is one of the following: +.NF +c civilians +m military +u uncompensated workers +f food +s shells +g guns +p planes +i iron ore +d gold dust +b bars of gold +o oil +l light construction materials +h heavy construction materials +r radioactive materials +.FI +and is a number specifying the level of commodity which +is desired. +.s1 +The census and commodity reports will indicate distribution thresholds +by the \*Qhundreds digit\*U of the threshold level. +In order to have a threshold take effect, it must be at least one. +.s1 +Sectors importing or exporting items can be seen by the \*Qroute\*U +command (marked with a \*Q$\*U) or by the sect command. +.s1 +Also, note that no distribution center will ship out its last civilian. +.s1 +.SA "distribute, census, commodity, route, level, Distribution" diff --git a/info/Commands/toggle.t b/info/Commands/toggle.t new file mode 100644 index 00000000..616bc649 --- /dev/null +++ b/info/Commands/toggle.t @@ -0,0 +1,45 @@ +.TH Command TOGGLE +.NA toggle "Toggle client flags" +.LV Expert +.SY "toggle [inform|flash|beep|coastwatch|sonar|techlists] [on|off]" +You use the toggle command to set various user-interface flags for +your country. The server will remember which flags you have set +between sessions. If you do not specify the second argument ("on" or +"off"), then the server will just flip the switch from on to off or +vice versa. +.EX "toggle inform" +Will toggle the "inform" flag (default off) for your country. When +inform is on, the server will inform you immediately whenever you +receive a telegram. +.s1 +.EX "toggle flash" +Will toggle the "flash" flag (default on) for your country. When +flash is on, you can receive instantaneous messages from your allies when +they use the "flash" and "wall" commands. +.s1 +.EX "toggle beep" +Will toggle the "beep" flag (default on) for your country. When beep +is on, your terminal will beep whenever there's a big explosion in +the game (shells, bombs, torpedoes...). You might want to turn beep +off if you don't want to disturb others. +.s1 +.EX "toggle coastwatch" +Will toggle the "coastwatch" flag (default on) for your country. When +coastwatch is on, then you will receive telegrams informing you of any +new ship sightings. Note that allied and friendly ships do not show up +in these automatic sightings. +.s1 +.EX "toggle sonar" +Will toggle the "sonar" flag (default on) for your country. When +sonar is on, then you will receive telegrams whenever any of your +sonar-equipped ships detect a sonar ping. +.s1 +.EX "toggle techlists" +Will toggle the "techlists" flag (default off) for your country. When +techlists is on, when you do a "show" command, the lists shows will be +in order of tech instead of grouping order. +.s1 +.EX "toggle" +Will list all your flags and show whether they are on or off. +.s1 +.SA "telegram, flash, wall, Communication" diff --git a/info/Commands/torpedo.t b/info/Commands/torpedo.t new file mode 100644 index 00000000..0f677d57 --- /dev/null +++ b/info/Commands/torpedo.t @@ -0,0 +1,71 @@ +.TH Command TORPEDO +.NA torpedo "Slip a torpedo to some poor sucker (from a sub or ship)" +.LV Basic +.SY "torpedo " +The torpedo command is used to shoot other naval vessels +in a sneaky manner. +.s1 +The argument is the victim ship number and +the argument is the number(s) of your submarine or other +ship(s) with torpedo ability. +The program will ask for these if not provided on the command line. +If using the multi-fire option, the program will prompt for targets for +EACH firing torpedo ship, if no target was given on the command line. +.s1 +Your must meet the following criteria: +.nf +.in +0.3i +1) It must have torpedo ability. (see info show) +2) It must have at least 1 gun (torpedo tube) +3) It must have at least 3 shells (3 shells = 1 torpedo) +4) It must be at least 60% efficient +5) It must have some mobility +.in -0.3i +.fi +Meeting all these criteria, your torpedo will be launched +toward the victim ship and a countdown of seconds +until the expected detonation will commence. +.s1 +The range of a torpedo depends on the type of sub, and its tech +level. Currently the range formula looks like this: +.nf + (frng) * (tech+50)/(tech+200) + + [Note: frng comes from show ship capability] +.fi +.s1 +If the target is out of range, you will be told so, +(after your torp is in the water). +See \*Qinfo Hitchance\*U for the chance of a torpedo hitting its target. +.s1 +If the target ship is not in a direct line of sight +but in range, the torpedo +will slam into land and you will be notified. Note that the victim ship +will still see the torpedo being launched and can return a depth charge +attack (see below.) +.s1 +A hit will be reported to you as \*QBOOM!\*U, +See \*Winfo Damage\*U for the damage that a torpedo does. +.s1 +In order to simulate the \*Qreal-time\*U situation, +your mobility will be decremented by mobility equal to 1/2 the cost +the torpedo-ship would pay to move a sector for each torpedo fired; +if it goes to zero (or beyond) you will be forced to stick around. +If your torpedo scores a hit, +your victim will be informed of the fact and will be told +the number of the torpedo-ship, but not the country (so you can deny it). +.s1 +The victim's only automatic protection against sub attacks is that +any ship of his/hers that is near you and has depth-charge ability +and has shells will drop them on you as depth charges. +Each depth charge does 10% to 40% damage to your sub, depending +on the armor of the sub, and the range of the destroyer. +.s1 +The range a ship can depth charge at is the same as its gun range. +.s1 +Against surface ships launching torpedo attacks, the victim gets to fire +all his ships & sectors within range at the attackers BEFORE the attackers +get to fire. Damage done by all defending ships is divided evenly over all +attacking ships. +.s1 +.SA "attack, assault, fire, Combat, Ships" diff --git a/info/Commands/trade.t b/info/Commands/trade.t new file mode 100644 index 00000000..fd7ccca3 --- /dev/null +++ b/info/Commands/trade.t @@ -0,0 +1,40 @@ +.TH Command TRADE +.NA trade "Buy planes/ships/land units" +.LV Expert +.SY "trade" +The trade report lists +all ships, planes and land units that are being sold and allows you +to buy them. +.s1 +It is based on a bidding system, and after the bidding time has passed, +the transactions are executed, and the highest bidder gets the goods +(maybe.) If there are no bidders once the time passes, the goods stay +on the market and the first bidder will get them. +.s1 +Your bid must be higher than the currently high bid. +.s1 +Typical output looks like: +.EX trade +.NF + + Empire Trade Report + Wed Mar 13 14:42:45 1996 + lot high bid by time left owner description + --- -------- -- --------- ----- ------------------------- + 0 $ 1000 2 0.06 hrs ( 2) tech 0 100% inf1 infantry 1 [f:21 ] #3 +Which lot to buy: 0 +Destination sector: 4,0 +WARNING! This market issues credit. If you make more + bids than your treasury can cover at the time of sale, + you can potentially go into financial ruin, and see no + gains. You have been warned. + +How much do you bid: 1100 +Your bid on lot #0 is being considered. +.FI +.s1 +The cargo of ships and land units are listed in the square +brackets, in this case, 4 guns and 40 shells. The nuclear armament of +planes is listed in parentheses. +.s1 +.SA "set, Market" diff --git a/info/Commands/transport.t b/info/Commands/transport.t new file mode 100644 index 00000000..14388902 --- /dev/null +++ b/info/Commands/transport.t @@ -0,0 +1,32 @@ +.TH Command TRANSPORT +.NA transport "Move planes or nuclear devices around" +.LV Basic +.SY "transport plane " +.SY "transport nuke " +The transport command is used to move planes and nuclear devices from +one sector to another, along the ground. +.s1 + is a normal empire path specification. You may also give a + sector on the command line, or at any time while giving +the route, and empire will use the cheapest path (in terms of mobility) +from the current sector to the destination sector. +.s1 +You would move 5 small nukes from 2,0 to 8,0 as follows: +.EX transport nuke 2,0 small 5 8,0 +.s1 +You could move all planes in wing d to -6,0 as follows: +.EX transport plane d -6,0 +.s1 +Note that while transporting, you may run into any landmines the +enemy has left in your sectors. In that case, the planes being +transported will take damage. See info \*Qlmine\*U for details. +.s1 +Also, if your enemy has any units on interdiction mission, then the +planes you're transporting may get hit by them. +.s1 +Nuclear warheads are transported in heavily armoured vehicles and are +immune to land mines and interdiction. +.s1 +See info \*QMobility\*U for the mobility cost to transport planes and nukes. +.s1 +.SA "arm, move, navigate, nuke, Mobility, Planes, Moving" diff --git a/info/Commands/treaty.t b/info/Commands/treaty.t new file mode 100644 index 00000000..cad63e9a --- /dev/null +++ b/info/Commands/treaty.t @@ -0,0 +1,32 @@ +.TH Command TREATY +.NA treaty "Listing of all current and pending treaties" +.LV Expert +.SY "treaty " +The treaty command will report on all outstanding treaties and all +pending treaties. The conditions and durations are displayed. +.s1 +A typical treaty report might be: +.s1 +.NF + *** Empire Treaty #7 *** +(proposed) +between Curmudgeon and Urp expires Mon May 4 00:42:04 1981 + Curmudgeon terms Urp terms +no attacks on ships no attacks on ships + no shelling ships +no sector attacks no sector attacks + no shelling land +no enlistments +no new land units no new land units + + *** Empire Treaty #2 *** +between Curmudgeon and East Eden expires Mon May 4 00:42:59 1981 + Curmudgeon terms East Eden terms +no attacks on ships no attacks on ships +no shelling ships no shelling ships +no sector attacks no sector attacks +no shelling land no shelling land +no new land units no new land units +.FI +.s1 +.SA "consider, offer, Diplomacy" diff --git a/info/Commands/turn.t b/info/Commands/turn.t new file mode 100644 index 00000000..cb621b78 --- /dev/null +++ b/info/Commands/turn.t @@ -0,0 +1,9 @@ +.TH Command TURN +.NA turn "Allow/disallow logins. Change login message." +.LV Expert +.SY "turn " +Use "turn on" or "turn off" to enable/disable logins. If you just +want to change the login message, then use "turn mess". In all three +cases, you will be put into the telegram prompter to enter a new motd +(message of the day) which is printed when the player logs in. +.SA "Deity" diff --git a/info/Commands/unload.t b/info/Commands/unload.t new file mode 100644 index 00000000..40b03c51 --- /dev/null +++ b/info/Commands/unload.t @@ -0,0 +1,17 @@ +.TH Command UNLOAD +.NA unload "Inverse of load (above)" +.LV Basic +.SY "unload " +.SY "unload plane " +.SY "unload land " +The unload command is the opposite of load and follows the +exact same syntax ... +so why look here for documentation? +.s1 +The only thing to know is that unload won't unload more of a thing if the +sector already has 999. For example, if a ship has 10 food, and the harbor +has 994, you can only unload 5 of the 10 food. +.s1 +Also, you must have Friendly relations with the owner of the harbour +in order to unload into it. +.SA "load, Ships" diff --git a/info/Commands/unsail.t b/info/Commands/unsail.t new file mode 100644 index 00000000..678a0928 --- /dev/null +++ b/info/Commands/unsail.t @@ -0,0 +1,7 @@ +.TH Command UNSAIL +.NA unsail "Stop a ship from sailing" +.LV Expert +.SY "unsail " +You use the \*Qunsail\*U command to remove a sailing path from ships. +.s1 +.SA "follow, sail, mquota, Ships" diff --git a/info/Commands/update.t b/info/Commands/update.t new file mode 100644 index 00000000..ac734119 --- /dev/null +++ b/info/Commands/update.t @@ -0,0 +1,8 @@ +.TH Command UPDATE +.NA update "Find out when the next update will be" +.LV Basic +.SY "update" +The update command shows you when the next update will occur, and +describes the current update policies. +.sp +.SA "zdone, Update" diff --git a/info/Commands/upgrade.t b/info/Commands/upgrade.t new file mode 100644 index 00000000..53f85f1b --- /dev/null +++ b/info/Commands/upgrade.t @@ -0,0 +1,19 @@ +.TH Command UPGRADE +.NA upgrade "Update the tech of a ship/unit/plane to the current tech level" +.LV Expert +.SY "upgrade " +The upgrade command allows a country to set the tech level +of its ships/land units/planes to the country's current tech level. +.s1 +Each ship/land unit/plane to be upgraded must be in one +of the country's harbors/headquarteres/airports +that is at least 60% efficient and has an available workforce +of at least half the size it would take to build the ship/land unit/plane +from scratch. +To be upgraded, a ship/land unit/plane must be at least 60% efficient. +.s1 +Refitting a ship/land unit/plane costs 50% of the initial cost of a +building new one, and reduces the efficiency of the ship/land +unit/plane by 35%. +.s1 +.SA "build, ship, plane, land, Technology, LandUnits, Planes, Ships" diff --git a/info/Commands/version.t b/info/Commands/version.t new file mode 100644 index 00000000..f3d65dfc --- /dev/null +++ b/info/Commands/version.t @@ -0,0 +1,72 @@ +.TH Command VERSION +.NA version "Display parameters of this world" +.LV Expert +.SY "version" +The version command prints out the current settings of parameters +affecting the Empire game. +Included are the creation date for this version, +the size of the world, (X by Y), +etc. +.s1 +For example: +.s1 +.EX version +.NF +Empire 4.0.0 +(KSU distribution 1.04, Chainsaw version 4.00, Wolfpack version 1.00) + +The following parameters have been set for this game: +World size is 64 by 32. +There can be up to 52 countries. +By default, countries use their own coordinate system. + +An Empire time unit is 10 seconds long. +Use the 'update' command to find out the time of the next update. +The current time is Thu Aug 1 23:23:47. +An update consists of 60 empire time units. +Each country is allowed to be logged in 1440 minutes a day. +It takes 8.33 civilians to produce a BTU in one time unit. + +A non-aggi, 100 fertility sector can grow 0.12 food per etu. +1000 civilians will harvest 1.3 food per etu. +1000 civilians will give birth to 5.0 babies per etu. +1000 uncompensated workers will give birth to 2.5 babies. +In one time unit, 1000 people eat 0.5 units of food. +1000 babies eat 6.0 units of food becoming adults. + +Banks pay $200.00 in interest per 1000 gold bars per etu. +1000 civilians generate $4.33, uncompensated workers $1.78 each time unit. +1000 active military cost $83.33, reserves cost $8.33. +Happiness p.e. requires 1 happy stroller per 5000 civ. +Education p.e. requires 1 class of graduates per 4000 civ. +Happiness is averaged over 48 time units. +Education is averaged over 192 time units. +The technology/research boost you get from the world is 50.00%. +Nation levels (tech etc.) decline 1% every 96 time units. +Tech Buildup is limited to logarithmic growth (base 2.00) after 1.00. + + Sectors Ships Planes Units +Maximum mobility 127 127 127 127 +Max mob gain per update 60 120 90 90 +Max eff gain per update -- 100 100 100 + +Ships on autonavigation may use 6 cargo holds per ship. + +Fire ranges are scaled by 1.00 + +Options enabled in this game: + PLANENAMES, LANDSPIES, LOANS, MARKET, FUEL, TRADESHIPS, NEWPOWER, + NOMOBCOST, SUPER_BARS, EASY_BRIDGES, ALL_BLEED, NO_PLAGUE, + NEW_STARVE, NEW_WORK, SHOWPLANE, ORBIT, PINPOINTMISSILE, SAIL, + NUKEFAILDETONATE, SHIPNAMES, UPDATESCHED, DEMANDUPDATE, + INTERDICT_ATT + +The person to annoy if something goes wrong is: + John Doe + (johndoe@bar.edu). +You can get your own copy of the source using: +ftp://ftp.wolfpackempire.com/pub/empire/server/ or +http://www.wolfpackempire.com/ +.FI +.s1 +.SA "Innards, Basics, Playing" diff --git a/info/Commands/wait.t b/info/Commands/wait.t new file mode 100644 index 00000000..c488fb4c --- /dev/null +++ b/info/Commands/wait.t @@ -0,0 +1,25 @@ +.TH Command WAIT +.NA wait "Wait for a telegram" +.LV Expert +.SY "wait" +The wait command is used to wait until new telegrams are received. +It's most common use is to wait for an attack, or a reply of some sort. +.s1 +.EX "wait" +.nf +You have a new telegram waiting ... +.fi +.EX +.sp +When telegrams arrive you are informed with: +.NF +\*QYou have a new telegram waiting ...\*U if there is just one new one, or +\*QYou have ten new telegrams waiting ...\*U if there are ten of them, or +\*QYou have several new telegrams waiting ...\*U if there are very many. +.FI +.s1 +The wait command will eventually time out. +.s1 +WAIT COMMAND IS DISABLED IN THE NEW SERVER. +.s1 +.SA "telegram, wire, Obsolete" diff --git a/info/Commands/wall.t b/info/Commands/wall.t new file mode 100644 index 00000000..2bfbd60f --- /dev/null +++ b/info/Commands/wall.t @@ -0,0 +1,25 @@ +.TH Command WALL +.NA wall "Send a message directly to all allies terminals" +.LV Expert +.SY "wall []" +.s1 +The wall command allows instant communication between allied nations. +It may be called in two different ways. You can either send your ally a one +line message as in: +.EX wall Hi there, I'm back from lunch +.s1 +Or you can send a multi-line message: +.EX wall +.NF +> Everyone ready? +> OK, let's hit the beaches! +> . +.FI +Note that you can end a multi-line wall with either a '.' (period) +on a line all by itself, or by hitting ^D on a line by itself. +Note also that all messages are truncated to 60 characters long! +.s1 +If you do not wish to receive any broadcast messages from your allies, +then you can temporarily turn the feature off by typing "toggle flash". +.s1 +.SA "flash, declare, telegram, Communication" diff --git a/info/Commands/wingadd.t b/info/Commands/wingadd.t new file mode 100644 index 00000000..61702284 --- /dev/null +++ b/info/Commands/wingadd.t @@ -0,0 +1,43 @@ +.TH Command WINGADD +.NA wingadd "Designate members of a \*Qwing\*U" +.LV Expert +.SY "wingadd " +The wingadd command is used to specify the wing groupings +of your planes. +.s1 +.EX wingadd +In the syntax is the alphabetic character to be used as the +wing designation. +This character can be chosen from the set of +upper or lower case a-z and tilde (~). +The pseudo-wing specification tilde +specifies all planes not currently in any wing. +.s1 +The specification of planes, , +can have one of several syntaxes: +.NF +example meaning +------- ------- +23 plane 23 +2/14/23 planes 2, 14, and 23 +c all planes currently in wing `c' +~ all planes currently in the \*Qnull\*U wing +2,3 all planes in sector 2,3 +-1:3,0:2 all planes in the square area bounded by -1,0 & 3,2 +.FI +All wings, (with the exception of the `~' wing), +are limited to some maximum size +and you will be informed how many planes can be added +when this command is run. +.s1 +Having planes organized into wings can be very helpful in +loading, moving, etc., +in that fewer commands are required to perform these commands +on groups of planes if they can be specified by wing number. +.s1 +Note that you can remove planes from a wing by adding them to +the `~' wing. e.g. +.EX wingadd ~ A +This command would purge all planes from wing `A'. +.s1 +.SA "plane, fly, Planes" diff --git a/info/Commands/wipe.t b/info/Commands/wipe.t new file mode 100644 index 00000000..ea86e71e --- /dev/null +++ b/info/Commands/wipe.t @@ -0,0 +1,42 @@ +.TH Command WIPE +.NA wipe "Remove all distribution thresholds" +.LV Expert +.SY "wipe " +The wipe command removes all distribution thresholds +from the specified sectors. +Note that this will have drastic effects on sectors +that rely on distribution in any way, so use with caution. +Also note that if you make a mistake, +it can cost lots of BTU's to reverse the effects of a wipe. +.s1 +.EX level #5 +.NF +Wed Aug 16 18:34:43 1995 +DISTRIBUTION LEVELS + sect dst civ mil uw food sh gun pet iron dust bar oil lcm hcm rad + -5,5 k -1,5 0 0 0 0 0 0 0 566 1 0 0 0 1 0 + -3,5 f -1,5 0 0 0 0 100 10 0 0 0 0 0 100 250 0 + -1,5 w -1,5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + -6,6 ! -1,5 0 0 0 0 200 50 200 0 0 0 1 200 200 0 + 4 sectors +.FI +.EX wipe #5 +.NF +distribution thresholds wiped from -5,5 +distribution thresholds wiped from -3,5 +distribution thresholds wiped from -1,5 +distribution thresholds wiped from -6,6 +.FI +.EX level #5 +.NF +Wed Aug 16 18:34:43 1995 +DISTRIBUTION LEVELS + sect dst civ mil uw food sh gun pet iron dust bar oil lcm hcm rad + -5,5 k -1,5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + -3,5 f -1,5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + -1,5 w -1,5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + -6,6 ! -1,5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 4 sectors +.FI +.s1 +.SA "distribute, census, commodity, level, threshold, Distribution" diff --git a/info/Commands/wire.t b/info/Commands/wire.t new file mode 100644 index 00000000..721f92a4 --- /dev/null +++ b/info/Commands/wire.t @@ -0,0 +1,17 @@ +.TH Command WIRE +.NA wire "Read announcements" +.LV Basic +.SY "wire [yes|no|]" +The wire command is used to read the announcements sent you by other countries. +After reading all your announcements you may discard them by answering +\*Qyes\*U to the question posed. If you answer \*Qno\*U the announcements +will remain pending but you will not be reminded of them. +.s1 +You can read announcements that you have previously discarded by +specifying the argument. For example: +.EX "wire 3" +would print the announcements from the last three days. +.s1 +In order to read telegrams, use the 'read' command. +.s1 +.SA "telegram, read, accept, reject, Communication" diff --git a/info/Commands/work.t b/info/Commands/work.t new file mode 100644 index 00000000..991ff47f --- /dev/null +++ b/info/Commands/work.t @@ -0,0 +1,19 @@ +.TH Command WORK +.NA work "Use engineers to raise sector efficiency" +.LV Expert +.SY "work " +This command causes a unit with the engineering ability +to increase the efficiency of a sector. (see info show for +information on finding out unit abilities) +.s1 +The increase in efficiency depends on mobility used. It costs a 100% +efficient land unit 6 mobility to raise a sector 1% efficiency. Less +efficient land units are charged proportionally higher amounts of +mobility. For example, a 50% land unit would be charged 12 mobility +to raise the efficiency of a sector by 1%. +.s1 +If the sector has been re-designated, the working unit will first tear +down the old, then start working on the new effic, in the same way that +sectors update normally. +.s1 +.SA "show, Unit-types, LandUnits" diff --git a/info/Commands/zdone.t b/info/Commands/zdone.t new file mode 100644 index 00000000..d37a2f73 --- /dev/null +++ b/info/Commands/zdone.t @@ -0,0 +1,30 @@ +.TH Command ZDONE +.NA zdone "Indicate willingness to have an update" +.LV Expert +.SY "zdone [yes|no|check]" +The zdone command allows you to say when you are done and ready +for an update. +.s1 +"yes" says that you are ready for an update. +.s1 +"no" clears any previous "yes" that you did. +.s1 +"check" checks to see what your zdone state is. +.s1 +The command will also show you how many countries want +an update. There are 3 possible update policies which could +be set in this game. The update policy is shown in the update command. +.s1 +Your zdone state is cleared when an update occurs. +.s1 +1. No demand updates. If so, then this command is useless. +.s1 +2. Updates occur upon demand, right after the last person sets +zdone. The threshold at which a demand update occurs is configurable, +and may be seen in the update command. +.s1 +3. Demand updates occur at specific times. If enough countries +have set zdone at one of those times, then an update will occur. +The times may be seen in the update command. +.sp +.SA "update, Playing" diff --git a/info/Concepts/Attack.t b/info/Concepts/Attack.t new file mode 100644 index 00000000..24a6e077 --- /dev/null +++ b/info/Concepts/Attack.t @@ -0,0 +1,388 @@ +.TH Concept "How to take a sector or ship from the enemy" +.NA Attack "Details for attack, assault, paradrop, board and lboard" +.LV Expert + +This info page describes 5 different commands: "attack", "assault", +"paradrop", "board" and "lboard". These are the four commands that you +use to take something (either a ship, land unit or a sector) from the +enemy by force. + +Note that much of the board information relates to the lboard information, +just apply it to a land unit instead of a ship. + +.NF +A combat has 15 steps: +(1) Ask the aggressor for the target sector/ship. +(2) Ask the aggressor further details about the offensive force. +(3) Estimate the odds and possibly ask the aggressor for confirmation. +(4) Move reacting defensive units to the target sector. +(5) Calculate defensive support. +(6) Fight. +(7) Spread the plague. +(8) Take mobility and supply from land units. +(9) Send reacting units home. +(10) If successful, the aggressor takes the target sector/ship. +(11) Remove mobility and efficiency from the target sector/ship. +(12) Remove mobility from the aggressor's sectors/ship. +(13) Possibly ask the aggressor for mil and units to move into the target. +(14) Possibly interdict the aggressor's mil and units as they move. +(15) Charge the aggressor BTU's. +.FI +.s1 +.L "(1) Ask the aggressor for the target sector/ship." +.NF +Sea, sanctuary, and wasteland are illegal targets. +You may not assault a mountain. +You may not paradrop into a mountain, capital, city, or fortress. +You may only board a ship from the sector the ship is in, you may +not board a ship which is faster than your ship, and you may not board +a submarine at sea. +You may only board a land unit from the sector the land unit is in. +.FI +.s1 +The "assault" command is the only command which will let you attack +your own sector (you can use this to get mil & assault units on +shore). You should not "attack" unowned land (see info explore). +.s1 +If the SLOW_WAR option is enabled, you will not be able to attack +a sector owned by a country you are not AT_WAR with, unless you +are the old owner of the sector. +.s1 +If the SNEAK_ATTACK option is also enabled, you can attack ONE sector +owned by a country you are not AT_WAR with, paying $5K for the +privilege. Once the sneak attack is done, you will automatically +declare war against the enemy, and go through the normal SLOW_WAR +sequence before you can attack again (see info relations). +.s1 +.L "(2) Ask the aggressor further details about the offensive force." +.s1 +When you board, you are asked for a ship or sector to board from. +If you are attacking or assaulting, then you have the option to +specify whether you want your forts/ships/plane/units to support your +attack. If no support is specified, then it is assumed that +you want support from all sources. +.s1 +If you are not paradropping, then you will be asked for mil and units +you would like to attack with. +You must always leave at least 1 mil in +the sector or ship you are attacking from, so you may never attack +with all of your mil out of a sector or ship. +The following limitations apply to the aggressor's mil: +.NF +Attack: You are limited by the mobility of the attacking sector + according to the mob-cost to move the mil into the target sector. +Assault: If the target sector contains mil, then you may only attack with + 1/10th of your mil on board, unless your ship has "semi-land" + capability in which case it is 1/4th, -or- if your ship has + "land" capability in which case there is no limitation. +Board: When boarding from a sector, the sector must have mob. When + boarding from either a ship or a sector, the number of mil + you may board with is limited to the maximum number of mil that the + target ship can hold. Note that you can board land units + from a sector only. + +The following restrictions apply to the aggressor's land units: +A land unit must have mobility and be in supply (see info supply) in +order to be able to enter the combat. Land units with "security", +"supply" or "flak" capability may not attack. Also, you may not +attack with artillery units (i.e. if frg > 0). Only land units with "assault" +capability may assault or board. +Attack: The land unit must have at least as much mobility that it + would cost for it to march into the sector. +Board: You may only board with as many land units as the target ship + can hold. You cannot board a land unit with other land units. +.FI +.s1 +When asked whether you'd like to include a certain land unit in the +combat, you will be given a prompt ending in [ynYNq?]. At this +prompt, you can type: +.NF +y - yes this unit +n - no this unit +Y - yes all units in this army +N - no all units in this army +q - quit attack +? - print this help message +.FI +.s1 +.L "(3) Estimate the odds and possibly ask the aggressor for confirmation." +.NF +The offense strength of your land units is mil * off where "mil" is the +number of mil in the unit, and "off" is the offense multiplier of the +unit (see show land stats), with the following exceptions: +Assault: If the unit doesn't have "marine" capability, then its + offense strength is cut in half. +Board: If the unit doesn't have "marine" capability, then its + offense strength is equal to half of the number of mil in the unit. +.FI +.s1 +The total offense strength is the number of mil plus the offense +strength of all offensive units. This number is then multiplied by +the offense value of the sector the mil and units are attacking from +(see show sector stats). Ships have an offense value of 1. +.s1 +The defense strength of a land unit is the total number of mil in the +unit times its defense multiplier (see show land stats). The only +exception to this is non-marine land units on ships which have a +strength equal to the total number of mil in them. The defense +strength of units out of supply is cut in half. The defense strength +of fortified units is multiplied by (127 + fortification) / 127. +.s1 +The total defense strength is the number of mil plus the defense +strength of all defensive units. This number is then multiplied by +the defense value of the sector the mil and units are in (see show +sector stats). Ships have a defense value of 1 + def/100 (see show +ship stats). You can use the "strength" command to see the defense +strength of your sectors. +.s1 +Now, When your scouts estimate the defense strength, they only count +land units and mil that they see. If your scouts didn't notice the +efficiency of the defending units, then they assume that they are at +100% efficiency. Your scouts also assume that none of the enemy units +are fortified. Once your scouts have come up with an "estimated +defense strength", then that number is compared with your offense +strength. The +output so far might look like this: +.EX attack -14,2 +.NF +-14,2 is a 100% 5 harbor with approximately 0 military. +Number of mil from headquarters at -15,3 (max 108) : 10 +cavalry #7 has a base attack value of 44 +attack with cavalry #7 in -15,3 (~ 100%) [ynYNq?] y +cavalry #24 has a base attack value of 44 + + Initial attack strength: 108 +Scouts report defending unit: inf1 infantry 1 #22 (efficiency 71, tech 169) +Scouts report defending unit: inf2 infantry 2 #41 (efficiency 94, tech 169) +Scouts report defending unit: inf2 infantry 2 #42 (efficiency 94, tech 173) +Scouts report defending unit: inf2 infantry 2 #43 (efficiency 65, tech 139) + Estimated defense strength: 1118 + Estimated odds: 8% + +.FI +.s1 +Note that your estimated odds are calculated before any enemy units +have reacted, and before support multipliers are calculated, so they +will not be particularly accurate. +.s1 +.L "(4) Move reacting defensive units to the target sector." +.s1 +If the target is not a mountain, then defensive units in nearby +sectors may react. Defensive units will keep reacting until the +defense strength is 1.2 times the offense strength. The following +restrictions apply to reacting land units: +.NF +- The efficiency of the unit must be higher than it's retreat percentage. +- The unit must be in supply. +- The unit must have enough mobility to get to the target. +- The unit must be in range. +.FI +If the unit is in a 60% efficient headquarters, then 1 is added to its +reaction radius. If it is on "reserve" mission, then 2 is added to +the radius. Note that you can limit the reaction radius of your land +units using the "lrange" command. +.s1 +.L "(5) Calculate support." +.s1 +For attack and assault, both offensive and defensive support is +calculated. For paradrop, only defensive support is calculated, and +for board and lboard there is no support (however, defending ships within range +will fire on the boarding ship or sector before the fight if boarding +a ship). +.s1 +The aggressor's support is calculated based on what the aggressor +asked for. Defensive support is only called in to the extent that it +would be useful. If the aggressor outnumbers the defender 10-to-1, +then the defender will not have any support. Otherwise, the defender +will keep calling in support until its strength is at least 1.2 times +the offense strength. +.s1 +Fort, ship, and unit support is simply those forts, ships, and units +in range that can fire (see info fire). Note that ships and units on +missions will not fire support. Plane support comes from +those planes on "support" mission. The support multiplier is +.NF +1.0 + fortdamage/100 + shipdamage/100 + planedamage/100 + unitdamage/100. +.FI +.s1 +Ships/forts/units belonging to allies of the combatants will support, +if they are at war with the other combatant. (For example, if A is allied +with B, and at war with C, and A attacks C, things belonging to B will +support the attack if able. The same is true for defense. If C attacks +A, the B stuff will help defend A) +.s1 +After these four supports are calculated, then land mine support is +added to the defense support. Defending land mines add (number of mines) * +0.02 to a maximum of 0.40. If there are attacking engineers present, +this number is cut in half. +.s1 +.L "(6) Fight." +.s1 +Total offense and defense strength are multiplied by their support +multipliers to obtain the final combat strengths. From this, odds are +calculated. Then in each "round", a chance according to the combat +odds determines whether an aggressor or defender troop is lost. Troops +killed in combat are first taken from the mil (from the sector +containing the most mil), and then from the units (from the unit +containing the most mil). Combat odds are recalculated and the +process continues until there is a victor. Each time there is a +casualty, a character is printed: +.NF +! means a defending soldier bit it +@ means one of your soldiers went doan +.FI +.s1 +If the effiency of a land unit is less than its retreat percentage when +it gets hit, then it will need to make a morale check. +The chance of failing a morale check is (retreat +percentage - efficiency). If the unit has nowhere to retreat to, then +it takes "extra losses" which amounts to an extra 10% docked from its +efficiency. Otherwise, the land unit retreats to the adjacent sector +containing the maximum number of civs. Units will never retreat into +mountains. +.s1 +Also note that once all of the military on a land unit are killed, the +land unit stops defending. What this means is that a land unit can +become "trapped" in an sector if an enemy takes it over after killing +all the military on a land unit while the land unit may not be destroyed. +.s1 +When planning an attack remember that overwhelming forces greatly increases +your odds; i.e., attacking 10 men with 40 will result in your losing +fewer troops than if you had attacked with 20. +.s1 +.L "(7) Spread the plague." +.s1 +If any combatant in a battle is infected with the plague, all potential +comnbatants in the battle are infected as well (if they do not already +have some level of plague already.) +.s1 +.L "(8) Take mobility and supply from land units." +.s1 +The "aggresor loss factor" is equal to the number of aggressor +casualties divided by the total number of aggressor troops that went into +the conflict. Similarly, the "defender loss factor" is calculated. +Then each land unit loses mobility equal to 10 * (loss factor). +Defensive land units on reserve mission only lose half of that. Also +there is a chance equal to the loss factor that the land unit will use +up some of its supply (see info supply). +.s1 +.L "(9) Send reacting units home." +.s1 +If the defending land unit did not retreat, then send it back to where +it came from at no mobility charge. +.s1 +.L "(10) If successful, the aggressor takes the target sector/ship." +.s1 +Either 1 aggressor mil (first choice) or one land unit (second choice) +is automatically moved into the conquered ship or sector to occupy it. +Since this mil or unit is effectively "chasing out" the remnants of +the defending forces, the defender will not interdict it (because he +won't want to damage his forces with "friendly fire"). +.NF +This is what happens to the sector when you take it: +- All delivery and distribution information is wiped. +- The production in the sector is stopped (see info stop). +- Planes in the sector owned by the player you just took the sector from + lose 30 plus random(100) efficiency and go to 0 mob. If the new efficiency + is less than 10%, the plane is blown up. +- Units in the sector owned by the player you just took the sector from + lose 30 plus random(100) efficiency and go to 0 mob. If the new efficiency + is less than 10%, the unit is blown up. +- The avail is set to 0. +- New che are created (see info Guerrilla). +- Set the loyalty of the sector to 50 (see info Loyalty). +- Reduce the mobility to 0. +- The civs in the sector become "conquered populace" (see info Occupation). + +When you take a ship: +- Mission, retreat info and fleet info is wiped. +- Planes and land units on the ship are reduced to 10%. + +When you take a land unit: +- Mission, retreat info and army info is wiped. +- Planes and land units on the unit are reduced to 10%. + +When you take someone's capital, the defender loses half of their +money or $3000 whichever is greater. If the defender wasn't broke to +begin with, then the aggressor gets half of their money times (1/5 + +4/5 * efficiency of the sector). +.FI +.s1 +.L "(11) Remove mobility and efficiency from the target sector/ship." +.s1 +The efficiency of the target sector or ship is damaged by a percentage +equal to the total number of casualties divided by ten. +.s1 +If the target is a sector, then it will lose a percentage of the +mobility equal to the number of defender mil casualties divided by the +total number of mil that were originally in that sector, up to a +maximum of 20 mobility. So if for example, your casualty fraction was +70/100, and your sector started with 50 mobility, then you would lose +min(20, 50*70/100) = min(20, 35) = 20 mobility. +.s1 +.L "(12) Remove mobility from the aggressor's sectors and ships." +.s1 +The pre-combat mobility costs are: +.NF +Attack: Remove mobility equal to the mob cost to move the mil into the + target sector. +Board: If boarding from a ship, the cost is the half of the speed of the + defending ship times the efficiency of the defending ship. + If boarding from a sector, the cost is the number of boarding + mil divided by 5. This applies for boarding of ships and land units. +.FI +.s1 +Only sectors are charged an additional post-combat mobility cost. +In this case, the amount of mobility the sector loses is calculated +using the same formula as is used for the defending sector's mobility cost. +.s1 +.L "(13) Possibly ask the aggressor for mil and units to move into the target." +.s1 +If the combat was an assault, paradrop, board or lboard, then all victorious +mil and units are automatically moved into the target. The mil are +moved in with no mobility charge. If the combat is assault, then +the mil will take an amount of food with them proportional to the +number of people leaving the ship. The mobility cost to land units is +as follows: +.NF +Assault: If the land units are attacking from a ship with "land" capability, + then land units are charged (update mob) mobility, except for + "marine" units which are only charged half of that. For all + other kinds of ships, land units go to -(update mob), except for + "marine" units which go to zero. Here, (update mob) refers to + the amount of mobility that units gain at the update. +Board: Marine units are charged 10 mobility and other land units are + charged 40. +.FI +.s1 +In the case of attack, the aggressor is asked what they'd +like to move in as follows: First, the aggressor is asked how many mil +they would like to move in from each attacking sector. This number is +limited by the amount of mobility left in the attacking sector. Then +the aggressor is asked which land units they'd like to move into the +sector with the same [ynYNq?] prompt as above, the only difference +being that 'q' now means "don't move anything in". The mobility costs +here are the same as for "move" and "march". +.s1 +.L "(14) Possibly interdict the aggressor's mil and units as they move." +.s1 +Post-attack interdiction only occurrs in the "attack" command (and not +in "assault", "paradrop", "board" or "lboard"). +When you move your mil into the target sector after an attack, you +will risk the same chances of interdiction (number of mil / 200) and +stepping on land mines (see "info lmine") as +if you were moving them using the "move" command. +.s1 +Similarly, once you have specified which land units you'd like to move +into the conquered sector, then all of your units will move in at +once, and they will be interdicted in the same way as though they were +being moved using the "march" command, including the danger of +stepping on land mines. Note that there is no +post-attack interdiction and no danger of stepping on land mines if the +INTERDICT_ATT option is disabled (see version). +.s1 +.L "(15) Charge the aggressor BTU's." +.s1 +The BTU cost is equal to 0.5 + (the total number of casualties) * 0.015. +.s1 +.SA "attack, assault, paradrop, board, lboard, Combat" diff --git a/info/Concepts/Autofeed.t b/info/Concepts/Autofeed.t new file mode 100644 index 00000000..12e36abe --- /dev/null +++ b/info/Concepts/Autofeed.t @@ -0,0 +1,76 @@ +.TH Concept Autofeed +.NA Autofeed "How to use fishing boats to automatically feed your civs" +.LV Expert +.NF + + For years now people have been setting up large groups of fishing +boats to feed their island. These groups get very large and are +difficult to keep track of. + + This is an example of how to set up a fleet of fishing boats +so they will take their food produced each update and drop it off +at the harbor of your choice. + + See 'info order' for a complete description and example of +syntax for the 'order' command. + +map #1 + 00000000001111111 + 01234567890123456 + -4. . . . . . . . . + -3 ? ? . . . . . . + -2? . . . . . . ) . + -1 ? . . . . . f . . + 0. . . . . g m . . + 1 . . . . f * w h . + 2. . . . . c + + . + +You have ships 0,12,88 in the harbor 15,1 +Sector 16,0 has a very good fert of 93 so you want to use that +as your fishing grounds. + +1) move your ships to sector 16,0 +"nav 0/12/88 16,0" + +2a) set up autonav using the 'order' command. + "order 0 des 15,1 16,0" + This will establish a circular trade route. + +2b) set up food levels for the ship + "order 0 level 1 start food 30" + "order 0 level 1 end food 30" + + You can also use a global '*' or a fleet letter here. + "order * level 1 start food 30" + "order * level 1 end food 30" + + "order F level 1 start food 30" + "order F level 1 end food 30" + + NOTE: You should set BOTH start and end fields to insure + autofeed will work correctly and set them at the + same levels! + + NOTE: if you are using autonav with normal cargo ships. + Fishing boats are a special case to the autonav code. + This setup will only work correctly with fishing boats. + If you want to use autonav with cargo ships please use + the examples found in the 'order' command. + +repeat 2a,2b for other ships in the area. + +During the update your fishing boats will now move to the harbor at +15,1 unload food until it reaches 30, then move back to 15,1 and STOP. +If you're using fishing boats that require fuel, i.e. fb2 +when the ship enters the harbor, and the fuel level is at 0, the +autonav code will automaticly refuel the ship for you. +So unless the ship gets sunk, or something happens to it, like the +civs starve on board if you don't leave enough food on it, +the ships will continue to feed your country and you won't even need +to think about them. + +The Max limit that autonav will stockpile is 99999 units. +So if your sector get overcrowded the ship will sit in the harbor +until it can unload all of its food. +.FI +.SA "Autonav, order, navigate, Ships, Populace, Update" diff --git a/info/Concepts/Autonav.t b/info/Concepts/Autonav.t new file mode 100644 index 00000000..acd63801 --- /dev/null +++ b/info/Concepts/Autonav.t @@ -0,0 +1,48 @@ +.TH Concept Autonavigation +.NA Autonav "Giving ships automatic sailing orders" +.LV Expert +In a very short while after acquiring ships the effort of moving ships after +every update gets very boring. And the more ships you have, the more work +it is. Hence the concept of autonavigation. Like any self-respecting +dictator, you don't personally drive your ships around (except when you want +to), instead you command you ship captains to take their vessels to a +specified destination. This is done via the \*Qorder\*U command. +.s1 +Each ship can be ordered to proceed to a destination. During each update, +the ship will try and use ALL the mobility it has and use the shortest +possible path. It will also avoid any known mines (sectors marked +with an 'X' or 'x' on your bmap). Note that this movement is all +done before mobility is accumulated, so that after the update is +complete the ship will have a full updates worth of mobility +in case you need to move it by hand. Should a ship be fired upon +by forts or strike a mine they will stop moving! This will prevent +your ship from foolishly getting sunk in enemy waters. The +\*Qorder\*U command covers many special cases. + +.s1 +The autonavigation capability is dependent upon the per country map database +accessed via the \*Qbmap\*U command. If you order a vessel to a destination +that causes it to cross a previously unexplored area, the ship will attempt +to cross that area as if it were water. One of the features of the bmap +functionality is that when a ship is navigated, it automatically uses its +radar to see the local sectors (much like real life). This sector information +is added to the per country map database. Thus upon running into a previously +unknown obstruction, that information is added to the map database and on the +next update, a new path to the destination will be calculated which avoids +the obstruction. This process applied iteratively means that a ships will +eventually find its way around any obstruction, provided that a path exists. +In reality, this is a limit to this process. In order to limit the processing +that is done to find a path to the destination, the internal path string is +limited to 28 characters. +.s1 +The other capability of the autonav function is autotrading. By specifying +two destinations and two commodities, the ship will move back and forth between +the two destination loading and unloading the appropriate commodities. +Specific examples can be found in the \*Qorder\*U info file. +.s1 +The same rules for navigating, loading, and unloading apply for +Autonavigation as they do when you do these things by hand, namely +that you may only use harbours owned by nations which consider you to +be a friendly trading partner (see info relations). +.s1 +.SA "navigate, order, Ships, Update" diff --git a/info/Concepts/BTU.t b/info/Concepts/BTU.t new file mode 100644 index 00000000..23bd06f4 --- /dev/null +++ b/info/Concepts/BTU.t @@ -0,0 +1,74 @@ +.TH Concept "Beurocratic Time Units" +.NA BTU "How BTUs are generated" +.LV Expert +.s1 +It takes time for decisions to be made by top level officials, and it +takes time for their orders to reach those who execute them. +The potential of your government to process new information is +measured in Bureaucratic Time Units (BTU). +.s1 +BTUs are generated in real-time based on the number of civilians that +are in your capital. Every time you log out and in again, the server +calculates how long you've been away, and based on that time awards +you a certain number of BTUs. +.s1 +Here is the procedure for determining how many BTUs you get: +.nf +If the game is a blitz, then as soon as your BTUs go below zero, then +they are automatically set back to 512. + +(1) Count the number of civs generating BTUs. + civs = maximum(999, number of civs in your capital sector) + Note that if you don't have a capital, then you will get _no_ BTUs. + +(2) Find out how many civs are required to make one BTU in one time unit. +The "version" command will tell you how many civilians are required to +produce one BTU in one time unit. + +(3) Calculate how many BTUs your cap produces in one time unit. +Divide the number of civs generating BTUs (step 1) by the number of +civs required to produce one BTU in one time unit (step 2). If your +capital is in a mountain or has zero efficiency, then multiply by +1/200. Otherwise, multiply by (sector efficiency) / 100. Note that +0% capitals and mountains generate BTUs as if they were 0.5% capitals. + +(4) Calculate how many time units have passed. +The number of "Time units" (TU) since your last login is: + TU = (number of seconds since last login) / (number of seconds per ETU). +The "version" command will tell you how many seconds are in an +"Empire time unit" (ETU). If more than 336 time units have passed +since your last login, then set TU = 336. + +(5) Calculate how many BTUs you get. +Multiply the number of BTUs your cap produces in one TU (step 3) by +the number of TUs which have passed (step 4). This is how many BTUs +you get. Note that there is a limit to how many BTUs you can have at +any given time. This number is usually 512 but can be changed by the deity. + +EXAMPLE: say you had a 100% capital containing 500 civs. +Suppose that version said: + +It takes 25.00 civilians to produce a BTU in one time unit + +Then first you would divide 500 by 25 to get 20. Now since your cap +is 100% efficient, you would multiply 20 by (100/100) and so the civs +in your cap would produce 20 BTUs per time unit. Now suppose that +version said: + +An Empire time unit is 1440 seconds long. + +and suppose that 1 day had passed since the last time you logged on. +Then that means that the number of time units which have passed is: + TU = (number of second in a day) / (number of seconds per etu) + = (24 * 60 * 60) / (1440) + = (1440 * 60) / (1440) + = 60 +(Note that another way to find out how many time units there are between +updates is to find out how many ETU's there are per update.) + Lastly, we multiply 20 by 60 to get 1200 BTUs. But since the +maximum is 512, we would have 512 BTUs. Note that if your capital had +been in a mountain sector, then you would have only gotten 6 BTUs in +24 hours. +.fi +.s1 +.SA "Innards, version, Time, Playing" diff --git a/info/Concepts/Bridges.t b/info/Concepts/Bridges.t new file mode 100644 index 00000000..f5e69aad --- /dev/null +++ b/info/Concepts/Bridges.t @@ -0,0 +1,34 @@ +.TH Concept "Bridges" +.NA Bridges "Building and destroying bridges" +.LV Expert +.s1 +BRIDGES +.s1 +Normally bridges can only be built from bridge-heads. (See info +\*QSector-types\*U). If the EASY_BRIDGES option is in use, +bridges can be built from any sector +that has enough hcm (heavy construction materials) and +workforce (see \*Qinfo show\*U and the \*Qshow\*U command), +providing you have enough money, and your technology level is high enough. +.s1 +Bridges can only be built over water sectors. +.s1 +If the EASY_BRIDGES option is in use, +you do not need to use bridgehead sectors (although the sector you +build from must still be at least 60% efficient), and +the sector the bridge span is to be built in must be adjacent to +at least 1 non-sea, non-bridge span sector. Note that you do not have to +OWN the sector is will be adjacent to, it just has to exist. This means that +you can build, for example, a 2 sector bridge out to an unowned island. +.s1 +To find out the required amounts of materials, workforce, and money +use the show command. +.s1 +Bridge spans cannot be re-designated. +A bridge span will collapse when it is below 20% in efficiency, +so shelling will destroy one, as will nuclear weapons and bombing. +.s1 +If the EASY_BRIDGES option is NOT in use, a bridge will also collapse +if its bridge-head sector goes below 20% or is re-designated. +.s1 +.SA "build, Technology, show, Sectors" diff --git a/info/Concepts/Citizens.t b/info/Concepts/Citizens.t new file mode 100644 index 00000000..a7e04e3c --- /dev/null +++ b/info/Concepts/Citizens.t @@ -0,0 +1,56 @@ +.TH Concept Populace +.NA Citizens "Work, starvation, and general management of your citizens" +.LV Basic +.s1 +Taxation of the civilian populace is one of the main providers of income +to an Empire nation (gold bars in banks, trade ships, and taxes from +uws being the only other sources of income in the game). +Also, only friendly civilians can be enlisted into the army, navy and +air force. +.s1 +The loyalty of a given sector, +also known as the willingness of the civilian population to work, +is initially 100% -- that is, all of the people are working. +In the event that the sector is captured, starves, +or falls victim to revolutionary subversion, +the work of the sector will decrease. +This will be shown by the work % decreasing. +.s1 +If people starve in a sector, the amount of work they do drops to 0 +(because they are too weak to work). +.s1 +If a sector is a conquered sector, +a star \*Q*\*U will be shown in the appropriate column +on the census report. +Friendly sectors allow enlistment of military, +as well as the ability to move the civilians freely about. +Occupied civilians will not move, +and friendly civilians cannot enter these sectors. +In addition, occupied civilians will not serve in the armed forces. +.s1 +If the thought of not being able +to move conquered populace bothers you, +then you have the option of converting these conquered people +into uncompensated workers, +involving the expenditure of BTU's and money +(for the paperwork). +If all the conquered people in one sector are converted to uw's, +then the sector is then marked as yours. +.s1 +If the people in a sector are unhappy +(due to starvation, subversion, or lack of happiness) +they can go on strike and cease working. +You can get them back to work by heavy-handed military control +(placing one military for each 20 striking civilians). +.s1 +Finally, your populace requires happiness to keep their enthusiasm +for work going. As technology and education increase, +your work force expects to share in the increased levels +by getting more consumer items (VCR's, BMW's, etc) +represented by happy strollers. +If you don't have at least one happiness point +per two units of education, +and a point for each forty units of tech, +your people will not be happy. +.s1 +.SA "attack, Happiness, Populace, Occupation" diff --git a/info/Concepts/Damage.t b/info/Concepts/Damage.t new file mode 100644 index 00000000..c66b5a5a --- /dev/null +++ b/info/Concepts/Damage.t @@ -0,0 +1,103 @@ +.TH Concept Damage +.NA Damage "How much damage stuff does" +.LV Expert +.nf +It is possible to be damaged by shells, bombs, land mines, sea mines, +and nuclear blasts. This info page shows you how much damage each of +these things does. In the following formulas, random(x) means a +random number from 1 to x. Once the damage has been calculated, then +it is applied. Damage applies to different kinds of things in +different ways (see below). + + +1. Calculating the damage + +Shelling +You can be shelled by a fort, artillery unit, ship, depth-charge, or torpedo: + fort damage = guns * eff * (random(30) + 20) / 7 + unit damage = guns * eff * (5 + random(6)) + ship damage = guns * eff * (10 + random(6)) + depth damage = 2 * eff * (10 + random(6)) + torp damage = 40 + random(40) + random(40) +Note that for forts, a maximum of 7 guns may be fired. + +Bombs +A plane drops a number of bombs equal to the "load" the plane can carry. +Each bomb does the following damage: + blam: 1 + random(6) + Blam: 5 + random(6) + BLAM: 8 + random(6) +When pinbombing a ship, plane, or land unit, damage is doubled. +Whether you get a blam, Blam, or a BLAM depends on the accuracy of the +plane and the difficulty of the target (see info bomb). + +Land mines +Land mines damage commodities by random(20) and land units by 10 + random(10). +If the land unit is an engineer, then the damags is cut in half. + +Sea mines +Sea mines damage ships 22 + random(20). If the ship can sweep, then +the damage is cut in half. + +Nuclear Detonation +Damage from nuclear detonation uses the following formula. From +"show nuke stats", you see that each nuke has a certain blast radius +and %damage. If you are groundbursting, then multiply the radius by +2/3. If you are airbursting, then multiply the radius by 3/2. Now +based on the distance from gound zero, the nuke does the following +amount of damage: + +Groundburst: dam / (dist + 1) + Airburst: 0.75 * dam - 20 * dist + +For the small, medium, and large nukes currently in the game +(damage 80, 90, 101 and radius 1, 2, 3) the following damage is obtained: + + Groundburst Airburst + 0 1 0 1 2 3 +small 80 60 40 +med 90 45 68 48 28 +large / 50 76 56 36 16 + + +2. Applying the damage + +Once you know how much damage the bombs or whatever have done, then +you apply the damage to what was hit. In the calculations below, +%damage will never be larger than 100%. If it is, then we just say +that the %damage was 100%. Once we have the %damage, then we apply it +as follows: + +new efficiency = (old efficiency) * (1 - %damage / 100) + +For example a 50% ship hit for 10% damage would go down to 45%. + +The following formulas show you how to get %damage from damage. Note +that these formulas are used in all cases _except_ nuclear damage. In +the case of nuclear damage, %damage is always equal to damage (except +for planes hardened in silos which subtract their "hardened" value +directly from the damage). + +Ship +%damage = damage / (1 + def / 100) + +Land unit +%damage = damage * (vul / 100) * (127 / fortification + 127) + +Plane +%damage = damage + +Sector +sectdamage = damage / ((sectdef - 2) * eff + 2) +%damage = (100 * sectdamage / (sectdamage + 100)) +commodities take %damage (bars take no damage and people take 0.4 * %damage) +land units take 0.3 * %damage +planes take no damage + +Commodity +%damage = (100 * damage / (damage + 50)) +bars take no damage +civs, mil, and uws take 0.4 * %damage + +.fi +.SA "fire, launch, torpedo, lmine, bomb, Hitchance, Attack, Combat" diff --git a/info/Concepts/Education.t b/info/Concepts/Education.t new file mode 100644 index 00000000..647e9f9b --- /dev/null +++ b/info/Concepts/Education.t @@ -0,0 +1,70 @@ +.TH Concept Education +.NA Education "How Education is calculated at the update" +.LV Expert +.s1 +Education is important for both technology and research production. +Your country will not be able to produce technology or research unless +your civilians have an education of at least 5. (See "info Products" +for more details). +.s1 +The \*Qnation\*U command will display, among other things, +your current education level. +.s1 +.nf +This is how your new education level is determined every update: + +(1) Graduates are produced in schools +See "info " or the "production" command to find out how many +Graduates you are going to produce. Your update telegram will tell +you the class of graduates produced in your various schools in a line +like this: + a class of graduates (135.00) produced in 3,1 + +(2) Calculate your education production efficiency +The higher your population, the lower your education p.e., as it takes +more graduates to maintain the same overall level of education. Note that +with low population you education p.e. can be greater than 1. +The version output will contain a line like this: + Education p.e. requires 1 class of graduates per 10000 civ. + +Your education p.e. is now calculated as follows: +education p.e. = "civ. per graduate" / + "total pre-update civilian population" + +number of graduates produced = class of graduates * education p.e + +For example, lets say you have a pre-update civilian population of +40,000 and have produced a class of 260 graduates. Your education p.e. +would be 10000 / 40000 = .25 and your number of graduates would be +260 * .25 = 65 + + (3) Calculate edu delta from the number of graduates +"edu log base" is always 4.0 and "easy edu" is always 5.0. +To find out what your edu delta for the update will be, subtract "easy +edu" from the number of graduates you are producing and call +this number "over easy". Now divide "over easy" by the log of ("over +easy" + "edu log base") base "edu log base", and then add "easy edu" back. +Simple eh? ;-) + +OK, here's an example: +Say you are producing 65 graduates. Then your "over easy" would be 65 +- 5.0 = 60. Now the log of (60 + 4.0) base 4.0 is 3 (since 4 to the +power 3 is 64), so our edu delta will be 60/3 + 5 = 25. + +(4) Calculate your new education as a weighted average +The version output will contain a line like this: + Education is averaged over 192 time units +And the number of etus per update is printed in the version output as: + An update consists of 60 empire time units. + +Your new education is now calculated as follows: +"new edu" = ("old edu" * "average etus" + "edu delta" * "etus per update") / + ("average etus" + "etus per update") + +So if, for example, your old education level was 40 and your "edu +delta" was 25, then your new edu would be: +"new edu" = (40 * 192 + 25 * 60) / (192 + 60) + = 36.43 +.fi +.s1 +.SA "Happiness, Innards, nation, Products, Research, Technology, Nation, Production, Update" diff --git a/info/Concepts/Fallout.t b/info/Concepts/Fallout.t new file mode 100644 index 00000000..a52f98a5 --- /dev/null +++ b/info/Concepts/Fallout.t @@ -0,0 +1,35 @@ +.TH Concept Fallout +.NA Fallout "The long lasting effects of nuclear war" +.LV Expert +This page describes fallout, and some of its effects. +.nf + +Fallout is the result of nuclear bombs going off. It is basically +just radioactive particles that float around in the air. + +After nuclear blasts, these particles are thrust into the atmosphere, +and take a long time to dissipate. In addition, these particles +may spread from sector to sector. + +When a sector has fallout, during the update, things in that sector +may die, melt, whatever from the radiation. The way it works is this: + +1) All sectors that have fallout are checked, and things there are + affected by the fallout. People die, commodities melt, etc. This + includes anything on land units and on ships within that sector. + +2) Next, fallout may spread from sector to sector, depending on the + amount of fallout in the sector. Note that fallout will spread + outward from ground zero, in all directions, at a maximum rate of + 1 sector per update. + +3) Lastly, fallout decays. Any fallout that is left decays. Decay + usually happens in 1/2 life mode, which means 1/2 the given fallout + in a sector (after spreading around) dies... + +Finally, if you are reading this info page, it probably means that +you are trying to figure out what fallout is going to do to your +country. Well, good luck, so are we. :) + +.fi +.SA "launch, nuke, Diplomacy, Damage, Combat" diff --git a/info/Concepts/Flak.t b/info/Concepts/Flak.t new file mode 100644 index 00000000..28e8414d --- /dev/null +++ b/info/Concepts/Flak.t @@ -0,0 +1,151 @@ +.TH Concept Flak +.NA Flak "How flak works" +.LV Basic +This page describes flak, and how it works. +.s1 +Flak is created from gunfire when enemy planes fly overhead. +.s1 +The way that flak works when planes fly over a sector is: +.nf + * Sector flak is fired. Up to a maximum of 14 guns can fire + before being scaled. + * Land unit flak is then fired. Up to a maximum of 14 guns can + fire before being scaled. Only 'flak' capable units will fire + in this volley (see "info show"), and only the guns loaded onto + a land unit are counted in the # of guns firing. + * Ship flak is then fired. Up to a maximum of 14 guns can fire + before being scaled. + * Defensive planes then intercept. +.fi +.s1 +In all of the above flak rounds, once the maximum # of guns firing +has been determined, the # of guns is then scaled by your country's +tech factor, and then doubled. So, for example, if you had 14 guns +firing, and have a tech factor of 35%, you would have a total of +(14 * .35) * 2 = 10 (after rounding) guns firing. +.s1 +In addition, if you are pinbombing a land unit or a ship, when +you make your bombing run, the specific unit/ship you are bombing +gets to fire flak at you again. This number of guns firing flak +in these cases is NOT scaled after the number of guns is determined. +.s1 +When a sector fires flak, the amount of shells required is the # of +guns fired divided by 2. If not enough shells are available, either no flak +is fired, or the flak is reduced to the number of shells available. +Note that the shells are not consumed during flak fire, they just need +to be available. +.s1 +When a ship fires flak, at least 1 shell must be available. +If no shells are available, no flak is fired. Note that the shell is +not consumed during flak fire, it just needs to be available. +.s1 +Land units use no shells when firing flak. Any land unit with an +aaf rating of > 0 will fire flak when pin-bombed. +.s1 +The formulas for determining the # of guns fired in a general volley +is: +.nf +Sector: + guns = (guns in sector); + if (guns > 14) + guns = 14; + +Ship: + guns = 0; + for (each ship in the sector) + guns += min(guns, guns able to fire) * (techfact of ship) * 2; + if (guns > 14) + guns = 14; + +Land unit: + guns = 0; + for (each land unit in the sector) + guns += (aaf rating) * (techfact of unit) * 3; + if (guns > 14) + guns = 14; +.fi +.s1 +Then, for each of the above general flak volleys, the # of guns is +scaled like so: +.nf + firing = guns * (techfact of nation) * 2; + +On specific bombing runs, the # of guns firing is determined by: + +Ship: + guns = min(guns, guns able to fire) * (techfact of ship) * 2; + +Land unit: + guns = (aaf rating) * (techfact of unit) * 3; + +The # of guns in these cases are NOT scaled. + +techfact is determined by: + techfact = (50.0 + tech) / (200.0 + tech); +.fi +.s1 +Once the number of flak guns firing has been determined, the planes +have to fly through it. The plane may have to fly through flak up +to 4 times in each sector, depending on circumstances. They are: +.nf + + 1) Fly through general sector flak (if any) + 1a) fight in a possible dog-fight + 2) Fly through general ship flak (if any) + 3) Fly through general unit flak (if any) + 4) If pinbombing, fly through specific unit or ship flak (if any) +.fi +.s1 +To figure out the damages that a plane takes each time it flys through +flak, the following formula's are used: +.nf + + flak = # of guns firing. + flak = flak - (planes defense + 1); + if (plane is stealthy) + flak = flak - 2; + if (plane is half stealthy) + flak = flak - 1; + if (flak > 8) + mult = flaktable[15] * 1.33; + else if (flak < -7) + mult = flaktable[0] * 0.66; + else { + flak += 7; + mult = flaktable[flak]; + } + mult *= flakscale; + damage = ((random number from 1 to 8) + 2) * mult; + if (damage > 100) + damage = 100; + + plane's eff = (plane's eff) - dam; + if (plane's eff < 10%) + plane is shot down + else if (chance((100 - (plane's eff)) / 100)) + plane aborts mission + otherwise the plane continues on it's mission + +For the above, use this table: + + flaktable[0] = 0.20 + flaktable[1] = 0.20 + flaktable[2] = 0.25 + flaktable[3] = 0.30 + flaktable[4] = 0.35 + flaktable[5] = 0.40 + flaktable[6] = 0.45 + flaktable[7] = 0.50 + flaktable[8] = 0.50 + flaktable[9] = 0.55 + flaktable[10] = 0.60 + flaktable[11] = 0.65 + flaktable[12] = 0.70 + flaktable[13] = 0.75 + flaktable[14] = 0.80 + flaktable[15] = 0.85 + +and a flakscale of 1.75 +.fi +.SA "bomb, fly, recon, paradrop, nation, Planes, Interception, Combat" + diff --git a/info/Concepts/Food.t b/info/Concepts/Food.t new file mode 100644 index 00000000..ba82b095 --- /dev/null +++ b/info/Concepts/Food.t @@ -0,0 +1,149 @@ +.TH Concept Food +.NA Food "How much people eat at the update" +.LV Expert +.s1 +In Empire, as in the \*Qreal\*U world, everyone must eat to survive, +(see SPECIAL NOTE below for the exception). +All of these numbers below are subject to change. +Execute the \*Qversion\*U command to get some of this information. +Ask the deity for the rest. +.s1 +Each civilian or military eats 0.0005 units of food per time unit, +(i.e. 0.024 units of food a \*Qday\*U in non-Blitz Empire). +.\" eatrate * 86400 / s_p_etu +.s1 +The ability of a sector to grow food is indicated by its \*Qfertility\*U. +Fertility values range from 0 to 100. +.s1 +Food can be grown in any kind of sector although agribusinesses +are able to grow more food with fewer workers. +.s1 +Every sector produces a base level of food according to the following: +.in +0.2i +.s1 +The amount of food that the sector can grow in one time unit is: +.s1 +.ti +0.3i +fertility * 0.002 +.\" ofgrate +.s1 +The amount of food that can be harvested in one time unit is: +.s1 +.ti +0.3i +(civilians + military / 5) * 0.002 +.\" ofcrate +.s1 +i.e. one civilian can harvest four times +.\" ofcrate / eatrate +the amount that he/she eats while +one military can harvest 4/5 +.\" 0.2 * ofcrate / eatrate +of the amount that she/he eats. +.s1 +Note that this means that although a sector with a fertility of 40 +can grow enough food to support 160 people +.\" 40 * ofcrate / eatrate +at least 10 of them must be civilians. +In fact, +any combination of civilians and military +that meets the following two criteria will be self-sufficient: +.s1 +.ti +0.3i +civilians + military \(<= 4 * fertility +.\" ofgrate / eatrate +(amount that grows) +.s1 +.ti +0.3i +military \(<= 15 * civilians +.\" (ofcrate / eatrate - 1) * 5 +(amount that gets harvested) +.in \\n(in +.s1 +In an agribusiness an \*(iFadditional\*(pF amount of food can be grown. +That amount is calculated by the following: +.in +0.2i +.s1 +An efficiency factor (effact) takes into account the state of repair +of the agribusiness itself (sector efficiency, effic) and +the technology level of your farmers +(the national technology level, tlev): +.s1 +.ti +0.3i +effact = (effic * (tlev + 10)) / (100 * (tlev + 20)) +.s1 +The amount of additional food that the sector produces +in one time unit is: +.s1 +.ti +0.3i +(civilians + military / 5) * effact * fertility / 1000. +.s1 +Thus, a 100% agribusiness with a fertility of 50 +and an educational level of 10 +has an efficiency factor is 2/3; +one civilian can harvest 0.033 units of food per time unit +beyond the food normally produced in that sector. +This extra amount is enough to support 33-three other +people while one military can harvest 0.0066, +enough to feed 13 other people. +.s1 +The amount of food cultivated by 10 civilians +in 10 time units in a 100% agribusiness are: +.s1 +.NF + | EDUCATION LEVEL | + | 0 | 10 | 100 | + ------+-----+------+------+ + F 10 | 0.5 | 0.67 | 0.92 | + E ---+-----+------+------+ + R 50 | 2.5 | 3.33 | 4.58 | + T ---+-----+------+------+ + . 100 | 5.0 | 6.67 | 9.17 | + ------+-----+------+------+ +.FI +.s1 +.in \\n(in +SPECIAL NOTE: Residents of a sanctuary need no food to survive; +thus no one ever starves in a sanctuary. +.s1 +On a ship the following applies: +.in +0.2i +.s1 +The amount of food that can be produced on a fishing boat +in one time unit is: +.s1 +.ti +0.3i +(civil * etus * fertil) / 10000; +.s1 +However, if the NEWFISH option is in use, the limit is: +.s1 +.ti +0.3i +(civil * etus * fertil) / 1000; +.s1 +The amount of food that can be produced on any other ship +in one time unit is: +.s1 +.ti +0.3i +0 +.in \\n(in +.s1 +Note that if a ship doesn't have enough food, it will try to draw it from +supply sources (see info supply). If it still hasn't enough food, it will +attempt to grab unneeded food from any land units it is carrying. +.s1 +Land units eat food as well, an amount based on the total number of military +in the unit (this is the efficiency times the number of mil needed to build +the unit). If a land unit doesn't have enough food, it will try to draw it +from supply sources (see info supply). If it still doesn't have enough, and +it is on a ship, it will attempt to get food from the ship. +.s1 +The presence of food also affects the birthrate in Empire; +if there is no food in a sector no babies will be born. +A baby consumes 0.3 units of food in growing to adulthood. +.\" babyeat +However, babies are only allowed to eat half the food in a sector. +Thus if a sector could produce 25 new +civilians but only has 2 spare units of food, +(after the current population has eaten), +only three babies will be born and one unit of food will be left. +.s1 +.SA "Innards, Populace, Update" diff --git a/info/Concepts/Guerrilla.t b/info/Concepts/Guerrilla.t new file mode 100644 index 00000000..eb8680c7 --- /dev/null +++ b/info/Concepts/Guerrilla.t @@ -0,0 +1,74 @@ +.TH Concept Guerrilla +.NA Guerrilla "Guerrilla warfare" +.LV Expert +.s1 +Guerrillas are created in several ways; +when a sector is captured by an enemy, +or when civilians riot for one reason or another +(starvation, no happiness, etc). +.s1 +Guerrillas have a generally detrimental effect +on the well-being of your country. +Depending on the amount of military in the sector they \*Qinfest\*U, +they will either attack the military there +(but only if they have a good chance of winning), +blow up things (lowering sector efficiency), +or, if they are too badly outnumbered, +they will try and move to a different sector. +.s1 +If there are no military in the \*Qinfested\*U sector +at the end of the update to break up guerrilla recruitment drives, +your civilians' loyalty will suffer. +If the sector is only occupied -- +not completely owned by you, that is -- +then it will revert back to the old owner, +renouncing the conqueror and returning to their old allegiance. +The guerrillas will then move on to \*Qconvert\*U more sectors. +Particular guerrilla bands will fight to the death, +or until you dissolve in disgust. +.s1 +Guerrillas will attempt to \*Qrecruit\*U new followers +from semi-loyal sectors and from the uncompensated worker population. +Loyal civilians will resist these recruiting drives, +but uncompensated workers will always flock to the banner +of the guerrilla warrior. +.s1 +The renowned guerrilla fighter Colonel (later Captain) Batguano +gave a talk to the special forces, which was later made into an +Armed Forces Technical Manual. +In it he states, +.s1 +.in +0.8i +.ev 2 +.ll 5.5i +The first thing you learn is that the che are hardier than cockroaches, +eat like birds, and are simply invulnerable to gunfire and napalm. +They hide in the sewers. +There are two ways to handle the guerrilla problem; +one way requires high yield fusion weapons, +and then they only die when everything else in the sector is destroyed. +Unfortunately, collateral damage to civilian assets renders this +strategy negatory ... \* Col. Batguano then launches into +a tirade against the \*Qwimpy-assed liberals\*U which interfere with the +proper guerrilla suppression techniques \* ... +Almost every fully-populated area we moved into +had a few dozen of the little monsters, +and troop levels of 50-100 per sector were found to adequately +pacify the region. +Of course, depopulating the area prior to takeover often had a salutary +effect on the number of che we later found... +.ll 6.5i +.ev +.in +.s1 +You will be notified of the varying civil disturbances +by \*Qproduction\*U telegrams showing a body count of guerrillas killed, +a sector being subverted by revolutionary propaganda, +or a sector lost to guerrilla activities! +.s1 +Land units present in a sector help to fight them, fighting without +any multiplier, either offensive or defensive and without any +fortification bonus. Any units with the +\*Qsecurity\*U ability will also kill some che before anything else is +done (commando raids). +.SA "Populace, Occupation, Update" diff --git a/info/Concepts/Happiness.t b/info/Concepts/Happiness.t new file mode 100644 index 00000000..6e03220d --- /dev/null +++ b/info/Concepts/Happiness.t @@ -0,0 +1,34 @@ +.TH Concept Happiness +.NA Happiness "How happiness is calculated at the update" +.LV Expert +.s1 +Happiness is required for countries which have any sort of technology +or education at all, with greater levels being required as +the expectation (and tech/edu levels) of the populace increases. +A country with an unhappy population can expect a decrease in the +\*Qwork\*U of some sectors. +.s1 +Also, the morale of your land units is determined by the happiness +of your people. The morale of a unit can be set by the player, but +the minimum level allowable is determined by happiness: +.ti 3 +75 - happiness +.s1 +Thus, a nation with a happiness of 20 would have a minimum allowable +morale level of 55% +.s1 +The \*Qnation\*U command will display, among other things, your current +happiness level. +.s1 +The procedure determining happiness level is exactly the same for +happiness as it is for education (see "info Education") except for the +fact that "happiness log base" is always 6.0 and "easy happiness" is +always 5.0. New happiness is averaged with old happiness in the same +way that education is averaged except that happiness averaging has its +own line in the "version" output: + Happiness is averaged over 48 time units. +.s1 +It has also been rumored that increasing happiness will help to keep +the rebels in check somewhat, but the exact results are sketchy at best. +.s1 +.SA "Education, Innards, nation, Products, Research, Technology, attack, Nation, Production, Update" diff --git a/info/Concepts/Hitchance.t b/info/Concepts/Hitchance.t new file mode 100644 index 00000000..2a5605d0 --- /dev/null +++ b/info/Concepts/Hitchance.t @@ -0,0 +1,121 @@ +.TH Concept Hitchance +.NA Hitchance "The chance of a projectile hitting its target" +.LV Expert +This page describes the chance of a mine, torpedo, ship anti-missile +defense, missile, or plane hitting its target. +.nf + +Sea Mine hitchance +The chance of a ship hitting a mine at sea is (mines/(mines+20)). (For +example, with 20 mines, the chance of hitting one is 20/40 = 50%) The +damage is dependent upon the size of the ship and the spot that the +mine hits. (see \*Qinfo Damage\*U). + + +Land Mine Hitchance +The chance of a land unit hitting a land mine is mines/(mines+35). +(For example, with 20 mines, the chance of hitting one is 20/55 = +36%). See \*Qinfo Damage\*U to find out how much damage things take +from land mines. Note that the chance of land units hitting land +mines is divided by 3 if the land units are accompanied by engineers. + +When moving commodities (civs, mil, shells, etc) or transporting +planes, the chance is also dependent upon the weight being moved. +First the above chance is checked, and then a chance equal to (weight +/ 100) is checked. + + +Torpedo hitchance +The chance of a torpedo hitting its target is equal to: + hitchance = 0.9/(range + 1) +where "range" is the range to the target. If the visibility of the +ship firing is less than 6, then (5 - visibility) * 0.03 is added to +the hitchance. + +Thus, the base chance of a sub hitting its target (before visibility +modification) is: + + Range Chance + 0 90% + 1 45% + 2 30% + 3 22.5% + 4 18% + 5 15% + + +Ships anti-missile defense +If a ship has "anti-missile" defense capabiilty, then it will +intercept any marine missiles launched at ships within 1 sector of the +ship. Only missiles belonging to a country you are "At War" with will +be intercepted. Only ships which are at least 60% efficient will be +able to use their anti-missile defenses. The chance of the ship +hitting the incoming missile it equal to: + + hitchance = gun * eff * tfact * 4.5 - (missile "def" value) +where + gun = the number of guns the ship is allowed to carry + eff = the efficiency of the shiip + tfact = tech / (tech + 200) +where + tech is the tech level that the ship was built at + + +Plane and missile hitchance +If the plane or missile is carrying a nuclear warhead or the target is +a sector, then the hitchance is 100%. Otherwise, the following +procedure is used to calculate hitchance. + +The formula for a plane or missile hitting its target depends on the +type of the target (ship, plane, land unit) and the "hardtarget" value +of the target (which represents how hard that target is to hit). + +Ship: + vis = the visibility of the ship (from 'show ship stats'). +For a sub, we set vis = visibility * 4. +If the ship is at sea, then: + hardtarget = (eff of ship) * (20 + speed/2 - vis) +otherwise: + hardtarget = (eff of ship) * (20 - vis) +The hardtarget of a fleet is the hardtarget if the "easiest" target in +the fleet. + +Land unit: + hardtarget = (efficiency) * (10 + (sector defense) * 2 + speed/2 - vis) +The hardtarget of an army is the hardtarget of the "easiest" target in +the army. + +Plane: +If the plane is in the air (satellite, icbm), then + hardtarget = the "def" value of the plane. +otherwise if the plane is on the ground: + hardtarget = 0 + +Once we have calculated the "hardtarget" value of the target, then the +chance of a plane or missile hitting its target is equal to: + + hitchance = acc - hardtarget + +where + acc = (efficiency) * (1 - 0.1 * tfact) * (1 - placc/100) +where + tfact = (pltech - mintech)/(pltech - mintech/2) +where + pltech = tech level of plane + mintech = min tech level required to build plane +and + placc = plane accuracy +and if the target is a ship and the plane is an ASW plane, then + placc = placc - 20 +and if the target is a ship and the plane does not have tactical capability + placc = placc + 35 + +Lastly we smooth out the bottom end of the hitchance curve. If +hitchance is less than 20, then it is "belled up" using the following +curve: + hitchance = 5 + 300 / (40 - hitchance). + +On the other hand, you can just find out the hitchance by pinbombing +or launching a missile--the hitchance is always printed! :-) +.fi +.SA "fire, launch, bomb, torpedo, Attack, Damage, Interception, Combat" diff --git a/info/Concepts/Infrastructure.t b/info/Concepts/Infrastructure.t new file mode 100644 index 00000000..688275ad --- /dev/null +++ b/info/Concepts/Infrastructure.t @@ -0,0 +1,62 @@ +.TH Concept "Infrastructure" +.NA Infrastructure "Making your sectors better" +.LV Basic +.s1 +INFRASTRUCTURE +.s1 +The infrastructure of your sectors determines how well your sectors +defend, and how well you can move commodities and vehicles (land units) +through your sectors. +.s1 +You can improve the "road", "rail" and "defense" efficiency of all of your +sectors, given that you have the correct commodities, enough mobility and +enough money. +.s1 +The "road" infrastructure determines how well (i.e. the mobility cost) +commodities and non-train vehicles travelling through your sector are able +to move at both distribution time and while you are moving them by hand. +.s1 +The "rail" infrastructure determines how well (i.e. the mobility cost) +trains are able to move through your sectors. +.s1 +The "defense" infrastructure determines how well (i.e. the defense factor) +your sector defends itself. There is a maximum amount that the sector +may obtain. Use the "show sect stats" to see what the maximum values are. +.s1 +So, what you can do, by using up some commodities, mobility and cash, +is to create a pseudo-highway network through non-highway sectors. You can +still create highway sectors for just the designation fee of the sector, +but it costs you a whole sector to use it. This is a trade-off for +both being able to use the sector and still move things through it at a +reasonable cost. +.s1 +When you "improve" the infrastructure of your sectors, you are improving on +the efficiency of part of that sector (either road, rail or defense.) By +improving it, it's statistics get better. For roads and rails, that means +that the mobility cost to move through goes down. For defense, that means +that you are building up the "defenses" of the sector towards the maximum +allowed (see "show sector stats" for the maximum values.) +.s1 +Since infrastructure is on an efficiency basis, it takes damage just like +regular efficiency. So, when a sector is shelled or bombed, the infrastructure +there is damaged in an efficiency based manner. +.s1 +Infrastructure is also not affected by rebuilding the sector. So, once +you build infrastructure, it stays in place until the sector is damaged in +some way. +.s1 +Use the "sinfrastructure" command to see what the current infrastructure of +your country looks like. +.s1 +Use the "improve" command to improve the infrastructure of your sectors. +.s1 +To find out the required amounts of materials, mobility, and money +use the "show sect build" command. +.s1 +Also, defensive infrastructure is not always improvable. See the version +info to see if the DEFENSE_INFRA option is enabled or not. If it is not +enabled, the defense infrastructure of the sector is always the same +as the efficiency of the sector. If it is enabled, you must improve your +sectors defensive values using the "improve" command. +.s1 +.SA "improve, sinfrastructure, Mobility, Sectors" diff --git a/info/Concepts/Innards.t b/info/Concepts/Innards.t new file mode 100644 index 00000000..65f0f562 --- /dev/null +++ b/info/Concepts/Innards.t @@ -0,0 +1,248 @@ +.TH Concept Innards +.NA Innards "Some details about the inner workings of the server" +.LV Expert +.s1 +Much of this file is now out-of-date. Correct information may be found +in the files Update-sequence and build. +.s1 +This topic contains fairly nitty-gritty descriptions of +some of the underlying mechanisms in the Empire system. +It is not meant for the weak-of-heart or casual reader. +(And it's usually out of date.) +.s1 +Sector Updates +.s1 +Several characteristics of the Empire game are dependent on +sector updates -- +mobility, efficiency, mining of ore, generation +of production units, etc. +.s1 +An understanding of the calculations +involved is often helpful in planning the timing of various +actions +and although it is unlikely that this description +is strictly up to date, +it should provide a feel for the overall philosophy. +.s1 +All commodities in a sector are kept as \*Qshort integers\*U. +The program cannot have \*Qnegative commodity values\*U, so the +theoretical capacity of a sector is 32767, while in practice +it is actually 9999 (for formatting reasons). +While it is possible to move more commodities than 9999 into +sectors, production of commodities will not go +above the level of 999. +So, an update that produces 450 units of iron in a sector that already +has 800 units can at most add 199 units. +.s1 +Here is an approximate description of the algorithm that is +called whenever an update occurs: +.s1 +Variables used are: +.in \w'workforce\0\0'u +.L etus +the # of Empire time units in this update +.L civ +civilians in the sector +.L mil +military in the sector +.L uw +uncompensated workers in the sector +.L desig +designation of the sector +.L effic +efficiency of the sector +.L miner +iron mineral content of the sector +.L gold +gold mineral content of the sector +.L t_level +technology level of the country +.L r_level +research level of the country +.L p_stage +plague stage in the sector +.L p_time +plague stage duration +.L workforce +an intermediate variable that represents work potential +.L work +the amount of work done in the sector +.in +.s1 +Parameters used are (see the \*Qversion\*U command for actual values): +.in \w'uwbrate\0\0'u +.L s_p_etu +seconds per Empire time unit +.L fgrate +the food growth rate +.L fcrate +the food cultivation rate +.L eatrate +how much food people eat +.L obrate +birth rate +.L uwbrate +uncompensated worker birth rate +.L babyeat +how much babies eat growing up +.L bankint +bank interest rate in $/bar +.in +.nf +.s1 +workforce = (civ*100/sector work + uw + mil / 5.) / 100. +If workforce = 0 go away and don't update anything + +/* increase sector efficiency */ +If the weather is good enough for construction and we're not broke then + effic becomes effic + work (if possible) and costs $1 for each + percentage point gained. +Otherwise charge the $1 for each percentage point that would have been + gained, (pay for workers to play cards). + +/* grow some food */ +Set dd = etu * sector_fertility * fgrate + (this is the amount of food that can be grown in etu time units) +Set dtemp = work * 100. * fcrate + (this is the amount of food that the people there can harvest) +If (dtemp < dd) (if there aren't enough people to harvest it all) + set dd = dtemp +Set foodtmp to the amount of food in the sector plus dd + +/* feed the masses */ +If desig is sanctuary then + set dd equal to 0. +Else + set dd equal to etu * (civ + mil) * eatrate + (this is the amount of food the people need to eat) +If (dd > foodtmp) then some people will starve + figure out what percentage of the population can be fed, + and kill the rest (up to a maximum of 1/2 the populace) + set food = 0 +Otherwise + set food = foodtmp - dd (with a maximum of 999) + +/* population growth */ +set q = etu * civ * obrate + the number of births possible in other sectors +If q is bigger than food / (2 * babyeat) set q to food / (2 * babyeat) + food available to mature this many babies into civilians +If q is bigger than 999 - civ set q to 999 - civ + enough room for that many +Set food = food - q * babyeat +Set civ = civ + q + +/* mobility */ +Add etu to mobil (to a max of 127) + +/* pay taxes */ +Collect the taxes, pay the military + civ_tax = (int) (.5 + (civs * eff * etu * civtaxrate / 100.)); + if (conquered) civ_tax /= 4.; + uw_tax = (int) (.5 + (uws * eff * etu * uwtaxrate / 100.)); + mil_pay = (int) (mil * etu * milpayrate); + + nat_money -= mil_pay + nat_money += civ_tax + uw_tax + +/* plague */ +If p_stage = \*Qthird\*U kill off a bunch of people, + alert the owner and the news and decrement p_time by dt. + If p_time \*(<= 0 set p_stage = zero (plague has burned itself out). +If p_stage = \*Qsecond\*U report + to the owner and the news and decrement p_time by dt. + If p_time \*(<= 0 set p_stage = \*Qthird\*U + and randomly reset p_time in the range of etu_per_update to + (etu_per_update * 2). +If p_stage = \*Qfirst\*U decrement p_time by dt. + If p_time \*(<= 0 set p_stage = \*Qsecond\*U + and randomly reset p_time in the range of etu_per_update to + (etu_per_update * 2). +If p_stage = zero and a random number in the range 0-99 + is less than the figure generated by the equation in \*Qinfo plague\*U + then set p_stage = \*Qfirst\*U + and set p_time to a random number in the range of etu_per_update to + (etu_per_update * 2). +.s1 +/* delivery & distribution */ +If anything is being delivered from this sector and there is +more of it than the delivery threshold (always a multiple of 8) +and the country is not broke + deliver as much of the excess as mobility allows. + If plague_stage is \*Qsecond\*U (the infectious stage) + set plague_stage and plague_time in the destination sector. +If there is a \*Qdistribution threshold\*U for this sector, and +if the sector isn't at this threshold, + import or export as necessary from the distribution warehouse + the number of commodities, mobility permitting. + +/* production */ +If effic is less than 60 skip the rest. +.in +3 +.s1 +.ti -3 +If desig is bank then accrue etu * bankint interest per gold bar +.ti -3 +If desig is capital pay etu * $1 for government salaries +.ti -3 +If desig is enlistment sector, then convert civilians to military + newmil = (etu * (mil + 10) * 0.05); + nat_money -= newmil * 3; +.ti -3 +If this sector produces something (mines, research labs, etc.) + calculate how much can be produced (see \*Qinfo Products\*U) + (Note that the amount that can be produced is limited by \*Qwork\*U) + produce it + pay for it (money, iron, gold mineral, oil, etc.) +.fi +.in \\n(in +.s1 +Several points are noteworthy: +.s1 +\(bu The work done in a sector (ore dug up, efficiency growth, +population growth, products generated, etc) is dependent on the +product of time since last update and work force (\*Qwork\*U above) +while the accumulation of mobility is independent of work force. +.s1 +\(bu If the population of a sector is very low it may never generate +any work at all due to conversion to integer truncation. +.s1 +Ship Updates +.s1 +Ships are also updated only when accessed however the mechanism is simpler. +The only characteristics that are changed by ship updates are +the mobility, +the efficiency, (if less than 100%). +the food, (and therefore the crew if starvation occurs), +the amount of oil, +and +plague status, (which can also change the size of the crew). +.s1 +The algorithm is essentially: +.in +3 +.nf +add etu to mobility (with a maximum of 127) +add etu to efficiency (with a maximum of 100) +add etu * civil * sector_oil / 10000. to oil if ship type is oil derrick +add etu * civil * sector_fertil / 10000. to food if ship type is fishing boat +feed the crew and passengers + starve a few if not enough food +check for plague progress, + (the same as in sectors except each stage lasts twice as long on a ship) +.fi +.in +.s1 +Bureaucratic Time Units +.s1 +There is one further update that is not handled in the sector +update routine; that is the update of bureaucracy time units (BTU's). +These are the numbers printed in brackets before the command +prompt. +Most commands given use BTU's, some use 1, some use 2 and some use +more, making BTU's a vital commodity. +The generation of BTU's is +dependent on the efficiency and the work force in the capital sector. +(see info BTU). +.s1 +.s1 +.SA "Education, Happiness, Products, Research, Technology, Time, BTU, Obsolete" diff --git a/info/Concepts/Interception.t b/info/Concepts/Interception.t new file mode 100644 index 00000000..ba280d0a --- /dev/null +++ b/info/Concepts/Interception.t @@ -0,0 +1,126 @@ +.TH Concept Interception +.NA Interception "How plane interdiction works" +.LV Expert +.s1 +Each time an enemy plane (i.e. a plane owned by a country that your are +HOSTILE to or worse) flies into over a sector you own, planes you +have with the intercept ability will intercept them if: + +.NF +a) The incoming plane is not stealthy, or is detected. +b) The sector is within 1/2 the interceptor's range (as modified +by rangeedit) +b) They have mobility +c) Their efficiency is 40 or more +d) They are at an appropriate place: + 1) planes without VTOL ability must be at an airport that + is at least 60% efficient. + + 2) planes on ships may only fly if the ship can operate + that kind of aircraft. + +e) There is petrol there equal to 1/2 the plane's fuel rating. + (rounded down) +.FI +.s1 +Before planes scramble to intercept incoming planes, any SAMs in range +will be launched. One SAM is launched at each incoming plane that +cost at least $1000 to build. See below for the damage that the SAM +does to the plane it hits. +.s1 +Enemy planes will be intercepted by up to 1 more interceptor, +i.e. 1 plane will be intercepted by 2 (if available), 2 by 3, +3 by 4, etc. The highest +numbered planes intercept first. Incoming missiles will only be intercepted +by ABM's +.s1 +Once the roster of attackers & intercepters is determined, attackers +and interceptors dogfight. First escorts & interceptors fight, +then planes being escorted & surviving non-aborted interceptors. +.s1 +First, an attacker and a defender are chosen, then each plane on each +list fights once. +.s1 +.L "Combat values" +.s1 +The attacker's combat value is calculated by adding up his planes attack +value, and modifying it for efficiency, bomb-load, and stealth. The attack +value of the plane is multiplied times the plane's efficiency, but cannot +go below 1/2 of the plane-type's base value (as shown by show plane stats). +(If the plane's attack value +is 0, the defensive value is used instead, with a minimum of 1/2 the plane- +type's defensive value) +.s1 +Two is subtracted if the attacking plane is carrying bombs. +.s1 +If the plane is stealthy, stealth%/25 is added. +.s1 +The defender's value is calculated in the same way, except that the +defensive value is always used. +.s1 +.L Odds +.s1 +Next, an odds ratio is calculated: (att/(def+att))*100. +.s1 +.L "Combat Intensity" +.s1 +Then, a combat intensity is rolled: (d20+d20+d20+d20) +.s1 +.L Combat +For each point of combat intensity (or until both planes are dead), +a d100 is rolled. If the value is less than the odds, the defender +takes a casualty, otherwise the attacker takes a casualty. +.s1 +Once all combat rolls have been made, the attacker and defender are +checked for aborting. If a plane is damaged below 80%, then it will +have a chance of aborting. The chance to abort is (100-plane eff). (Example: a +plane at 70% has a 30% chance to abort. +.s1 +Missiles intercepting die after the combat is done. +.L Example +.s1 +Suppose that a fighter 2 (30% efficient, tech 154, attack value 7) is +conducting a recon mission. As it enters an enemy controlled sector, a +fighter 1 (100% efficient, tech 131, defense value 4) rises up to fight it. +The attacker's combat value is calculated: +.s1 +.NF +1) 7 * (30/100) = 2.1 = 2 + +2) 2 is less than 1/2 the base attack value of an f2 (6), so the value +is changed to 3 + +3) The attacking plane is not stealthy. No modifier. + +4) The attacking plane is not carrying bombs. No modifier. +.FI +.s1 +The defender's defense value, calculated similarly, is 4. +.s1 +The odds ratio is (3/(3+4)) = .429 = 43% +.s1 +The intensity is randomly determined to be 30. A d100 is rolled 30 times. +Each time that is 43 or less, the defender takes a hit. Each time it is +44 or more, the attacker takes a hit. +.s1 +In our example, the attacker takes 17, the defender 13, leaving them at +13% and 87% efficiency, respectively. The attacker has an 87% chance to +abort, and the defender a 13%. If neither aborts, the attacker flies on. If +both abort, the mission is over. If only the defender aborts, the attacker +will fly on to the next sector in his flight path (perhaps to have combat +again) If only the attacker aborts, the defender flies home with the +knowledge of a job well done. +.s1 +.L ABM's +ABM's do not use the normal combat procedure. They simply have a % +chance of destroying an incoming warhead equal to their defensive value. +.s1 +If you have land units in the enemy plane's target sector, your plane will +intercept the enemy planes AGAIN. If you have non-sub ships in the enemy plane's +target sector, your planes will intercept them yet again. If you own +the target sector, and have ships & units there, your planes will therefore +intercept them a total of three times in that sector. Note that a 'target +sector' is a sector that is the target of a bombing or para mission. Merely +having ships in a sector will not cause interception of planes flying over. +.s1 +.SA "Plane-types, plane, fly, recon, bomb, range, Planes, Missions" diff --git a/info/Concepts/Land-units.t b/info/Concepts/Land-units.t new file mode 100644 index 00000000..3b27d539 --- /dev/null +++ b/info/Concepts/Land-units.t @@ -0,0 +1,344 @@ +.TH Concept "Land Units" +.NA Land-units "How to use land units" +.LV Basic +.s1 +Land units are organized collections of mil (militia). They are considerably +more effective and cost-efficient than militia, and have many extra +abilities. With the addition of land units, mil are now more or less +considered to be militia instead of military, and are less important. +.s1 +The way that military are incorporated into units are that the mil are +loadable commodities of the unit. The offensive or defensive +.s1 +Commands for land units are generally similar to those of planes/ships, and +will usually start with 'l'. +.s1 +.L "Land unit characteristics" +.s1 +Land units have some characteristics of both ships and planes, plus some +unique ones. Like both ships & planes, they have efficiency & mobility. +Like ships, they can carry cargo, may have/use fuel, and may be able to fire +guns at distant targets. Like planes, they have attack and defense values, +and may be able to act automatically to defend your country. +Let's look at a typical land unit: +.s1 +.EX land * +.NF + # unit type x,y a eff mil fort mu fd tech retr rd xl ship + 0 inf infantry 8,0 96% 100 0 93 24 0 42% 1 0 +1 unit +.FI +.s1 +This land unit is an infantry unit, located at 8,0. In many games, you will +start with 1-2 basic land units of this type. Some of the things about it are +familiar. It is 96% efficient, has 93 mobility units, carries 1 food, no fuel, +and is tech 0 and currently contains 100 mi. It carries 0 extra-light +planes, and is not on a ship. The 'a' +stands for army, and is just like fleets or wings, i.e. a way of grouping your +units. (See info \*Qarmy\*U for more information) +Fort is the level of fortification of the land +unit. The higher the fortification, the harder the unit is to hurt. +.s1 +The 'retr' stands for retreat percentage. This +land unit must begin rolling morale checks in combat whenever its efficiency +goes below 75%. This is user settable in a range determined by the happiness +of the owning country. The happier your people are, the more determinedly +they fight. If, on the other hand, you \*Qwant\*U the unit to retreat easily, +you can set this to 100% or some other high number. (For information on +setting this, see info morale. For information on morale checks, see info +attack) +.s1 +The 'rd' field is referred to as the unit's 'reaction radius', +and is the distance to which the unit can react to defend your country. +Basically, if an enemy attacks a sector close enough to the unit, it will go +to the threatened sector and fight, like a plane intercepting. If it survives +the attack without failing a morale check, it will return to the sector it +started from, just like a plane would. (For more information on reacting and +morale checks, see info attack) Just as you can use rangeedit to change the +range of your planes and control how far away they'll intercept, so you can +change the reaction radius with \*Qlrangedit\*U. Units with a base reaction +radius of 0, or those whose radius you have set to 0, will not react. +.s1 +.L Cargo +.s1 +Each land unit can carry cargo. The cargo display for land units is very +similar to that of ships, and is gotten with the \*Qlcargo\*U command. +.s1 +.EX lcargo * +.NF +lnd# unit type x,y a eff sh gun pet irn dst bar oil lcm hcm rad + 0 infantry 8,0 96% 0 0 0 0 0 0 0 0 0 0 +1 unit +.FI +.s1 +The land unit is not carrying anything. Potentially, land units can carry any +of the commodities listed above. Unlike ships, they cannot carry mil, civs, +or uw's. Land units are loaded and unloaded using the lload command, which +works pretty much like the load command for ships. (See info \*Qlload\*U) +Units on ships can transfer supplies to/from the ships with the \*Qltend\*U +command. +.s1 +.L "HQ's & Building land units" +.s1 +Like planes and ships, land units are built in special sectors. For land units, +the sector is the headquarters sectors, designation !. Like other units, +they may require hcms and lcms, and will generally require money. +.s1 +Some land units may require guns to build. All this info can be gotten with the +\*Qshow\*U command. +.s1 +.EX show land build +.s1 +.NF + lcm hcm guns avail tech $ +inf infantry 10 5 0 40 0 $500 +.FI +.s1 +The infantry unit takes a total of 10 lcms, 5 hcms, and 0 guns to build. +Like ships and planes, units are built at a lower percentage, and 'grow' up +to 100%, and any unit with an efficiency of less than the build percentage +is dead. For land units, this minimum efficiency is 10%. +The build requirements for land units, like those listed above, are +for a 100% unit. Thus, the infantr1 would require 1 lcm and .5 hcms +(Fractional amounts are randomly rounded... i.e. .5 has a +50% chance of being 1 or 0. It'll all even out over time) +.s1 +When 'growing', land units +require materials which must be present in the sector. The +amount of growth is calculated in the same fashion as planes/ships. Generally +a land unit can grow by up to 2x the ETUs per update. (See the \*Qversion\*U +command for exact maximums, as these are deity-settable) So, for example, in +a 32 ETU game, a land unit could possibly grow by 64% per update. For the +infantry unit shown above, this would require 6.4 lcms and 3.2 hcms. +If any of these things aren't present in the sector, the unit won't +gain efficiency. +.s1 +.L "Repair of Land units" +.s1 +Ships can repair themselves in any sector, and can use work from their crew, +or from a harbor they are in. Planes can only be repaired in airports, and +only use work from the airport. Land units can be repaired in HQ's, \*Qor\*U +in fortresses, and use the work of the HQ or fort. This means that front-line +units in forts will repair themselves each update, assuming that the +necessary materials and work are available. They can also gain efficiency +in other sector types, but at a much reduced efficiency (1/3rd normal gain) +.s1 +.L "Land unit statistics" +.s1 +Each land unit has certain vital statistics which show how it will +operate. These are obtainable from the show command: +.s1 +.EX show land statistics +.s1 +.NF + s v s r f a d a a x + p i p a r c a m a f f p + att def vul d s y d g c m m f c u l +infantry 1.0 1.5 60 23 15 2 1 0 0 0 0 0 0 0 0 +.FI +.s1 +The infantry unit has an attack multiplier of 1.0, and defensive multiplier +of 1.5. It has a vulnerability rating of 60, a speed of 23, a visibility of +15, spy value of 2, reaction radius maximum of 1, no firing range, no accuracy, +no firing damage, uses no ammo, has no aa fire, doesn't carry of use fuel, +and can't carry extra-light planes. +.s1 +When attacking, a unit's value is expressed in 'mil-equivalents', i.e. 1 +mil-eq is as strong as 1 mil. To find a unit's attack value, find the number of +mil currently in it, and multiply by the attack multiplier and efficiency. +In the case of our infantry unit the unit has an attack value of 96 +(100*1.0*.96), and a defense value of 144 +(100*1.5.96). Some units, like tanks, will have high attack multipliers, +and medium +defense multipliers. Some, like most infantry, will be better at defending than +attacking. Some, like artillery units, will be bad at both. +.s1 +As time goes on, and your tech increases, the stats of your land units +will get better. This reflects the technological breakthroughs you have +made in that you can now build better units of the same type. +.s1 +The vulnerability of a unit determines how easy it is to hurt the unit by +shelling it, bombing it, or when it encounters land mines. The lower the +vulnerability, the better. Values range from 1-100. +.s1 +Spd is the relative speed of the land unit. Land units move by marching (see +info \*Qmarch\*U), and use mob depending on their speed and the terrain they +are moving through. For more info and formulas, see info \*Qmarch\*U. +.s1 +Vis is the visibility of the unit. This is a measure of how easy it is to +see/detect the unit. Lower is harder to see, and the numbers can range from +1-100 or so. When a land unit tries to use the \*Qllookout\*U command to look for +enemy land units/planes, its chances of success are affected by the target +units' visibility (see info \*Qllookout\*U for more details). +.s1 +Spy is the other side of the equation, i.e. how well can the unit find things? +A unit with a low spy won't be very good at locating other units, and won't +be able to report much when it encounters them in battle. A high-spy unit +will be able to use the \*Qllookout\*U command with more chance of success, and +will be able to more accurately report information about the units it runs +into in battle. (See info \*Qattack\*U for information about intelligence +reports) Units with radar capacity also use their spy value to determine how +far they can see. Spy values range from 0-127, with low numbers being most +common. +.s1 +Don't confuse this spy value with the "spy" capability of a unit. See +"info Spies" for more information. +.s1 +Rad is the maximum reaction radius for the unit. When built, the unit will +have this as its reaction radius. If you change the reaction radius by using +the \*Qlrangedit\*U command, you will be able to select any value that is +between 0 and the maximum. +.s1 +Frg is the unit's firing range. The unit can fire as far as the frg, modified +by the unit's tech. Accuracy is the unit's firing accuracy, and helps to +determine how much damage it will do, along with the dam of the unit. When +firing at sectors, damage is based solely on the damage. When firing in +defense of a sector, or firing at ships, damage is based on both acc and dam. +(See info \*Qfire\*U for more information) +.s1 +Ammo is the number of shells a land unit uses every time it fires or +participates in combat. If the unit does not have enough shells when +firing, damage will be reduced proportionately. If a unit does not have +enough shells in combat, it will be out of supply, and have its combat +strength cut in half. (See info \*Qsupply\*U and info \*Qattack\*U for +information on supply and how it affects combat. +.s1 +Aaf is the unit's anti-aircraft fire value. The higher the value, the more +damage the unit will do to planes flying overhead. +.s1 +Fc/fu are the unit's fuel capacity and use. If the fc/fu are 0, the unit +does not need fuel to gain mobility. If the fc/fu are non-zero, the unit +will need fuel to gain mobility, and will use fu fuel whenever it fights. +(See info \*Qfuel\*U for information on fuel) +.s1 +Xpl is the number of extra-light planes the unit can carry. Planes can +operate from a land unit in the same fashion as if it were a carrier. +Normally, extra-light planes are SAMs, so units can carry SAMs for +air-defense. This particular unit can't carry any. +.s1 +.L "Land unit capabilities" +.s1 +There are many different capabilities that land units may have. They may +be seen with the show command: +.s1 +.EX show land capability +.s1 +.NF + capabilities +infantry 5f light assault +.FI +.s1 +The command shows the cargos the unit can carry (5 food in this case), and its +abilities. See info \*QUnit-types\*U for a complete description of the +various capabilities. +.s1 +.L Moving +.s1 +Land units move with the \*Qmarch\*U command, which is pretty identical to the +navigate command. Marching units can run into land-mines, be interdicted, etc. +See info \*Qmarch\*U for more info. See info \*Qmission\*U for information on +interdiction. +.s1 +.L "Units & ships" +.s1 +Each type of ship is rated on the number of land units it can carry. +Land units that are 'light' can be loaded onto ships using the normal \*Qload\*U +command (see info load). Units that also have the 'assault' ability (see info +\*Qshow\*U and info \*QUnit-types\*U for explanations of abilities) can be +used in assaulting sectors. (See info \*Qassault\*U). +.s1 +.L Supply +.s1 +Units need supplies in order to attack. Each update, and each time they +attack, units will attempt to draw supplies. See info \*Qsupply\*U. +Really, I'm serious. If you don't read info supply, you'll die a horrible +death. I'm not kidding. +.s1 +.L Fortification +.s1 +Land units are able to \*Qfortify\*U themselves to better resist damage. Each +point of mobility spent increases the fortification level by 1, up to a maximum +equal to the maximum mobility of a land unit. A fully fortified unit takes one +half the normal amount of damage. Fortification is lost when the unit moves or +retreats. (Note that a reacting defending unit \*Qcan\*U have a fortification +value. This is an abstraction) Read info \*Qfortify\*U for more details. +.s1 +.L Looking +.s1 +Land units can use \*Qllookout\*U to look around. This command is analogous to the +look command used by ships. When llooking, land units have a chance to spot +other land units and also planes. Recon units tend to have better spy values, +and so are better at this. +(See info \*Qshow\*U and info \*QUnit-types\*U to +find out more about recon units). +.s1 +.L Radar +.s1 +Some units can use the \*Qlradar\*U command. This command works like the +radar command. Radar range is determined by the unit's spy value. +(See info \*Qshow\*U and info \*QUnit-types\*U to +find out more about radar units). +.s1 +.L Engineers +.s1 +Some land units have the 'engineering' ability. These units can do several +things. Engineers are the only units that can lay land-mines, and the only units +that can sweep them when moving (like a minesweeper). Attacking engineers +also halve the defender's mine bonus. Engineers can also use the \*Qwork\*U +command, which allows them to raise sector efficiency. (See info \*Qwork\*U) +They also tend to be quite expensive. +.s1 +.L "Attacking & defending" +.s1 +Info \*Qattack\*U has a complete treatment of this, but I will summarize here. +When you decide to attack a sector, you can use mil and units from adjacent +sectors. The attack value of your forces is the combined attack values of all +attacking land units, plus the number of mil coming in from adjacent sectors. +.s1 +The defense value is equal to the mil in the defending sector, plus +the defense values of any defending units in the sector, as well as any that +react and move there. +.s1 +Friendly ships/forts/artillery units/planes can contribute +\*Qsupport\*U. Support starts at 1.0. Each friendly ship/fort/artillery unit/ +plane that can help adds its damage/100 to the support. For example, if you +were attacking a sector, and a friendly battleship was close enough to fire +there, it could support you. If it would normally do 23% damage when firing, +it would add +.23 support, making your support number 1.23. The enemy also +gets support from all his stuff. +.s1 +When all support is totaled, the attacker strength is multiplied by +the attacker's support to get the total attacker strength. The defender's +total strength is determined similarly. Both sides have their strength modified +by the terrain. (show sector stats will show the defensive value of a sector) +He can also get support +by having mine-fields in the sector (see info \*Qlmine\*U and info +\*Qattack\*U for more information). Planes support only if assigned to a +support mission. See info \*Qmission\*U for information on support missions. +.s1 +Combat is done fairly normally, with a series of rolls for attacker/ +defender casualties, until one side is dead or retreats. Land units take damage +after all mil on their side are dead, and each 'hit' on a land unit does 1 mil +damage. (Therefore, a unit that takes 100 mil to build would take 1% damage +when it suffers a casualty. A unit that takes 50 mil would take 2%, etc) +When a land unit's level of damage taken in a battle reaches it's 'retreat +level', it must begin taking morale checks. When it fails one, it will retreat. +Retreating attacking units go back to the sector they came from. Defending +units will attempt to retreat to an adjacent owned sector. If there are none, +the unit will take extra damage and continue fighting. +.s1 +If the attacker wins, he captures the sector, and his mil/units will +move into the sector if he ordered that. If the defender wins a combat, +his units in the sector stay there. His reacting defending units that did not +fail a morale check return to their starting point. Defending units who +started in the sector stay in the sector. +.s1 +In both cases, retreated units end up in the sector they retreated to. +.s1 +.L "Units and retreating" +.s1 +Ships can use the \*Qretreat\*U command to specify when and how they will +run away from trouble. Land units use a similar command \*Qlretreat\*U to +do the same thing. See info \*Qlretreat\*U for more details. +.s1 +.SA "Unit-types, show, supply, LandUnits" diff --git a/info/Concepts/Maintenance.t b/info/Concepts/Maintenance.t new file mode 100644 index 00000000..5e63d1af --- /dev/null +++ b/info/Concepts/Maintenance.t @@ -0,0 +1,31 @@ +.TH Concept "Maintenance" +.NA Maintenance "The cost to maintain ships, planes, and land units." +.LV Expert +During each update, nations must pay to maintain their units, ships and planes. +.s1 +The cost to maintain a ship, or land-unit is: +.NF +8 + .001 * cost of thing * ETUs/update +.FI +.s1 +The cost to maintain a plane is: +.NF +8 + .001 * cost of thing * ETUs/update + 5 * mil_cost * crew +.FI +.s1 +Note that this cost can be changed by the deity. +.s1 +Also note that if you have purchased high-tech items, and your tech +is not at least 85% of the item's tech, you are charged double +to maintain the item. +.s1 +Also note that engineering land units costs 3 times what +normal units cost, after the tech is figured in. +.s1 +If you can not afford to pay maintenance costs or you choose not to +pay them (see info budget) then your unit will lose ETU/5 points of +efficiency. Thus, if you were playing in a 60 ETU game, and you did +not pay your maintenance costs for a 50% frigate, then the frigate +would drop to 38% efficiency. +.s1 +.SA "Unit-types, Ship-types, Plane-types, Ships, LandUnits, Planes, Update" diff --git a/info/Concepts/MakeSrcs b/info/Concepts/MakeSrcs new file mode 100644 index 00000000..8573cca4 --- /dev/null +++ b/info/Concepts/MakeSrcs @@ -0,0 +1 @@ +INFOSRCS=Attack.t Autofeed.t Autonav.t BTU.t Bridges.t Citizens.t Damage.t Education.t Fallout.t Flak.t Food.t Guerrilla.t Happiness.t Hitchance.t Infrastructure.t Innards.t Interception.t Land-units.t Maintenance.t Mobility.t Move.t Nuke-types.t Plague.t Plane-types.t Products.t Quick-ref.t Research.t Sector-ownership.t Sector-types.t Selector.t Ship-types.t Spies.t Syntax.t Taxes.t Technology.t Time.t Trade-ships.t Unit-types.t Update-sequence.t diff --git a/info/Concepts/Makefile b/info/Concepts/Makefile new file mode 100644 index 00000000..d2224a61 --- /dev/null +++ b/info/Concepts/Makefile @@ -0,0 +1,62 @@ +# +# Empire - A multi-player, client/server Internet based war game. +# Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, +# Ken Stevens, Steve McClure +# +# 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 2 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, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# --- +# +# See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the +# related information and legal notices. It is expected that any future +# projects/authors will amend these files as needed. +# +SRCDIR = ../.. +NROFF = nroff +TROFF = troff + +INFOSRCS = empty + +INFOOBJS = $(INFOSRCS:.t=) + +HTMLOBJS = $(INFOSRCS:.t=.) + +include MakeSrcs + +.SUFFIXES: .t + +all: + @echo INFOSRCS=`echo *.t` > MakeSrcs + @make nroffs + @echo Done. + +html: + @echo INFOSRCS=`echo *.t` > MakeSrcs + @make htmlfiles + @echo Done. + +htmlfiles: $(HTMLOBJS) + +nroffs: $(INFOOBJS) + +$(INFOOBJS): + @$(NROFF) $(SRCDIR)/info/CRT.MAC $@.t | awk -f $(SRCDIR)/info/Blank.awk > $(SRCDIR)/info.nr/$@ + @echo Created $(SRCDIR)/info.nr/$@ + +$(HTMLOBJS): + @perl $(SRCDIR)/info/emp2html.pl $@t > $(SRCDIR)/info.html/$@html + @echo Created $(SRCDIR)/info.html/$@html + + diff --git a/info/Concepts/Mobility.t b/info/Concepts/Mobility.t new file mode 100644 index 00000000..8ace4f23 --- /dev/null +++ b/info/Concepts/Mobility.t @@ -0,0 +1,230 @@ +.TH Concept Mobility +.NA Mobility "How much mobility stuff costs" +.LV Expert +.nf + +Mobility represents the amount of time and energy it takes to do +something. In "Real Life" a ground offensive takes hours. In Empire, +it takes less than a second. Now the way Empire *could* work would be +for you to give your troops "orders" and then wait a "realistic" +amount of time for them to carry these orders out. But who wants to +type "nav 15 yh" and then wait 30 minutes for the ship to get there? +Certainly not you! That's why mobility was invented. Every update, +all of your units and sectors get more mobility, and that means that +enough time has passed for you to be able to do more stuff! + +In Empire, four things have mobility: sectors, ships, planes, and land +units. You can see how much mobility each of these gets every update +in the output of the "version" command: + Sectors Ships Planes Units +Maximum mobility 127 127 127 127 +Max mob gain per update 60 120 90 90 + +If the mobility cost for something is a fraction, for example 2.4, +then there will be a percentage chance that the actual cost is rounded +up or down. In our example, there would be a 60% chance that 2.4 is +rounded down to 2 and a 40% chance that it is rounded up to 3. + +-- Land Units -- +Land units are charged mobility for the following actions: + +1. Fighting +See "info Attack" for the mobility cost to attack. + +2. Fighting rebels +For each 2 points of efficiency a land unit looses fighting rebels at +the update, it looses one point of mobility. + +3. Fortification +To fortify ("dig in") a land unit costs one point of mobility per +point of fortification. + +4. Converting civs +Security units are charged 10 mobility every time civs are converted +in a sector they are in. + +5. Laying mines +A land unit is charged one point of mobility for every land mine laid. + +6. Work +The increase in efficiency depends on mobility used. It costs a 100% +efficient land unit 6 mobility to raise a sector 1% efficiency. Less +efficient land units are charged proportionally higher amounts of +mobility. For example, a 50% land unit would be charged 12 mobility +to raise the efficiency of a sector by 1%. + +7. Supply +When supply is drawn from a supply unit, that unit pays the mobility +cost to move the goods to the destination sector. That cost is the +same as it would cost the sector to move the goods using the "move" +command. + +8. Marching, reacting or retreating +The mobility cost for a land unit to march, react or retreat is: + (path cost) * 5 * 480 / (unit speed) +See "Path Cost" below for the path cost formula. Note that reactung +land units only pay mobility to move "to" the attacked sector; they +return to their start sector for free. Land units on "reserve" +mission only pay half the mobility cost to react. + +Note that the efficiency of a land unit does not affect the mobility +costs it pays to march, unless the unit is a supply unit. Then the +mobility costs are proportional to the efficiency of the unit. + +9. Shell damage +When a land unit is shelled, its mobility goes down in exactly the +same way that its efficiency goes down (see "info Damage"). + + +-- Planes -- +Plane mobility can never go below -32. Planes are charged mobility +for the following: + +1. Air combat +For every two points of damage the plane takes from air combat, the +plane looses one point of mobility. + +2. Launching satellites +A satellite is charged one point of mobility for each sector it passes +over in its launch trajectory. + +3. Flying +The mobility cost for a plane to fly is: + 5 + (flight cost) * (distance flown) / (max distance plane can fly) + +For excorts and interceptors, the flight cost is: + 10 / (plane efficiency) +For all other flights, the flight cost is: + 20 / (plane effciiency) +For planes flying on an air defense mission, this cost is cut in half. + +4. Land mine, pinbombing, a-sat, and nuclear damage +A land mine, pinpoint bomb, anti-sat missile or nuclear detonation +will damage the mobility of the plane in exactly the same way that the +efficiency of the plane is damaged (see "info Damage"). + + +-- Ships -- +Ships are charged mobility for the following: + +1. Firing a shell +The mobility cost to fire a shell is 15, unless the NOMOBCOST option +is enabled in which case ships are charged nothing. + +2. Firing a torpedo +The cost for a ship to fire a torpedo is one half of the cost for it +to move one sector. + +3. Boarding a ship from a ship +See "info Attack" for the mobility cost to board a ship from a ship. + +4. Navigating and retreating +The mobility cost for a ship to navigate or retreat is: + (sectors travelled) * 480 / (ship speed) +where + ship speed = (base speed) * (1 + (tech factor)) + base speed = max(0.01, efficiency * speed) + tech factor = (50 + tech) / (200 + tech) + +5. Shell damage +When a ship is shelled, its mobility goes down in exactly the same way +that its efficiency goes down (see "info Damage"). + + +-- Sectors -- +Sectors are charged mobility for the following actions: + +1. Converting civs +Each civ converted costs 0.2 mobility. + +2. Shooting civs & uws +The mobility cost to shoot civs or uws is + (number shot + 4) / 5 + +3. Enlisting mil +The mobility cost for enlisting mil depends on what fraction of the +civs present you are enlisting: + (new mobility) = (old mobility) * (1 - newmil / (starv civs)) + +4. Fighting +See "info Attack" for the mobility cost of attacking. + +5. Moving commodities +Sectors move commodities in the "move" and "explore" commands, when +"supply" is drawn from them, and when they "deliver" and "distribute" +at the update. + +Mobility is used from the source sector when moving. Mobility used is +a factor of the commodity involved, the amount of the commodity, the +types of the sector and dist sector, the efficiency of both, and the +cost of the path to the destination sector. When the move is +finished, move reports the total mobility used, and the amount of +mobility left in the sector. + +The exact formula is: + mob cost = (amount) * (weight) * (path cost) / (source packing bonus) + +If the movement happened at the update, then the cost is: + delivery cost = (mob cost) / 4 + distribute cost = (mob cost) / (10 * (destination packing bonus)) + +Weight +Each commodity has a weight: + bar 50 + gun 10 + rad 8 + dust 5 + uw 2 + other 1 + +Packing Bonus +Some sectors are better at moving certain commodities than +others. This ability is known as their packing bonus. These sectors +only get these bonuses for moving items "from" them--not for moving +items "to" them. If the sector is less than 60% efficient, it doesn't +get its packing bonus. Here are the packing bonuses: + warehouse/harbor bank other + mil 1 1 1 + uw 2 1 1 + civ 10 10 10 + bar 5 4 1 +other 10 1 1 + +Path Cost +The path cost is the cumulative mobility cost of moving through each +sector in the path. The cost to enter a sector is based on the +sector's type and efficiency. All sectors cost 0.4 to move into when +they have a 0% road factor, except for mountains which cost 5.0 at 0%. +The mobility cost to move into a sector goes down linearly as the +road efficiency increases. This represents the construction of roads. + +You can also build railways to make the moving of trains faster. When +marching trains about, the rail factor is used. Otherwise, the road +factor is used. + +See "info improve" for more information on improving the efficiency +ratings of your sectors, and see "info sinfrastructure" for information +on showing the infrastructure of your sectors. + +See "info Infrastructure" for more general information on Infrastructure. + +Update mobility bonus +Commodities get moved at the update through delivery and distribution. +All goods moved this way get their mob cost divided by 4 for deliver, +and 10 for distribute. Furthermore, commodities distributed into a +harbor or warehouse get the warehouse packing bonus (normally, packing +bonuses only apply for the type of the source sector and not the type +of the destination sector). These two bonuses represent the fact that +moving goods through an established distribution network is more +efficient. + +6. Transporting planes or nukes +The weight of a plane is lcm + 2*hcm. The weight of a nuke is the +number of "lbs" it has (from "show nuke stats"). + +7. Shell damage +When a sector is shelled, its mobility goes down in exactly the same +way that efficiency goes down (see "info Damage"). + +.fi +.SA "Sectors, Ships, LandUnits, Planes, Moving" diff --git a/info/Concepts/Move.t b/info/Concepts/Move.t new file mode 100644 index 00000000..24f05b27 --- /dev/null +++ b/info/Concepts/Move.t @@ -0,0 +1,36 @@ +.TH Concept "Moving Things About" +.NA Move "A quick reference for moving things around" +.LV Basic +.s1 +Most of Empire consists of you moving something from one place to +another. The following table tells you which commands you use +to move the kind of thing that you want to move. +.s1 +.NF +What From To Command +---------------------------------------------------- +comm sector sector move +comm/land/plane sector ship load +comm/plane sector unit lload +comm/land/plane ship sector unload +comm/land ship ship tend +comm ship unit ltend +comm/plane unit sector lunload +unit sector sector march +ship sector sector navi +plane sector sector trans +nuke sector sector trans +nuke sector plane arm +nuke plane sector disarm +.FI +.s1 +Note that in the case of load, lload, unload, tend, and lunload, the +way you specify whether you are moving a commodity, land unit or plane +is by using the word "land" or "plane" instead of the commodity name +in the field. If is "land" or "plane", then is +the unit or plane id. So for example, to load ship #1 with land unit +#2, you would type: +.EX "load land 1 2" +.s1 +.SA "Mobility, Moving" + diff --git a/info/Concepts/Nuke-types.t b/info/Concepts/Nuke-types.t new file mode 100644 index 00000000..20d970d3 --- /dev/null +++ b/info/Concepts/Nuke-types.t @@ -0,0 +1,79 @@ +.TH Concept "Nuke Types" +.NA Nuke-types "Description of different kinds of nuclear weapons" +.LV Expert +There are two different types of nuclear devices in Empire: +fission bombs, fusion bombs. +Both fission and fusion bombs perform similarly, +with fusion bombs giving \*Qmore bang for the buck\*U. +.s1 +In general, the only way to avoid damage by a nuclear detonation +is to avoid the area prior to and during actual detonation. +\*QHardening\*U missiles (in silos) is the only exception, +and even that cannot protect from a direct hit +by the larger nuclear devices. +.s1 +The details of the nuclear devices present in Empire can be seen using +the show command. +The meaning of the fields are as follows: +.s1 +.in \w'name\0\0'u +.L name +The nukes name. +.L lcm +The amount of lcm needed to build the nuke +.L hcm +The amount of hcm needed to build the nuke +.L oil +The amount of crude oil required to build it. +.L rad +The number of radioactive products required to build it. +.L tech +The minimum tech level required to construct the nuke. +.L $ +The cost of the nuke to construct. +.s1 +.in +The other fields given in the capabilities are as follows. +.s1 +.in \w'blst\0\0'u +.L blst +The blast type of the nuke +.L dam +The damage rating of the nuke +.L lbs +the weight of the warhead, limiting missile and plane nuclear +device carrying capacity. +.in +.s1 +As a guide (these numbers are subject to change): +.EX show nuke build +.NF + lcm hcm oil rad tech $ +10kt fission 50 50 25 50 200 $7500 +50kt fission 60 60 30 75 225 $9000 +100kt fission 75 75 40 100 250 $12000 +250kt fusion 50 50 25 50 280 $7500 +500kt fusion 60 60 30 75 295 $9000 +1mt fusion 75 75 50 100 310 $12000 +3mt fusion 100 100 75 127 325 $19000 +.FI +.s1 +.EX show nuke capab +.NF + blst dam lbs tech $ +10kt fission 3 80 4 200 $7500 +50kt fission 3 100 6 225 $9000 +100kt fission 4 120 8 250 $12000 +250kt fusion 4 150 4 280 $7500 +500kt fusion 5 170 6 295 $9000 +1mt fusion 6 190 8 310 $12000 +3mt fusion 7 210 10 325 $19000 +.FI +.s1 +The larger the megatonnage, the more damage done by the weapon. +Effects (as in the real world) can only be determined +by experimentation, +although research suggests that radioactivity left behind by nuclear +detonations may have lasting effects. +.s1 +.SA "launch, fly, build, transport, show, Planes" diff --git a/info/Concepts/Plague.t b/info/Concepts/Plague.t new file mode 100644 index 00000000..88211a62 --- /dev/null +++ b/info/Concepts/Plague.t @@ -0,0 +1,113 @@ +.TH Concept Plague +.NA Plague "The Plague" +.LV Expert +.s1 +Plague is used in Empire to symbolize all forms of disease and is +the only health hazard associated with the Empire game, +(ignoring it's effects on the players). +The characteristics of plague are, therefore, +a compromise of disease features (or \*Qbugs\*U). +.s1 +Note that if the NO_PLAGUE option is in use, a kindly deity +has wiped out the plague for you. If not, worry about it. +.s1 +All of the timelines below are based on a game with 32 ETU updates. +.s1 +The Empire Plague takes between 96 and 189 time units to +run its course on land, +(i.e., 2 to 4 days in any particular sector/ship/land unit +if an Empire time unit is 1/2 and hour.) +In so doing the plague goes through three stages: +.s1 +.in +3 +.ti -3 +Stage I -- The gestation or incubation phase +in which no symptoms appear. +Sectors or ships that are in this stage of the plague +are indistinguishable from healthy sectors or ships. +This stage lasts 32 to 63 time units, +(less than a day and a half). +.s1 +.ti -3 +Stage II -- The infectious phase in which the symptoms first appear -- +orange blotches on the face and hands, +sometimes accompanied by grey stripes on the genitalia, +itching of the liver and spleen, +an uncontrollable fear of ripe tomatoes, etc. +During this phase the plague is extremely communicable; +for example, a simple delivery from an infectious sector +will infect the destination sector. +.s1 +.ti -3 +Stage III -- The terminal phase in which people die, +often in the act of fleeing from (real or imagined) tomatoes. +The number of people that die is roughly inversely proportional +to the research level of the country (plus 100). +.in -3 +.s1 +All three phases are of roughly equal average duration, +(about 48 time periods or 1 day). +.s1 +Plague usually arises in countries with high technological development +and comparatively little medical research. +It arises specifically in sectors with high population density +and low efficiency. +.s1 +Recently archaeologists have uncovered a treatise +by a Dr.\ M.\ Welby entitled +\*QDemographic considerations and the Empire Plague\*U. +In part it states: +.s1 +.in +0.8i +.ev 2 +.ll 5.5i +It appeared that our original hypothesis +based on the high percentage of Lumbagan Legionnaires +among the afflicted had led us down a blind alley +and that if we were to solve this complex puzzle +before the end of the series in the spring +\*[possibly a reference to the series of tests +leading to the mysterious \*QNeilson Rating\*U\*] +we would have to turn to other disciplines for help. +It was only by the merest lucky coincidence +that as I drove home one evening ... +\*[here Dr. Welby relates an amusing anecdote +about a Brownie Scout and the director of a film +entitled \*QClose Encounters of the Third Grade\*U\*] ... +leading us to the following amazing formulation +of the relationship between medical research, +technology, population, standard of living and the Empire Plague: +.ll 6.5i +.ev +.in +.s1 +.NF +0.4i +likelihood civ + mil + uw t_level + (iron + oil + rad * 2) / 10 + 100 + of = -------------- * ------------------------------------------- + plague 999 r_level + effic + mobil + 100 +.FI +.s1 +Later formulations of this relationship show great similarity +to his statement (see \*Qinfo Innards\*U). +.s1 +Many researchers have commented on the surprising lack of correlation +between food supply and plague outbreak. +.s1 +Fortunately, the plague is only infectious while the sector is +actively battling the plague (Stage II). The most effective method +for curing plague has been to isolate the sector by stopping all +distribution, deliveries, movement, etc. originating from the sector +once an outbreak has been spotted. +.s1 +This includes loading and unloading of ships and land units (since +they can, of course, carry plague), allowing explorations out of the +sector, moving commodities out of the sector, distribution or +deliveries from the sector, etc. Basically, any people or commodities +that originate from a sector actively battling plague will cause the +destination sector (or ship or land unit) to become infected. +.s1 +Once an outbreak has been spotted, the plague takes on an infectious +state at the next update. There is very little time to isolate the +sector and limit deaths caused by plague. +.s1 +.SA "Innards, Research, Sector-types, Technology, Populace, Update" diff --git a/info/Concepts/Plane-types.t b/info/Concepts/Plane-types.t new file mode 100644 index 00000000..5a8cfdd8 --- /dev/null +++ b/info/Concepts/Plane-types.t @@ -0,0 +1,309 @@ +.TH Concept "Plane Types" +.NA Plane-types "Description of different kinds of planes" +.LV Basic +The general plane types currently available in Empire are: +.s1 +.NF +fighter A general offense/defense plane. Historical examples include + the FE.2B, the Sopwith Snipe & Camel, the Nieuport V-XVII, the + Spad, and the Fokker planes. From WWII are the Me-109, the + FW-190, the English Spitfire & Hurricane, the Japanese Zero, + the American P-39, P-40, P-38, and the Soviet Yak series. + Later planes include the Me-262, the Gloster Meteor, P-80, + Mig-15. Korean War vintage planes are the F-87 Sabre, F-100 + SuperSabre, and the Mig-17. Vietnam Era planes are the F-4 & + Mig-21. Later, NATO & WP models include the F-16 & F-15 and the + Mig-23, 25, and 29. + + The main points of similarity are: 1 or 2 high performance + engines, a single pilot, and plenty of guns/missiles. Duties + include patrol/interception, escort, and light bombing. + +escort These are planes optimized for escorting, with superior range, + sometimes at the expense of fighting capacity. Examples are + the Me-110 & the P-51. Note that this type is relatively rare, + as long range heavy bombing was rare. + +naval +fighter These planes all sacrifice range and/or fighting power in order + to fit on a carrier and carry the gear necessary to operate + from one. Examples are the series of Short biplanes built in + Britain, the Sopwith Baby & Cuckoo, the Gloster Gladiator, the + American Wildcat & Corsair, versions of the Japanese Zero, the + F8 Corsair, the F-4, F-14, and F-18. Many of the planes were + multi-role, due to the relatively small plane capacity of their + carriers. They were almost always inferior in performance to + land fighters. Many of them carry dual engines. + +light +bomber These planes are tactical bombers, suited for strafing, combat + support, etc. These range from the first trench bombers, such as + the Junkers J-I and the Sopwith Snark & Dolphin, the Ju-87 + Stuka, the American P-47, various ground-attack versions of the + Yaks, the Japanese Val and Kate, the British Typhoon, and many + others. Modern versions are the A-3 SkyWarrior, the A-4 + Skyhawk, the A-6 Intruder, the Su-22 Frogfoot, the Su-27, and + various British models. A modern and most effective example is + the A-10 + + The common factors are maneuverability, the ability to take + damage and still fly, and the ability to hit targets precisely. + (Either through low-speed bombing, dive-bombing, or rocket or + guided bombs/missiles) Their performance against fighters of + any sort is poor, with few exceptions (notably the P-47, which + was designed as a fighter, and used as a ground-attack plane + due to its toughness) Many are naval, or have naval versions, + since the requirements of a naval plane do not affect them as + greatly as fighters. + +heavy +bomber These planes are build for long range and great load-carrying + ability, and the ability to defend themselves against fighters. + (Although that never worked more than middling well) Examples + are the Handley-Paige bombers of WWI (especially the O/400), the + German Gothas and Giants, the B-17 Flying Fortress, the B-24 + Liberator, the B-29 SuperFortress, the Avro Lancaster, the Short + Sterling, and the Vickers Wellington, as well as the more modern + B-36, B-47, B-50, B-52, B-1, and the Soviet Ant-4, Tu-20 Bear, + Tu-2? Backfire, and others. + + The common factors are the extreme range, the ability to carry + several tons of bombs, the wide range of defensive armament, and + four engines. + +medium +bombers These were basically an intermediate stage between the light & + heavy bomber, and were used for both purposes. Examples are the + He-111, the Do-17, the B-25 Mitchell, B-26 Marauder, the A-20 + Havoc, the Avro Manchester, Armstrong Whitworth Whitely, the + Russian Il-4 & I-15, and the Japanese Betty & Sally. + + These planes were essentially compromises, and were phased out + as time went on. They could not bomb as precisely as a light + bomber, nor as heavily as a heavy bomber. + +transports + + Initially, these were basically similar to civilian airliners. + They could carry supplies or troops. (In Norway, the Germans + captured airports and flew in troops) Later, they were used for + paratroop landings. Eventually paratrooping became too dangerous + for these planes (with the introduction of SAMs) and they were + replaced by helicopter assault, with the transports going back + to carrying supplies and equipment. + +transport +helicopters + + These were made to transport assault troops. They also carry + supplies & wounded, but their main duty was to deliver troops + with greater precision, rapidity, safety, and cohesion than was + possible with paratrooping. (They were also to replace the + landing craft, as the Marines looked at the odds of an invasion + fleet standing up to nukes) + +attack +helicopters + + These supplement the light bombers, and specialize in the very + precise application of firepower, as well as evading + interception, by use of terrain. + +recon +planes & +satellites + + These provide precise information about enemy troop dispositions + and movements. The first recon planes had no protection. Then, + it was attempted to make them un-interceptable. This was done by + simply being faster than anything the enemy had, such as the + stripped down British Hurricanes, US P-38's & P-51's, or German + FW-190's or Blitz-Bombers. Later, emphasis shifter to also being + able to fly higher, as with the U-2 & SR-71. These planes are + largely superseded by satellites now (for good or ill). + +ssm's +& icbm's + + The first ssm's were used as strategic harassing weapons, and + were almost useless. (German V-1 & V-2) There were also combat + rockets, such as the Russian Katayusha's and the German + Nebelwerfers, but these were essentially similar to artillery. + The first true SSM's were the Russian missiles in the 1950's, + such as the Frog. They were intended to deliver nuclear or + chemical warheads at medium ranges, and to be un-interceptable. + Later missiles increase payload & range. + + However, since we've artificially restricted the blast effects + of nuclear weapons, I am merging these in with tactical + missiles. (no need for an icbm unless you've got big nukes) + +marine +missiles + These are modern smart-missiles. They are naval weapons, such + as the Harpoon, Penguin, Exocet. They are accurate missiles which + may be launched at ships. + +sam's + The first sams were nuclear-tipped, and intended to break up + large attacking bomber forces. Later, they were made smaller + and more accurate, and were intended to hit single targets + at any speed or altitude. + +abm's These are to shoot down missiles, and are mostly fantasy. + +asw +planes These are either long-range bomber type aircraft, with some + sort of equipment for locating & killing submarines, or also + helicopters, able to fly from most naval vessels. +.FI +.s1 +These plane types differ in their fundamental capabilities; +some can fly bombing missions, +other carry cargo, others exist to shoot down other planes. +Missiles are special; +they are planes which fly one-way missions +and cannot be shot down by opposing planes. +.s1 +The technology level at which the plane was built is very important. +The same model plane built at a higher tech level +will outperform the planes built at a lower tech level. +.s1 +The particular planes available and their attributes +are given by the show command. +The fields given in the output are as follows. +For building: +.sp 1 +.in \w'avail\0\0'u +.L lcm +the amount of lcm to build the unit, +.L hcm +the amount of hcm to build the unit, +.L crew +the number of military this plane has as crew +.L avail +the amount of avail used to build this plane +.L tech +minimum tech level to build this unit, +.L $ +cost of the unit in dollars, +.s1 +.in \\n(in +For the stats report the fields are: +.s1 +.in \w'stealth\0\0'u +.L acc +bomb accuracy, low is best; a 0 accuracy implies no ability. +.L load +bomb load/cargo capacity. +.L att +air-to-air combat attack rating (reduced by low eff, can't go below 1/2 of base). +.L def +air-to-air combat defense rating (reduced by low eff, can't go below 1/2 of base). +.L ran +base range (in sectors). +.L fuel +amount of fuel used each trip. +.L stealth +the percentage chance this plane has of evading detection +.in \\n(in +.s1 +The abilities are given as a set of attributes for each plane. +These include: +.s1 +.in \w'intercept\0\0'u +.L tactical +Pinpoint bombing ability. Can be put on interdiction and support +missions. Tactical missiles may be launched at sectors unless they +have "marine" ability in which case they may only be fired at ships. +.L bomber +strategic bombing ability +.L intercept +Interception and escort ability. May be put on escort or air defense missions. +.L cargo +cargo-carrying ability +.L VTOL +vertical take-off ability -- no need to use airports +.L missile +missile -- one shot, can be launched (see info launch). "marine" +missiles may only be fired at ships, "tactical" missiles which don't +have "marine" capability may only be fired at sectors. +.L light +light, can land on carriers or be carried on a submarine +.L spy +spy ability, for recon missions (see info recon, info bomb, info satellite) +.L image +full imaging capability - satellites with this ability show much more +(see info satellite) +.L satellite +a satellite - stays in orbit until shot down +.L stealth +a stealth plane - has a chance of not triggering intercepts +.L SDI +Intercepts tactical missiles. +.L half-stealth +a stealth plane - has a smaller chance of not triggering intercepts +.L x-light +xtra-light, can be carried and used on any ship or land unit with a non-zero +xl capacity. (see info Ship-types) +.L helo +ship-helicopter, can be carried and used on any ship with a non-zero +hl capacity. (see info Ship-types) +.L ASW +Has ASW (anti-submarine warfare) ability. May use sonar & bomb subs. +.L para +may be used to paratroop +.L escort +Escort ability only. May be put on escort missions. +.L mine +Can lay mines (see info mine). +.L sweep +Can sweep mines (see info sweep). +.L marine +Missiles with this ability may only be launched at ships. +.in \\n(in +.s1 +Each plane has a stealth rating. The +stealth rating of a group of planes is that of the plane with the LOWEST +rating. +.sp 1 +As an example of the output +.EX show plane build +.NF + lcm hcm crew avail tech $ +Zeppelin 6 2 3 6 70 $1000 +f1 fighter 1 8 2 1 7 90 $400 +lb1 lt bomber 1 10 3 1 9 100 $550 +nf1 naval fighter 1 8 2 1 7 100 $500 +hb1 hvy bomber 1 20 6 2 17 110 $1100 +as1 anti-sub plane 1 10 3 2 9 110 $550 +f2 fighter 2 9 3 1 8 150 $600 +es escort 9 3 1 8 150 $700 +.FI +.s1 +.EX show plane stats +.NF + acc load att def ran fuel stlth +Zeppelin 60 2 0 -3 15 2 0% +f1 fighter 1 90 1 3 2 7 1 0% +lb1 lt bomber 1 50 2 1 2 7 1 0% +nf1 naval fighter 1 80 1 2 2 7 1 0% +hb1 hvy bomber 1 90 5 1 3 15 2 0% +as1 anti-sub plane 1 85 2 1 2 15 2 0% +f2 fighter 2 60 1 6 4 9 1 0% +es escort 60 1 4 5 15 2 0% +.FI +.s1 +.EX show plane cap +.NF + capabilities +Zeppelin tactical cargo VTOL spy +f1 fighter 1 tactical intercept VTOL +lb1 lt bomber 1 bomber tactical VTOL +nf1 naval fighter 1 tactical intercept light +hb1 hvy bomber 1 bomber +as1 anti-sub plane 1 tactical ASW +f2 fighter 2 tactical intercept +es escort tactical escort +.FI +.SA "fly, build, show, Planes" diff --git a/info/Concepts/Products.t b/info/Concepts/Products.t new file mode 100644 index 00000000..0c7d4d4d --- /dev/null +++ b/info/Concepts/Products.t @@ -0,0 +1,133 @@ +.TH Concept Products +.NA Products "Formulas for the production of commodities" +.LV Basic +.s1 +Many Empire sector types exist specifically +to turn \*Qraw\*U materials into products. +Some of those products may, in turn, +be considered raw materials for other industries +which produce other products. +.s1 +This table gives the constituents and costs for each type of product. +.s1 +NOTE: All costs given in the table are for 100% production efficiency. +Many processes depend on technology level +or educational level of the country; +a note like \*Qp.e.=(tlev+10)/(tlev+20)\*U means +that a country with a technology level of 0 +has a production efficiency of 50% +and will only produce one-half of the specified product amount +for the given costs, +whereas a country with a technology level of 100 +will have a production efficiency of 92%. +.s1 +In addition, some sectors don't produce raw materials as well as others, +and some produce much better than others. Use the "show sector capabilities" +command to see production efficiencies and other useful information on +producing sectors. +.s1 +The rate at which constituents are turned into products +is governed by the \*Qwork\*U accrued to a sector +(see \*Qinfo Innards\*U) divided by the units of constituents +per unit of product. +E.g., it takes 3 units of \*Qwork\*U to produce 1 shell; +2 units to incorporate the light construction materials +and 1 unit for the heavy. +\*QNatural resources\*U such as fertility +count as one unit of constituents; +e.g., it takes 1 unit of work per unit of food produced. +.s1 +.in \w'technology\0\0'u +.L shells +Shell production efficiency depends on technology level; +p.e.=(tlev-20)/(tlev-10) +Shells cost $3 each to manufacture. +Each requires 2 units of light construction materials +and 1 unit of heavy construction materials. +You must have a minimum technology of 20 to produce shells. +.L guns +Gun production depends on technology level; +p.e.=(tlev-20)/(tlev-10) +Guns cost $30 each to manufacture. +Each requires 5 units of light construction materials, +10 units of heavy construction materials, +and 1 unit of oil. +You must have a minimum technology of 20 to produce guns. +.L iron +Iron ore production depends on mineral content in mines. +Extracting iron ore is free, +and the mineral content of the sector is not depleted +by mining iron. +.L dust +Gold dust production depends on gold mineral content in gold mines. +Extracting gold dust is free, +but the gold mineral content of the sector is depleted +by mining gold dust. In addition, mountains may sometimes produce +gold dust as well. The efficiency of mountains producing gold dust +may not be as good as gold mines. Use the "show sector capabilities" +command to see the production efficiency of sectors. +.L bars +Gold bars are produced in banks. +Gold bar production depends on gold dust in gold mines. +Gold bars cost $10 to produce and require 5 units of gold dust each. +.L food +Food production efficiency depends on technology level +and the fertility of the sector; +p.e.=(tlev+10)/(tlev+20). +Growing food is free, +and the fertility of the sector is not depleted by growing food. +.L oil +Oil production efficiency depends on technology level +and the oil content of the sector; +p.e.=(tlev+10)/(tlev+20). +Pumping oil is free, +but the oil content of the sector is depleted +by extracting and refining oil. +.L petroleum +Petroleum production depends on technology level; +p.e.=(tlev-20)/(tlev-10). +A unit of petroleum costs $1 to manufacture. +Every 10 units of petroleum require 1 unit of oil to produce. +You must have a minimum technology of 20 to produce petroleum. +.L lcm +Light construction material production efficiency +depends on technology level; +p.e.=(tlev+10)/(tlev+20). +Producing lcms does not cost money, but requires 1 unit of iron ore. +.L hcm +Heavy construction material production efficiency +depends on technology level; +p.e.=(tlev+10)/(tlev+20). +Producing hcms does not cost money, but requires 2 unit of iron ore. +.L rad +Radioactive material production efficiency depends on technology level, +which must be at least 40. +p.e.=(tlev-40)/(tlev-30). +Producing rads cost $2 per ton, +and depletes the uranium content of the sector. +.L education +A unit of education (a \*Qclass of graduates\*U), +costs $10 to produce and requires 1 unit +of light construction materials (see "info Education"). +.L happiness +A unit of happiness (\*Qhappy strollers\*U), +costs $10 to produce and requires 1 unit +of light construction materials (see "info Happiness"). +.L technology +Technology production efficiency depends on education level; +p.e.=(elev-5)/(elev+5). +A unit of technology (a \*Qtechnological breakthrough\*U), +costs $5 times the number of ETUs per update +to produce, and requires 10 units +of light construction materials, +5 units of oil and 1 unit of gold dust. For more details about how +technology level is calculated from technology units, see "info Technology". +.L research +Research production efficiency depends on education level; +p.e.=(elev-5)/(elev+5). +A unit of research (a \*Qmedical discovery\*U), +costs $90 to produce and requires 10 units +of light construction materials, +5 units of oil and 1 unit of gold dust (see "info Research"). +.in +.SA "Production, Update" diff --git a/info/Concepts/Quick-ref.t b/info/Concepts/Quick-ref.t new file mode 100644 index 00000000..b8e91af0 --- /dev/null +++ b/info/Concepts/Quick-ref.t @@ -0,0 +1,42 @@ +.TH Concept "Quick Reference Card" +.NA Quick-ref "A quick reference card for sector types and production" +.LV Basic +.NF + +Sector-types: + BASICS INDUSTRIES MILITARY / SCIENTIFIC + . sea d defense plant t technical center + ^ mountain i shell industry f fortress + s sanctuary m mine r research lab + / wasteland g gold mine n nuclear plant + - wilderness h harbor l library/school + c capital/city w warehouse e enlistment center + p park u uranium mine ! headquarters + COMMUNICATIONS * airfield + + highway a agribusiness FINANCIAL + ) radar installation o oil field b bank + j light manufacturing + # bridge head k heavy manufacturing + = bridge span % refinery + +(Petrol is per 10 units; others per unit) + +Products: +Item $ Lcm Hcm Iron Dust Oil Rad Tech Production Eff. +Shells: 3 2 1 0 0 0 0 20 (tlev-20)/(tech-10) +Guns: 30 5 10 0 0 1 0 20 (tlev-20)/(tech-10) +Iron: 0 0 0 0 0 0 0 0 0 +Dust: 0 0 0 0 0 0 0 0 0 +Bars: 10 0 0 0 5 0 0 0 0 +Food: 0 0 0 0 0 0 0 0 (tlev+10)/(tlev+20) +Oil: 0 0 0 0 0 0 0 0 (tlev+10)/(tlev+20) +Petrol 1 0 0 0 0 1 0 20 (tlev-20)/(tech-10) +Lcm: 0 0 0 1 0 0 0 0 (tlev+10)/(tlev+20) +Hcm: 0 0 0 2 0 0 0 0 (tlev+10)/(tlev+20) +Rad: 2 0 0 0 0 0 0 40 (tlev-40)/(tlev-30) +Educate: 9 1 0 0 0 0 0 0 0 +Happy: 9 1 0 0 0 0 0 0 0 +Tech: 5*ETUS 10 0 0 1 5 0 0 (edu-5)/(edu+5) +Resrch: 90 10 0 0 1 5 0 0 (edu-5)/(edu+5) +.FI +.SA "Sectors, Production" diff --git a/info/Concepts/Research.t b/info/Concepts/Research.t new file mode 100644 index 00000000..4a117521 --- /dev/null +++ b/info/Concepts/Research.t @@ -0,0 +1,37 @@ +.TH Concept Research +.NA Research "How Research level is calculated each update" +.LV Expert +.sp +.s1 +If the RES_POP option is in use, +the research level of a country determines the maximum number of civilians, +mil, and uw's +that can live in a sector. The maximum then is: +.s1 +.ti 3 +400 + 600 * ((research*4 + 50)/(research*3 + 200)) +.s1 +So, for example, at 0 research, after an update, the max you +could have in a sector would be 550 civs, 550 uws, and 550 mil. +Note that in the case of captured sectors, +the research level of the current owner governs, even if the old +owner of the sector had a higher/lower research. +.s1 +If, after population growth, there are more civs than the limit, the +excess are lost. Uw's & mil work the same way, each being individually +limited. +.s1 +The research level also affects the likelihood of plague outbreaks. +(Unless the NO_PLAGUE option is used, of course) +.s1 +The \*Qnation\*U command will display, +among other things, +your current research level. +.s1 +The procedure determining how much your research level goes up every +update is exactly the same for research as it is for technology +(see "info Technology") except for the fact that "research log base" +is always 2.00 and "easy research" is always 0.75. But besides this, +research bleeds, decays, and leaks in exactly the same way as technology. +.s1 +.SA "Innards, nation, Products, Technology, Nation, Production, Update" diff --git a/info/Concepts/Sector-ownership.t b/info/Concepts/Sector-ownership.t new file mode 100644 index 00000000..d60dbc51 --- /dev/null +++ b/info/Concepts/Sector-ownership.t @@ -0,0 +1,31 @@ +.TH Concept "Sector ownership" +.NA Sector-ownership "Sector ownership" +.LV Basic +.s1 +In order to own a sector, you must have at least one of the following +present in the sector: + +.NF +1) mil +2) a land unit +3) non-captured civilians +.FI + +.s1 +If at any time you do not have at least one of those 3 things in a sector, +you will lose control of it. +If you are not the old owner at the time you lose the sector, +it will revert to the old owner. Otherwise it will +revert to the deity, country #0, even if another country's land units +are present in the sector. +If there are no people at all in the sector, it will revert to the deity. +.s1 +Note that this means that if you attack a sector and do not move in, +you will not gain possession of it. If there are civilians in the sector, +the sector will revert back to the original owner. If there are no civilians +in the sector (and no mil or units, because you just killed them), the sector +will revert back to the deity. +.s1 +Similarly, if you abandon a sector, it'll revert immediately. +.s1 +.SA "attack, Sectors, Occupation" diff --git a/info/Concepts/Sector-types.t b/info/Concepts/Sector-types.t new file mode 100644 index 00000000..75d7b0c3 --- /dev/null +++ b/info/Concepts/Sector-types.t @@ -0,0 +1,397 @@ +.TH Concept "Sector Types" +.NA Sector-types "Description of different sector types" +.LV Basic +.NF +0.2i + BASICS INDUSTRIES MILITARY / SCIENTIFIC + . sea d defense plant t technical center + ^ mountain i shell industry f fortress + s sanctuary m mine r research lab + \ wasteland g gold mine n nuclear plant + - wilderness h harbor l library/school + ~ plains w warehouse e enlistment center + c capital/city u uranium mine ! headquarters + p park * airfield + COMMUNICATIONS a agribusiness FINANCIAL + + highway o oil field b bank + ) radar installation j light manufacturing + # bridge head k heavy manufacturing + = bridge span % refinery + @ bridge tower +.FI +.s1 +.s1 +.ce +BASICS +.s1 +SEA - Sea sectors form natural barriers that can +only be crossed by ships, (made in harbors, below), +or spanned by bridges, (also below). +You can not designate anything else to be sea +nor can sea be designated to be anything else. +.s1 +MOUNTAIN - Mountain sectors form another natural +barrier that cannot be redesignated; however, they can be +moved through (at great expense in terms of mobility units). +In an emergency, they can be used as capital. See \*Qinfo capital\*U +for more information. In addition, mountains can only hold a maximum +of 1/10th the civilians and uncompensated workers that other sectors +can normally have. And military, civilians and uncompensated workers that +will actually produce anything there are also limited to 1/10th. +.s1 +SANCTUARY - Sanctuary sectors are created when +a new nation is created. +They are inviolate in that no one can fire at them or attack them. +This protection ends +when the new country first moves out of the sanctuary +(called \*Qbreaking sanctuary\*U); the sector then becomes a capital. +NOTE: in games with multiple sanctuaries per country ALL sanctuaries +become capitals when any one does! +.s1 +WASTELAND - This is the result of the explosion of a nuclear device. +Wastelands are uninhabitable forever. +.s1 +WILDERNESS - Most of the world is wilderness +at the beginning of the game. +Wilderness has no particular attributes; +you can move into it if unoccupied, thereby +making it your territory, but will probably want to +designate it as something else once you own it. +.s1 +PLAINS - Plains sectors form another natural barrier that cannot +be redesignated. They can be occupied and moved through however. +In addition, plains can only hold a maximum of 1/20th the civilians +and uncompensated workers that other sectors can normally have. +And military, civilians and uncompensated workers that +will actually produce anything there are also limited to 1/20th. +.s1 +CAPITAL - Capitals are the source of bureaucracy time units (BTU's). +They accrue in proportion to the efficiency +of the capital and the number of civilians at work in it. +(see info BTU). +Most commands use up BTU's, +(see \*Qlist of commands\*U for numbers of BTU's used per command). +A nation may only have one active capital at a time +(although many sectors may be designated as capitals). +The capture of a capital will result in the loss of money from +the victim nation (see info capital), +Capitals are twice as efficient at defending +against attack as other sectors (except fortresses). +Use the capital command to make a capital the active one. +In a pinch, mountains can be used as capitals. They generate +very few BTU's, and represent being 'holed up in the mountains', +perhaps like Pancho Villa. Note that if the BIG_CITY option is +enabled, then 'c' sectors stand for 'cities' and can hold 10x as many +civs. They also get a 10x packing bonus for moving civs, and require +a certain number of lcm's, hcm's, and $$ to build (see show sect build). +.s1 +PARK - Parks are provided solely for the convenience of the +people. +Parks require construction materials to provide maintenance +services and +add to a nation's \*Qhappiness\*U level. +The conversion of \*Qraw\*U materials takes place automatically +at a rate dependent on the efficiency of the sector, +the presence of the required materials, +and the number of workers in the sector. +.s1 +.s1 +.ce +COMMUNICATIONS +.s1 +HIGHWAY - Whenever you move civilians, ore, gold, +etc, mobility units (\*Qmob\*U on the census) are consumed dependent +on how far and how much you move. +However if the movement is through 100% efficient highway +it costs much less to move. +.s1 +RADAR - Radar stations can scan the surrounding +area (up to 16 units away for 100% efficiency) and generate +a radar plot identifying sector types at distances up to 1/3 +their range and ships up to their full range. +.s1 +BRIDGE HEAD - Bridge heads are the land based ends of bridges. +They, like harbors, turn construction materials into +bridge spans; see \*Qinfo build\*U for the details of this process. +and are much like highways except for three things: +.br +(1) Bridge spans provide food through fishing, +(the fertility can be thought of as fish-count). +(This is deity-settable, however.. in many games, bridges do not +provide food. Be sure to ask) +.br +(2) Bridge spans must maintain at least 20% efficiency or else they +collapse. +.br +(3) If the only bridge head supporting a particular bridge span is +redesignated as something else the bridge span will collapse. +(If the EASY_BRIDGES option is in use, bridges do not need bridgeheads. +Check \*Qinfo build\*U for the details) +.s1 +BRIDGE TOWER - Bridge towers are like bridge heads you can build +out in the ocean. You can only build bridge towers from a bridge +span, and in open water (not adjacent to any land or other bridge +towers.) From a bridge tower, you can build other bridge spans. +The BRIDGETOWERS option must be enabled for you to be able to +build bridge towers. +.br +Bridge towers must maintain at least 20% efficiency or else they +collapse. Any bridges connected to the tower will collapse as +well, unless held up by another adjacent structure (bridge head, +bridge tower or land if EASY_BRIDGES is enabled.) +.s1 +.s1 +.ce +FINANCIAL +.s1 +BANK - Banks are used for smelting and storing gold bars. +They include a smelter to refine gold dust into gold bars. +While the bars are stored in the bank the busy little bankers +invest them and return a profit on their use. +Banks are of the Fort Knox variety; they are more impervious to shelling +than any other sector and militia in them fight twice as hard +against attack as those in industries. +Banks are also particularly adept at moving gold bars around; +bars are moved and stored in groups of four thus fewer mobility units +are required to move a gold bar from a bank than anywhere else. +.s1 +.ce +INDUSTRIES +.s1 +DEFENSE - In defense plants construction materials are turned into guns. +The conversion of \*Qraw\*U materials into guns +takes place automatically at a rate dependent on +the efficiency of the sector, +the presence of the required materials, +the technology level of the country, +and the number of workers in the sector. +See \*Qinfo Products\*U for information on the materials required to +produce guns. +.s1 +SHELL INDUSTRY - These sectors are similar to defense +plant sectors except they turn construction materials into +shells. +The conversion of \*Qraw\*U materials takes place automatically +at a rate dependent on the efficiency of the sector, +the presence of the required materials, +the technology level of the country, +and the number of workers in the sector. +See \*Qinfo Products\*U for information on the materials required. +One shell is used each time you fire, +(except for submarines which use three shells to make one torpedo). +.s1 +MINE - Mines produce iron ore by digging it out of the ground. +The rate at which it is produced is dependent on three factors; +the efficiency of the mine, +the number of civilians working in the mine, +and the mineral sample for the sector (\*Qmin\*U on the census report). +Iron is a \*Qrenewable\*U resource; i.e. digging up iron does not +deplete the mineral content of the sector. +.s1 +GOLD MINE - Gold mines are similar to ordinary +mines, (above), except that they produce gold dust. +The rate at which it is extracted is dependent on three factors; +the efficiency of the sector, +the size of the labor force in the sector, +and the gold sample for the sector (\*Qgmin\*U on the census report). +The raw gold dust can be transported to any sector but if it is left +in a bank sector it will be refined into bars automatically . +Gold is a non-renewable resource; i.e. extracting the gold depletes +the gold content of the sector. +.s1 +URANIUM MINE - Uranium mines are very similar to gold +mines, (above), except that they produce radioactive materials. +The rate at which it is extracted is dependent on three factors; +the efficiency of the sector, +the size of the labor force in the sector, +and the uranium content of the sector +(\*Quran\*U on the census report). +Uranium is a non-renewable resource; i.e. extracting it depletes +the content of the sector. +.s1 +HARBOR - Harbors combine shipyard facilities and docks. +Construction materials are converted into ships +and the ships can be loaded and unloaded in the harbor, +(see \*Qinfo load\*U). +No ships are constructed until the \*Qbuild\*U command is given, +(see \*Qinfo build\*U). +.s1 +WAREHOUSE - Warehouses are used to store shells, +guns, iron, gold dust, food, oil, light construction materials, and +heavy construction materials. Moving the above out of a +warehouse only takes one tenth the mobility cost it normally would. +Note: warehouses are often used as distribution centers. +.s1 +AIRFIELD - Airplanes can only be built in airports and most can +only take off and land at airports. (though some can take off +and land in other sectors and some can take of and land on +aircraft carriers see Ship-types for details) +.s1 +AGRIBUSINESS - These sectors are large farms and provide food. +Agribusiness sectors produce as much as five times as much food +as other sectors. +The harvesting takes place automatically +at a rate dependent on the efficiency of the sector, +the fertility of the sector (\*Qfert\*U in the census), +the technology level of the country, +and the number of workers in the sector. +See \*Qinfo Products\*U for details. +.s1 +OIL - Oil fields produce oil by sucking it out of the ground. +The extraction of oil takes place automatically +at a rate dependent on the efficiency of the sector, +the oil content of the sector (\*Qoil\*U on the census report), +the technology level of the country, +and the number of workers in the sector. +Oil is a \*Qnon-renewable\*U resource; i.e. extracting oil +depletes the oil content of the sector. +.s1 +REFINERY - Refineries produce petroleum by processing oil. +This production takes place automatically +at a rate dependent on the efficiency of the sector, +the number of workers in the sector, +and the technology level of the country. +.s1 +LIGHT - Light manufacturing plants produce light construction materials +from iron. +This production takes place automatically +at a rate dependent on the efficiency of the sector, +the iron in the sector, +the technology level of the country, +and the number of workers in the sector. +.s1 +HEAVY - Heavy manufacturing plants produce heavy construction materials +from iron. +This production takes place automatically +at a rate dependent on the efficiency of the sector, +the iron in the sector, +the technology level of the country, +and the number of workers in the sector. +.s1 +.s1 +.ce +MILITARY / SCIENTIFIC +.s1 +FORTRESS - Fortress sectors have many special characteristics; +you can fire guns from fortresses, +whenever an attack is launched from a fort or on +a fort the militia in the fort are stronger than military +in any other type of sector by an amount proportional to +the efficiency of the fort. (See information below in sector +stats) +Also, forts and commodities in forts are MUCH more resistant +to damage than normal sectors. +.s1 +TECHNOLOGY - Technical centers are bastions +of \*Qpure\*U technology research, +which is to say universities with massive defense department grants. +They turn construction materials +into technological advances thereby raising the technology +level of the country (which affects gun ranges, pollution, etc.). +The conversion of \*Qraw\*U materials takes place automatically +at a rate dependent on the efficiency of the sector, +the presence of the required materials, +the education level of the country, +and the number of workers in the sector. +.s1 +RESEARCH - The research lab is a bastion of \*Qpure\*U medical research, +which is to say it is a large university +with massive March-of-Dimes funding. +The research lab turns construction materials into medical +discoveries which raise the research level of the country and +help retard the spread of disease, (usually caused by the pollution +from technical centers). +The conversion of \*Qraw\*U materials takes place automatically +at a rate dependent on the efficiency of the sector, +the presence of the required materials, +the education level of the country, +and the number of workers in the sector. +.s1 +NUCLEAR - The nuclear lab is a bastion of applied technology, +which is to say it is an immense underground building filled with +evil geniuses playing Adventure on huge computers. +The nuclear lab turns construction materials into nuclear weapons. +No devices are constructed until the \*Qbuild\*U command is given, +(see \*Qinfo build\*U). +.s1 +LIBRARY/SCHOOL - The library/school sector is the foundation +of a country's educational structure. +They use up construction materials to produce units of education +which raise the educational +level of the country (which affects the efficiency of research and +technology sectors). +The conversion of \*Qraw\*U materials takes place automatically +at a rate dependent on the efficiency of the sector, +the presence of the required materials, +and the number of workers in the sector. +.s1 +ENLISTMENT - The enlistment sector is the boot camp of Empire. +It converts civilians into militia, once the efficiency level +has been raised to 60%. +Unlike the other production sectors, +it uses only militia as a workforce, +and converts civilians in the sector into military. +.s1 +HEADQUARTERS - This is where basic militia are converted into units. +Headquarters also give a bonus to reaction radius for units in them, +allowing them to defend better. +.s1 +The \*Qshow\*U command can be used to show special things about sector +types. For example: +.EX show sect build +.NF +sector type cost to des cost for 1% eff lcms for 1% hcms for 1% +f 500 5 0 1 + +Infrastructure building - adding 1 point of efficiency costs: + type lcms hcms mobility $$$$ +road network 1 1 1 1 +rail network 2 2 1 3 +defense factor 1 1 1 1 +.FI +.s1 +Cost to des is the cost to designate the sector type. This is charged when you +give the designate command. Note that if the BIG_CITY option is +enabled, then 'c' sectors also cost money, lcm's and hcm's to build, +and they can hold 10x as many civs as other sectors. +.s1 +You can also build infrastructure into your sectors. That is how the +mobilty, for both commodities and units, is determined. You can also +raise the defensive value of your sectors to a maximum amount (which is +shown in the "show sect stats" described below.) +.s1 +.EX des 2,0 f +That just cost you $500 +.s1. +Cost for 1% efficiency is the $$ cost per point of efficiency built. +Lcms/Hcms for 1% are similar. + +.EX show sect stats +.NF + max max -- packing bonus -- + sector type mcost off def mil uw civ bar other +. sea 0 0.00 0.00 1 1 1 1 1 +^ mountain 25 1.00 4.00 1 1 1 1 1 +s sanctuary 0 0.00 99.00 1 1 1 1 1 +\ wasteland 0 0.00 99.00 1 1 1 1 1 +- wilderness 2 1.00 2.00 1 1 1 1 1 +c capital 2 1.00 2.00 1 1 1 1 1 +u uranium mine 2 1.00 2.00 1 1 1 1 1 +p park 2 1.00 1.50 1 1 1 1 1 +d defense plant 2 1.00 1.50 1 1 1 1 1 +.FI +This shows the relative cost to move through the sector types, and the +offensive and defensive values of the sector types. For example, a capital +with a 100% defensive efficiency is twice as good as a park (since the +base value is 1.00.) All sectors start with a 0% defensive efficiency, +thus they all start with a defense of 1.00. You can increase the +defensive capability of any sector up to the amount shown by the "max def" +column. + +.EX show sect capabilities +.NF +There is no information on sector capabilities. +.FI + +There may someday be a sector capabilities list. +.s1 +.SA "improve, designate, show, BTU, Sectors" diff --git a/info/Concepts/Selector.t b/info/Concepts/Selector.t new file mode 100644 index 00000000..ebb4e75b --- /dev/null +++ b/info/Concepts/Selector.t @@ -0,0 +1,261 @@ +.TH Concept "Conditional Selectors" +.NA Selector "Selectors you can use in Empire conditionals" +.LV Basic +This is a complete list of all selectors you can use in Empire +conditionals. A selector is for example \*Qmil\*U in the following +command: +.EX cen * ?mil>10 +Most selectors are self-explanitory, so definitions will only be givin +where necessary. +.s1 +Commodities: +.in +\w'nchoppers\0\0'u +.L civil +.L milit +.L shell +.L gun +.L petrol +.L iron +.L dust +gold dust +.L bar +bars of gold +.L food +.L oil +.L lcm +light construction materials +.L hcm +heavy construction materials +.L uw +uncompensated workers +.L rad +radioactive materials +.s1 +.in +Sector: +.in +\w'nchoppers\0\0'u +.L xloc +.L yloc +.L owner +.L des +designation/infrastructure +.L effic +.L mobil +.L terr +.L timestamp +.L road +.L rail +.L dfense +(this isn't defense or it will conflict with des) +territory +.L work +.L coastal +is a coastal sector +.L newdes +new designation +.L min +mineral resources (iron) +.L gold +gold resources +.L fert +food fertility +.L ocon +oil content +.L uran +uranium resources +.L oldown +old owner +.L off +whether production is turned off +.L xdist +distribution centre +.L ydist +distribution centre +.L avail +available workforce +.s1 +.in +Ship, plane, or land unit: +.in +\w'nchoppers\0\0'u +.L xloc +x location +.L yloc +y location +.L owner +.L type +type of unit (e.g. cavalry or frigate) +.L effic +.L mobil +.L timestamp +.L sell +.L tech +tech level the unit was built at +.L uid +unit id number +.L group +fleet/wing/army +.L opx +mission operations sector +.L opy +mission operations sector +.L mission +.nf +1 = interdict +2 = support +3 = reserve +4 = escort +5 = sub interdiction +6 = air defense +7 = defense support +8 = offense support +.fi +.s1 +.in +Ship: +.in +\w'nchoppers\0\0'u +.L fleet +.L nplane +number of planes the ship is carrying +.L fuel +.L nxlight +number of xlight planes the ship is carrying +.L nchoppers +number of helecopters the ship is carrying +.L autonav +.s1 +.in +Plane: +.in +\w'nchoppers\0\0'u +.L wing +.L range +.L ship +ship the plane is on (-1 = no ship) +.L att +.L def +.L harden +.L nuketype +Type of nuke on the plane (-1 = no ship, 0..n = index into nuke table) +.L flags +.L land +land unit the plane is on (-1 = no land unit) +.s1 +.in +Land Unit: +.in +\w'nchoppers\0\0'u +.L att +.L def +.L army +.L ship +ship the land unit is on (-1 = no land unit) +.L harden +fortification +.L retreat +.L fuel +.L land +number of land units on the unit +.L nxlight +number of xlight planes on the unit +.s1 +.in +Nuke: +.in +\w'nchoppers\0\0'u +.L xloc +.L yloc +.L number +.L ship +.L trade +.L timestamp +.s1 +For distribution and delivery selectors, the first letter is the first +letter of the name of the commodity. For example, civilian +distribution threshold is 'c_dist'. +.s1 +.in +Distribution: +.in +\w'nchoppers\0\0'u +.L c_dist +.L m_dist +.L u_dist +.L s_dist +.L g_dist +.L p_dist +.L i_dist +.L d_dist +.L b_dist +.L f_dist +.L o_dist +.L l_dist +.L h_dist +.L r_dist +.s1 +.in +Delivery: +.in +\w'nchoppers\0\0'u +.L c_del +.L m_del +.L u_del +.L s_del +.L g_del +.L p_del +.L i_del +.L d_del +.L b_del +.L f_del +.L o_del +.L l_del +.L h_del +.L r_del +.s1 +.in +Deity: +.in +\w'nchoppers\0\0'u +.L pstage +.L ptime +.L che +.L fallout +.L lmine +.s1 +.in +Treaty: +.in +\w'nchoppers\0\0'u +.L cna +.L cnb +.L status +.L acond +.L bcond +.L exp +.s1 +.in +Loan: +.in +\w'nchoppers\0\0'u +.L loaner +.L loanee +.L sell +.L irate +.L ldur +.L amtpaid +.L amtdue +.L lastpay +.L duedate +.s1 +.in +News: +.in +\w'nchoppers\0\0'u +.L actor +.L action +.L victim +.L times +number of times action happened +.L time +time +.s1 +.in +Trade: +.in +\w'nchoppers\0\0'u +.L type +.L owner +.L unitid +.L price +.in +.s1 +.SA "Syntax, Playing" diff --git a/info/Concepts/Ship-types.t b/info/Concepts/Ship-types.t new file mode 100644 index 00000000..36fb7f81 --- /dev/null +++ b/info/Concepts/Ship-types.t @@ -0,0 +1,311 @@ +.TH Concept "Ship Types" +.NA Ship-types "Description of different types of ships." +.LV Basic +Some of the ships currently available in Empire are: +.s1 +.nf +torpedo-boat These ships have been misrepresented in Empire. They were + designed to kill large ships by swarming them and launching + torpedoes. In fact, they were projected to be so effective + that the French 'Jeune Ecole' (Young School) of naval officers + advocated abandoning battleships entirely, saying that they + would be helpless in the face of the torpedo-boat. In reality, + the torpedo boat was limited by it's short range, deficient + sea-keeping ability, and the battleship's quick acquisition of + numerous light quick-firing guns and machine guns. They were + effective when used in large numbers, but tended to die a lot. + +destroyer These include three kinds of ships. First is the 1880-1910 + destroyers, originally 'torpedo-boat destroyers', and meant to + be cheap ships to screen the battleships. Second is the + 1910-1950 version, meant to kill submarines with sonar and + depth-charges. Lastly is the 1950-1965 destroyer, an all around + ship, with ASW and ASuW (anti-surface armament). After that, + they type mostly died out, as it had gotten too large. + +frigate Originally, these were ships of about 200-400t, with a crew + of 200-500, armed with from 30-50 large cannon plus numerous + small cannon. They were intended to scout for ships of the + line, and protect/destroy commerce. After about 1860, the type + died out entirely, and was replaced by light cruisers. In the + 1960's, the type was resurrected for a new class of ASW (anti + submarine warfare) ships of small-medium size. + +light cruiser The class came into existence in the 1860-1905 period to provide + fast ships suitable for extended deployment in far-away places. + They were intended to out-class local defense boats, and not + much else. Much was sacrificed to give them long-term speed + end endurance. They were not intended to have a role in a major + battle. + +heavy cruiser This class has a dual role. It was intended to reinforce the + light cruisers in the colonies, providing a heavier punch and + more armor, and also to be scouting elements in major fleet + battles. + +ship-of-the-line +pre-dreadnought +dreadnought +battleship While the names change, the purpose remained the same: a ship + that brings heavy guns close to the enemy and destroys him. It + also was much used for off-shore bombardment, and for ships + of the line, minor invasions. (A complement of 300-400 marines + and 600 sailors allowed a ship of the line to land up to 750 + fighting men at any desired point. Small squadrons of these + ships could (and did) take over towns, attack fortresses by + surprise, and generally make life miserable for the defense). + + The pre-dreadnought was a battleship with a limited number + (usually 4) of heavy guns, numerous lighter guns ('secondary' + and 'tertiary' armament), and heavy armor on vital portions + of the ship. They were hard to kill, even for themselves, as + they had only a few guns that could penetrate the armor of + their peers. + + The dreadnought was introduced in an article in Jane's Fighting + Ships by an Italian designer, who received permission to publish + his design after the Italian government decided that it was + too large and expensive for them. The design/concept was seized + upon by First Sea Lord Jacky Fisher, who rushed completion of + the first ship, the Dreadnought, through in only 1 year. (An + amazing feat and a major record) The Dreadnought gave its + name to the entire type of ship, having 8-12 large calibre + guns, few secondary & tertiary weapons, and good armor. (As + can be guessed, the threat posed by torpedo boats had diminished + considerably, mostly with the quiet abandonment of the policy + of close blockade, and the advent of the destroyer) + + The battleship of the 1918-1945 period was faster, and carried + a new AA capacity, especially in the latter years of the period. + + After 1945, the class died out (except for 4 ships) + + For our purposes, a battleship 1 is a ship of the line, a + battleship 2 is a pre-dreadnought, a battleship 3 is a + dreadnought, and a battleship 4 is what was called a battleship + or (sometimes) super-dreadnought. + +battlecruiser These special ships existed in the 1905-1920 period, prior to + the widespread introduction of oil fuel. They had full battle- + ship guns, and a large speed advantage over the battleships, + but very little armor. They were initially the pet project of + First Sea Lord Jacky Fisher, who intended them to both kill + the heavy/armored cruisers of the time, and to scout for the + battleships. With their heavy armament (and name), their + function inevitably blurred, and they were used in combat + against full-fledged battleships, where they died like flies. + With this (and with the introduction of oil fuel, which made + battleships their equal in speed), they were phased out. + +ASW cruiser These ships came into being in the 1965-present period in + response to a need for a large ASW ship to carry ASW helicopters + and command equipment. It typically carries full ASW armament, + as well as a minor ASuW capability. + +missile boat +missile frigate +missile cruiser These ships range in size from 100t missile boats (the modern + replacement for the torpedo-boat) to the 6000-8000t missile + cruiser. They all are designed to bring missiles to bear on + the enemy. (The first successful missile boats were Egyptian, + and used against the Israelis in the 1967 Arab-Israeli war) + + The missile frigate and cruiser also serve as SAM ships. + +landing craft These ships are relatively unique, being used mainly in the + 1942-1950 period. Before that, landings were carried out by + frigates, ships-of-the-line, light & heavy cruisers, & + pre-dreadnoughts, all of which could land a large number of + men. With the introduction of the concept of beach-defense by + the Germans, these ships were invented to get large numbers of + men on the beaches quickly. After 1950, their functions were + largely assumed by the helicopter. + +aircraft carrier +light carrier +escort carrier These ships are designed for various purposes. At first, + carriers concentrated on scouting for the battleships. Later, + it was proved that airplanes could sink battleships (Thanks to + Billy Mitchell here), and the emphasis moved to all-around sea + control. Still later, with the disappearance of the battleship, + a large power-projection capacity was added. + + Light carriers were simply smaller versions of the large or + 'fleet' carriers, and were used for the same duties. + + Escort carriers were usually hastily converted merchantmen, + and carried small numbers of fighters and ASW planes. (Some + merchantment, in fact, were equipped with 1 fighter and a + temporary catapult. When threatened by enemy planes, the + fighter took off. When it was done, it ditched, and the pilot + was (theoretically) picked up by the merchant ship's convoy. + This was used several times, and worked!) + +submarine The submarine was originally intended, in the 1900-1910 period, + to fill the same role as the torpedo boat, using stealth to + get to the battleships instead of speed. It was a strictly + defensive weapon, without much speed or endurance. + + In the 1910-1925 period, the sub was much enlarged, and use in + a combination anti-battleship (sank at least 20)/anti-commerce + role. Endurance was much improved, and the sub could now + operate a long distance from its home port. + + In the 1925-1945 period, the sub steadily grew large and more + capable, gaining mostly in speed, sonar ability, and endurance. + + After 1945, nuclear power vastly increased the subs endurance, + making it effectively infinite. Sonar was also vastly improved, + and removed the reliance upon the periscope. The subs armament + was also vastly improved with the addition of the SLM & SLBM. + +minesweeper Usually converted fishing vessels, small, and expendable. They + found and destroyed mines with a variety of tricks, including + cables & magnetism. + +oiler These ships represent the whole range of refueling ships. +.fi +.s1 +These units types differ in their fundamental +capabilities; some can fire guns, some cannot; +each has it's own specific abilities & roles. +The capabilities of each ship are given by the show command. +The headings are as follows. For the building data: +.s1 +.EX show ship build +.s1 +.in \w'avail\0\0'u +.L lcm +The lcm required to build the ship. +.L hcm +The hcm required to build the ship. +.L avail +The avail (work) required to build the ship. +.L tech +The minimum technology required to build the ship. +.L $ +The cost of the ship. +.in \\n(in +.s1 +The headings for the stats listing are +.s1 +.EX show ship stats +.s1 +.in \w'fir\0\0'u +.L def +defensive armament of the ship +.L spd +the distance/mu for moving (in relative units) +.L vis +how visible the ship is, (relative units) +.L spy +how far the ship can see, (i.e. how good the +communication equipment is), again in relative units +.L rng +twice the distance the guns can fire, +The range formula is (rng/2) * ((tech + 50) / (tech + 200)) +.L fir +the number of guns the ship can fire at once +.L hel +The number of helicopters the ship can carry. (If the SHIPCHOPPER option is +enabled) +.L xpl +The number of extra-light planes the ship can carry. (If the XLIGHT option is +enabled) +.L pln +The number of light planes the ship can carry. +.L lnd +The number of 'light' land units the ship can carry. If the ship is a supply +ship, it can carry even non-'light' units. +.L fuel c/u +The ship's fuel capacity & usage. (see info fuel) (If the FUEL option is +enabled) +.in +.s1 +Each ship can carry a certain amount of products and has certain +capabilities. These are listed under the cargoes & abilities section. +The cargoes give the number of each product that can be carried. +The abilities are as follows. +.s1 +.EX show ship capabilities +.s1 +.in \w'sonar\0\0'u +.L fish +The vessel will accumulate food by fishing +.L torp +The vessel can fire torpedoes. +.L dchrg +The vessel can drop depth charges +.L plane +The vessel can carry planes with the light attribute set. +.L miss +The vessel can carry missiles. +.L oil +The vessel can drill for oil +.L oiler +The vessel can fuel other ships at sea +.L sonar +The vessel has sonar capabilities to detect submarines +.L mine +The vessel can lay mines +.L sweep +The vessel can sweep the sector for mines and recover them +.L sub +The vessel is a submarine +.L spy +The vessel can engage in spying activities +.L land +The vessel can be used as a landing craft. (see info assault) +.L semi-land +The vessel can be used as a semi-landing craft. (see info assault) +.L sub-torp +The vessel can torpedo submarines +.L trade +The vessel is a trade ship. (only if TRADESHIPS are enabled) +.L anti-missile +The vessel will intercept enemy marine missiles (see \*Qinfo Hitchance\*U). +.L +.in +.s1 +Some examples of the output: +.s1 +.EX show ship build +.NF + lcm hcm avail tech $ +fishing boat 1 25 15 12 0 $300 +cargo ship 1 60 40 29 0 $500 +ore ship 1 60 40 29 0 $500 +slave ship 1 60 40 29 0 $500 +passenger ship 1 60 40 29 0 $500 +trade ship 1 200 100 81 0 $2500 +frigate 30 30 19 0 $600 +battleship 1 50 50 31 0 $800 +.FI +.s1 +.EX show ship stats +.NF + s v s r f h x p l fuel + p i p n i e p l n c/u + def d s y g r l l n d +fishing boat 1 10 10 15 2 0 0 0 0 0 0 0/0 +cargo ship 1 20 10 35 3 0 0 0 1 0 0 0/0 +ore ship 1 20 10 35 3 0 0 0 1 0 0 0/0 +slave ship 20 10 35 3 0 0 0 1 0 0 0/0 +trade ship 1 20 10 35 3 0 0 0 1 0 0 0/0 +frigate 50 25 25 3 1 1 0 1 0 2 0/0 +.FI +.s1 +.EX show ship cap +.NF + cargos & capabilities +fishing boat 1 300c 10m 900f 15u fish +cargo ship 1 600c 50m 300s 50g 900f 1400l 900h 250u supply +ore ship 1 30c 5m 990i 990d 200f 45u 990r +slave ship 20c 80m 200f 1200u +trade ship 1 50c 50m 100f trade +frigate 60m 10s 2g 60f semi-land +battleship 1 120m 20s 4g 120f semi-land +fishing boat 2 300c 10m 900f 15u fish +.FI +.s1 +.SA "coastwatch, fire, load, lookout, mine, navigate, tend, torpedo, fly, show, Trade-ships, Ships" diff --git a/info/Concepts/Spies.t b/info/Concepts/Spies.t new file mode 100644 index 00000000..8df64e7c --- /dev/null +++ b/info/Concepts/Spies.t @@ -0,0 +1,38 @@ +.TH Concept Spies +.NA Spies "How spies work" +.LV Expert +.s1 +There is a land unit type "spy". These can be very valuable land units +to have wandering around the planet... +.s1 +Spies are very special land units. They are able to march into any sector +(owned or unowned) and look about. Of course, if you are marching in unallied +territory, there is a chance you will get caught. +.s1 +If a spy is caught by a friendly or neutral country, the country will get a +message that a spy was spotted in their country. If the spy is caught +by a hostile or at war nation, the spy gets shot on the spot. The chance +of getting caught while marching about is inverse to the efficiency of the +spy. So, at 100%, a spy has a 10% chance of getting caught. at 10%, +a spy has a 100% chance of getting caught. Thus, you want efficient spies. +.s1 +Spies are also very fragile. If they are caught in any kind of combat, +shelling, bombing, etc. and take ANY damage at all, they die. +.s1 +Spies may also be snuck on shore via ships using the "assault" command. If +you assault a sector using just spies, they have a 10% chance of making it on +shore without being spotted (no matter what their efficiency). If spotted, +the same rules apply for how a spy is dealt with. If you mix spies and mil, +the spies must fight just like normal units. And, since any damage they take +kills them, this is very risky usage of spies. +.s1 +You may locate spies using the "llookout" or the "spy" command. +.s1 +Use your imagination on how to eradicate errant spies. ;-) +.s1 +Submarines may carry up to two spy units. +.s1 +When unloaded from a ship, spies are not given over to the owner of the +sector as other units are. +.sq +.SA "lboard, bomb, fire, spy, llookout, LandUnits" diff --git a/info/Concepts/Syntax.t b/info/Concepts/Syntax.t new file mode 100644 index 00000000..3b1c95e3 --- /dev/null +++ b/info/Concepts/Syntax.t @@ -0,0 +1,153 @@ +.TH Concept "Command Syntax" +.NA Syntax "The Empire command syntax" +.LV Basic +.de AB +.in 0.3i +.ti -0.3i +.. +.s1 +The Empire Shell (command interpreter) +expects input in the form: +.EX VERB ARG1 ARG2 ... +VERB is any one of the Empire commands on the \Q*command list\*U +(what you see when you type \*Qlist\*U-- e.g. +\*Qmap\*U, \*Qmove\*U, \*Qinfo\*U, etc). +.s1 +The number of ARGs varies from command to command. +In most cases the ARGs need not be supplied on the command line; +any that are not supplied will be obtained by prompting. +The exception to this rule are those ARGs +that are enclosed in [square brackets] +in the command list. +The presence of these ARGs changes the way the command is carried out. +.s1 +Certain basic argument types recur often and are abbreviated in the +following ways. +.s1 +.AB + ::= 'se', 'sh', 'l', or 'p' for sector, ship, land unit, or +plane respectively. If "sector" is not a possibility, then 's' will +likely suffice for "ship". +.s1 +.AB + ::= either a country number or a country name +.s1 +.AB + ::= any one, (or unambiguous abbreviation), of the list of +commodities found in \*Qinfo Selector\*U: +.AB + ::= loan number +.AB + ::= sector coordinates in the form: x,y +.AB +.ne 4 + ::= sector(s) in the form: +.NF +0i +lox:hix,loy:hiy ?cond&cond&... +.FI +\*Qlox\*U, \*Qhix\*U, \*Qloy\*U, \*Qhiy\*U are coordinates bounding +the rectangular area to be considered +.s1 +\*Qcond\*U is a condition of the form: +.NF +0i + +.FI + is either a , as above, +a number in the range 0 to 65536, +a sector designation, +(\*Qm\*U for mine, \*Qc\*U for capital, etc), a type of unit +(\*Qfrigate\*U, \*Qcavalry\*U, etc), or a selector found in \*Qinfo +Selector\*U. +.br + can be any one of: +.in +\w'#\0\0'u +.L < +less than +.L = +equal +.L > +greater than +.L # +not equal +.in +.s1 +Thus \*Qmob=100\*U, \*Qore#0\*U, \*Q7=guns\*U, \*Qciv#mil\*U, +\*Qdes=b\*U are examples of legitimate conditions, +(note lack of embedded spaces), +and +.EX census -3:3,-3:3 ?des=+&gun=5&mil>civ +will list all highways +within 3 of your capital +with exactly 5 guns and more military than civilians. +.sp +Similarly, +.EX deliver f -9:9,-9:9 ?f_del=0 +will allow you to set up food delivery +in all the sectors that don't already +have food delivery. +.sp +Note that \*Qhix\*U, \*Qhiy\*U, and \*Q?cond\*U are all optional. +Also, the entire \*Qlox:hix,loy:hiy\*U section may be replaced +by either \*Q#\*U, \*Q#0\*U, \*Q#1\*U, \*Q#2\*U, +or \*Q#3\*U, ... which refer to +\*Qrealm\*Us which you can define. +(See \*Qinfo realm\*U.) +Note that \*Q#\*U and \*Q#0\*U are equivalent. Also \*Q*\*U refers to +all sectors, and \*Q@x,y:dist\*U refers to all sectors within dist of x,y. +.AB + ::= one ship number +.AB + ::= fleet designation, +which may be a list of ships separated by slashes (`/'), +a fleet letter, +the character tilde (`~') which means all ships not in a specific fleet, +or a rectangular sector area. +.AB + ::= either a single ship number or a fleet designation. +.sp +Note that specifications may have an optional ?cond&cond... +argument like that used for arguments. +For instance: +.EX ship ~ ?des=d&mil>5 +will list all destroyers that have more than 5 military +which are not currently in any fleet. +.s1 +.in \\n(in +.s1 +The output from commands may also be sent to a file or another +process by utilizing these alternate syntaxes: +.s1 +.ne 2 +.EX VERB ARG1 ... > FILE +which sends the output to the file \*QFILE\*U. +.s1 +.ne 2 +.EX VERB ARG1 ... >> FILE +which appends the output to the file \*QFILE\*U. +.s1 +.ne 2 +.EX VERB ARG1 ... >! FILE +which sends the output to the file \*QFILE\*U, +replacing the file it if it already exists. +.s1 +.ne 2 +.EX VERB ARG ... | PROGRAM [ARGS...] +which send the output of the command to the program \*QPROGRAM\*U +with optional arguments \*QARGS\*U. +This is most useful when \*QPROGRAM\*U is some type of +pager like \*(iFmore\*(pF(1) or \*(iFless\*(pF(1). +.s1 +The Empire shell also recognizes a few control characters: +.s1 +.in +\w'interrupt\0\0'u +.L \f2name\fP +\f2meaning\fP +.L interrupt +Abort command and return to Empire command level +.L quit +Exit Empire +.L EOT +Exit Empire +.in +.s1 +.SA "realm, Move, Selector, Playing" diff --git a/info/Concepts/Taxes.t b/info/Concepts/Taxes.t new file mode 100644 index 00000000..fe8024f0 --- /dev/null +++ b/info/Concepts/Taxes.t @@ -0,0 +1,36 @@ +.TH Concept Taxes +.NA Taxes "How taxes are calculated" +.LV Expert +.s1 +Civilians exist in Empire to work and provide cash to the government. +Simply by existing, +they generate revenue to their host country +in proportion to the efficiency of the sector +in which they work. +.s1 +The military-industrial complex exists +in order to siphon off hard-earned tax dollars. +Military cost (in general) about ten times as much +as a civilian pays in taxes. +.s1 +In addition, \*Qfinal goods and services\*U cost money to produce. +Ships, land units, planes, guns and shells are all examples of the costs +inflicted upon a helpless government by the military-industrial complex. +Also, \*Qservices\*U such as technology research, medical research, +and even happiness (money and lcm's can buy happiness here...) +cost something to create. +Consumer items such as food, lcm, hcm, and all other \*Qintermediate +goods\*U (or raw materials) cost nothing other than the hard work of +the oppressed citizenry. +.s1 +Note that it takes ten civilians to keep one soldier in the field. +Note also that the only way to make money is either to be pacifistic +and let your nation accumulate wealth by having a small standing army, +or by selling products to other nations. Also, land units can multiply +the strength of each mil, making them perhaps more economical, if you +already have made the technological investment. +.s1 +Also note that captured civilians only pay 1/4 the normal taxes. They +like to hide money until they are all finally agree to become naturalized +citizens of their new government. +.SA "Update, Nation" diff --git a/info/Concepts/Technology.t b/info/Concepts/Technology.t new file mode 100644 index 00000000..86bb2292 --- /dev/null +++ b/info/Concepts/Technology.t @@ -0,0 +1,92 @@ +.TH Concept Technology +.NA Technology "How technology level is calculated each update" +.LV Expert +.s1 +Your technology level affects the range that guns can fire, +the range over which radar is effective, +the range that planes can fly +and the range that torpedoes can travel, among other things. +.s1 +The \*Qnation\*U command will display your current technology level +and technology factor. +.s1 +.nf +This is how your new technology level is determined every update: + +(1) Technological breakthroughs are produced in tech centres. +See "info Products" or the "production" command to find out how many +technological breakthroughs you are going to produce. Your update +telegram will tell you the number of technological breakthroughs +produced in your various tech centres in a line like this: + technological breakthroughs (7.2) produced in 3,1 + +(2) Calculate tech delta from technological breakthroughs +In the output of the "version" command, you will see a line like this: + Tech Buildup is limited to logarithmic growth (base 2.00) after 3.00. + +In this example, the "tech log base" is 2.00 and the "easy tech" is +3.00. To find out what your tech delta for an update will be, subtract +"easy tech" from the number of technological breakthroughs you are +producing and then add 1, then take the logorithm with base "tech log +base" and then add the "easy tech" back on. + +For example, say you had a number of tech centres producing a total of +18.0 tech units. Then to calculate your delta, first subtract "easy +tech" from it and then add 1 to obtain 16.0, then take the log base 2.0 +of that which is 4.0 (since 2 to the power 4 is equal to 16), and then +add the "easy tech" back on to get a tech delta of 7.0. + +(3) Tech bleed +If the ALL_BLEED option is enabled, then you will gain extra technology from +all countries producing tech, and there will be a line in the +"version" output like this: + The technology/research boost you get from the world is 50.00%. + +If the ALL_BLEED option is turned off, then you will gain extra +technology from the countries with whom you share a two-way alliance, +and the line in the "version" output will look like this: + The technology/research boost you get from your allies is 50.00%. + +In both cases, the amount of tech you get is 50% of the average amount +of tech delta for all eligible "bleeders". Note that a fundamental +difference between these two cases is that in the ALL_BLEED case, only +countries which are producing tech are counted in the average, whereas +in the case where ALL_BLEED is turned off, the amount of tech bleed is +averaged among all of your allies whether they are producing tech or not. + +Your net tech delta will be printed in your update telegram as: + 3.000 technology (2.0000 + 1.0000) +where the 3.0000 is your net tech level gain, and that is broken down into +how much you produced (2.0000) and how much you got from tech bleed (1.0000). + +(4) Tech decay +After your net tech increase has been added to your country's +technology level, then your technology level will decay. The amount of tech +decay is printed in the version output as: + Nation levels (tech etc.) decline 1% every 96 time units. +The number of time units in an update is printed in the version output as: + An update consists of 60 empire time units. +Every update, your tech is reduced by + decay = (tech level) * (decay rate) * (etu per update) / (decay etus). +So if your tech level was 200.0, and the decay rate was as above, then +you would lose: + decay = 200 * 0.01 * 60 / 96 = 1.25 +and so your tech would go down to 198.75 from decay. + +(5) Tech leak +If your tech level is much lower than the tech level of the highest +tech country in the world, then every update, there is a chance that +one of their high tech secrets will get leaked into your country. + +Take the tech level of the highest tech country in the world and +divide by 5. Call this the "minimum tech". If your tech level is +lower than the "minimum tech", then every update, there is a 20% +chance that your tech level will increase by one third of the +difference between your tech level and the minimum tech. +.fi +.s1 +Note that if the TECH_POP option is enabled, technology costs +proportionately more $$$ to make as your civilian population grows +past 50,000 civilians. +.s1 +.SA "Innards, nation, Research, Nation, Production, Update" diff --git a/info/Concepts/Time.t b/info/Concepts/Time.t new file mode 100644 index 00000000..133f82ae --- /dev/null +++ b/info/Concepts/Time.t @@ -0,0 +1,30 @@ +.TH Concept Time +.NA Time "Definitions of BTU and ETL" +.LV Expert +.s1 +Because of the unique nature of Empire governments, +(i.e. the decision makers spend most of their time on vacation. +Hmmm, not so unique actually), +and the fact that ideally the Empire \*Qenvironment\*U +will mirror the \*Qreal\*U world, +various heuristics dealing with time have been implemented. +.s1 +The first is the Bureaucratic Time Unit (BTU) concept +which keeps track of the potential for doing \*Qwork\*U +possessed by your government. +.s1 +The second heuristic, (i.e. hack), +is the Elapsed Time Limit (ETL) which limits the amount of time +that players may be logged on each day. +The ETL is not cumulative and is reset to some particular value, +(often two hours, check the \*Qversion\*U command to be sure), +every night at midnight. +.s1 +The ETL and BTU counts are displayed with each command prompt +as follows: +.EX +The first \*Q##\*U is the Elapsed Time today, in minutes. +This number starts at 0 every midnight. +The second \*Q##\*U is the number of BTU's remaining. +.s1 +.SA "Innards, version, BTU, Playing" diff --git a/info/Concepts/Trade-ships.t b/info/Concepts/Trade-ships.t new file mode 100644 index 00000000..95034546 --- /dev/null +++ b/info/Concepts/Trade-ships.t @@ -0,0 +1,92 @@ +.TH Concept "Trade ships" +.NA Trade-ships "How to use trade ships" +.LV Basic +Trade ships are special ships, with a different function than most Empire +ships. They are in the game only if the TRADESHIPS option is enabled. +.s1 +Trade ships simulate internal or external trade. In the real world, countries +make goods that they can make cheaply, ship them somewhere they're expensive, +and sell them, making a profit. +.s1 +In the empire version, you make a trade ship, using lots of cm's, and costing +$2500. You then sail it to a harbor somewhere and scuttle it. You then receive +money, with a varying rate of return. +.s1 +The trade ship MUST be scuttled in a harbor that is at least 2% efficient to +make money. (In other sectors, +it sinks quietly, like most ships) You may scuttle it in either a harbor you +own, or the harbor of an ally. Pirates who capture a trade ship may also gain +money from it, just as if they were the lawful owner (although the news knows +the difference) +.s1 +The return rate is based on the straight-line map distance from the harbor +where the trade ship was built to the harbor where it is scuttled. +.s1 +You have to sail it at least 8 sectors to get any money at all. At less than +8 sectors, you get nothing, not even your $1750 back. Nothing, nada, zilch, +zip, nothing. Once you make a trade-ship, you're pretty much committed to +sailing it at least 8 sectors... + +Currently, the return rates are: + +.NF + Distance sailed Return rate + 0-7 NO MONEY + 8-13 2.5% * distance + 14-24 3.5% * distance + 25+ 5.0% * distance +.FI +.s1 +For example, if you sail the ship 10 sectors from the harbor where it was +built and scuttle it in a harbor there, you would get 125% of the money you +paid for it, or $2188. If you sailed it 15 sectors to a harbor and scuttled it, +you would get 153%, or $2678. +.s1 +Use the \*Qpayoff\*U command to see how much the trade ship would pay +were it scuttled in a harbour at its present location. +.s1 +If you scuttle a trade ship in the harbor you do not own, you get a 20% bonus +(applied after the value is multiplied by the return rate above), AND the +person owning the harbor gets 10% of the cash you make as a bonus (the amount +before the +20% bonus is applied) +You still get the full amount, but he makes money as well. +(Peaceful trade enriches BOTH countries more than trading only internally). +For the devious, no, being allied with yourself does not mean you get +20% when +scuttling in your own harbors. +.s1 +For example, using the #'s from above, if you sailed 15 sectors, and scuttled +in an allied harbor, you'd get $2188 * 1.2 = $2.6K, and your ally would get +$2188/10 = $218. +.s1 +CASH GAINED IS ALSO MULTIPLIED BY THE EFFICIENCY OF THE TRADE SHIP. +So, if you get shot down to 21%, don't expect to get the full amount... +.s1 +If you capture a trade ship, you are free to scuttle it in any harbor you can +get it into, receiving full cash calculated normally. +.s1 +The cash return is multiplied by the efficiency of the ship, so less efficient +ships produce less money. +.s1 +Captured trade ships may be scuttled as if they were yours (although you will +get some bad publicity in the news) Payoff is still based on the distance from +the harbor where the trade ship was built, not the sector in which it was +captured. +.s1 +You can also use the "order" command to set up automated trading routes with +trade ships and have them navigate and automatically scuttle themselves when +they reach their destination. See "info order" for more information on this, +but basically you can do things like this: +.NF + Step 1) Make a harbor + Step 2) Get cms distributed/delivered to your harbor each update. + Step 3) Find a destination harbor to sail to + Step 4) build tradeships in the harbor each update + Step 5) load civs and food on the trade ships each update. + Step 6) order the trade ships to sail and autoscuttle in the dest harbor. +.FI +.s1 +You can then just repeat steps 4, 5, and 6 each update, and never worry +about your trade ships again. Unless someone starts intercepting them, +that is... +.s1 +.SA "payoff, order, Ship-types, scuttle, Ships" diff --git a/info/Concepts/Unit-types.t b/info/Concepts/Unit-types.t new file mode 100644 index 00000000..8c333516 --- /dev/null +++ b/info/Concepts/Unit-types.t @@ -0,0 +1,235 @@ +.TH Concept "Unit Types" +.NA Unit-types "Description of the different types of land units" +.LV Basic +Some of the units currently available in Empire are: +.s1 +.nf +infantry The Bloody Infantry. Lotsa guys on foot with guns. They're + slow, and they carry their supplies in horse-drawn wagons, + which slows them down even more. Slow. They're also not + terribly good at scouting. They don't attack very well, + with a multiplier ranging from 1 to 1.5 or so with better + tech. However, they really shine on defense, with a multiplier + from 1.5 to 3.0. If you want to hold a line... use infantry. + They're fairly resistant to shelling and bombing, with the + later types of infantry units being better. + +cavalry Empire starts just at the end of the age of cavalry. They're + quick, and they scout pretty well. They're better at attacking + than defending. They are pretty easy to kill with shelling or + bombing. Still, if you want a low-tech unit to go somewhere + quick, they're the guys. + +supply Supply units range from horse and wagon to truck units. Early + supply units are slow, but the later supply unit types are + motorized and are faster. Supply units carry a bunch of stuff, + but try your best not to get them in combat, because they don't + enjoy it, and they're REALLY bad at it. Supply units can give + supplies to land units, as well as forts/ships/sectors. See + info supply. + +lt armor Armor units may be light, medium, or heavy. Light armor units +armor have much the same uses as cavalry, although they are a good +hvy armor bit less fragile. Medium armor is medium-fast, good for general + attacking, while heavy armor is slow, but good for assaults, + any situation where you need to destroy a heavily-defended + fixed point. + + All armor is better at attacking than defending. Higher tech + types of armor units are better at defending, however. Armor + gets much of its combat advantage from its mobility, being + able to attack and move in, severing supply lines & blocking + reaction & reinforcements. + + Armor is fairly resistant to shelling/bombing. + +artillery Artillery is a long range killer. You can use it to shell +lt artillery sectors, but it can often be more effective when used as +hvy artillery support for your attacks. Lt artillery has more mobility, +mech artillery but less damage. Hvy artillery has less mobility, but more + damage. Mechanized artillery gives you good damage and good + mobility, but is very expensive. + + The better the accuracy of the artillery, the better it is + at assisting your troops or shelling ships. The better the + damage rating, the better the damage done. High-damage, low + accuracy artillery is mostly good for shelling sectors, while + high-accuracy artillery is good at supporting your troops, + or shooting at ships. + + All artillery is bad at attacking, but can usually defend in + a not-horrible fashion. Artillery units are, however, pretty + vulnerable to shelling and bombing. (except for mech artillery) + +engineers Engineers are the most versatile unit. They can lay mines, +mech engineers clear mines, defend well, attack well, work on sectors, etc. + The drawbacks? Well, they're VERY expensive and not very + big. Mech engineers have vehicles and are much faster and + more resistant to damage. + +mech infantry These two types of infantry are faster. Mech infantry is +motor infantry also more resistant to damage and even better on defense. + +marines These units are like improved infantry, but more expensive and + harder to make. Their best use is for assaulting beaches, but + they do make superior infantry if you have to use them that + way. + +security These units are good at fighting guerrillas, but not for + much else. They fight about as well as low-tech infantry, + and their smallish size makes them not worth much. + + They do help you when shooting helpless civs (see info shoot), + and fight guerrillas during the update. The security troops + get a chance to 'raid' the guerrillas and kill some of them + before the guerrillas fight. This will reduce your casualties + from guerrilla war. + +radar units These units are high-tech. They give you the ability to + map the enemy easily as you advance. Try not to get them + into combat, as they're horrible at it, and they're very costly. + They're generally motorized, so they're pretty fast, and they + all get shelled/bombed hard. + +aa unit These units are good defensively, and fight planes well. They + are a mechanized unit, and move & survive pretty well. Only + units with the FLAK ability can fire AA. + +Use the "show" command to see units stats and capabilities. + +.fi +.s1 +These units types differ in their fundamental +capabilities; some can fire guns, some cannot; +each has it's own specific abilities & roles. +The capabilities of each unit are given by the show command. +The headings are as follows. For the building data: +.s1 +.EX show land build +.s1 +.in \w'shells\0\0'u +.L lcm +The lcm required to build the land unit. +.L hcm +The hcm required to build the land unit. +.L guns +The guns required to build the land unit. +.L avail +The avail (work) required to build the land unit. +.L tech +The minimum technology required to build the land unit. +.L $ +The cost of the land unit. +.in \\n(in +.s1 +The headings for the stats listing are +.s1 +.EX show land stats +.s1 +.in \w'fir\0\0'u +.L att +the attack multiplier of the land unit +.L def +the defensive multiplier of the land unit +.L vul +the vulnerability of the unit to bombing/shelling (1-100) +.L spd +the distance/mu for moving (in relative units) +.L vis +how visible the land unit is, (relative units) +.L spy +how far the land unit can see, (i.e. how good the +reconnaissance equipment is), again in relative units +.L rad +the unit's reaction radius +.L rng +twice the distance the guns can fire, +The range formula is (rng/2) * ((tech + 50) / (tech + 200)) +.L acc +the firing accuracy of the unit +.L fir +the number of guns that fire when the unit fires +.L amm +ammo: the number of shells the unit uses when fighting or firing +.L aaf +the aa fire rating of the unit +.L fc/fu +The land unit's fuel capacity & usage. +(see info fuel) (If the FUEL option is enabled) +.L xpl +The number of extra-light planes the land unit can carry. +(If the XLIGHT option is enabled) +.in +.s1 +Each land unit can carry a certain amount of products and has certain +capabilities. These are listed under the cargoes & abilities section. +The cargoes give the number of each product that can be carried. +The abilities are as follows. +.s1 +.EX show land capabilities +.s1 +.in \w'engineer\0\0'u +.L xlight +the unit can carry xlight planes. (If the XLIGHT option is used) +.L engineer +the unit can lay/sweep mines, work on sectors/fortifications/etc. +.L supply +the unit can supply other units +.L security +the unit is good at fighting guerrillas and shooting helpless civilians +.L light +the unit can be carried on ships (note that any unit, even +units that are not 'light', can be +carried by a non-submarine supply ship that is otherwise +able to carry units) +.L marine +the unit is good at assaulting +.L recon +the unit is good at gathering intelligence. It will do better using llookout, +and will report enemy units in batter better. +.L radar +the unit has radar capability +.L assault +the unit may be used in assaults +.L +.in +.s1 +Some examples of the output: +.s1 +.EX show land build +.NF + lcm hcm mil guns shells avail tech $ +War band 5 0 100 0 0 1 0 $500 +Supply Wagon 5 5 50 0 0 2 0 $500 +GPG Commandos 15 15 25 1 2 5 150 $800 +artillery 1 40 60 70 20 40 17 100 $1000 +Jump infantry 35 25 100 5 10 9 400 $3000 +marines 1 20 10 100 2 4 5 200 $2000 +.FI +.s1 +.EX show land stats +.NF + s v s r f a d a a x + p i p a r c a m a f f p + att def vul d s y d g c m m f c u l +War band 1.3 1.0 99 23 5 1 1 0 0 0 0 0 0 0 0 +Supply Wagon 0.1 0.2 100 15 6 1 0 0 0 0 0 0 0 0 0 +GPG Commandos 1.0 1.0 70 30 1 2 1 0 0 0 5 1 10 1 0 +artillery 1 0.0 0.5 50 15 6 1 0 6 40 4 5 15 0 0 0 +Jump infantry 5.0 6.0 20 55 1 4 4 0 0 0 5 35 10 1 5 +marines 1 1.0 2.0 70 23 3 3 2 0 0 0 5 5 0 0 2 +.FI +.s1 +.EX show land cap +.NF + capabilities +War band 5f engineer light recon +Supply Wagon 50s 5g 100f 200l 100h 100r 200d 10b 100i supply light +GPG Commandos 5f security +artillery 1 5f 10g 20s +Jump infantry 5f 2g 10s xlight +marines 1 5f 10s xlight light marine +.FI +.s1 +.SA "land, LandUnits" + diff --git a/info/Concepts/Update-sequence.t b/info/Concepts/Update-sequence.t new file mode 100644 index 00000000..9f21755f --- /dev/null +++ b/info/Concepts/Update-sequence.t @@ -0,0 +1,98 @@ +.TH Concept Innards +.NA Update-sequence "The order of events at the update" +.LV Expert +.s1 +This document gives a rough order of events during the update. +.s1 +.nf +1) First, prepare all sectors in the world, row by row, going from top + to bottom, left to right + + a) fallout is checked, if FALLOUT is defined + b) guerrilla warfare is checked + c) if the sector doesn't have the plague, see if it catches it + otherwise plague the people + d) if there are no civs or mil in the sector, it reverts to the deity + e) taxes are collected from civs & uws. Mil are paid. + f) if the sector is a bank it makes $$ proportional to its efficiency + +2) Then, in order of country #, deal with each country: + a) pay for military reserves. + b) in order of set priorities, 1-39, 1 going first, then 2, etc. + 1) produce for owned sectors of that type + a) if the sector is a cap, it costs $$ equal to + the # of etus: np->nat_money -= etus; + b) people in non-sanctuary sectors eat + 1) If not enough is available, the sector + uses the supply routines to draw more. + 2) If still not enough is available, + the excess people will starve off. + a) No more than 50% of the people + in a sect can die + b) If the NEW_STARVE option is not + enabled, all types of people + (civs, uw, mil) starve evenly. + c) If the NEW_STARVE option is enabled, + the uw's die first, then + the civs, then the mil. + c) if there was starvation, the work percentage is set + to 0, otherwise the work rate rises by + 8+(1-15), max of 100 + d) population grows and is truncated + e) sectors that are stopped are skipped.(see info stop) + f) first increase eff + g) then make things + + c) If ship maintenance is not yet done, do it now + d) If ship building is not yet done, do it now + e) If plane maintenance is not yet done, do it now + f) If plane building is not yet done, do it now + g) If unit maintenance is not yet done, do it now + h) If unit building is not yet done, do it now + i) produce for all sectors that have not yet produced + a) if the sector is a cap, it costs $$ equal to + the # of etus: np->nat_money -= etus; + b) people in non-sanctuary sectors eat + 1) If not enough is available, the sector + uses the supply routines to draw more. + 2) If still not enough is available, + the excess people will starve off. + a) No more than 50% of the people + in a sect can die + b) If the NEW_STARVE option is not + enabled, all types of people + (civs, uw, mil) starve evenly. + c) If the NEW_STARVE option is enabled, + the uw's die first, then + the civs, then the mil. + c) if there was starvation, the work percentage is set + to 0, otherwise the work rate rises by + 8+(1-15), max of 100 + e) population grows and is truncated + f) sectors that are stopped are skipped. (see info stop) + g) first increase eff + h) then make things + +3) Then, do deliveries for all sectors in the world, row by row, going from + top to bottom, left to right + +4) Then, do exporting via distribution for all sectors in the world, row by + row, going from top to bottom, left to right + +5) Then, do importing via distribution for all sectors in the world, row by + row, going from top to bottom, left to right + +6) modify tech/res/hap/edu levels & do tech bleed +7) decrease levels due to passing of time +8) update war declarations (for slow war) + +9) If MOB_ACCESS is not enabled, mobility is updated as follows: + a) Add mobility to ships + b) Add mobility to sectors + c) Add mobility to planes + d) Add mobility to land units + 1) Units with negative mobility have their mob halved (-100 goes to -50) + 2) Mobility is added +.fi +.s1 +.SA "Innards, Update" diff --git a/info/INFO.MAC b/info/INFO.MAC new file mode 100644 index 00000000..eef2f868 --- /dev/null +++ b/info/INFO.MAC @@ -0,0 +1,133 @@ +.\" EMPIRE TROFF MACRO FILE +.\" +.\" +.\" $Header: INFO.MAC,v 1.6 89/09/29 01:55:49 mr-frog Exp $ +.\" +.\" The TH Macro is for specifying the title of a new section +.\" +.\" In english: +.\" +.\" Define the string Ts to be "$1 : $2" where $1 and $2 are the +.\" first and second args to .TH +.\" +.\" push an "environment" onto the stack so that changes in +.\" font, etc. don't inturrupt what is going on in the +.\" text +.\" +.\" make sure that proportional spacing is on +.\" +.\" print the string Ts, centered +.\" +.\" restore spacing (not covered by environment) +.\" +.\" pop off the enviornment +.\" +.de TH +.ds Ts \\$1\\\\0:\\\\0\\$2 +.ev 1 +.cs \\*N +'ce 1 +\\*(nF\\*(Ts\\*(pF +.if \\n(CS>0 .cs \\*N \\*(cS +'sp +.ev +.. +.\" +.\" +.\" +.\" +.\" +.\" +.de EX \" Start of macro EX +.nf +.ti +0.3i \" Temporary indent of 3/10 inch +.\" Constant spacing for EF font = 26/36 ems +.cs \*(EF 26 +.nr CS 1 \" Indicate constant spacing on +.lg 0 \" Turn off ligature mode +.ps 8 \" 8-point +\*(eF[##:##] Command: \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9\*(nF +.ps 10 \" 10-point +.lg \" Turn ligaturing back on +.\" Turn off constant spacing +.cs \*(EF +.nr CS 0 \" Indicate constant spacing off +.br \" Break +.fi +.. +.de SY \" Start of macro SY +.s1 +.\" Print out "SYNTAX" in bold font +\*(bFSYNTAX\*(pF +.ti +0.3i \" Temporarily indent 3/10 inch +.\" Constant spacing for EF font, 26/36 ens +.cs \*(EF 26 +.nr CS 1 \" Indicate constant spacing on +.lg 0 \" No ligatures +.ps 10 \" 10 point +.\" Print out in EF font +\*(eF[##:##]% \\$1\*(pF +.ps 10 \" 10 point +.lg \" Turn ligatures back on +.cs \*(EF \" Turn off constant spacing +.nr CS 0 \" Indicate constant spacing off +.s1 +.. +.de LV +.s1 +Level: \\$1 +.s1 +.. +.de NA \" Start of macro NA -- name of command/concept +.s1 +.\" Print out "NAME" in bold font +\*(bFNAME\*(pF +.ti +0.3i \" Temporarily indent 3/10 inch +\\*(nF\\$1 \- \\$2\*(pF +.s1 +.. +.de SA \" Start of macro SA -- SEE ALSO +.s1 +.\" Print out "SEE ALSO" in bold font +\*(bFSEE ALSO\*(pF +.ti +0.3i \" Temporarily indent 3/10 inch +\\*(nF\\$1\*(pF +.s1 +.. +.de L \" Start of macro L +.br \" Break +.ti -\w'\\$1\\0\\0'u \" Indent backwards with of 1st arg + 2 spaces +.\" Print 1st arg + 2 spaces +\\$1\0\0\c +.. +.de NF \" Start of macro NF +.nf \" No-fill +.\" Constant width 26/36 ens +.cs \*(EF 26 +.nr CS 1 \" Indicate constant spacing on +.lg 0 \" No ligatures +.ps 8 \" 8-point +.di Nf \" Send output to macro Nf +\*(eF \" Switch to EF font +.nr nF \\n(.i \" Store current indent in nF number register +.in +0.3i \" Add indentation 3/10 inch +.. +.de FI \" Start of FI macro +.in \\n(nFu \" Restore previous indentation +\*(nF \" Interpolate nF register +.di \" Terminate output to macro Nf +.ne \\n(dnu \" Give me at least as much space as in dn number reg +.Nf \" Call macro Nf +.ps 10 \" 10-point +.lg \" Restore ligatures +.\" Turn off constant width +.cs \*(EF +.nr CS 0 \" Indicate constant spacing off +.fi \" Back into fill mode +.. +.hy 15 \" Auto hyphenation with restrictions -- see troff man +.de s1 \" Start of macro s1 +.sp 1 \" Blank line +.ne 4 \" Give me 4 vertical lines +.. +.ds HT \t \" Define HT macro as a horizontal tab diff --git a/info/Introduction/Basics.t b/info/Introduction/Basics.t new file mode 100644 index 00000000..a9a94a07 --- /dev/null +++ b/info/Introduction/Basics.t @@ -0,0 +1,41 @@ +.TH Introduction Basics +.NA Basics "The basic rules for playing Empire" +.LV Basic +.s1 +First, there are no real rules to playing empire. What you do +is what you do. There are some general guidelines here, and some +deities may be more forgiving than others. +.s1 +One player, one country. +You man NEVER use any country other than your own. +It is ok for two people to play one country +but it is NEVER ok for one person to play two countries. +If you are caught doing this, your countries will be removed +from the game. +In addition, your registrations for future games may be +declined. +DON'T DO IT. +.s1 +Ok, but what do I do when I'm away? +.s1 +.in +.5i +1) you may turn over your country to someone who has never +played anyone else's country in that game. +You MUST tell the deity if you do this +as he/she/it will be watching who is playing what. +.br +2) you may turn your country over to the deity. +.in -.5i +.s1 +Bugs: if you find a bug, +you are REQUIRED to report it to the deity. +I will not let other people know about the bug +and in most cases, you may exploit it until it is fixed. +Punishment for use without telling: at least $50,000 or +getting your country removed from the game. +.s1 +Denial-of-service attacks are forbidden. Any form of attack that +prevents a player from connecting to the server is against the rules. +This includes letter bombing. +.s1 +.SA "Introduction" diff --git a/info/Introduction/Clients.t b/info/Introduction/Clients.t new file mode 100644 index 00000000..f69cb09d --- /dev/null +++ b/info/Introduction/Clients.t @@ -0,0 +1,56 @@ +.TH Introduction "Empire4 Compatable Clients" +.NA Clients "Clients which communicate well with the Empire4 Server" +.LV Basic +.NF +What follows is a list of clients which support the new Empire4 +protocol. All of these clients may be found on the Wolfpack Empire +Archives located at: + http://www.wolfpackempire.com +or + ftp://ftp.wolfpackempire.com/pub/empire/ + +empclient-2.8 - full support + +If you are using one of these clients, then you should type +"toggle inform" once you have broken sanctuary. These clients +are fully asynchronous, which means that they are able to respond +immediately when an unexpected message arrives from the server. So, +for example, if someone sends you a "flash" message, then the message +will be printed on your screen immediately. Similarly, with "inform" +toggled on, you will be informed the moment a telegram arrives. Note, +the server remembers your toggle flags when you log out, so you do not +have to type "toggle inform" again the next time you connect. + + +other clients - no support + +Most other clients should work fine with the Empire4 server, however +they may get confused if a flash message comes in. Users of other +clients should keep the "inform" flag toggled off, and ask a friend to +send them a "flash" message to see how the client handles it (note, +you must declare friendly relations towards them in order to receive +the flash message). If the flash message confuses your client, then I +recommend you type "toggle flash" to turn flash mode off. +.FI +.s1 +In addition, there are a list of commands which have been added to the +server to help the development of clients. They are: +.NF + dump - Dump sector information + ldump - Dump land unit information + sdump - Dump ship information + pdump - Dump plane inforamation + ndump - Dump nuclear stockpile information + lost - Report lost items +.FI +.s1 +See the various info pages on these for complete documentation on how they +work and how you can use them to help improve your clients. +.s1 +In addition, there is a "timestamp" field on each object (sectors, ships, +land units, planes, nuclear stockpiles, lost items) that you can use to +compare against to keep data between clients and the database in sync with +each other. These timestamps are kept in systems seconds, so they should +be accurate down to 1 second. Every time an object is changed, it's +timestamp is updated. +.SA "toggle, dump, ldump, sdump, pdump, ndump, lost, Empire4, Communication, Introduction" diff --git a/info/Introduction/Expert.t b/info/Introduction/Expert.t new file mode 100644 index 00000000..7f74878c --- /dev/null +++ b/info/Introduction/Expert.t @@ -0,0 +1,219 @@ +.TH Introduction "Expert Advice" +.NA Expert "Advice to expert Empire players" +.LV Expert +.ce 3 +\*(iFDefense Against Nuclear Attacks +Through the Denial of Information\*(pF +by Tom Tedrick +.s1 +A very good defense against nukes is to make +it as difficult as possible for other players to find out +where your country is, and thus to make maps of it. +.s1 +Here are some simple steps that you can follow: +.in +\w'MM)\0\0'u +.s1 +.L 1) +Shoot down all planes that fly over your airspace. +It helps to have numerous airfields, +say one airfield for every 25 sectors or so. +Every airfield should be within interception distance +of several other airfields, +so that it is more difficult for an enemy to destroy or capture it. +If an airfield is detected and nuked, +you still have backup airfields. +Every important sector should be within interception distance +of several airfields. +.s1 +.L 2) +Seal off all entrances to your inland seas by building +bridges and laying mines +(so no enemy ships can penetrate the area for mapping purposes). +.s1 +.L 3) +Sink all surface vessels and submarines near your coastline. +Have large fleets of destroyers posted around exposed coastal areas +covering all sea sectors where enemy subs +might try to sneak in for mapping purposes. +Usually two fleets of 30 destroyers each are enough. +Navigate the whole fleet one sector, stop and look for subs, +navigate one more sector, stop and look for subs, and so on, +until the fleet has made a circle and is back in its starting position. +Sink any subs you find, of course. +.s1 +There is a maximum number of around 30 ships that can be in a +fleet if you want to maneuver the whole fleet by fleet name +(see \*Qinfo fleetadd\*U). +.s1 +.L 4) +Establish alliances under the condition that secrecy is maintained +with respect to map information. +Thus other allied countries can serve as +a buffer zone against enemy countries. +Many players are willing to be good allies. +.s1 +.L 5) +Destroy or capture nearby radar stations. +.s1 +.L 6) +Destroy or capture enemy air bases +within range of your country. +Until enemy technology gets high enough +to launch against any target world-wide, +they will often try to get someone to let them have an airbase +hidden near your country and launch nuclear strikes from there. +I've always been able to find these if I worked at it. +.s1 +.L 7) +Use psychological warfare. +Nukers get tired of nuking you if it seems to have no effect. +For example, have numerous false capitals, so that when, +after great efforts, they manage to find +what they think is your capital, and nuke it, only to +discover that it was a fake, they will get discouraged. +These fake capitals are also very useful as backups in case your +real capital is discovered and destroyed. +.s1 +When an enemy gets close to doing real harm, +a counterattack can often divert attention away from the current attack. +Psychologically, attackers seem to underestimate the harm +they are doing to you if you don't give out any information about how +you are being affected, +and they seem to overestimate the danger to themselves +from your counterattack. +.in +.s1 +.ce 3 +\*(iFShip Networks and the Art of +Transferring Supplies\*(pF +by Tom Tedrick +.s1 +Build large quantities of ships. +When they're 100% efficient, +load them with military and food (and civilians) if possible. +Load guns and shells if you have them, +but since they tend to be scarce, only a few ships will have them. +Navigate them one by one as far as they will go. +Leave only one ship in each sector +(this makes it difficult for an enemy to sink very many of them, +due to mobility restrictions +and the problem of locating and identifying them one by one). +On your maps, mark the ship number in the appropriate sector. +Each sea sector thus has at most one ship number. +.s1 +Unless there is something in particular you want to do with +a particular ship, leave it sitting in its sector indefinitely. +.s1 +As you build more and more ships, +move them out one by one. +If you leave ship \*(iFX\*(pF +in a sector that already contains ship \*(iFY\*(pF, +ship \*(iFY\*(pF should have full mobility by then. +Navigate ship \*(iFY\*(pF as far as it will go, +then leave it sitting until a new ship comes along. +.s1 +Every ship in the network is now likely to be within range of +some other ships in the network. +If a ship requires any supplies, +you can load them on a ship in a harbor, +navigate it out, transfer the cargo via tend, +navigate the tended ship, +transfer its cargo, and so on, +until you reach the any ship in the network. +If you need military for assaulting or boarding, +guns and shells for firing, torpedoing or laying mines, +or if you simply want to move stuff into a distant harbor, +you can do it using several tend and navigate operations. +.s1 +This has been particularly useful for sinking subs. +I don't have enough guns and shells +to keep all of my 100 or more destroyers fully armed, +but when one of the unarmed destroyers spots a sub, +I can arrange to transfer guns and shells to it from a loaded +ship (or from a harbor). +.s1 +It's a very simple system from the player's standpoint, +because all the player has to do is build the ship, +navigate it, mark its number on the map, +and forget about it until a use for it arises. +As more ships are built, +the network automatically expands without requiring any planning. +You don't have to keep anything in memory, +except the ship number on your map. +If any enemy surface ship gets trapped in the network, +it's quite likely you can capture it, +even if all you have is cargo ships +(battleships, landing craft, and carriers could take some work though). +If an enemy sub is spotted by your destroyers, +you can almost always sink it. +If a convenient target for an assault appears, +you can get the necessary military there. +.s1 +.ce 3 +\*(iFSome Tricks to Use When Fighting\*(pF +by Various People +(Mostly by Tom) +.s1 +The trick for boarding destroyers: +you need a bunch of cargo ships, +both to make several boarding attempts and to tend military. +When you try to board a ship, both the attacker and defender +lose the same amount of mobility. +First you have to get the destroyer's mobility to be negative. +Then you just keep trying to board it from one ship after +another until you win. +That's where my ship network method comes in handy. +I usually have swarms of ships I can surround enemy ships with. +.s1 +If I have planes, my normal method is to take a sector I can see, +put enough military to hold it, +designate it \*Qe\*U if it has lots of food, +or maybe something else if there is a reason. +Then get information about the adjacent sectors +and take the most promising one. +Without planes it's more of a struggle. +Anyway, I kind of zig-zag into the country taking the most +interesting sectors, ignoring the others. +This really seems to freak people out, +when an enemy takes a path right through the heartland. +.s1 +I would use planes (so having numerous airports +each with a fair supply of fighters, spread around +your country, would be the best countermeasure), +ships (having forts loaded with guns and shells +covering all coastlines helps a lot; +also having destroyers and subs spread around your coastal +waters in order to spot and counterattack enemy +ships, also have bombers to bomb enemy ships, and +radar stations to spot them is useful). +.s1 +I would invade by land, firing from forts, +(mainly you need to counterattack actively when the enemy takes any +sectors in your area, also forts with guns and shells help a lot). +I would capture islands and build bridges to get into your country +(so watch all offshore islands with bridge span range). +.s1 +Have a lot of shells in warehouses ready to be moved to +the front (you can move four for no mobility cost). +.s1 +Bombing enemy ships spotted by radar seems to work pretty +well for the most part. +If he has an aircraft carrier you can torpedo it. +.s1 +You never know exactly what may happen, +sometimes you get lucky when you think it's hopeless. +Even if a plan has only a small chance of working, +sometimes it's worth a try, +especially if the enemy has to actively do something to stop it. +.in 0 +.s1 +You should always have at least two capitals sectors, in case you +lose one. +.s1 +Just a tip on empire tactics: mobility is the key +to dealing with many empire problems. Its often the +bottleneck which interferes with various things, and +the decisive advantage that gives victory to the attacker. +.s1 +.s1 +.SA "Overview, Novice, Hints, Introduction" diff --git a/info/Introduction/Guide.t b/info/Introduction/Guide.t new file mode 100644 index 00000000..0f7995db --- /dev/null +++ b/info/Introduction/Guide.t @@ -0,0 +1,3408 @@ +.TH Introduction "The Empire Users Guide" +.NA Guide "The Empire Users Guide" +.LV Basic +.nf +| | +| *** *** | +| *** *** * | +| *** *** ****** ****** ** **** * ****** | +| *** *** ** ** ** **** ** * ** | +| *** *** ***** ******* ** ***** | +| *** *** ** ** ** ** | +| *** *** ****** ****** ** ****** | +| *** *** | +| ********* ++++ + + +++++ ++++ +++++ +++++ +++ | +| + + + + + + + + + + | +| + ++ + + + + + +++ + + + | +| ************ + + + + + + + + + + + | +| *********** +++ +++ +++++ ++++ +++++ + +++ | +| *** | +| *** *** **** **** ******** ********* ******** ******* | +| ******* ***** **** *** *** ** ***** *** *** *** *** | +| *** **** ** ** *** ** *** *** *** ******** | +| *** *** ** ** *** ** *** ******** *** | +| *********** *** ** ** ******** ***** *** *** *** *** | +| ************ *** ** ** *** ********* *** *** ******* | +| ** | +| By Geoff Cashman | + + +User's Guide to Empire 1 + + . . . . . . . . . . . . . . . . . . . . +. . . . . . . . . . . . . . . . . . . . + . . . . . . . . . . . . . . . . . . . . +. . . . . . . . . . . . . . . . . . . . + . . . . . . . . . . . . . . . . . . . . +. . . . . . . . . . . . . . . . . . . . + . . . . ---------------------------------------------. . . . . +. . . . .| | . . . . + . . . . | This work copyright 1991, Geoff Cashman |. . . . . +. . . . .| All rights reserved except you may copy | . . . . + . . . . | this work using electronic methods. Non |. . . . . +. . . . .| electronic copying, hard copies for the | . . . . + . . . . | purpose of distribution and/or selling, |. . . . . +. . . . .| is strictly prohibited without author's | . . . . + . . . . | express written consent. No changes may |. . . . . +. . . . .| be made to the content of this edition. | . . . . + . . . . | |. . . . . +. . . . .--------------------------------------------- . . . . + . . . . . . . . . . . . . . . . . . . . +. . . . . . . . . . . . . . . . . . . . + . . . . . . . . . . . . . . . . . . . . +. . . . . . . . . . . . . . . . . . . . + . . . . . . . . . . . . . . . . . . . . + + +User's Guide to Empire 2 + + Preface + +This guide's intended audience is the beginning player and those players +who have played a game or three and would like to have some insight on some +more subtle aspects of the game. Some experienced players may find some +benefit from reading this guide as well. While you may feel you are an +expert, it is always possible to learn. Nothing in this guide is intended +to be difficult to understand, and every effort has been made to make this +guide an easy learning tool. + +This publication is current to Berkeley version 1.1 patch level 5 + + + + +User's Guide to Empire 3 + + Foreward + +It has been over a year now since I first sat down and thought in a serious +way about writing this guide. It has been a long trip with many interesting +turns and developments. When I first started, the version of Empire that +this guide has ultimately been written for had not yet been released. Now, +with this project nearing release I find that yet another new version of +Empire is coming out. I look on in near despair as I realize that this guide +may very well soon be outdated. Nevertheless, I feel compelled to release +this information in what might be considered a final form. + +However, I hope that this is not the final form. With new versions of +Empire coming out in the very near future I hope that some other potential +author steps forward and takes up the banner of educating the new player. +I caution you though that such a work as this takes quite an effort. + +To the reader and any critics or even cynics that might be reading, I say +that I am not writer. I never was, and I never intend to be. There are +certainly enough writers in the world to write almost everything the world +could want to know about in print. I was never skilled in the art of proper +style for any sort of writing. Please, be kind and keep this in mind. + +I wrote this guide because I felt there was a great need for something of +this nature. I have watched so many players come to the network looking +for information on Empire, such as the rules, or information on how to play. +One can get information about the various commands available to oneself +within the game, but to understand how to use those commands effectively +and get skilled at running a country is a far greater task. Many new +players have despaired after playing their first game for lack of the +requisite knowledge to play effectively. Some come back fighting hard +in the next game, but many just disappear never to be heard from again. +This guide was written with the hope that if the new player is supplied +with the basics, they can advance in skill more quickly than previously +possible and not despair at their first defeat. + +I am hoping that within the near future two other companion guides to +this one will be written and released to the net. These two guides will +be intended to make the average player a better player or even expert, +and to teach fledgling deities how to compile and establish a, solicit +entries for , and effectively run, a game. Some people have commented +to me that the time spent on these guides would be better spent if I +were to spend time programming for Empire instead. It is my belief that +in teaching players to be better players, and teaching deities how to be +a deity should that guide be released, the potential pool for +programmers of Empire will increase. + +I can not take credit for the idea of this guide. The need for such +a guide I think was painfully obvious to a great many players. Some in +fact did engage in projects to fill that need. Every such attempt has +fallen short, in my humble opinion. Witness the large number of people + + +User's Guide to Empire 4 + +who still ask the network, "How do I play?" and even more importantly +the lack of sufficient answer to such people's questions. In my highest +hopes, I dream that someday soon that answer will be "Get a copy of the +User's Guide to Empire, which is available via FTP from xx.xx.xx". + +This work was made possible by the contributions of several Empire players. +This work would not have been completed without the insights and assistance +of many Empire players and deities. To the Empire community as a whole, +I say thank you for your priceless contributions. + + + + +-------------------------------------------------------------------------------- + + +User's Guide to Empire 5 + + *** Contents *** + +Preface +Foreward +1. What is Empire? . . . . . . . . . . . . . . . . . . . . . . . 6 +2. How to get into a game of Empire. . . . . . . . . . . . . . . 8 +3. The primitive basics. . . . . . . . . . . . . . . . . . . . . 16 +4. Geography in Empire. . . . . . . . . . . . . . . . . . . . . 18 +5. The beginning phases of Empire. . . . . . . . . . . . . . . . 21 +6. Diplomacy. . . . . . . . . . . . . . . . . . . . . . . . . . 28 +7. Setting up your defenses. . . . . . . . . . . . . . . . . . . 33 +8. Nuclear warfare. . . . . . . . . . . . . . . . . . . . . . . 38 +9. Technology. . . . . . . . . . . . . . . . . . . . . . . . . . 42 +10. The economy. . . . . . . . . . . . . . . . . . . . . . . . . 45 +11. War. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54 +12. Other helpful or not so helpful hints. . . . . . . . . . . . 57 +13. Some tricks and subtle tactics. . . . . . . . . . . . . . . . 59 +14. Tools. . . . . . . . . . . . . . . . . . . . . . . . . . . . 63 + +Appendices + a) glossary + b) known bugs + c) ftp sites + + +Figures: + 1. Sample of how to FTP and compile a client program + 2. Killing a process on a remote Empire host + 3. Example of an Empire map + 4. Realistic version of an Empire map + 5. Table of sector types and designations + 6. Unexplored island prior to breaking sanctuary + 7. Island showing exploration using theory 1 + 8. Island showing exploration using theory 2 + 9 Island showing exploration using theory 3 + 10. Results from 'show planes capability' + 11. Results from a 'nation' report + 12. Map of region hit by nuclear weapon + 13. Table of types of commodities in Empire + 14. Sample output of 'prod' command + 15. Results of a 'census' command of a library + 16. Map of area requiring some distribution + 17. Results of a distribution command + 18. Map of an area requiring delivery path + + +User's Guide to Empire 6 + +Chapter 1 :-: What is Empire? + + Empire is a game in which you are pitted against several other + players in a country vs. country format. There are economies to + run, armies to support, policies to generate, and allies and + enemies to make. The game supports various features that make + certain aspects of the game seem to parallel the "realistic" + world. These include satellites, planes, banks, parks, etc. + + Empire, in the version herein described, is a very complex + game. The closest game that most people will know that is + analogous to it is the game known as Risk. However, Empire is + more complex by a factor of at least one hundred. Nevertheless, + as a result of the computer aiding you every step of the way, the + game is not difficult to play, though it can be difficult to + learn. If you read this guide thoroughly, and use it as a + continuing resource, you can help make learning this game a lot + easier. + + It should be noted that in learning to play this game, you + may become frustrated or feel daunted by its complexity. + Several players have noted that they almost gave up on Empire, + until one day when everything seemed to start to make sense. + I call it the "threshold level of understanding" after which + learning the art of Empire becomes several grades easier, and + players learn substantially faster. I urge you to stay with + it until you get to that level. It may take some time, but it + is well worth the effort. This guide is intended to get you + to that threshold level of understanding. + + Games usually take two to three months depending on various factors + that are changeable by the person who runs the game prior to its + inception. Some games, known as blitz games, last a day or three + and will wear out your finger tips from typing too much, will cause + your family and loved ones to be tremendously upset with you for + missing breakfast, lunch and dinner for three days straight, will cause + your stomach to argue constantly with you about its right to + food, and are a tremendous amount of fun. Blitz games are not + for the light of heart nor are they meant for the beginner. + + For more information concerning the basic scope of Empire, + refer to the game itself. Within the game, there are + various help entries accessible through the command 'info'. + This guide is intended to go well beyond the scope of help + available from 'info'. + + Empire, the game, has evolved through many different forms + over the last decade. There are still numerous versions + for various computers around. The version herein discussed + is BSD Empire, written for the most part by Dave Pare along + with a lot of help from net people. As release time approaches + I am aware that Mr. Pare is working on BSD Empire V2.0. + This guide is only current to version V1.1.5 of BSD. I wish + + +User's Guide to Empire 7 + + the future author of the guide to V2.0, whomever that might be, + the best of luck and bequeath that person a family size bottle + of aspirin for personal use. + +Summary: Empire is a very complex game that has a rather steep learning + curve. Most of the complexity of the game can be handled by + the commands available to you, the game server itself, or tools + that you use to better your country. Tools are described later + in this text. + + +User's Guide to Empire 8 + +Chapter 2 :-: How to get into a game of Empire. + + The most common way of finding about about games that are about to + happen is by monitoring the newsgroup rec.games.empire on your local + news reading program. Other ways are via e-mail by getting to know + several players with whom you correspond over the network. Some + games are by invitation only but these are few and far between as + usually a game is better with more people in it. If you do not know + how to use your local news reading program, ask a local site consultant + or find a brochure about the news programs available. One of the most + common newsreaders can be reached by typing 'rn' from your unix + prompt. If you have VMS for an operating system this may not be true. + To go directly to the rec.games.empire newsgroup you could type in + 'rn rec.games.empire'. + + Before entering a game of Empire, consider the amount of time that + you have available to play the game. Two hours a day for a four + update per day game is usually the norm. If you are inexperienced, + and have not fought in wars before, that two hours will dramatically + increase should war break out between you and another country. + + Note that it is easy to get addicted to the game. The player should + be aware of this prior to playing. Play in moderation. This is + obviously not meant to scare you off. It is merely a word of caution + to some people. Remember to play in moderation. + + If you do decide to join in an upcoming game of Empire, then you will + have the pleasure of playing one of the best games around. Empire has + been described as being the most complicated game ever created. + Despite the fact that the game was created for computers and has + been in existence for several years, as yet no robot player has been + developed nor is it anticipated. It is possible to build such a + robot, but it would be a huge task. Do not be dismayed though. + Most of the complexity of Empire is handled by the server and client. + There is a fair amount of what is called "micro-managing" that may + need to be done to be a highly successful nation. However, it is + not a necessary thing to do. Furthermore, there are many tools + (described later) that can handle the micromanaging aspects to + a great degree. + + After you find out about a game, and decide that you do want to + play in that upcoming game, you need to contact the "Deity". The + "Deity" is the person who runs the game. You should mail him/her + with information about yourself and your country. A customary + basic form for registering your country to play might contain + the following information: + + Country name: (any name you like, from Brianville to USofA) + Rep: (this is your *password*) + Net address: (the address at which you can be contacted over the net) + Skill level: (1-10..10 being the best, 1 being beginner) + + It might be necessary depending on the Deity to include all addresses + + +User's Guide to Empire 9 + + from which you might be playing. With the proliferation of suns as + general user machines this is becoming more and more a chore, and + few deities require it. It might suffice to say "mickey@*.buffalo.edu" + which might cover all machines you play from if you played from + SUNY-Buffalo. Mickey, of course, is just an arbitrary username chosen + for this example. + + Empire players connect to games in progress through a program known + as a "client". This program handles communication between your + computer and the computer that the game is running on. + + There are several versions of clients available. Some are more + "capable" than others in that they can make decisions easier for + you or make the decisions themselves. They are intended to reduce + the amount of work you have to do to maintain your country though + in some cases they actually increase the amount of work you have + to do. I have listed places from which you can get other types + of clients from in the FTP listings in appendix C. + + Sources for basic client program is available by FTPing to + ucbvax.berkeley.edu. For the user's benefit, I have included + a copy of a session in which a user FTPs to ucbvax, retrieves the + source, compiles the source and establishes the appropriate + environment variables to connect to a game. + + Note that the following example will work ONLY on a unix, + ultrix, or other flavor of unix operating system. This will + not work for the VMS client. + +-------------------------------------------------------------- + +(PLEASE NOTE: Walk through comments in this sample will be enclosed + in [** and **]. They are not part of what actually appeared on screen + in collecting this sample. They are meant only as guides.) + +[** First, I create a directory to put the client in. I then cd into that + directory and then proceed with the ftp to ucbvax. **] + +autarch{tmp}!>mkdir myclient +autarch{tmp}!>cd myclient +autarch{myclient}!>ftp ucbvax.berkeley.edu +Connected to ucbvax.berkeley.edu. +220 ucbvax.Berkeley.EDU FTP server (Version 5.30 Tue Mar 28 18:11:37 PST 1989) ready. +[** Type in anonymous for your name **] +Name (ucbvax.berkeley.edu:mickey): anonymous +[** Send your real identity for the password **] +331 Guest login ok, send ident as password. +Password: +230 Guest login ok, access restrictions apply. +[** I am now logged in to ucbvax's public access FTP area. Now + I cd into the "pub" directory, then the "games" directory, and then + the "bsd-empire" directory where I know the Empire client source + resides. **] + + +User's Guide to Empire 10 + +ftp> cd pub +250 CWD command successful. +ftp> cd games +250 CWD command successful. +ftp> cd bsd-empire +250 CWD command successful. +[** Now, I set my file transfer mode to "binary" and set hash on so that + I can see transmit progress on screen (# = 1024 bytes.) **] +ftp> bin +200 Type set to I. +ftp> hash +Hash mark printing on (1024 bytes/hash mark). +[** Now, I view the directory listing to confirm the name of the client + source. **] +ftp> ls +200 PORT command successful. +150 Opening ASCII mode data connection for .. +empire-1.1.tar.Z +empire-1.1.patch.5 +empire-1.1.patch.4 +empire-1.1.patch.3 +contrib.tar.Z +client.tar.Z +empclient-1.1.tar.Z +[** ^^^^^^^^^^^^^ it's this one. **] +README +emptools.tar.Z +# +226 Transfer complete. +143 bytes received in 0.03 seconds (4.7 Kbytes/s) +[** Now, I "get" the file and the transmission to my directory begins. **] +ftp> get empclient-1.1.tar.Z +200 PORT command successful. +150 Opening BINARY mode data connection for empclient-1.1.tar.Z (20859 bytes). +######################################### +226 Transfer complete. +local: empclient-1.1.tar.Z remote: empclient-1.1.tar.Z +20859 bytes received in 1.8 seconds (11 Kbytes/s) +[** The client source now resides in my directory, so I log out of Berkeley **] +ftp> quit +221 Goodbye. +[** I next confirm that the client is in my directory. **] +autarch{myclient}!>ls +empclient-1.1.tar.Z +[** Next, I have to uncompress the file (the Z postfix means it is in + compressed format). I again ls to confirm it's presence. **] +autarch{myclient}!>uncompress empclient-1.1.tar.Z +autarch{myclient}!>ls +empclient-1.1.tar +[** Next, I have to tar the file (tar postfix means it's in tar format). + Again, I ls to confirm operation completed. **] +autarch{myclient}!>tar -xf empclient-1.1.tar +autarch{myclient}!>ls + + +User's Guide to Empire 11 + +client/ empclient-1.1.tar +[** Ah, ok. I tar'ed the file and it created a directory for itself. + So, I cd into that directory and ls it. **] +autarch{myclient}!>cd client +autarch{client}!>ls +Makefile empire.6 host.c main.c saveargv.c +README expect.c hpux.c misc.h servercmd.c +bit.c fnlist.h ioqueue.c proto.h serverio.c +bit.h globals.c ioqueue.h queue.c termio.c +dtable.c handle.c login.c queue.h termlib.c +[** There's the README file up there. That will tell me what to do next. **] +autarch{client}!>more README + + BSD Empire 1.1 + + +This is the empire client for BSD Empire. + +To make the program, edit globals.c and change localhost to +point at the machine where the game is running. + +Type "make". + +You can change hosts on-the-fly by using environment variables -- see +the man page for details. + +[** Simple enough. I don't bother modifying globals.c since I can modify + the environment variables using the unix command 'setenv'. So now, + I just type 'make' and hope everything goes ok. NOTE: This was done + on a sun4. Your results may vary slightly. **] +autarch{client}!>make +[** Now, it does the compilation automatically without me having to + do it by hand, I just typed the make and it does it by itself. **] +cc -g -sun4 -c bit.c +cc -g -sun4 -c dtable.c +cc -g -sun4 -c expect.c +cc -g -sun4 -c globals.c +cc -g -sun4 -c handle.c +cc -g -sun4 -c host.c +cc -g -sun4 -c hpux.c +cc -g -sun4 -c ioqueue.c +cc -g -sun4 -c login.c +cc -g -sun4 -c main.c +cc -g -sun4 -c queue.c +cc -g -sun4 -c saveargv.c +cc -g -sun4 -c servercmd.c +cc -g -sun4 -c serverio.c +cc -g -sun4 -c termio.c +cc -g -sun4 -c termlib.c +cc -g -o empire bit.o dtable.o expect.o globals.o handle.o host.o hpux.o +ioqueue.o login.o main.o queue.o saveargv.o servercmd.o serverio.o termio.o +termlib.o -ltermlib +autarch{client}!>ls + + +User's Guide to Empire 12 + +Makefile expect.c hpux.c misc.h serverio.c +README expect.o hpux.o proto.h serverio.o +bit.c fnlist.h ioqueue.c queue.c termio.c +bit.h globals.c ioqueue.h queue.h termio.o +bit.o globals.o ioqueue.o queue.o termlib.c +dtable.c handle.c login.c saveargv.c termlib.o +dtable.o handle.o login.o saveargv.o +empire* host.c main.c servercmd.c +empire.6 host.o main.o servercmd.o +[** Walla, it compiled, and now there is a file in the directory called + 'empire' with a * next to it (meaning it's an executable. Not all + ls's will do this, see 'man ls' for further info on parameters for ls). + That file is the client. I could delete all of the '.c', '.h', and + '.o' files right now to clean things up, but I am anxious to get into + the Empire game that is already in progress. So, I next setup my + environment variables so my client knows which computer to call and + which port to use on that computer. **] +autarch{client}!>setenv EMPIREHOST oleander.cs.odu.edu +autarch{client}!>setenv EMPIREPORT 1617 +[** EMPIREHOST and EMPIREPORT variables will have been given to you by + the deity running the game. + With that done, I can now run my client and connect to the game. **] +autarch{client}!>empire +Country name? [** I type in my country name **] +Your name? [** And my password, NOT my real name. **] + + -=0=- + +You have six new telegrams waiting... + +[0:255] Command: +[** And you are now connected to the game and are ready to play dictator **] + + + Figure 1 + Sample of how to FTP and compile a client program + +------------------------------------------------------------------ + + + Since you are playing across a network of computers, it is possible + that there will be problems along the way in connecting to the server + from the computer you play on. What follows are some common connection + errors. + +Problem 1: +autarch{client}!>empire +connect: Connection refused + +Problem This generally means that you have either set your environment + variables wrong (see 'setenv' from earlier in this chapter), or + the server at the host site is not currently running. +Solution (1) Check your environment variables by issuing a 'setenv' command. + + +User's Guide to Empire 13 + + (2) Wait for the server to come up. + +Problem 2: +autarch{client}!>empire +connect: Connection timed out + +Problem This generally means that there is a network outage somewhere + along the network. +Solution (1) You can monitor the network by using two unix commands located in + /usr/etc on most unix systems. These are 'ping' and 'traceroute'. + /usr/etc/ping 128.205.7.3 for instance will send a ping at the + host with ip address 128.205.7.3. If that machine can be reached + from your machine across the network it will return: + 128.205.7.3 is alive + traceroute 128.205.7.3 will request responses from each site along + the way. This is useful for seeing which site along the way is + causing the outage. + (2) This solution is easier, but more frustrating. Wait. + +Problem 3: +autarch{client}!>empire +Country name? +Your name? + + -=O=- +3 country in use by mickey@lictor.acsu.buffalo.edu (pid=5797) + +Problem This one is potentially nasty. It means that another process is + logged into your country. This could be from multiple sources. + 1: Your friend who is playing your country as well. + 2: A process of yours that got accidentally hung. + 3: The network hung your remote process even though your local + process is now terminated. +Solution (1) Go kick your friend in the head :-) + (2) Kill your process 'nicely'. To find the process execute a + 'ps -x' command and find the appropriate process number: + autarch{client}ps -x + PID TT STAT TIME COMMAND + 3555 t1 S 0:00 -usr/new/csh (csh) + 3575 t1 R 0:00 ps -x + 3559 ? S 0:00 -usr/new/csh (csh) + 3560 ? S 0:00 (empire) + The offending process number in this list is 3560. To kill it, + simply type the command 'kill 3560'. After that, all should be + well. Try entering the game again. + (3) If your process is hung on the server machine, you can + do one of two things. First, you can mail the Deity with the + "pid", or process identification number. This number is listed + in the original error message and in our case is 5797. Secondly, + you can log in to the remote site and kill the process yourself + via the process illustrated below. Note that in the first line + of the illustrated process that the name storm.tamu.edu is the + host site for the particular game I am using for this example. + + +User's Guide to Empire 14 + + Also, 1617 is the port on that machine that Empire is being run + through. Commands that you should type in are indicated + by a "<----" at the end of the line. + +------------------------------------------------------------------------------- + +% telnet storm.tamu.edu 1617 <---- +Trying 128.194.15.98 ... +Connected to storm.tamu.edu. +Escape character is '^]'. +2 Empire server ready <---- [** your country name in quotes **] +coun "Terminus" +0 country name Terminus +pass "busyemperor" <---- [** your password in quotes **] +0 password ok +kill <---- [** this terminates the hung process **] +3 process 1056 (from mickey@autarch.acsu.buffalo.edu) terminated +[** next type in 'ctrl-]' and then type 'close' **] +^] +telnet> c +Connection closed. +% + + Figure 2 + Killing a process on a remote Empire host + +------------------------------------------------------------------------------- + + Your process is now unhung, and your country should be ready to play + once again. + +Problem 4: +autarch{myclient}empire +Country name? +Your name? + +Bad password + +Problem The server does not accept the password you typed as being correct. +Solution Try typing it again. Try using capital letters at the beginning of + the password as well, or the entire password in caps. If this does + not work, mail the Deity and inform him or her of the problem + and what the password should be. + +Problem 5: +autarch{myclient}empire +Alarm clock + +Problem Your connection to the server is not responding. +Solution The delay time for waiting for a response that is built into + the client is not exceedingly long. The theory behind this being + that if it is taking you that long to get a response from the + Empire server then it is not worth playing, since response times + + +User's Guide to Empire 15 + + for information from the game are going to be pretty unbearable. + Keep trying is probably the best solution. + + + These are most of the problems that you will encounter in connecting to + the game server. There are some more problems that you might + encounter, but generally they are not common. If you can not reach + your game server for more than a day, contact your deity and let + him/her know that you can not connect. + +Summary: Getting into a game of Empire is not terribly difficult. Setting up + a client program should be a fairly painless task. If it is not, + do not be dismayed. Get help from a consultant or another player + if you can. Some problems with the network may temporarily prevent + you from playing. Be patient, the network is a horse that should + be shot, but generally it comes around after a while. + + +User's Guide to Empire 16 + +Chapter 3 :-: The primitive basics. + + + There are a few basic commands and ideas that will help you get + acquainted with Empire. These are here summarized. + +Concept: Sanctuary. + All players begin a game of Empire in what is known as a sanctuary. +While you are in a sanctuary state you can not be attacked, overrun, or +otherwise hurt. However, while you are in sanctuary you can not do +very many things. In order to really begin playing the game you need +to do what is known as "break sanctuary". You can do this using the +'break' command. When you do this, your two sanctuary sectors (which +everyone starts with) will become capital sectors. You are no longer +protected from attacks from enemy countries. + +Concept: Movement in Empire. + Paths of movement are indicated by several keys. Path indicators +exist in a hex shape around the letter H on your keyboard. Thus, y means +travel North-West, u for North-East, j for East, n for South-East, b for +South-West, and g for West. Also, h means "stop" which terminates movement +of whatever you are moving. There is one other key, v which "views" the +sector you are currently moving through. Thus if I gave a movement path +of gggvgh the game would move whatever I am moving three sectors West, view +the sector at three sectors west of my starting point, then move one more +sector west and then stop. + +Concept: Update + Empire games have "turns" known as updates. When an update occurs, +your country goes through economic growth or decline, interests are paid +on gold bars, military costs are paid for, mobility increases in your +sectors, etc. You can do a great many things between updates, an update +merely does book keeping more or less, at a predetermined time. To find +out when the next update is going to happen, you can type 'update' as +a command. + +Command: map -10:10,-7:7 + This command will give you a map of the area immediately surrounding +your beginning two sectors. Specifically, it will give you a map from ten +sectors West of your 0,0 to ten sectors East and from seven sectors North to +seven sectors South of your 0,0. + +Command: explore civ 0,0 1 + This command allows you to move one civilian from your 0,0 and +"explore" into wilderness and mountain sectors. + +Command: info commands + This command will list the various commands available in Empire. +It is a very good idea to go through the information on each command +by typing 'info '. This will help you get more acquainted +with the game. Though this guide shows many commands and how to use them, +it is no substitute for the game's help itself. + + +User's Guide to Empire 17 + +Command: designate 1,1 + + This command will enable you to designate a sector you own into +whatever you desire. Usually, in the beginning of the game you will designate +sectors that you will not be using actively for a while into highways. +The above shown example of the command will designate your 1,1 sector into +a highway. + +Command: telegram + Countries in Empire communicate with each other via telegrams. +These are private letters sent just like a telegram would be. They have +a size limit, but there is usually more than enough room to say what you +want to say. There is no limit to the number of telegrams you may send. + +Command: announce + Countries broadcast to the world via the command 'announce'. These +announcements are similar to telegrams except instead of one country reading +the telegram the entire world can read it. + +Command: read + This command allows you to read any incoming telegrams or +announcements. Empire will notify you when you have new incoming traffic. + +Command: news {x number of days} + This command will allow you to peruse the Empire newspaper. It does +not make for great reading. However, it is useful for intelligence gathering. +If you just enter 'news' as a command, it will print all the news since you +last read the news. Entering 'news 3' will give you the news for the last +three days. In big games, the news file gets quite large. + +Summary: These are the basic ideas and commands of Empire. Empire has a great + many commands however, and the player should endeavor to learn them. + Empire can be played with only a few commands but the additional + commands are there for your best interests. If you do not understand + a command shown here, simply type 'info ' while in the + game itself. + + +User's Guide to Empire 18 + +Chapter 4 :-: Geography in Empire. + + Maps in Empire are based on a simple hex design. For example: + +---------------------------------- There are three basic sector types in + Empire (note: "type" is different than + / \ / \ / \ / \ / \ "designation". Designation refers to what + / \ / \ / \ / \ / \ that sector has on it, a factory or school +-4 | . | ^ | - | ^ | . | for example. Type refers to what it is + \ / \ / \ / \ / \ / built on). There are: + \ / \ / \ / \ / \ / seas : . +-3 | - | - | . | . | mountains : ^ + / \ / \ / \ / \ / \ wilderness : - + / \ / \ / \ / \ / \ When using the Empire map, you use an "X,Y" +-2 | . | - | - | - | . | system. The X coordinate refers to how far + \ / \ / \ / \ / \ / along the horizontal you are, the Y referring + \ / \ / \ / \ / \ / to the vertical. Thus, there are seas on +-1 | - | - | . | . | example map at 5,-1 7,-1 0,-2 8,-2 + / \ / \ / \ / \ / \ 5,-3 7,-3 0,-4 and 8,-4. Negative X is + / \ / \ / \ / \ / \ to the left (to the East) of 0,0 just as + 0 1 2 3 4 5 6 7 8 in your high school math courses. However, + negative Y is above (to the North of) 0,0. + Figure 3 This is different from high school math. + Example of an Empire map Why the maps have coordinates in this way + is one of the great mysteries of Empire. +---------------------------------- + + Figure 4 below is a real map of Empire, in its real size and form. + Figure 3 is "zoomed in". Note that the '?' marks on the right part of + the map belong to a neighboring country. In this figure all wilderness + type sectors have been designated into something other than a + wilderness There are several mountains, and a lot of ocean visible as + well. + + + +User's Guide to Empire 19 + +-------------------------------------------------------------------------------- + +[309:112] Command : map #1 + 33333322222222221111111111---------00000000001111111111222222 + 5432109876543210987654321098765432101234567890123456789012345 + -3 + + + + + . . . . . . . . + . . . . . . . -3 + -2 a ^ + m ^ + . . . . o . + . . . . . . . . -2 + -1 + + + + + + + + . . . a o a . + + + . . . . -1 + 0 + + + + + + + g o o o + + + . + o c m . . . 0 + 1 + + ^ o + a j m g w g ^ ^ m + j j + . + . . . 1 + 2 + + a + + + + + + + + . b j + m + w + . . . . . . 2 + 3 + a . a a + b + m o j + t + + + + + + . + . + + + . . ? ? ? 3 + 4 . . . . . a g + ^ + m + + l ^ ^ ^ + o + + + + + + + + ? + ? 4 + 5 + . . + + + + + ^ + ^ m + j ^ ^ c + m + + + + + + + ^ + + + ^ 5 + 6 . . . + + ^ + + + + m + + o o + k + + + + + + ^ ^ + + + + 6 + 7 . + + + + + + + + o m + a o + e + + + ^ ^ a + + + + + ? 7 + 8 . + + + + a + ^ + g d m + w m + m + + + + + ^ + + + + ? 8 + 9 . + + + + + + + + + + + k + g t + + + + + + + + ? ? ? ? 9 + 10 . . + + + + ^ + ^ ^ g + + + p g + i g + + + + ? 10 + 11 . + + + + + ^ + + + ^ + + m + g o + g + + + + + ? ? ? ? 11 + 12 . + + + + + + + + + + + g g + + + + g + + + + + + + + ? 12 + 13 . + + + + + + + + + + + + + g + g m + w + + + + + + + + ? 13 + 14 . . . + + + + + + + + + + + g + + m + + + + + + + + + + 14 + 15 . + + + + + + a + + + + + + + + m + + + + + + + a + + + + 15 + 33333322222222221111111111---------00000000001111111111222222 + 5432109876543210987654321098765432101234567890123456789012345 + + Figure 4 + Realistic version of an Empire map + +------------------------------------------------------------------------------- + + The following listing is taken directly from the command + 'info sector-types' in the game. There is a lengthy description of + each sector type also in this command, but I have omitted it here + for brevity. + + +User's Guide to Empire 20 + + +-------------------------------------------------------------------------------- + + +BASICS INDUSTRIES MILITARY / SCIENTIFIC + . sea d defense plant t technical center + ^ mountain i shell industry f fortress + s sanctuary m mine r research lab + / wasteland g gold mine n nuclear plant + - wilderness h harbor l library/school + c capital w warehouse e enlistment center + p park u uranium mine + COMMUNICATIONS * airfield FINANCIAL + + highway a agribusiness b bank + ) radar installation o oil field + j light manufacturing + # bridge head k heavy manufacturing + = bridge span % refinery + + Figure 5 + Table of sector types and designations + +------------------------------------------------------------------------------- + + As you can see, there are a wide variety of sector types in Empire. + However, until your country becomes populated the most useful sector + is the highway ('+'), for it allows you to move things around easier, + even if the highway has only begun being constructed + (ie, 0% efficient). + +Summary: Empire maps are based on a simple hex design, with the movement + keys based similarly around the letter h on standard keyboards. + These movement keys are a basic tool in Empire and must be learned. + + +User's Guide to Empire 21 + +Chapter 5 :-: The beginning phases of Empire. + + + Typically a game starts with a `speed' phase. If it does not, then + initial play can get boring quickly. A `speed' opening also demands + more time for the period when the updates are frequent, but hopefully, + that will be balanced by your efficient country and the less time + spent running it when your classes/real life demand more time. + + There are several opening strategies for Empire players. I am going + to go through a few of them here. If you feel you can make a better + strategy feel free to do so. + + Basically, all strategies for the opening phases revolve around a + few basic ideas. First, you want to secure as much land for yourself + as possible. Secondly, if you share an island with some other person, + you want to leave yourself in a strategically advantageous position + against your opponent, optimally to surround him/her before s/he breaks + sanctuary. These two ideas are the most important things to consider + prior to the first update. There are other things to consider, which + will be reviewed later. + + It is highly important for you, the player, to begin playing the game + as soon as the game begins. If you do not, you risk being surrounded + before the first update. Furthermore, not breaking sanctuary prior to + the first update can cost you a great deal in terms of population + growth and the establishment of your economy. + + Some players will use tools, which are reviewed in chapter 14, to + break sanctuary and occupy land from the beginning. There are other + means to aid your land occupation as well. If you have a programmable + terminal, or terminal program, you can program a key to contain a + particular command such as "explore civ 0,0 1 jjjujuuu". This could + be a path along a line of land that you have already occupied, and + wish to expand beyond. If you had to repeatedly type in that command + and path you would take a much greater amount of time to occupy land. + This can also be done through X windows, using the mouse and cut/paste + capabilities. + + There are a few different theories on how to explore out from your + sanctuaries to claim as much land as possible for yourself. + + In the following maps, the square island shown is entirely wilderness + except for the two sanctuaries in the middle. It is important to note + that prior to exploring the entire island, the only thing you would + be able to see on your map would be this: + + +User's Guide to Empire 22 + + + - - - - - + - - - - - - + - - - - - - - + - - - s s - - - + - - - - - - - + - - - - - - + - - - - - + + It is your job to explore the island, while occupying, or securing for + yourself, as much land as possible. Note that for the sake of + simplicity I have not placed another country on this example island. + If a sector is a "+","c", or "s" it is an occupied (by you) sector. + If it's a "-" it's a wilderness sector, and if you can move into it, + it is unoccupied. This is an important piece of information. If you + can note move into a wilderness sector it means that it is occupied by + another country. Note that "." are seas, as indicated in chapter 5. + The basic commands to complete this exploration are 'explore' and + 'designate'. Learn about those commands either from chapter 4 or + the game before attempting these theories. + + First, I show the entire island prior to your breaking sanctuary and + exploring: + +-------------------------------------------------------------------------------- + + . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . + . - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - . + . - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - . + . - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - . + . - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - . + . - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - . + . - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - . + . - - - - - - - - - - - - - s s - - - - - - - - - - - - - - - . + . - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - . + . - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - . + . - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - . + . - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - . + . - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - . + . - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - . + . - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - . + . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . + + Figure 6 + Unexplored island prior to breaking sanctuary + +-------------------------------------------------------------------------------- + + Next, I show theory 1, occupying in a concentric circle. + Note that once you have broken sanctuary (using the 'break' + command) that your two sanctuary sectors immediately become + capitals, with your real capital at 0,0. + + +User's Guide to Empire 23 + + +-------------------------------------------------------------------------------- + + . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . + . - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - . + . - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - . + . - - - - - - - - - - - + + + + + + - - - - - - - - - - - - - . + . - - - - - - - - - + + + + + + + + + - - - - - - - - - - - - . + . - - - - - - - - - + + + + + + + + + + - - - - - - - - - - - . + . - - - - - - - - + + + + + + + + + + + - - - - - - - - - - - . + . - - - - - - - - + + + + + c c + + + + + - - - - - - - - - - . + . - - - - - - - - + + + + + + + + + + + - - - - - - - - - - - . + . - - - - - - - - - + + + + + + + + + + - - - - - - - - - - - . + . - - - - - - - - - + + + + + + + + + - - - - - - - - - - - - . + . - - - - - - - - - - + + + + + + + + - - - - - - - - - - - - . + . - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - . + . - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - . + . - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - . + . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . + + Figure 7 + Island showing exploration using theory 1 + +-------------------------------------------------------------------------------- + + So far, 84 sectors have been occupied. Now I show theory 2, + occupying in spokes with concentric hexes spaced every few sectors + apart: + +-------------------------------------------------------------------------------- + + . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . + . - - - - - - - - - - + + + + + + + + - - - - - - - - - - - - . + . - - - - - - - - - + + - - - - - + + - - - - - - - - - - - - . + . - - - - - - - - - + - + - - - - + - + - - - - - - - - - - - . + . - - - - - - - - + - - + + + + + - - + - - - - - - - - - - - . + . - - - - - - - - + - - + + - - + + - - + - - - - - - - - - - . + . - - - - - - - + - - + - + + + - + - - + - - - - - - - - - - . + . - - - - - - - + + + + + + c c + + + + + + - - - - - - - - - . + . - - - - - - - + - - + - + + + - + - - + - - - - - - - - - - . + . - - - - - - - - + - - + + - - + + - - + - - - - - - - - - - . + . - - - - - - - - + - - + + + + + - - + - - - - - - - - - - - . + . - - - - - - - - - + - + - - - - + - + - - - - - - - - - - - . + . - - - - - - - - - + + - - - - - + + - - - - - - - - - - - - . + . - - - - - - - - - - + + + + + + + + - - - - - - - - - - - - . + . - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - . + . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . + + Figure 8 + Island showing exploration using theory 2 + +-------------------------------------------------------------------------------- + + + +User's Guide to Empire 24 + + Now, 84 sectors have once again been occupied. However, an additional + 56 sectors are now within the borders of your country. Thus, securing + a total of 140 sectors for yourself. The disadvantage? You have three + lines of occupation ( the "+" sectors) between the center of your + country and unsecured wilderness. In theory 1, the same number of + sectors provides for 4 lines for most of the country. Another + disadvantage is that it costs more mobility to use theory 2. The more + lines of occupation you have between the central areas of your + country and the unexplored wilderness or an enemy the easier it is + to defend your country. + + A third theory is the idea of coastal occupation as a means of securing + a large island. The idea being to secure the land immediately around + you and then explore in one direction until you find seas, and then + proceed to occupy the coast: + +------------------------------------------------------------------------------- + + . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . + . + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - . + . + - - - - - - - - - + - - - - - - - - - - - - - - - - - - - . + . + - - - - - - - - - - + - - - - - - - - - - - - - - - - - - . + . + - - - - - - - - - - + - - - - - - - - - - - - - - - - - - . + . + - - - - - - - - - - - + + + + - - - - - - - - - - - - - - . + . + - - - - - - - - - - + + + + + - - - - - - - - - - - - - - . + . + - - - - - - - - - - + + c c + + + + + + + - - - - - - - - . + . + - - - - - - - - - - + + + + + - - - - - + - - - - - - - - . + . + - - - - - - - - - - - + + + + - - - - - - + - - - - - - - . + . + - - - - - - - - - - - - - - - - - - - - - + - - - - - - - . + . + - - - - - - - - - - - - - - - - - - - - - - + - - - - - - . + . + - - - - - - - - - - - - - - - - - - - - - - + - - - - - - . + . + - - - - - - - - - - - - - - - - - - - - - - - + - - - - - . + . + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - . + . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . + + Figure 9 + Island showing exploration using theory 3 + +-------------------------------------------------------------------------------- + + Here, once again, 84 sectors have been occupied. In addition, 179 + sectors of wilderness have been secured, ie cut off from another + country. This brings a total of 263 sectors occupied or secured. + This is obviously impressive. However, it has its drawbacks as well. + If there was a country bordering this country, that country would + need only to attack and occupy one of your sectors and then they + could explore into all of the "secured" sectors. In addition, there + are only 2-3 lines of occupied sectors between the borders and the + center of the country. This also costs more in terms of mobility than + either theory 1 or 2. + + The next section contains a strategy submitted by Scott Yelich. Scott + adheres in this summary to theory 1 as his method of exploration: + + +User's Guide to Empire 25 + + + "Designate one of the two initial [sanctuary] capital sectors to +an agricultural center. Then move a civ out from either sector to +either 1,-1 or 1,1 and designate it a +. Then, I continue to move out +one civilian at a time from both of my initial sectors. Only move +the civ one spot into the wilderness and then I designate that sector +as a highway (+). Then, do a map to see if there is anything +especially interesting... such as, a mountain, more land or ANOTHER +PLAYER. Of course, Only do that map at certain times... it's not +necessary to do a map after EVERY explore since explore will show you +a one sector radius! + +[Editor's note: exploring with one civilian across a wilderness sector +takes .8 mobility. Across a highway, even a 0% highway, it will cost +only .2 mobility. Thus, the reason for designating new land as soon +as you occupy it. You will conserve mobility if you only explore into +lands bordering your new highways.] + + "Here is where quick action comes into play. If you spot any controlled +sectors (?) or a (-) that can't be entered (if you can note move into the +sector it is occupied by someone else! hurry!), try to make a boarder as +quick as possible by following the pattern above... move one civ, look, +repeat. If you don't find any controlled sectors, simply [try] to +AVOID MOUNTAINS at ALL costs... especially during the first couple of +updates. Typically, from 30 to 70 sectors can be grabbed this way +within the first minute or two. + + "To sum up, the strategy for this is: 1) You want to see who is out there, +2) You want to see what land is out there, 3) when you take more sectors +during the initial updates, you will get more mobility each update +(typically 8, 'version' will tell...). Anyway, the more sectors you grab +with the first update, the more you can grab the second. It's like an +exponential function." + + + This next section is a strategy submitted by Geoff Cashman. Geoff + adheres in this summary to theory 2 as his method for exploration: + + "The basic strategy of moving one sector into the wilderness and then +designate them with a command such as this: designate #1 ?des=- + which will +designate all sectors in realm #1 that are wilderness into highways, is a +common one. Using it wisely is not always done. My personal method is to +expand only in a few directions, ie 3-6 different directions from your 0,0 2,0 +area. The idea here being to make "spokes" of exploration radiating out from +your 0,0 and 2,0 area. Using this method, you can use less mobility and see +more land though not actually own more land until after the first update. +Another advantage is you might reach an opponent before s/he reaches you. A +weakness is that an opponent can explore inbetween your spokes. If I feel +this is possible inbetween two spokes then I connect the spokes via concentric +(on 2,0 0,0 ) arc several sectors out from the 0,0. If you do not use this +method, then you would use up all of your mobility to achieve the same number +of sectors by the second update. + + + +User's Guide to Empire 26 + + "Why save mobility? Mobility in the 0,0 sector is especially critical. +The reason is because the 0,0 starts out with 999 civs. If a sector has +999 or more civs it will not give birth to more civilians. Half of the +battle in winning Empire is population explosion at the beginning of the +game...ESPECIALLY if you get involved in a low tech war with a neighbor +early on. More population means more resources mined, more supportable +military, and more taxpayers. If you are going to be a tech producer then +it may be desireable to limit population, but early on I do not recommend +it. So, with 999 civs in your 0,0 sector you need to be able to move out +many civs (depends on the number of ETUs per update (see the version command) +as to how many you should move out, see number of births per 1,000 civs per +etu in the version command). Thus, my strategy is slightly different. +I concentrate on getting a 100% highway built at 1,-1 or 1,1. Why those +sectors? because I can then use the mobility in 1,-1 or 1,1 to move civs +or products into 2,0." + + + The use of the third theory requires a player with some experience + to deal with its shortcomings. For the beginner, I do not recommend + it. + + The following was submitted by another player to point out their means + of establishing their production and the beginning stages of their + economy: + +"Setting up a distribution network, even with inefficient warehouses, is +fairly critical early on. If you starve civilians in the beginning of the +game, you will fall behind in production. It is not uncommon to lose +contact with the game for a day or more due to net failures. Do not +depend on your capability to connect to the game to feed your civilians. + +"Some people never leave their 0,0 or 2,0 designated as a capital during the +beginning of the game. They check the resources in 0,0 and then determine if +it's suitable for being a mine or a gold mine. If neither, then they designate +2,0 into a mine. If mine, then 2,0 becomes a gold mine. Using this method +they can get maximum production from their civilians that are essentially +trapped for the time being in their 0,0 and 2,0 sectors due to lack of +mobility. Note that in doing this that you must conserve BTUs. Having +a 0% efficient capital somewhere else will cause a lack of production of +BTUs. You must be careful not to run out of BTUs completely, or it could +cause you a great deal of grief. + + +"NOTE: IT IS EXTREMELY DANGEROUS TO LEAVE A CAPITAL ON THE COAST AFTER +ANYONE PRODUCES A BOAT. Until that time, a capital on the coast is +an advantage in some ways. It is easier to defend (less places that +it can be attacked from). You MUST get some civilians into the capital +at -2,0 (about 50) before the first update along with some food. +In general, your capital will not produce BTUs for a while, but neither +do you need them for a while. However, leave your 0,0 sector as your +capital until JUST prior (like 2-4 minutes, make it 10 to be safe) to +the update. Does this all sound complicated? Yep. But it works. + + + +User's Guide to Empire 27 + + +"After the first or second update I will occupy the remaining wilderness +that I can see, using the mobility from the sectors that I explored into +in the previous update. I will then continue to move civs out of 0,0 and +into 1,-1 or 1,1 (the highway that I am trying to make 100%) and move from +there. If I am not going for tech production then I don't need the library +or parks (you can still make education, it helps in some regards, but for +the most part you don't need it if you are not going the way of tech. + +You can then pretty much do as you please and work towards the goals you +think are reasonable for your country. " + + One matter that can not be overlooked by any player is the simple + fact that people need food to survive. If a sector has less than + 60 people in it total, including civs, soldiers, and uws, then it + will not starve. But if after the update it has more than 60 total + people will starve. Make sure to feed your people! + + Ultimately, you want to take over every sector on your island. + If you have neighbors on your island, you will probably have to share. + Just try to get a bigger portion of it than your neighbors do. + +Summary: There are several basic ideas expressed in this chapter: + 1) Break sanctuary as soon as the game begins. + 2) Secure as much land for yourself as possible. + 3) Use your civilians efficiently. + 4) Do not allow your 0,0 sector to have a lot of civs in it. + 5) Get a distribution system set up early (explained later). + + + +User's Guide to Empire 28 + +Chapter 6 :-: Diplomacy. + + It's your own ruin or success. One of the best players of the game + (who shall go un-named) has had severe problems due to lack of skill + in diplomacy. Remember, there is another person on the other end of + that telegram. They are human like you are, and like to be treated + like it for the most part. There are jerks, and there are non-jerks. + Determine for yourself and go along with what you think is best, but + remember, it is ok to lose a few battles so long as you win the war. + A diplomatic loss can be an overall victory. + + One of the most powerful weapons in the game is information. + What types of information can you use to your benefit? Information on; + the locality of other countries, the plans of opponents, the trading + going on between certain countries, etc. There is also a very powerful + tool right here in this document: how to play the game well. There + was a classic case of a country (myself) who accidentally announced + his attention to attack a bordering country. The bordering country + happened to be on, an began an attack. The attack stalemated for the + most part because of the obvious inexperience of the person running + that country. I offered information to him on how to play the game + better in exchange for his surrender and some other terms of agreement. + I turned a horrendous diplomatic mistake into a diplomatic success + within two hours. This is obviously the rare case (surprised me too), + but is a good example of the power of information. + + Another aspect of diplomacy is style. You project a style in your + telegrams and announcements whether it is intentional or not. If + people like you they tend to side with you more than the next guy. + Of course, if you are a jerk but a powerful one people tend to + reluctantly side with you. Then again, they are more likely to + backstab you. + + While I am on that subject: Backstabbing is a bad idea in general. + It leads to distrust of many players with regards to yourself and tends + to give yourself backstabbist's wrist if you do it too much. Even if + you change your country name from game to game people tend to pick + out who the major jerks are and their previous names or even net + addresses. Trust is important. If you have allies you can trust + implicitly you will sleep a lot better at night and also have people + who you can trust to run your country for you while you are away for a + few days pursuing real world goals. If you are going to backstab + someone crush them while you can and make sure their allies can not + get at you. Furthermore, make the world see that the person was a + fool for trusting you in the first place (like, due to previous war + or some such). Sometimes, that extra attack you get without + interference from automatic defenses due to a declaration of alliance + with your opponent can be critical. You can also map an opponent + country if you are allied with them and they will never know it. + Thus another good reason why you should be trustable and can trust + other close allies. Having allies is important, especially + in the current market games. + + + +User's Guide to Empire 29 + +A) What is diplomacy? + The dictionary defines diplomacy as "1: The art and practice of + conducting negotiations between nations. 2: Skill in handling + affairs without arousing hostility." The second definition may + not be entirely accurate in that in Empire, diplomacy can sometimes + be used to cause battles, rather than avoid them, to gain a particular + end. I will go into this later. + +B) What purpose, diplomacy? + Since Empire is a multi-user game the diplomacy side of the game + is one of the main factors inherent to its playing. Being able + to interact with other players, make bargains, treaties, alliances, + sales, war, etc. leads to an incredibly variety of possible + scenarios among various countries. In asking, what purpose is + there to diplomacy, it must first be realized that diplomacy in + the game of Empire is virtually unavoidable. To what degree + you involve yourself in diplomacy is the true measure. + + Diplomacy can be utterly disastrous for you. It can also be + very beneficial. It can also be a mediocre tool that goes mostly + unused. If you master the techniques of diplomacy you will find + yourself with a very valuable and powerful tool. If you fail + at grasping the basic concepts of diplomacy, then you may find + yourself the quick victim of a diplomatic trick. + +C) General types of relations amongst nations in Empire + 1) No contact. The two countries have never been in contact. + 2) Allies. Several types: + a) Old friends, or local site friends. + b) People whom you trust more than other people + in the game, but are not entirely comfortable with. + Nevertheless, you ally with them for lack of allies. + c) Enemy allies. People whom you ally with whom you + intend to attack. + d) Undeclared allies. You conduct a lot of business with + the country, but you do not officially declare your + alliance. + 3) Hostile. Generally speaking, any country who is unfriendly + towards you. May not necessarily be declared hostile. + 4) At war. If you have not figured out what this means, stop + reading, never play Empire, and go back to elementary school :-) + 5) Neutral. The broadest category. You've dealt with this person + but have not decided one way or another your relations. It might + be a person from a previous game or a total unknown. + +d) Types of diplomacy + 1) Active diplomacy + You interact with the country on a very high level. Whatever + their relations with you, a lot of correspondence is going on. + This is probably the easiest form of diplomacy to invoke. + 2) Passive diplomacy + Low level contact only. In essence, you do not work with + this country. Some goals served by this: Country in question + + +User's Guide to Empire 30 + + learns little about you; Country in question may give you more + info than you give him or her; etc.. + 3) Indirect diplomacy + Diplomacy through a middle country to another country. This + is most often seen in situations where a known friend is an + ally of a country you want to be allied with. You attempt + to use your friend to convince the prospective ally to ally + with you. + 4) Median diplomacy + Being the middle person in a triad or more of allies that + may not be already allied. This can be a VERY dangerous + position to be in. The other sides of the triad or more + may have certain expectations of you, which go against what + another country may want from you. This is essentially + sitting on a fence. + +E) Some goals that can be achieved through diplomacy: + 1) Getting another country to ally with you so that you can + overfly his country at will without planes scrambling. + 2) Getting two countries whom you dislike to go to war against + each other. + 3) Getting another country to perform an act that is beneficial + to you or your allies. + 4) Getting a reduction in price of certain commodities or articles + from another country. + 5) Gaining an ally. + 6) Assisting in destroying an enemy. + + + + One of the most dangerous means by which diplomacy can be used was + written about in the book "Red Storm Rising" by Tom Clancy. If you + have not already read this book and you are an Empire buff, it is + strongly recommended reading. This method is referred to as "The + Maskirovka" or "Masquerade". It is often referred to as the "big lie" + by the victims of this trick. Essentially it works as follows: + + a) You wish to attack another country, but would like to have things + sightly different before the attack begins. + o You may want that person to be your ally before the attack + so you can overfly him/her without being shot down. + o You might want to get him/her to give you a loan prior to + your attack. + o You might want them to move their fleet off in another + direction or in closer to your forts. + o You might want them to give you certain materials of war + that you can use in your attack against them. + All of these things and much more can be accomplished with + the concept of maskirovka. Decide what you want to achieve. + b) You set out to give the impression to the target country that you + are in a particular state of matters. This can be accomplished + in various ways depending on what you are trying to achieve. + You can have another country attack you for instance to make it + + +User's Guide to Empire 31 + + appear that you need military arms or supplies to hold them off. + This is one small example of what can be done. Ensure that the + image you are presenting can ultimately lead to getting what you + want to achieve accomplished. + c) You must be convincing in your impression. Use all means reasonable + to ensure the target country is getting the right image. Using + e-mail with collaborating countries to coordinate such matters + is often best. + d) As you begin feeling that you have achieved the correct image, + begin asking the target country for whatever it is you are trying + to achieve. Do not come right out and say it. That may cause + the whole trick to collapse on you. Approach it sideways so to + speak, and try to get the target country to offer whatever it is + without you directly asking for it. + e) If the country agrees to the transaction of events you are seeking, + all is well and good. You have achieved your goal. Keep in mind + that if you have played the maskirovka well, you have not yet + committed yourself in any particular direction with any sense of + strong commitment. At this point, you can always back down from + your further goals for which the maskirovka was designed to help. + The maskirovka at this point will have given you a more favorable + situation without having committed yourself. It may also have + enabled you to see more into the mind of your opponent, often + a valuable commodity. + f) If you have failed in your maskirovka, you may still have made + some gains. You again might know more about your opponent than + before. You might have reached some of your goals that the + maskirovka set out to accomplish. Lastly, you have not committed + yourself in any particular direction, yet you have tried to + enhance your position. Not a bad proposition. + + There are many variations to maskirovkas. The guides listed above are + very general at best, and are meant more to give you an idea of how to + build a plan for maskirovka than anything else. + + Chess players who have ever played in matches or tournaments will + probably feel right at home in scheming a maskirovka. You must try to + get into the mind of your opponent, understand what s/he sees from + his/her vantage point and get a feel for how you think s/he will + respond. You must think as if you were your opponent. Understand + their vantage point as best as you can. Do not think of what you + would do in a given situation, think what they would do. Think + consequences to every action you can take. + + This usage of diplomacy is "active diplomacy", sometimes mixed with + "indirect diplomacy". + + Another oft seen ploy of sorts is one in which you befriend a dying + rich country. They may be on there way out, and there may not be a + whole hell of a lot you can do for them. However, befriending them + towards the end may bring you gifts of money or lower market prices + from them when they dissolve. Show sympathy for their situation. + You can be sincere, or you may chose not to be. Sometimes a dying + + +User's Guide to Empire 32 + + country has no friends to whom they will leave their money. If your + the first to show sympathy, they may be willing to give you much in + return. This is an active form of diplomacy, but is rarely seen + except after a long period of passiveness relative to that country. + + Posturing. Probably the most common form of diplomacy. This basically + means presenting an image to a possible attacker that you are more + capable than you appear. In general, people tend to believe it. + Consider the simple fact that generally speaking a good Empire player + spends a lot of time working on his or her country. Then, let them + believe through posturing that they are at a greater risk than + they actually are. They may tend to get possessive about their + country and not want to risk its destruction and the eventual loss + of so many sleepless nights and hours building the country in the + first place. + + +Summary: Diplomacy is a powerful tool. Some players consider it the + most powerful aspect of the game. In many ways that can be shown + to be true. However, do not let other facets of your country + decline and spend a huge amount of time building an excellent + diplomatic situation. The success or failure of diplomacy depends a + great deal on the other players perception of your words. If your + diplomacy fails, you may find that you will be forced to back up what + you say with military force. + + + +User's Guide to Empire 33 + +Chapter 7 :-: Setting up your defenses. + + There are various means of "automatic" defense that Empire employs + against enemy invaders. These can be outlined in three major areas: + + 1: Home air defenses + + Empire has numerous planes and plane capabilities. The higher + your tech level, the better the planes you can build. For + automatic defenses you are concerned with planes that have the + "intercept" capability listed next to them in the command, + 'show planes c'. + + Generally speaking, as some games diverge from this list, the + planes that have intercept capability are: + a: Fighter 1 (also has VTOL capability) + b: Fighter 2 + c: Escort 2 (in SOME games) + d: Jet fighter + e: Jet fighter 2 (also has VTOL capability) + + These planes are based out of airbases (except for the VTOL + planes which can scramble from airbases and non-airbase + sectors) and will automatically intercept incoming enemy + planes. + + notes: 1: Planes will only scramble if there is petrol in + the sector they are scrambling from. + 2: Airbases must be at 60% or better efficiency to + scramble. This does not apply to other sectors + from which VTOL planes are scrambling, nor does it + apply to VTOL planes in airports. + + In this version of Empire it is VERY important to have a good + home air defense network. Having a great many planes with + intercept capability without proper planning is not a good + defense. You must learn to use the planes wisely. + + Hints for good home air defense: + 1: Have airports within intercept range of each other. + A plane's intercept range is 1/2 of its range indicated + in the command 'show planes c'. For example: + + +User's Guide to Empire 34 + + +------------------------------------------------------------------------------- + +[513:36] Command : show planes c + acc load att def ran fuel abilities +Sopwith Camel, fight 30 1 3 2 6 1 tactical intercept VTOL light +TBD-1 Devastator, lt 30 2 1 2 8 1 bomber tactical VTOL light +C-56 Lodestar, trans 0 7 0 1 15 2 cargo +B-26B Marauder, hvy 85 6 2 3 15 2 bomber + + Figure 10 + Results from 'show planes capability' + +------------------------------------------------------------------------------- + + In this list of planes, only the Sopwith Camel plane is + capable of interception. It has a range of 6, and thus + it can intercept enemy planes up to 3 sectors away from + the sector it is based in. Have your planes based in + sectors that are three sectors away from each other. + 2: Always have a substantial number of military in your + airports. It is all too easy for an enemy to track + down your airport and capture it, thus possibly destroying + all your planes, and in the very least taking them + from you. + 3: Ensure that all sectors that you have planes based in + have a sufficient amount of petrol for them. Note that in + the above figure, the Sopwith Camel uses 1 fuel per + mission. Thus, having 10 or more petrol per Sopwith + would be sufficient. + 4: Do not base your entire defense on non-VTOL capable + interceptors. If you do, then your enemy can remove + your air defenses just by taking out your airports. + Sopwith Camels (Fighter 1s) and Jet Fighter 2s are + the VTOL intercept capable planes. Sopwith Camels + generally become useless for intercept duty as the + game wears on. After all, a paper airplane can not + put up with cannon fire from an F-15 for very long! + 5: It is a good idea to have each sector in your country + covered by at least two airbases (or non airbases from + which your are basing VTOL planes). This makes it more + difficult for your enemy to locate where your airbases are. + + 2: Forts and guns + + Forts will automatically fire on any enemy army units that + attack land of the defending nation, assuming that the guns + in the fort have the range to reach the aggressor. This + also assumes that the fort has shells and military. + + Fort gun range is determined by multiplying the number of guns + in the fort by the technology factor of the nation. This + number can be found in the nation report [see command: nation]. + + +User's Guide to Empire 35 + + Here's an example of calculating your gun range: + +-------------------------------------------------------------------------------- + +[77:144] Command : nation + + Terminus Nation Report Sun Oct 20 18:27:08 1991 +Nation status is ACTIVE Bureaucratic Time Units: 144 +100% eff capital at -3,5 has 999 civilians & 0 military +# 0 -70:-40,-30:-16 # 1 -35:25,-3:15 # 2 -30:15,-4:7 +# 3 -45:5,7:22 # 4 -45:5,7:17 # 5 -65:-20,-31:0 +# 6 -65:-20,-12:0 # 7 -80:-30,-5:10 # 8 -8:10,-5:5 +# 9 -32:32,11:22 #10 -50:18,-12:10 #11 -40:-10,-5:5 +#12 -38:29,-3:23 #13 -65:30,-18:6 #14 -20:20,16:22 +#15 -30:30,-3:23 #16 -40:20,7:25 #17 -80:30,-30:23 + The treasury has $57485.00 Military reserves: 1676 +Education.......... 17.78 Happiness....... 13.42 +Technology......... 52.78 Research........ 1.44 +Technology factor : 40.66% Plague factor : 1.51% + + Figure 11 + Results from a 'nation' report + +-------------------------------------------------------------------------------- + + To calculate the gun range, multiply the number of guns in + the fort (up to a maximum of seven) by the number listed in + "Technology factor" which is shown in this figure as 40.66. + Then, divide the resulting number by one hundred and that + is the number of sectors away the gun can fire at. In this + case, if you have seven guns the resulting range is 2.85 + sectors. Effectively, the fort can fire just short of three + sectors away. + + There is an additional aspect of forts which make them + useful as defensive sectors. Military forces inside of + a fort have four times the defensive factor of military in + most other sectors. Ie, 100 soldiers in a fort is equal to + 400 regular troops if they are defending the fort. + + Also note that forts can not be taken by paratroops dropped + from planes. They can only be taken via amphibious assault + and overland attack. + + Forts are generally useful along your border sectors early + in the game and later on in the game throughout your country. + Ensure that they each have sufficient (seven or more) guns + and shells each, when you are able to devote that many guns + and shells to them. Forts are sometimes very critical when + your country is being over run. + + + +User's Guide to Empire 36 + + 3: Naval support + + Your navy will defend itself if it has the capability to do + so. Ships do not automatically come with guns when they are + built; they must be provided with guns and shells by loading + them onto the respective ship. Most ships have the capability + to fire guns. Should a ship of your nation be attacked, it + will defend itself if it can. In addition, ships within range + will also retaliate. Note that submarines will *not* fire + no matter how often they are fired at. + + Ships will not defend your land sectors. + + If ships are attacked from the air, they will fire their + anti-aircraft guns (which are the same as your regular guns, + and again are not automatically installed upon their + construction). Anti-aircraft guns on ships are pretty much + worthless on defense. Additionally, if enemy planes fly + over your ships but do not attack those ships, your ships + will not fire on them. Thus having a line of ships as + radar pickets will not work. + + In addition to these three major modes of automatic defense, there + are a few more minor ones. + + Any gun in any sector of yours that is overflown by enemy planes + will fire on those planes if it has shells, guns, and military + available. + + Military in any sector of yours that is attacked will automatically + fight back to the best of its ability. There is no such thing as + retreat in automatic military fighting. In addition, there are three + sectors which multiply the effectiveness of military within them. + We have already mentioned forts in this capacity, in that they + multiply the effectiveness of troops within them by four. Capitals + and Banks multiply troops effectiveness by two, when on the defensive. + + Also note that Capitals and Forts, as previously mentioned, can not + be taken by airborne paratroopers. Neither can mountains. + + Lastly, should sectors of yours be taken, the enemy will have to deal + with your patriotic guerillas. Guerillas will attempt to retake + sectors from the enemy every update until they are defeated (which + takes some time). They are large in numbers, but have been known to + reach strengths of a hundred or more soldiers, though this is rare. + If they can not hope to retake the sector they may try to blow things + up in the sector the enemy has conquered. This results in loss of + efficiency to the sector as well as reduction in the work capability + of the sector. + + You have *no* control over your guerillas whatsoever. They are + completely automatic. Should guerillas win a sector back from your + enemy then the surviving guerillas become members of your regular + + +User's Guide to Empire 37 + + military, and you can use them as such. + + If your guerillas manage to take a sector back behind enemy lines + it is possible for you to enlist reservists in that sector. In + so doing, you may throw a major thorn into the side of your attacker. + This is a major reason for maintaining a large amount of reserves. + +Summary: Automatic defenses in Empire are a critical part of every country. + If your country can not defend itself then you can expect to be + quickly over run. Use the automatic defenses described in this + chapter, and you will become a more difficult opponent. Remember + the three basic areas of automatic defense. In addition, keep in + mind that your airforce is probably the most important component of + your automatic defenses. + + + +User's Guide to Empire 38 + +Chapter 8 :-: Nuclear warfare. + + Nuclear war in Empire is not currently the dreaded end of the world + doomsday machine it is in the real world. Nuclear weapons in the + standard release of Empire have no fallout, no radiation, no dust + clouds, etc. Nuclear weapons in Empire are essentially big + conventional bombs. They are "clean" weapons in that the only + difference between them and conventional bombs is that they are + bigger and create nuclear wasteland. + + As such, a nuclear war is much more survivable. + + There are several things that you need in order to wage nuclear + war against an enemy. First, you need the nuclear warheads themselves. + You will also need a missile or plane of sufficient type and range to + launch the warheads on. Lastly, you need to have target information, + ie where to land the nuclear warhead to cause the damage you want it + to cause. + + Next, you need to decide if it is worth the cost to wage a nuclear + war. Should the enemy country know where you are, and have the means + to retaliate in kind, s/he will most likely do so. This can cause + grave damage to your own country, and eliminate any gains you may have + achieved by beginning a nuclear war. + + There is also the large chance of great diplomatic cost. Most + countries do not tend to favor countries that rely on nuclear weapons + for victory, since it is the "easy" way out. + + However, the scenario that the beginner needs to be most concerned + about is being the victim of a nuclear attack. Most beginners never + come close to achieving enough strength to have an effective nuclear + force. It may take several games before you become practiced enough + to maintain an economy and military that is capable of having the + resources, etc. necessary for such a force. Nuclear weapons can be + bought from larger powers, however the beginner still rarely tends + to have these. + + In the event that you are attacked with nuclear weapons you need + to take immediate steps in order to ensure your survival. You must + first decide if it is in fact worth it for you to continue. Most + nuclear attacks are survivable. In many cases, you may be hit by + only one warhead. Depending on the size of your country, a small + number of warheads hitting you is survivable. This all assumes the + warheads are of the 5mt variety. 5mt warheads create a wasteland + that is 5 sectors long from left to right. 3mt warheads create + wasteland that is 3 sectors from left to right. Diameter in both + cases is the same north-south as east-west. These are the only + nuclear weapons that can really create serious problems for you. + Other nuclear weapons cause problems, but are essentially nuisances + that can be easily overcome. + + The following is a map of your -20:0,-10:3 region. You have been + + +User's Guide to Empire 39 + + hit with a 3mt nuclear warhead at your sector -12,-6. It wastelanded + 7 of your sectors and damaged nearly the entire area. + +-------------------------------------------------------------------------------- + + 21111111111---------- + 098765432109876543210 + 10 . . . . . . . . . . . 10 + 9 . . ) . . h f . . . 9 + 8 . . a m g o + m . . . 8 + 7 . a + \ \ + * m . . 7 + 6 = # + \ \ \ w b ) . . 6 + 5 . . h \ \ + e f . . 5 + 4 . . f + + c f l . . . 4 + 3 . . k j + f m m . . 3 + 211111111119876543210 + 09876543210---------- + + Figure 12 + Map of area hit by 3mt nuclear warhead + +-------------------------------------------------------------------------------- + + Here is a basic outline of what you will need to do should you be hit + with one or more 3mt or greater warheads: + + 1: Get food to the people in areas that need food. Especially areas + that are partially or totally cut off from the rest of your country. + ON THE MAP ABOVE: This would probably be necessary for all sectors + east of -12 and/or north of -4. + + 2: Distribution routes *will* be cut off by a nuclear hit. Redo your + distribution routes around the nuclear wasteland areas. Make sure + that your new distribution center has enough food to feed the people + you are trying to support with it. + ON THE MAP ABOVE: This would probably be necessary for all sectors + in the region. + 3: Move people into the area affected by the blast. Get highways in + the area back up to efficiency as soon as possible. This will + allow for increased movement in the immediate area of the blast + which could be critical to the survival of the people in that area + as well as defense of the area. + ON THE MAP ABOVE: You will probably need to restructure your + highway system in the region. Move people in + from the south-east (off the map). + 4: Lastly, try to get production back online in the area. This is + not as critical as the first three things. + + Those are the essentials for recovering from a nuclear blast. The + + +User's Guide to Empire 40 + + first three items should be done as soon as possible top to bottom, + ie number one is priority one. + + There are also defense considerations after you have been hit by + a nuclear blast. Your air defenses in the area might be wiped out + which would allow your opponent to take over your land in that area. + There are also steps you can use to shore up your defenses in the + area while you are getting the area back on its feet: + + 1: Enlist military in the region. Looking at the map in figure 12, + You might do something like: + + [23:210] Command: enlist -20:0,-10:3 -25 + + That would enlist military in the region so that every sector had + at least 25 military in it. Note that you can only enlist half of + the population in a sector at one time, but you can enlist in the + same sector over and over again. + + Doing this would hamper an enemy's progress should they attempt a + paradrop assault in the region. + + 2: Move undamaged or nearly undamaged VTOL fighter planes from the + south-east (off the map) into the area. Do not put them on + the airbase. Provide them with petrol as well. This will + shore up your air defenses which were damaged by the blast. It + will also make it much more difficult for an enemy power to attack + by air in the region. + + 3: Move guns and shells into the forts on the map if they are not + already there. Make sure there is at least 7 guns and a lot of + shells in each fort. Also make sure there are substantial military + forces in each. This will help prevent extended military action + on land by an enemy. + + 4: Move naval forces into the region if possible. This will help + to prevent amphibious assaults. + + If you do all of these things, recovery from the blast will not + take long at all. These things will minimize the effect of the + blast and get the area back on its feet again. + + Do not be dismayed by loss of resources etc. You *can* recover. + I have been a victim of nuclear war probably half a dozen times, + and so far have found only one case in which I was crippled by + the effects. My entire homeland (of ~100 sectors) was + wastelanded except for less than 10 sectors. No, I could no + longer hope to win the game, but I did hang on long enough to + purchase a nuclear warhead and missile and attack the person + who nuked me. Doing something like this will make the player + who nuked you respect you more in future games, and consider + the consequences before pushing that button. + + + +User's Guide to Empire 41 + + It has become fairly routine lately for games to end with a world + wide nuke-off. Generally speaking, nations having nuclear weapons + threaten the world with destruction if they are not acknowledged + as victors. Other people protest of course, and nuclear war happens. + A game that has taken eight weeks to evolve to that point can be + destroyed in less than an hour in the hottest nuclear wars. This + of course does not lead to any clear cut winner, and is rather + pointless but people do it anyway. It is after all, a game, and + people want to have fun. Nuclear war, to many people in Empire, + is fun. + +Summary: Do not be demoralized by a nuclear attack. Powers using nuclear + weapons expect their opponents to get demoralized. Recovery from a + nuclear attack of larger degree is possible as well. It takes + perseverance and sometimes hard work. Don't be dismayed by mass + starvations. Populations can recover if you work at it. Your + reputation may be greatly improved if you do recover from a nuclear + blast. + + + +User's Guide to Empire 42 + +Chapter 9 :-: Technology. + + By most people's definitions technology or the means to purchase + technological weapons from another country is one of the most + critical elements in doing well in Empire. + + Having technology allows you to: + 1. Have increased ranges on your land based radar. + 2. Build higher capability planes. + 3. Build more advanced types of planes. + 4. Build higher capability ships (not as great an effect as in planes) + 5. Build more advanced types of ships. + 6. Build bridges. + 7. Build nuclear weapons. + 8. Have increased ranges on your guns in forts. + + Thus, having a high technology country is a very useful thing. + However, attaining a high technology level is very difficult for + the beginner. Running a country that has an economy balanced well + enough to produce technology at a rate sufficient to stay in the + technology race is a very difficult task, even for players who are + more experienced and/or have a lot of allies supporting their + economies as well. + + Producing tech is expensive. It costs a lot in terms of money + and materials. Not only do you have to produce tech, but you + have to educate your people to a high enough degree that tech + production can be done efficiently. Doing this takes a great + many light construction materials (lcms) for education, and a + large amount of oil, gold dust and lcms for tech production. + + It is not uncommon for tech nations to be one of the smallest + and poorest nations around. Most of their time and resources + have to be devoted to tech production rather than ships for + exploration and military to defend outlying colonies. + + Do not fantasize. If you are a beginner, forget about producing + tech no matter how good you think you are. You will be wasting + your resources in doing so and crippling your economy while other + countries will run far far ahead of you in production. + + In general, until you have played a few games it is far better to + purchase high technology items from other players. Diplomacy, + discussed at length in chapter 7, is an effective tool for + purchasing technologically superior items. + + Should you decide to run tech, there are several things you should + know. If you are able to take these into account, and balance these + factors against each other you may be able to produce tech at a + sufficient rate to stay with the leaders. + + Education is important to produce tech. You have to have an + education level of at least five before you can produce any. However, + + +User's Guide to Empire 43 + + an education level of five will produce tech only in an inefficient + manner. The higher your education level, the more efficiently tech + will be produced. This means that a single tech center can produce + more tech per update, and cost you less in raw materials, though it + will cost the same per unit of tech produced. The savings in raw + materials is critical. + + Some countries feel it is better to keep your population low when + they are planning on having a high education level. The reasoning + behind this is that it takes less effort to educate a small number + of people and costs less money as well. There is a bad side to this + plan though. With a small population it is hard to produce things + in large quantities, and exploring into and occupying new lands is + very difficult. + + Technology production demands a large amount of resources. Especially + oil. However, the higher tech you are the more oil you are able to + refine per amount of crude oil in the ground. Thus, it is better to + only take out of the ground what oil you need to keep your country + running, and leave the rest for later on when you have higher tech, + and get more per barrel of crude. Thus, if you were to do the + following: + + [23:512] Command: resource 4,0 + + You might see that your 4,0 sector has 100 units of oil in the ground. + At tech 0 you'll be lucky if you get 500 barrels of oil out of that. + However, at tech 100 you will probably get somewhere around 700-750. + That's a big difference. So, only take approximately what oil you will + need for each update out of the ground, and leave the rest for later. + + Tech production also requires gold dust. Gold dust mining is not + affected by tech like oil wells are. Thus, mining the gold dust + right away or saving it later has no impact on how much is produced + per unit of gold dust in the ground. There are other considerations + though. If you have a lot of gold dust sitting around in your + warehouse or other storage place, other countries will see via the + power report that you have a lot of dust. If they are low on dust they + just might look at you as a possible target. So, if you are going to + mine a lot of your dust right away you might want to consider putting + a good portion of it into banks where the dust gets converted into + bars, which will give you more money per update. This especially + applies to the Kent State version of Empire, where you can grind up + your gold bars into gold dust at a loss of 20% of the original amount + of dust put into the bars. + + Uncompensated workers are also useful for tech production, as well + as many other things. However, it has been noticed that a tech + center with 999 uws will produce tech less efficiently than one with + 500 uws. The loss in efficiency is greater than what is expected + from the tech limitation function, which is a non-linear function + designed to limit fast tech production. Most players do not feel that + the loss in efficiency is worth it for the greater amount of tech + + +User's Guide to Empire 44 + + production, especially in small countries where having two or even + three tech centers is unrealistic due to the small amount of land + available. + + As your technology increases, the possibility of there being an + outbreak of plague in your country increases. This is not of great + concern until such time as your plague factor (found by the command + "nation") increases above a factor of 3.0 or more. Even if plague + does break out in your country, if the plague factor is less than + 3.0 or so, the plague will have minimal effect on your country. + During your first outbreaks of plague, you will lose some civilians + but the birth rate of the civilians will be greater than the death + rate. Thus, increasing your research level (by opening and operating + a research center, which requires the same materials as a tech center) + prior to your plague factor reaching 3.0 is actually a waste of + resources, time, money and effort. This fact has been lost on a + great many people and it is not uncommon to find many players + boasting of a high research level long before you would have a + plague factor of 3.0 without any research production. While we + have emphasised "3.0" as a point at which things start getting + bad with plague, that is a vague figure. Things start getting + bad before that point, and get worse afterwards. Its a matter of + how much you want to put up with civilians dying off. + + There is a command called "report" which will list other countries, + their status, and their levels of tech, research, and education + relative to you. If your tech is significantly higher than + say a country called 'Canada' then report will indicate that + Canada's technological level is 'backward' relative to you. + If Canada's technological level is significantly higher, than + report will indicate 'advanced', meaning Canada is advanced + relative to you. If its roughly the same, 'similar' will be + shown. There are two other possibilities, 'primitive' and + 'superior' which are used for extreme differences in levels. + It should be noted that report is inaccurate at best, and only + gives a very vague idea of levels. + +Summary: Technology is one of the basic aspects of having a country that + lasts to the end of the game. Generally, the higher tech you are + the greater chance of your survival. However, if you have a high + technology friend, you chances of survival are still increased + greatly. Empire is a classic case of cold war as far as + technological development is concerned. As a beginner, you are + probably better off not producing a great deal of tech until you + become well versed in how to run a strong economy. + + + +User's Guide to Empire 45 + +Chapter 10 :-: The economy. + + There are several products produced in Empire economies. + +-------------------------------------------------------------------------------- + + Group 1 Group 2 + 1. Gold dust 8. Light Construction Materials (LCM) (3) + 2. Oil 9. Heavy Construction Materials (HCM) (3) + 3. Iron 10. Gold bars (1) + 4. Rads 11. Petrol (2) + 5. Food 12. Soldiers (6) + 6. Civilians + 7. Uncompensated workers + + Group 3 Group 4 + 13. Education (8) 17. Ships (8,9) + 14. Research (1,2,8,13) 18. Planes (8,9) + 15. Technology (1,2,8,13) 19. Bridges (9) + 16. Money (6 or 7 or 10) 20. Nuclear weapons (2,4,8,9) ???? + + Special items: Beaurocratic Time Units (BTUs), Available work (Avail) + + + Figure 13 + Table of types of commodities in Empire + +-------------------------------------------------------------------------------- + + Beaurocratic Time Units (BTUs) are used when executing a command, such + as "build" for example. They are also used to shuffle paperwork + around, say for soldiers killed in combat. + + Available Work (Avail) is used up by producing sectors and those + sectors in which you build things (planes, for example). It is an + indices of the amount of labor hours available for work. + + Running your economy efficiently as possible is one of the keys to + being a good Empire player. Without a good economy it is impossible + to wage a long lasting war, especially an offensive one. It is + possible to last a long time defensively even with a weak economy + but your chances are greatly increased if you have a strong economy. + + So, what defines an efficient and strong economy? An efficient + economy is one in which the amount of a product being produced in a + sector is nearly equal to the amount that the civilians can produce in + one turn. For example, if a light construction materials (LCM) plant + can produce two hundred LCMs an update, but is only producing one + hundred, then fifty percent of the people in that plant are basically + doing nothing. They could be used elsewhere on something that needs + more civilians or you could put more iron into the LCM plant to allow + the civilians to make more LCMs. + + + +User's Guide to Empire 46 + + A strong economy is an economy that produces a lot of materials, + resources, etc relative to the size of the country. If your country + has only say ten thousand civilians but is producing a large amount + of materials per update then your country may in fact be a strong + country. This is a very unlikely scenario, but it is a good example. + A strong economy is usually the result of an efficient economy, + though there are other factors, those mainly referring to population + growth. To find out how much work your civilians are going to perform + at an update you can issue the "prod" command to get a production + simulation. Using this you can see if all the civilians in a given + sector will be making something or if some will be sitting around and + doing nothing. Here is a sample output from a prod command: + +-------------------------------------------------------------------------------- + +[138:250] Command: prod #1 +Mon Sep 30 20:18:37 1991 +PRODUCTION SIMULATION + sect des eff wkfc will make- p.e. cost use1 use2 use3 max1 max2 max3 max + -2,0 o 39% 422 39 oil 0.50 $0 39 + 2,0 m 100% 807 387 iron 1.00 $0 387 + -10,2 b 100% 653 36 bars 1.00 $360 180d 310d 62 + -8,2 j 100% 576 138 lcm 0.50 $0 276i 276i 138 + -4,2 g 27% 615 79 dust 1.00 $0 79 + -11,3 t 100% 620 0.00 tech 0.00 $0 0d 0o 0l 0d 0o 0l 0.00 + -8,4 l 100% 499 40 edu 1.00 $360 40l 239l 239 + 7 sectors + + Figure 14 + Sample output of the 'prod' command + +-------------------------------------------------------------------------------- + + The important columns to note here are the "will" and "max" columns. + If the number indicated in the "will" column is less than the "max" + column by more than 1, then you have civilians who are sitting around + doing nothing. The way you calculate the number of civilians you have + sitting around is fairly simple. First, it is important to note that + the number indicated in the "wkfc" column is the number of civilians + and uncompensated workers (UWs) you will have in the sector *after* the + next update. You need to reduce the number of civs and/or UWs in the + sector to optimum *before* the next update. + + For this example, and for sake of ease, I am going to assume that + there are no UWs or soldiers in this sector, which both produce work. + We will assume that there are only civilians, and happy, content ones + at that. Civilians that are starved, or recently starved do not work + as hard. + + In the above shown production simulation there are two sectors which + have civilians sitting around idle. These two sectors are the bank + ('b') at -10,2, and the library ('l') at -8,4. We will use the library + for our example. + + + +User's Guide to Empire 47 + + The library is going to produce 40 education, but it is capable of + producing 239. It doesn't have enough lcms (the only material needed + to produce education) to produce 239 education. Thus, only the civs + necessary to produce 40 education are actually working. The remaining + number of civilians, as a percentage, is calculated by this simple + formula: + + ((# in max column) - (# in 'will' column)) / (# in max column) + + Thus, the percentage of civilians in the library not actually doing + work is (239 - 40) / 239, or 83.26%. That's a large percentage! Now, + to calculate how many civilians you can move out of the sector without + reducing your production beneath 40 education in that sector, multiply + .8326 * the number of civilians currently in that sector. So, you need + to do a census command: + +-------------------------------------------------------------------------------- + +[162:166] Command : cen -8,4 +Mon Sep 30 20:19:07 1991 +CENSUS del dst + sect eff mob uf uf * civ mil uw food work avail ter fallout + -8,4 l 100% 127 .. .0 403 0 0 49 100% 54 0 0 + + Figure 15 + Results of a 'census' command of a library + +-------------------------------------------------------------------------------- + + There are 403 civilians listed in the 'civ' column for the library at + sector -8,4. Thus, you multiply 403 by .8326 and you find that you can + safely remove 355 civilians from that sector and still be producing + 40 education. That's 355 civilians that can be doing valuable work + elsewhere instead of sitting around doing nothing! + + The other alternative to get the sector producing efficiently + is to move lcms into the library up to the number that the library can + possibly process with the current number of civilians. Once again, we + refer to the production report and note the 'use1' and 'max1' columns. + The library will use 40l (40 lcms) at the next update unless you put + more lcms into the library. It can use up to 239 (239l in 'max1') + lcms. Thus, it can process an additional 199 lcms. So, you find lcms + somewhere else in your country and move the 199 lcms into the library. + At the next update your library will produce 239 education. Once + again, all of the civilians in the sector are now doing something. + + Of course, you can also use a combination of these two methods to + achieve an equitable balance. + + There are other aspects to running an efficient economy as well. + Ideally, you do not want to have an abundance of raw materials lying + around especially in the early stages of the game. The best situation + is to have your economy using the same amount of resources per update + + +User's Guide to Empire 48 + + as it is making, thus having a zero delta situation with respect to + all materials in your economy, you neither gain nor lose surplus of + materials. Keep in mind however that it is important to create and + maintain a surplus of materials from which to draw on in times of war, + especially later on in the game. Without spare materials, you can not + wage war very effectively. In doing this you are getting the best + balance of production, and are producing finished items at a faster + pace then if you spent more work producing raw materials. If you + spent more work producing finished materials, you would run out of + raw materials, and find that you have to move your civilians around + to produce more raw materials or have them sitting idle doing nothing + while your other civilians produce sufficient raw materials for them + to do work. The benefits of a balanced economy are obvious. + + There are additional tasks that are somewhat rewarding in running an + efficient economy, but they become increasingly technical in nature + and their impact as a whole against your economy is significantly less. + + As you become more experienced you will no doubt discover these thing + yourself, or hear about them in a game or on the network. These basic + elements are more than enough for you to run smooth production if you + adhere to them. + + There are still more elements of an economy which, while very useful, + are not exactly related to the strength or efficiency with which your + economy is running. Your country, should it live for some time and + develop a well balanced economy, will produce a huge amount of + materials. It is impossible for you to keep track of everything in + each and every sector of your country. Of course, the Empire creators + realized this and have developed some critical commands for reducing + by a very large amount the quantity of time you need to spend adjusting + your economy. These are the 'distribute' and 'deliver' commands. + + 'Distribute' and 'deliver' are commands in Empire which allow + you to set up your economy to run automatically, with little + intervention from yourself. Distribution is the most commonly used + command in doing this. However, deliver has certain features which + are useful as well. + + Distribute is based on the central warehouse scheme of production + and consumption of materials. An iron mine produces iron, which it + ships off to the central warehouse. A light construction materials + plant needs iron to make lcms, and thus requests iron to be sent to it + from the warehouse. The lcm factory produces lcms, and sends them + off to the warehouse. A library plant needs lcms to produce + education, and requests lcms from the warehouse to do so. The + warehouse handles regional traffic for your economy. Some smaller + countries only have one warehouse. + + Deliver is based on the local delivery truck idea. A nearby farm + produces a certain amount of food per update, and sends it directly to + the neighboring sector. You know that the neighboring sector can + consume more food per update than that farm can produce (this is very + + +User's Guide to Empire 49 + + rarely true, this is just an example). So, the farm sends all the + food it produces to the neighboring sector. The neighboring sector + notes how much food has been delivered from the farm, and then requests + from the warehouse enough food to feed the rest of the civilians in + the sector. In so doing things in this manner, you are possibly saving + mobility by not having the food automatically move to the warehouse + from the neighboring farm and then to the neighboring sector. The same + result would be achieved however, though as stated at a possible + greater loss of mobility. Nevertheless, most people prefer to depend + entirely on 'distribute' to handle automatic distribution of materials + around their country. + + To set up a distribution system, or network, you have to set a + distribution 'path' *from* every sector *to* the warehouse. I + emphasize the direction that the path is moving in because all + distribution paths go *to* the warehouse, not from the warehouse + to the sector, though materials can and will go from the warehouse + to the sector along that same path. The idea here is say a farm + outside of St. Louis about 50 miles produces 500 units of food, the + farm needs to know the route by which it should send its trucks to get + to a warehouse in St. Louis before it can send the food to that + warehouse (this of course being a real life scenario). The best path + to choose is across highways. A 100% highway requires no mobility to + move anything in to it. Obviously you don't want to travel the 50 + miles to St. Louis across dirt roads. You would prefer an interstate + if you were a truck. In Empire, a 100% highway is essentially an + interstate. Your goal is to have a distribution path from each sector + to the warehouse travel the route over the least mobility cost path. + The greater the percentage of that path that is 100% highways the + better. It is important to note that distribution paths have a maximum + length of 10 sectors. For example: + + +User's Guide to Empire 50 + + +-------------------------------------------------------------------------------- + +[529:32] Command : map -20:10,-3:6 + 21111111111---------00000000001 + 0987654321098765432101234567890 + -3 . . . . . ) . . . . . . . -3 + -2 . . . f . o . . . . . . . . -2 + -1 . . . a k a . a a h . . . . -1 + 0 k l k a + + + . + + c m . . . 0 + 1 m w o ^ ^ m + j j + . + . . . 1 + 2 + + + + . b j + m + w + . . . . 2 + 3 m j j + t + + + + + + . ) . + 3 + 4 + ^ j m + + l ^ ^ ^ + * a a o m 4 + 5 ^ + ^ m + j ^ ^ c + m m + + + 5 + 6 + + + g m + + m b + k o + j w g 6 + 21111111111---------00000000001 + 0987654321098765432101234567890 + +[529:32] Command : + + Figure 16 + Map of area requiring some distribution + +-------------------------------------------------------------------------------- + + Let's say that in the previous figure you wanted to set up a + distribution path from the oil well at -15,1 (the 'o' sector left of + the middle of the map) to the warehouse at 0,2 (the 'w' sector right + of the middle of the map). The command to set up the distribution + path from that oil well to the warehouse would be: + +-------------------------------------------------------------------------------- + +[529:32] Command : distribute -15,1 nnnjujjjuj +oil field at -15,1 has no distribution path. +<10: 0,2>h +New path distributes to 0,2 + +[534:31] Command : + + Figure 17 + Results of a distribution command + +-------------------------------------------------------------------------------- + + Now there is a path along highways from the oil well to the warehouse. + If you do not understand the nnnjujjjuj command above, refer to chapter + 3 and the section under "movement in Empire". + + Next, you need to set thresholds for the sector. This sector is an + oil well, and it produces, you guessed it, oil. So, you want the oil + that is produced to be shipped to the warehouse. You have to tell the + + +User's Guide to Empire 51 + + people in the oil well that all oil over 1 unit is to be shipped. + This is called a "threshold", a level at which any quantity of that + unit over that amount if shipped to the warehouse. Note that the + lowest threshold you can have and still have the item shipped is 1. + If the threshold is 0, then it will not be shipped. The command to set + the threshold in the sector -15,1 for oil is: + +[534:31] Command : threshold oil -15,1 1 + + Next, you want to make sure that food gets out to the oil well. The + other aspect of thresholds is that if there is less than the threshold + of a commodity, then the warehouse will send out enough of that + commodity to equal the threshold, assuming it has such commodities in + the warehouse. The command to set the threshold for for in the sector + so that food will go to the sector from the warehouse could be this: + +[534:30] Command: threshold food -15,1 50 + + Which means at each update, the warehouse will attempt to ensure + that there is 50 food in the oil well at -15,1 by sending enough + food, if it can, to raise the stockpile of food in that sector to + 50 units. + + Again, distribution paths must be set up for every sector that you + intend on doing anything with. Essentially, as the game progresses, + this means all of your sectors. You must also set appropriate + thresholds as well. Some sectors need iron from the warehouse to + produce, and thus a threshold will be required for iron. Some need + more than one commodity, so thresholds must be set for each of those + commodities. EVERY sector should have a threshold value set for food. + You do not want to starve your civilians! To find out what + commodities a sector needs to produce an item, use the 'production' + command discussed earlier in this chapter. + + Some things to note about distribute: + +1) No distribution path may be longer than 10 sectors. +2) A distribution path must go through sectors controlled by you. +3) Sometimes it may seem that the warehouse is not getting the commodities + to the sectors requesting it. Empire updates sectors one at a time, and + as such the warehouse may actually run out of a commodity, receive the + request for that commodity, be unable to fill it and move on the the + sectors it updates after that sector. Those sectors in turn may send + commodities to the warehouse, thus giving it enough to fill the previous + request. However, since it has already updated that sector, it will not + fulfill the backlogged request. Empire updates the world left to right + and top to bottom. Thus in a map of your country the most north-west + sector gets updated first and the most south-east sector gets updated last. +4) The warehouse has to spend mobility to send commodities to the requesting + sectors. Warehouses do this at a great reduction in the cost to the + normal mobility. However, if the warehouse runs out of mobility it + will NOT distribute any more commodities for that update. +5) Do NOT set thresholds for all commodities in a sector. Only set the + + +User's Guide to Empire 52 + + thresholds for the commodities you KNOW that sector will need. Distribute + will not distribute commodities to sectors with the thresholds set for + every commodity. + + + Deliver is much more basic. As a result however, it is much less + powerful, though it is useful. Deliver works as explained earlier in + that it does local deliveries of a specified commodity. Deliver is + capable of delivering an item to only neighboring sectors. During the + update, deliver is done before distribute. It is important to note + that. Let's say that a farm has a lot of food to send to the + warehouse. It may not have the mobility to send it all to the + warehouse, and thus you get a large surplus left over in the farm. + Eventually, the farm will not have room to store the surplus anymore. + This is of course bad, since the farm will no longer produce very much + food. It will produce only enough food to replace what was taken from + the storage at the farm. + + The solution to this is to have the farm sends its surplus to a + neighboring 100% efficient highway. This will cost the farm no + mobility and will open up its storage areas for new production at the + farm. The highway can then spend mobility sending the food to the + warehouse. Once again, we use the map: + +-------------------------------------------------------------------------------- + +[529:32] Command : map -20:10,-3:6 + 21111111111---------00000000001 + 0987654321098765432101234567890 + -3 . . . . . ) . . . . . . . -3 + -2 . . . f . o . . . . . . . . -2 + -1 . . . a k a . a a h . . . . -1 + 0 k l k a + + + . + + c m . . . 0 + 1 m w o ^ ^ m + j j + . + . . . 1 + 2 + + + + . b j + m + w + . . . . 2 + 3 m j j + t + + + + + + . ) . + 3 + 4 + ^ j m + + l ^ ^ ^ + * a a o m 4 + 5 ^ + ^ m + j ^ ^ c + m m + + + 5 + 6 + + + g m + + m b + k o + j w g 6 + 21111111111---------00000000001 + 0987654321098765432101234567890 + + Figure 18 + Map of an area requiring delivery path + +------------------------------------------------------------------------------- + + Let's say the farm at -5,-1 (just north of the middle) has a huge + surplus of food. You can send that surplus to the highway at -4,0 by + issuing this command: + +[566:115] Command : deliver food -5,-1 n (50) + + + +User's Guide to Empire 53 + + Which means, deliver all food in the sector at -5,-1 in excess of 50 + units in the 'n' direction. Note the deliver threshold in parentheses + must be in parentheses and that deliver thresholds are different than + distribute thresholds. + + While I have described how to use the basics of deliver, I do not + recommend it for the beginner. Using a distribution network is quite + sufficient for the beginning player, and you will not notice any great + difficulty in running your economy without using the deliver command. + In fact, some of the best players in Empire do not use deliver at all. + + +Summary: The things discussed in this chapter may seem time consuming, and + may seem to require a lot of detail. However, these things are + important to you as an Empire player to learn and understand. They + become easy to use after only a short while. Having a strong + economy is the basic element in having a strong country. If you + have not understood this chapter, read it again. Better yet, read + it while experimenting with a couple of your own sectors in a game. + While understanding 'deliver' is not very important, understanding + 'distribute' is. + + + +User's Guide to Empire 54 + +Chapter 11 :-: War + + The art of waging war is certainly beyond the scope of this guide. + There are a great number of books written on the history of man's wish + to destroy themselves. In this chapter, I only intend to give the + player some rudimentary basics for waging Empire style wars. Even more + pertinent in the case of the beginner, how to defend against or + hopefully repulse an invader. + + Keep in mind that as a beginner, you stand a very good chance of losing + your first war. Consider it a learning experience. The person who + defeated you is better than you are in most circumstances, and just by + their actions you can learn how best to wage an offensive or defensive + war. + + There are several things that you can do to defend your country + in the event of an attack. However, it is always best to be prepared + for an attack before it happens. There are some basics already + discussed in this guide on these preparations. Refer to chapter 8 + for information on automatic defenses, and how they can help your + country. I will review the essentials here. + + 1) Have a strong airforce with many fighter planes with the intercept + capability. Make sure they are used as indicated in chapter 8. + 2) Have forts with overlapping fields of fire. + 3) Have a large number of reserves (typically 1/10 of your population). + 4) Have at least two enlistment centers ready to produce more fresh + recruits. Ie, at 100%. You can "shut off" enlistment centers, that + is stop them from producing recruits, by leaving 1 civ in them + or having a military population in the sector equal to one half + of the civilian population. To turn them on, put in more civs or + reduce the number of military. + 5) Have a strong navy to guard your coast. + 6) Mine your own coast. This prevents many amphibious assaults. + It also helps to prevent people from mapping your coastline. + 7) Have a good highway network. This allows you to move materials + and armies around your country quickly and with ease. + 8) Have more than one capital. If your real one is taken, you will + need a back up immediately. + 9) Have a lot of food in all of your sectors if possible. This allows + sectors that are cut off from your warehouse to be self sufficient + at least with respects to feeding the people with food for a few + updates until you can open up a path to them. + + These are just *basic* hints. Some more hints are given later in this + guide. These are meant to get you started. + + Of course, it is better to not be attacked at all. But, how do you + avoid being attacked? This is not simple, but there are some things + that you can do to make yourself less of a target. + + One, do NOT allow people to map your coast using their ships, + especially patrol boats. Maps of your coastline are deadly. + + +User's Guide to Empire 55 + + The opposing country knows where your country lies, and can furthermore + send that information on to another player who might be interested + in attacking you in exchange for some commodity or assistance. + Maps are a critical piece of intelligence gathering. Some of the + best players in the game sink ships on sight without warning. If you + warn a ship off it might be able to use some of its mobility to + make a final swing along your coast before going away, and seemingly + out of your hair without having caused further trouble. Every piece + of information about your coast is valuable military intelligence. + Additionally, it is a good idea to try to map other people. Do not + get upset when your ships get sunk. They will get sunk. Just consider + them expendable commodities that are doing a temporary job with + permanent results. + + Two, if you appear tough people generally will not attack you. + Posturing can be an effective tool. Furthermore, if you have a large + airforce and/or army, people tend to avoid you. It does not matter if + your airforce only has wimpy planes in it, your opponent can only + tell the quantity of planes that you have, not the quality. They + might have a general idea of the quality of your airforce, but a large + airforce is still an intimidating presence. + + Three, do not make yourself a target by having a lot of valuable + commodities showing up on your power report. Having lots of money + in a money poor game for example makes you a juicy target. The same + holds true with gold dust or oil. You need not worry about iron and + food, since those are renewable resources. Try to use gold dust and + oil as you make it. Having some surplus around is fine, but the more + you have sitting around the more of a target you become. + + If you are attacked, it is always best if you are logged on to the game + so that you can actively defend your country rather than relying + entirely on automatic defenses. However, as can obviously be seen, you + probably will not know that your enemy is going to attack you. Neither + will s/he broadcast that they are going to attack unless they are very + foolish or extremely confident. + + In light of this, your opponent will try to attack you at a time when + they know you are not logged on. Thus, a great many Empire wars begin + in the wee hours of the morning, when most people are asleep. What can + you do to overcome this shortcoming? Have allies for one. If one of + your allies is going to be up most of the night you can have them + telephone you if you are being attacked. Of course, this is for the + more diehard types :-) + + There are many tactics that an enemy will use against you. Again, + these tactics are beyond the scope of this guide, but there are some + general tactics that you should be aware of. An opponent may try one + or more (usually more) of the following tactics: + + 1) Remove your airforce as an effective retaliatory force. + 2) Remove your airforce as an effective defensive force. + 3) Take your capital (you lose half your money). + + +User's Guide to Empire 56 + + 4) Take your banks (you could lose all your gold bars, very valuable!). + 5) Destroy your highway system. + 6) Take your warehouses (lose your stored commodities. OUCH!). + 7) Bomb your enlistment centers. + 8) Take your radar stations. + + + In addition, your opponent may try to destroy your distribution and/or + delivery system (if you so opt to use deliver). After you take a + sector back from your enemy check the thresholds and distribution path + in the sector. Sometimes if you take a great deal of sectors back it + is best to just use the 'wipe' command and start from scratch. + Remember to check your delivery thresholds as well, by issuing a + 'level' command. Your opponent will probably also redesignate the + sector to something useless or even detrimental to you. + + It is important to be on around update times when you are at war, + either defensively or offensively. Things can go very quickly right + before and after an update. + + One of the best ways of being a good military tactician is to be + imaginative. Think of ways to do things that might surprise your + opponent. Think of ways to do things that will cost you less lives, + or less resources than your original way. + + There is a saying that sometimes the best defense is a good offense. + This can be very true in Empire. If you are attacked it might be a + good idea to launch a counter attack against your opponent's homeland + if you are able to. This will certainly surprise them, and may lead + them to think you are stronger than you actually are. This can be a + very powerful tool. + + If you want to win the war, be resilient and tenacious. Fight as hard + as you can with every last soldier and resource. If you make your + enemy pay a heavy price they may withdraw. Sometimes breaking an + opponent's will to fight is the most important factor in winning a + tactical or strategic situation. Even if they do not withdraw, or you + do not win, you may at least be helping to defend the future of your + allies. That in itself is an honorable achievement. There is also the + point that if you are a tenacious fighter your opponent will respect + you more in future games than if you just roll over and play dead while + his/her armies pillage your country. Reputation does count for a lot in + Empire. You may lose now, but your defiance in losing can help you a + great deal in future games. Some countries simply will not attack + another country because they know that country's reputation as a good + player. Alternatively, some countries have a poor reputation and + are attacked in every game they play in! + + +Summary: The art of Empire war is one that is different from the real life + world that we live in. However, many tactics from the real world + can be applied to Empire. Remember to be imaginative, learn from + your mistakes. Learn from your allies and your opponents. Fight + as if it was a real world nation, and you are the leader. + + + + +User's Guide to Empire 57 + +Chapter 12 :-: Other helpful or not so helpful hints: + + + Here are some hints on how you might be better able to run + your country. Note that a lot of these hints were garnered through + many player years of play. You are free to disagree with them, and + are certainly encouraged to come up with your own ideas. However, + keep in mind these recommendations. + + - Build your military reserves to a reasonably high level + (I try to aim for 5-10% of my total population). Reserves are + not expensive to maintain, and it is a commodity that can not + be destroyed by any military action. + - As soon as someone starts building ships guard your coastal + sectors with at least 1 military in each. This prevents an + opponent from making landings in mass quantity on your homeland + with measly cargo ships. If you have military in a coastal sector + then opponent ships really need the "land" capability (see + show ship capability command for further insight) in order to be + truly effective. Guard harbors with more military, say 50 or + so. Else an opponent can assault a harbor, move his or her invasion + fleet in, unload the ships and walla several hundred foreign military + are sitting in your former harbor. + - As soon as planes start being built, try to get at least 10 military + into every sector. This makes it more difficult for a country to + wipe you out quickly. In this manner they usually need 2 or more + transports to take a single sector. This makes it costly in air + mobility for them and softens the blow of their attack. In addition + reinforce capitals with a lot of military. Same with banks, airbases, + and warehouses. + - Do not base your entire air defenses on non-VTOL (vertical take off + and landing) planes. Base your VTOL planes in non airport sectors. + In doing this, you prevent your enemy from knocking out your airbases + through any number of means and then flying at liberty over your + country. There are two VTOL fighters. Fighter 1s, which are + essentially biplanes with very brave souls in them and Jet Fighter 2s + which are akin to the British Harrier jet. Fighter 1s are not + necessarily a bad plane. Against low tech transports they do not + fair too badly. There are two other means of air defense if your + airbases are knocked out. Anti-aircraft guns exist in any sector + that has guns and shells. They will fire if the sector in question + is at war with the planes in question. They are mostly worthless. + The other method is SAMs (surface to air missiles). These can be + quite effective but are shoot once only weapons. + - Forts are an integral part of any home auto-defense scheme. They + will fire on any enemy aggressors that are within range whenever + any sector of yours within range is attacked. + - Naval units become essentially useless later on in the game except + for some actions. Nevertheless, be careful to have naval units in + appropriate places around your coast for coastal defense. Especially + until you have planes that can pinpoint bomb well (jet lt bombers, + jet f/bs, helicopters). + - Always have several fake capitals in reserve. + + +User's Guide to Empire 58 + + - If you are not using planes that are 100% and are not planes used + in air defense, get them off your airports. Otherwise they become + easy targets for air assault and bombs. + - Bridge span sectors are effective means of food production and + are especially useful in that role in countries with few sectors + or countries with limited fertility. They are usually somewhat + expensive to build, but pay for themselves quickly. + - Keep in mind that allies are important. You might want to go it + alone, but at some point along the way you will need an ally or + three. Allies can do many things for you, not the least of which + is call you over the phone when you are under attack at four in the + morning. Its nice to know that even though your country is not + being played, someone is watching it from a distance and seeing + whether it gets attacked or not. You sleep easier :-) + - If you are positive there is no one else on your island with you + at the beginning of the game then demobilise your military and + put them on reserve. This will save you a lot of money, and help + in population growth. + - Never put airports, banks, or capitals on your coast. They are + easy targets for your enemies if you do. Sometimes it is necessary + to place an airport on your coast to get that extra one sector + of range for your planes in an attack. If you do that, don't leave + your planes in that sector for very long. You might be surprised. + +Summary: Many of these ideas can only be gained through experience. Do not + be come distraught for lack of knowledge. Experience is a wonderful + teacher. These hints cover some of the major pitfalls of beginners, + and that is all. There are far more things to be learned that can + only be taught through experience. + + +User's Guide to Empire 59 + +Chapter 13 :-: Some tricks and subtle tactics + + I have listed here some of the tricks used by the more advanced + players in victimizing the beginning players. I divulge this hard won + information because I feel it will make for a better Empire game for + everyone. In reading these, I hope that you will be encouraged to + develop tactics of your own. It is not hard to be imaginative. + + Note that not all tricks and subtle tactics will work as advertised. + Some games have slightly different implementations that have a + negative effect on these hints. + + - Sacking a warehouse. This is an old tactic that is useful + only in those games that have a market. Essentially the trick is to + take an opponent's warehouses or distribution points and sell off + everything that is in the sector to the market. You don't need a + buyer immediately, just sell everything off. If you want the items + for yourself, sell them to the market at an exhorbinately high price + and wait for a friend to buy them and sell them back. + - Tracking an airbase. This is a less known trick. Non-VTOL planes + intercept from airbases. They also intercept from airbases in a hex + pattern. Ie, if the plane has a six sector intercept range it will + intercept up to six sectors west, six sectors north-west, etc in all + the six directions. If you can find two corners of that plane's + interception hex you can triangulate to find the sector from which it + is intercepting. This does work for VTOL planes as well, but isn't + as useful since airbases usually have far more planes in them to be + dealt with. Once you have tracked the originating sector of the + intercepting planes, what you do to that sector is your option. Most + often, a concerted effort will be made to crack the defensive fighter + cover and blast the airbase. Sometimes countries will use their + surface to surface missiles (which do not get intercepted) to take + out the airbase. For non-VTOL planes taking out an airbase just + means getting it below 60% efficiency. + - Fort "walking". If you have a land border with a country, you can + use your forts to demolish a bordering sector with that country. + By demolishing it, your are completely destroying every living + civilian and soldier in that sector. When that is accomplished you + can explore into that sector as if it were wilderness. You can then + designate that sector into a 0% fort, which it will become + immediately, and then move guns and shells into that sector. + Then, you can do the same thing to a sector bordering your new + sector. In this manner you can slowly invade another country + beyond a one sector advance in one update without the use of + planes or ships. This costs A LOT of BTUs and shells, but in + critical situations is very useful. + - Fire base. This tactic has some relation to the tactic used in + the Vietnam conflict by U.S. Forces. The idea is to take an enemy + sector in an area that you want to wreak havoc on. Next, use your + pinpoint bombing capable planes to bomb your own position's sector + efficiency. You will have some collateral damage on your troops, + but it is well worth it. When the efficiency drops below 5% you can + then designate the sector into a 0% fort, place guns and shells + + +User's Guide to Empire 60 + + in it using air transports, and then have a base from which to + blast away at your enemy without the use of much airpower. It is + possible to use the fort walking tactic from this position. + - Messing up a country's distribution paths and or thresholds. + This is most often an "annoyance" tactic. Most players know about it + and check the distribution paths and thresholds of sectors they take + back from an invading country. The idea is to set the thresholds so + that a lot of commodities will be distributed to the sector from the + warehouse of your opponent after your opponent takes the sector + back. Then you can take the sector again and get the commodities + if s/he has not noticed they are there. Even if s/he notices it is + a pain getting the commodities back to the warehouse. + Alternatively, you can screw up the distribution path to run through + a mountain and then to his warehouse, and also set the thresholds + of the commodities quite high. This will cause mobility in her/his + warehouse to be used in great quantities to get the commodities to + the recaptured sector. Either of these ideas can get particularly + nasty. Say you conquer a sector, and set the thresholds on food to + 9000 units. Your opponent takes back the sector, and neglects to + reset the threshold. At the next update the warehouse moves 9000 + food (or at least as much as it can) into the sector. This might + leave your warehouse without food to deliver to the rest of the + country. Food stocks begin to drop, with obvious repercussions. + - Messing up a country's delivery routes and thresholds. + Same as above except using deliver. Many countries do not use + deliver at all, and as a result are susceptible to this tactic. + You can cause mass starvation in a country that you attacked, but + no longer control without the leader ever knowing how. + - Destroyer trap. Move a submarine near a destroyer, say one sector + away. Lay some mines from the submarine, and then send out an active + sonar ping using the "sonar" command. Enemy destroyer rushes over to + see what it is and KAWHOMP! hits a mine. You can leave a sector that + has mines in it safely but can not necessarily enter safely. Every + mine laid in a sector increases the chance of a ship hitting a mine + while entering that sector by five percent. + - Determining if someone is on. You can get an idea of when someone + is usually logged on by doing something like this: + +[65:255] Command : news 10 | grep + + This will scan the news file from the server for the last ten days + (or however many days up to ten are being preserved in the news). + You can then get an idea of when your opponent is logged on. + There are tools that can do this for you, but so far none has + reached public distribution. + - Attacking any sector with one soldier repeatedly. Within the code + there is a small chance that against incredible odds a small + collection of soldiers might win. Taken to the extreme, there is + a chance for one soldier to win, even against 400 soldiers, or so + says the game. Thus a player who wants a particular sector bad + enough, may spend thirty minutes attacking a sector of yours + over and over again with one military. They might win eventually, + and if it is important enough then they have gained a major sector. + + +User's Guide to Empire 61 + + - A player might offer to sell you a type of commodity in several + batches. Or, you might just start buying batches of a commodity + from any given commodity. If the player you are buying from is on, + they might change the price on you between batches that you are + purchasing. For example, DoDo starts buying food in batches of + 9000 from WabbleHead at 10 cents per food. This costs DoDo $900 + per batch of food. Suddenly between DoDo's 2nd and 3rd purchase + of 9000 food, WabbleHead changes the price on the food from 10 cents + to 10 dollars per unit. DoDo never realizes it and pays $90,000 + for the 3rd batch of food. Moral: Don't purchase anything without + checking the price first, and never buy in several batches at once. + This applies to market and trade. + - It is possible to move small quantities of a commodity across any + sector in your country and not have it cost mobility. To do this, + you have to have the commodity moving from a warehouse to whatever + sector you want to move it to. The basic trick, is to move the + commodity in batches of 5 or less. Note this does not work for + bars, and some other commodities. It does work for food, shells, + etc; items that do not take a great deal of mobility to move to + begin with. This trick is very effective for getting supplies + to a region cut off from your main area without highway access + and possibly even a mountain range separating you from it. + - Mine your coast. This prevents your opponents from effectively + mapping your coast, and you can catch their ships in the act since + a damaged ship moves a lot slower than a 100% ship. Some people + might even scuttle the ship in question to avoid detection. + - Be aware that submarines will try to map your coast. Use your + submarines and destroyers to find them. Use minefields as a + preventative measure. + - Do not give out your net address to anyone except the Deity unless + people offsite can not finger you, or you have an account on + another machine, and can regularly play from it. People can finger + you over the net to see if you are logged in or not. If you're not, + it's a good time to attack probably. + - Beware of people offering you loans. Make sure you know the terms + of the loan. Someone might offer you a loan that looks nice, say + for $30,000. But, the loan might expire in one day and have an + interest rate of 127%. The lending country can collect sectors + directly from you without your permission if you are in arrears + on the loan. + - Defend your radar stations. Always have at least 20 military in + each of your radar stations, especially ones that are on the coast. + Otherwise a passing ship might decide to capture it and take a + snapshot of your country. + - If a sub attacks one of your ships, it is possible to wander around + the area with a ship that is not capable of sonar or depth charging, + and still find that sub. How? Try boarding the sub by its hull + number. If a sub attacks you, you will get a message saying that + sub number so and so did such and such to your ship. Use a ship + in the area to wander from sector to sector trying to board the + sub. If you find it, you will get a message saying that you can not + board a sub. Walla, you have found the sub without sonar, which + other ships can hear anyways. This is a nice quiet form of anti- + + +User's Guide to Empire 62 + + submarine warfare. + - You can load a missile cruiser full of anti-shipping missiles, and + then create a script file with firing commands for every ship in + existence. Remove your own ships of course. Then execute the + script, and the missile cruiser will fire at only those ships + that are in range, regardless of whether the ships are in radar + range of the cruiser or not. They need only be in range of the + anti-shipping missiles. This is an effective, if blundering, way + of removing approaching fleets before you see them on your radars. + Note: anti-shipping missiles are not available in standard BSD code, + but are available in some other versions, namely the Kent State + code. + + +Summary: Be sneaky. Be imaginative. Think of tricks you can pull on your + opponent. Quite often, they will in fact work. Most players of this + game are not Rommels, Pattons, or Montgomerys. Many can be duped + by very simple tricks. + + + +User's Guide to Empire 63 + +Chapter 14 :-: Tools + + Tools are programs used by players on their local machines to + assist them in developing their country, analyzing another country, + conducting war on another country, etc. Tools are very powerful + devices at times. As such, many players have tools that they consider + to be military secrets and they do not release copies of them. As a + result, many programs doing basically identical tasks have been + written. I encourage those players that are reading this that have + such secret tools to release them to an anonymous FTP site with a + directory for Empire. Not only does this make the game better for the + beginners, but it also helps to keep the experts on their toes, and + give a challenge to those of us who have been playing for quite some + time. + + Some players feel that playing with tools takes something away from + the playing aspect of the game, and feel that in so doing they are not + really playing the game anymore. This has lately turned into a + religious war of sorts in the Empire community, with many people taking + both sides of the coin. + + You do not need tools other than your client to play Empire. + Empire is designed such that any player can play the game without + hindrance without the use of a tool other than the basic client itself. + + What follows is a list of tools that are most commonly found + among players of the game. Most of these are publically available at + an FTP site listed in Appendix C. + +Tool Purpose +autodist Automatically sets distribution paths for an entire + country or realm within the country. +autofeed automatically feeds the people in your country. +pmvr,civmvr Automatically redistributes your population so that sectors + will be able to have population growth rather than maxing + out at the limit of 999 civilians. +econ Provides an analysis of your country's economic progress + at the next update. +GEET Gnu-Emacs Empire Tool. An emacs interface for Empire that + has a great many capabilities and functions. Provides for + better automatic defenses as well. +EIF A more advanced client than the basic client. Allows + for aliasing commands, command editing, etc. +XEMP Empire client for X windows. Provides many nice features + including an on screen map constantly displayed. A very + nice interface that unfortunately still has several bugs. + + These are just a few of the Empire tools out there. There are still + many more programs not listed. Some cover news analyses, country + analyses over several updates, etc. + + Most tools come with documentation on how to use them, and it is + beyond the scope of this guide to illustrate how each one of them + + +User's Guide to Empire 64 + + is used. + + There are other aids that are often called tools which are called + scripts. Scripts can do a great many things for you. The most common + of these applications are simply files containing a list of commands + that you want to execute in Empire. + + For example, let's say that at each update you wanted to dump the + current news into a file in your local directory, get a new power + report and dump that into another file, and dump all current telegrams + into yet another file. This would be three commands that you could + consolidate into one command by doing this: + + Construct a file in your local directory that has the appropriate + commands in it. In this case you could write a file with three lines: + +news >>news.file +power new >>powerfile +read >>old.tele + + You could call this file update.do + + While in Empire you could then request the Empire client to access + that file and execute those commands by using the exec command followed + by the file name. Thus: + +[102:253] Command: exec update.do + + Building such a simple script is useful for doing a set of commands + over and over again without typing it in each and every time. + + Lastly, remember to exercise wisdom in the use of tools. It is + possible that the execution of a simple tool can damage your country + irrepairably. Use tools, especially those written by others, with + caution. Try them out on small sections of your country first. Look + at the source code prior to running it if you have access to the + source code. It is theoretically possible for someone to write + a tool that will scan the list of countries in a game, and if the + author's country name is in that list, send valuable information + about your country to him or her. Yes, it is true, some people + have no morals believe it or not. + + +Summary: Tools are very powerful items if used wisely. It is not necessary + to have tools to play Empire effectively. Some experts of the game + refuse to use tools of any type, and they remain among the best + players. Tools are no replacement for skill. Be careful when using + tools, they can ruin your country. + + + +User's Guide to Empire 65 + +******************************* Appendices ************************************ + + +Appendix A :-: Glossary of terms, names, and etc. + +Amphibious assault - Attacking a sector using ships, usually landing ships. +Avail - A unit of measuring available labor hours in a sector. +Backstab - To harm another country with whom you had prior treaties + and or alliances that were in effect at the time of your + harmful action. Usually a severe action. +Blitz game - An implementation of an Empire game that is very fast paced. + Usually these games last no more than two days. +BSD - Berkeley Standard Distribution. A term borrowed from Unix. + It indicates that the version is a release version from Berkeley, + ie Dave Pare. +BTU - Beaurocratic Time Unit. A unit of government activity. Used + by various commands as cost for executing that command. +Capital - The government center of a country. BTUs are produced by + only one capital in a country, regardless of how many are + designated. Only the actual capital of the country produces. +Client - A program that allows you to connect to the Empire server. +Commodity - Just as in the real world; any of a plethora of raw and refined + materials that can be traded, stolen, etc. +Dave Pare - Not the original author of Empire, but the person who has + made it possible for it to be what it is. THE major author + of Empire. Also known as Mr. Frog. +Deity - Person (yes, a real life human) who runs/referees a game. +Deliver - A means of managing economic resource allocation via orders + from neighboring sectors. +Designation - What the sector has been ordered to be, ie a highway for example. +Distribution- A means of managing economic resource allocation via a central + warehouse scheme. Often referred to as a "distribution + network" +Education - Activity on the part of a country to raise the overall + intelligence level of a country, to promote research and + technological development. +Eif - "Empire Interface". A version of the client with certain + enhancements. +Empire host - The computer the server is running on. +ETU - Empire Time Unit - A subdivision of an update. An update's + value is measured in terms of ETUs. +FTP - "File Transfer Program". This is a means of transferring + files over the computer networks. Most computers are capable + of using FTP. For more information you may refer to your + host computer's help. For example, "man ftp" or "help ftp". +GEET - Gnu-Emacs Empire Tool. An emacs based client, also known + (to the chagrin of the author of GEET) as GEEK. +Geurilla - A patriot behind enemy lines. They will attempt to do damage + to the enemy's military or the sector the enemy is occupying. + You can not control guerilla actions. +HCM - Heavy construction material. A unit of material used in + Empire economies for bridges, planes, etc. +KSU, Kent State code - refers to the version of Empire based on the Berkeley + + +User's Guide to Empire 66 + + release. There are several enhancements in this version, and + many think it is better than the Berkeley release. +LCM - Light construction material. A unit of material used in + Empire economies for education, technology, research, planes, + boats, etc. +Megatons - A unit of measure of nuclear warhead yield. One megaton + equals one million tons of TNT explosive power. Often + represented as 'mt' as in '5mt'. +Mobility - A number indices indicating the available amount of moving + capability in a sector, for a plane, or for a ship. +Plague - An all encompassing term representing disease in the Empire + world. Can be kept in check by the country doing research. +Representative,Rep - Your password for your country in the game. NOT your + real name. +Research - Activity on the part of a country that keeps plague in check. +Reserves - Civilian soldier. A soldier not on active duty who is paid + a small sum to retain training in case of times of need. +Sanctuary - Your starting area in any game. Usually comprised of two + sectors. Can not be attacked, or otherwise affected by + any opponent. +Script - A file containing several Empire commands that can be + automatically run or run manually from the client. +Sector - A unit of geography, comprising an area represented by a + single character on maps. +Server - The program (running usually at a remote site) that handles + the functioning of the game. In essence, the game itself. +Spy - A member of your military forces sent across neighboring + country borders to gather information. +Technology - The scientific development of a country. Relates most directly + to a country's capability to create better weapons. Also known + as 'tech'. +Threshold - A break off point for the 'deliver' and 'distribute' commands + that indicates a quantity beyond which every unit of a + specific commodity is moved automatically at an update. +Tool - A program used on a player's local machine to aid in there + goals in Empire. +Update - A 'turn' in Empire. Mobility is increased in sectors, + civilians multiply and eat food, military is paid for, etc. +UW - Uncompensated worker. A nicer name for slave. +VTOL - Vertical Take Off and Landing capability for planes. Requires + no runways or other developed airport like structures. +Wasteland - A permanent sector designation caused by a nuclear blast of + one megaton or larger. Can not be traveled across by land, + but can be flown over. +Warehouse - A central collection and distribution point for products + of an economy. +Wilderness - Undesignated areas other than mountains and ocean. Represented + by a '-' character on maps. +XEMP - An X windows based client. + + + +User's Guide to Empire 67 + +Appendix B :-: Known exploitable bugs + + As a result of Empire having several thousand lines of code, there +are numerous bugs. Some are simply annoying, others you never notice. Some, +like the following, are bugs that you can be used against you. + + a) "Intercept" bug - Non-VTOL planes can and will rise and intercept + hostile planes from any sector as long as there is petrol in the + sector, the plane has the intercept capability (see show plane c), + it is at least 40% efficient, and it has mobility. + + b) "Escort" bug - Planes that are capable of escort duty can escort + themselves on various missions, as long as they are capable of + the mission in question (such as a bombing raid). Say for example + that you want to fly a reconnaissance mission over enemy territory, + but you know that enemy planes are going to intercept you. + When the game asks you for the plane that will be doing the recon, + you can give it plane 345 for example, which for the sake of + this guide is a jet fighter. When it asks you for the planes + that are going to escort it, you can say 345 again. The game will + respond as if two planes are flying the mission when in fact only + one is. Enemy planes will think there are two planes. Enemy planes + will first do battle with the escort. Let's say they did 16% damage + to the escort, and the escort did 14% damage to one of the enemy + interceptors. Next, the enemy interceptor attacks the recon plane, + which is the same plane, and inflicts 21% damage. The recon plane + inflicts 13% damage on the interceptor, and the recon plane aborts + the mission. It looks like you lost the dogfight. In actuality, + you did not. The intercepting plane suffered a total of 27% damage. + It looks like you suffered 37% damage. However, you actually only + suffered the *last* damage inflicted, which was to the recon plane. + Thus, you only suffered 21% damage and you won the dogfight. + + c) "Flying Bridge" bug - Say for example you have a 100% bridgehead + sector with enough HCMs, workers, and avail to build a bridge. + Normally, you would say "build bridge x,y" and then it would ask + you for a direction to build the bridge. If after you built the + bridge you were to redesignate the bridgehead, the bridge would + collapse. However, if you redesignate the bridgehead sector + before you build the bridge, the bridge will be built and will + not collapse. At the next update, the bridgehead will become + the sector you redesignated it to (say, a highway) and the bridge + will still be there. Note: It is believed that most current + games of Empire have a new patch that prevents this bug. + + d) "Resource sucker" bug - Let's say you have a sector with 23 gold + content left, and it is a gold mine. Normally it might produce + say, 111 gold dust at the next update. If you were to put 9000 + civilians into that sector, it would produce over 900 dust at + the next update. The sector's resource content of gold will go + to 0, but instead of getting a roughly 115 dust from the sector + with the remaining content, you have gotten over 900 dust. + Civilians reproduce quickly enough that losing 8000 civs this way + + +User's Guide to Empire 68 + + is really of no concern especially when you consider what you + have gained. This bug works also for oil wells and uranium + mines. + + I have listed the bugs here because it is important that players + know about these bugs in case they are used against them. I do not + condone the use of these bugs, nor do many players of the game. + Many deities (the people who run the game) take action against + players using these bugs, such as taking away your technology or + your money. Do not use them. Simply be aware that others may use + them and come up with ways to counter their use. If you are aware + that another player is using one of these bugs, report it to the + deity of the game. S/he might give you a reward of some sort. + + Also note that since these bugs have been published> here, it is likely + that some programmer has written bug fixes for these. Most, and + possible all of these bugs might not work in a game you are + participating in. + + + +User's Guide to Empire 69 + +Appendix C :-: FTP sites and other sources for Empire related items + + Herein listed are the net address of computers that have files + related to Empire in there anonymous FTP directories. An example of + anonymous FTP is found in chapter 2 of this guide, and that method + with appropriate substitutions for file names can be used to retrieve + files off of these FTP sites. If you have trouble using anonymous FTP + seek out your local site consultant for more information. + +Host Directory Files available +ucbvax.berkeley.edu - pub/games/empire/bsd Empire client, server, + various tools, this guide. +empire.bbn.com - pub/Emp Various tools, VMS client, + this guide. +star.cs.vu.nl - xemp Xemp +hylka.helsinki.fi - public/vax/games-etc/empireclient.dir + VMS client +uunet.uu.net - games Tools, server. +alcazar.cd.chalmers.se - pub/emp Various tools, patches, eif + eddie, this guide. + + +User's Guide to Empire 70 + +Index + +Agriculture centers 25,49,51 Naval operations +Announcements 17 Defensive 36,54,57 +Avail 45 In mapping 55,61 +Backstabbing 28 Anti-submarine 61 +Banks 56 Amphibious 35,40,54,57 +Bridges 42,45,58,67 Mining 54,60,61 +BTUs 26,45 Nuclear weapons +Capitals 16,26,36,54,55,57 Damage from 38 +Clients 9 Ending games 41 + Basic client 9 Getting 38,42 + Compiling 9-12 Recovering from 39 +Deliver 48,52-53,56,60 Defense of areas hit by 40 +Designate 17,21,25 Oil 42,43,45,50,54,55,67 +Diplomacy 28-32 Paratroops +Distribution network 27,48-52,56,60 In nuclear war 40 +Education 42-43,44,45,47,48 Against capitals 36 +Empire Against forts 35,36 + Addictive 8 Against defended sectors 57 + Blitz games 6 Plague 44 + Compared to Risk 6 Planes + Description 6 In defense 33-34,54,57 + Game length 6 In mapping 28 + Time needed to play 6 VTOL 33,34,40 +Enlistment 40,54 Out of airbases 33,34,59 +ETU, Empire Time Units 26 In nuclear war 38,40 +Exploring 16,21-25 Defending from 57 +Food in sectors 27,54 In escort 67 +Forts 30,34-35,40,54,57,59-60 Population 26,43 +FTP 9,63 Posturing 32 +Gold dust 26,42,43,45,54,55,67 Registering +Guerillas 36-37 Hearing of games 8 +Guns 34-35,36,40 Standard registration 8-9 +HCMs 45,67 Rec.games.empire 8 +Help 16,17 "Red Storm Rising" 30 +Kent State Empire 43, 62 Research 44,45 +LCMs 42,45,47,48 Reserves 37,54,57 +Loans 30,61 Sanctuary 16,21,22,25,27 +Mapping 28,54,55,61 Scripts 64 +Maps 16,18-20 Sectors 20 +Maskirovka 30-31 Server, connecting problems 12-15,26 +Missiles Starvation 26,46,51,54 + In nuclear war 38 Technology 26,27,33,34,42-44 + Against planes 57 Telegrams 17 + Against airbases 59 Thresholds 50-53,56,60 + Against ships 62 Tools 7,8,21,63-64 +Mobility 24,25,26,49,51,61 Uncompensated workers 43,46 +Mountains 25,36 Updates 16,21,25,26,27,36,46,51,56 +Movement 16,20 Warehouse 26,43,48,49-51,56,59,60,61 + Wilderness 20,21,22,23,24,25 + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +.fi +.SA "Introduction" diff --git a/info/Introduction/Hints.t b/info/Introduction/Hints.t new file mode 100644 index 00000000..8a12aac9 --- /dev/null +++ b/info/Introduction/Hints.t @@ -0,0 +1,177 @@ +.TH Introduction Hints +.NA Hints "Hints to help you play Empire better" +.LV Expert +.s1 +Military and the Demobilization of Same +.in +0.3i +.s1 +It's generally a good idea to put +demobilized military on active reserve. +You should also consider whether you need an enlistment center +to generate more military. +You can't enlist more military than you have military reserves. +The \*Qnation\*U command will tell you how many military you have. +Be careful, as many players have lost their countries +through carelessness with their military +at the start of the game. +.s1 +Actually, the enlist command cannot activate more military than +you have on reserve. +Even then they have to be in sectors +with an efficiency of 60% or greater. +Enlistment sectors can produce as many military as they are capable of, +but will never produce more than one-half +of the civilian populace there. +So you need to keep moving them out, or demobilizing them, etc. +Also, the more military you have in an enlistment center, +the more military get trained per update. +.s1 +Any civilian may be enlisted +(no restriction on the efficiency of the sector). +No more may be enlisted than the number of reserves. +Enlistment costs mobility whereas +while demobilization costs cash. +Military can only be demobilized in sectors +with a 60% efficiency or greater. +No more than one-half the number of civilians in a sector +may be enlisted in one \*Qenlist\*U command, +but if it is issued many times, +virtually all civilians in a sector may be enlisted. +.s1 +One thousand reserves is enough for now, +although I figure I always put them on reserve when I demobilize, +at least up to 10,000. +.s1 +So you don't need to push for more reserves now, +but might as well put all demobilized military on reserve. +.s1 +You make back the cost of demobilizing military in just +two or three days I think, +so I generally demobilize the military I don't have any use for, +and put them on reserve. +.s1 +Depends on how you want to use them, I guess. +I figure with 200 jet transports at 127 mobility, +I can land 20,000 military in an enemy country in one night, +so I'd say 20,000 is a safe upper limit for reserves. +I've never needed more than that. +.in +.s1 +Distribution Hints +.in +0.3i +.s1 +When distributing stuff to a warehouse, +set the thresholds in the sector that is sending to or receiving +from the warehouse to the amount that you want left in that sector. +Don't set thresholds for the warehouse itself +(unless its also distributing to another warehouse) +.s1 +The minimum threshold for distribution is one. +A threshold of 0 means no distribution of that commodity +will take place. +.in +.s1 +Something to Remember about Technology +.in +0.3i +.s1 +An education level of five is required to build technology. +After "easy tech", the tech you build is put through a +logorithm with "tech log base" (see version). +.in +.s1 +War Zones +.in +0.3i +.s1 +It makes it much easier if the player doesn't +have to do anything to keep his country running, +but can instead do the things that are of interest. +There's also the problem of what to do in an invasion. +I guess if invaded I just accept the damage, +and don't try to fix it until the war ends. +.s1 +In a war zone I generally follow one of two basic plans. +If I'm the invader, I either leave the sectors as they are +and let the country being invaded fall apart, +or if I can do something to make it worse for the enemy, +I sometimes do that. +I sometimes designate conquered sectors to agribusinesses +if they need food, banks to reduce shelling damage, +enlistment centers for military, +forts for firing and attacking, harbors to get ships in, +warehouses to collect, move, and distribute supplies, +airbases for planes and bridge heads for easy movement. +.s1 +When being invaded, I also generally postpone any +long term development and just concentrate on the +basic sectors types for combat (a,b,c,e,f,h,w,#,*) +.s1 +I've found it's a mistake to worry about long term +development in a war zone, until the battle is over. +I will let a war zone be completely wrecked in order to achieve victory. +So you need to keep your home area away from any war zones. +.s1 +So far the method of treating war zones and +peaceful zones differently and keeping them separated +has worked pretty well. +The mistake I made in the past was to try to develop a war zone +before the fight was over. +Now I'm willing to completely wreck the area to win, +and in fact you pretty much have to. +The guerrillas take several days to get rid of even when +the war is over. +.s1 +I mostly turn the sectors in the front lines into forts, enlistment +centers, banks, and bridgeheads. +Then maybe some warehouses, airports, and harbors +within range of the front lines. +And maybe some radar stations. +.in +.s1 +Work Percentages are Important! +.in +0.3i +.s1 +I've found it good policy to produce a large surplus +of food and aim to have at least 100 food in each sector, +when I have enough. Actually I now put 990 food in each +sector, except for aggies (100) and warehouses (9990). +.s1 +Before moving civilians, +check the work in the sector the civilians are in. +If it's less than 100%, DON'T move any of them out. +The reason: work in the destination sector will drop to +the same level as the starting sector. +.s1 +It's a good idea to check after every update, +to see if any sectors have work less than 100%. +\*Qcen\ #0\ ?work<100\*U is what I use. +If work is less than 100%, workers won't work at full efficiency, +and if it gets very low, +the civilians may revolt and you'll lose the sector. +Build lots of happiness, and keep extra mil in sectors with +work less than 100%. +That seems to help. +.in +.s1 +Definitions and a Good Thing to Remember +.in +0.3i +.s1 +\*QWorld tech\*U and \*Qworld research\*U refers +to the technology and research made by other countries +which will automatically leak to the less developed countries. +.s1 +If you let education get higher than happiness, +then find work going to 0% in your sectors, +don't say you weren't warned.... +.in +.s1 +On Nuclear Devices +.in +0.3i +.s1 +Just a note on nukes: in this version, there is +a nice balance between nukes and economics. +A player can do a lot of damage with nukes, but it costs a LOT. +So it's rare that a country is completely annihilated +by a nuclear attack, +as used to be the case in PSL Empire. +.in +.SA "Overview, Introduction" diff --git a/info/Introduction/Kill.t b/info/Introduction/Kill.t new file mode 100644 index 00000000..02da30aa --- /dev/null +++ b/info/Introduction/Kill.t @@ -0,0 +1,35 @@ +.TH Introduction Kill +.NA Kill "How to kill your process on the server" +.LV Basic +.s1 +At some point you may lose your connection to the game. +When this happens its possible that the game will not +log your country off and you will get a message saying that +you are still playing the game. This can be easily fixed by the player +if you type in the following. +.s1 +.nf +.in +1i +telnet your.local.empire.machine 6666 +coun +pass +kill +quit +.in -1i +.fi +.s1 +What happens is that you are connecting directly to the Empire Server. +From there you enter your country name and password. +You can then kill the job that's running and then quit so you can +login again using the client. +.s1 +This little trick will work on just about any Empire game. +Of course you need to telnet to that game and +and enter the correct country and password. +.s1 +Its a good idea to write this down somewhere and DON'T LOSE it cause +chances are that you will have to use it at sometime. +.s1 +Note that many clients offer a "kill" command which does this. +.s1 +.SA "Introduction" diff --git a/info/Introduction/MakeSrcs b/info/Introduction/MakeSrcs new file mode 100644 index 00000000..57b48365 --- /dev/null +++ b/info/Introduction/MakeSrcs @@ -0,0 +1 @@ +INFOSRCS=Basics.t Clients.t Expert.t Guide.t Hints.t Kill.t Novice.t Overview.t Suggestions.t diff --git a/info/Introduction/Makefile b/info/Introduction/Makefile new file mode 100644 index 00000000..d2224a61 --- /dev/null +++ b/info/Introduction/Makefile @@ -0,0 +1,62 @@ +# +# Empire - A multi-player, client/server Internet based war game. +# Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, +# Ken Stevens, Steve McClure +# +# 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 2 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, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# --- +# +# See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the +# related information and legal notices. It is expected that any future +# projects/authors will amend these files as needed. +# +SRCDIR = ../.. +NROFF = nroff +TROFF = troff + +INFOSRCS = empty + +INFOOBJS = $(INFOSRCS:.t=) + +HTMLOBJS = $(INFOSRCS:.t=.) + +include MakeSrcs + +.SUFFIXES: .t + +all: + @echo INFOSRCS=`echo *.t` > MakeSrcs + @make nroffs + @echo Done. + +html: + @echo INFOSRCS=`echo *.t` > MakeSrcs + @make htmlfiles + @echo Done. + +htmlfiles: $(HTMLOBJS) + +nroffs: $(INFOOBJS) + +$(INFOOBJS): + @$(NROFF) $(SRCDIR)/info/CRT.MAC $@.t | awk -f $(SRCDIR)/info/Blank.awk > $(SRCDIR)/info.nr/$@ + @echo Created $(SRCDIR)/info.nr/$@ + +$(HTMLOBJS): + @perl $(SRCDIR)/info/emp2html.pl $@t > $(SRCDIR)/info.html/$@html + @echo Created $(SRCDIR)/info.html/$@html + + diff --git a/info/Introduction/Novice.t b/info/Introduction/Novice.t new file mode 100644 index 00000000..ee27b46c --- /dev/null +++ b/info/Introduction/Novice.t @@ -0,0 +1,585 @@ +.TH Introduction "Advice for Novices" +.NA Novice "Advice for Novices" +.LV Basic +.ce 3 +.s1 +\*(iFA Preface\*(pF +by Ken Stevens +.s1 +While most of this document applies to the game of Empire in its +current form, it is important to keep in mind that the sections which +follow this preface were written long before missions or land units +were introduced into the game. The main impact that missions and land +units have had on the game is that they greatly strengthened the +defense. Here are "ten easy steps" for setting up a strong defense in +the new server: +.NF +(1) Build 100% forts and put 10 guns and at least 100 shells in them. +(2) Put at least 5 mil in all of your coastal sectors. +(3) Build infantry units, put them in the forts, "fortify" them, and + put them on "reserve" mission (info mission). +(4) Build battleships and artillery and put them on "interdiction" + mission. Put the artillery in forts and fortify them. +(5) Put infantry units in your banks and capitals, fortify them, and set their + reaction radius to 0 (info lrange). + +---later in the game--- + +(6) Put lots of land mines in your ground (info lmine). +(7) Build fighter planes. +(8) Always guard your ships with destroyers (or other kinds of ASW ships). +(9) Build some ASW planes and put them on interdiction mission. +(10) Build lots of sam's and abm's. +.FI +.s1 +\*(iFA Treatise of Advice on War and Peace +for Budding Empire Players\*(pF +by Dave Pare +.s1 +This article contains advice for beginning players. +It deals mainly with staying alive and not economic development, +because staying alive is tougher for beginners +than is playing with the various Sector-types. +.s1 +The most important thing I can say is that beginners should remember +that Empire is not realistic. +There are dozens of \*Qtricks\*U to learn; +until you master them, you will lose because of small oversights +Beware of patterning your Empire actions after real-world strategies; +they may not work as expected. +.s1 +When you start, grab as much land as possible. +Locate and identify other players, +and get an idea of the size of your land mass. +Send them all telegrams. +Everybody likes to get telegrams; +the telegram facility gives you the chance to make friends, +influence people, and have fun role-playing your country. +If you get to know somebody, +you may not be attacked because you come across as a nice guy. +Of course, if you sound like a bozo, you may get stepped on. +.s1 +Establish a definite border with your neighbors by inhabiting +sectors with one civilian. +This establishes your claim +to the land behind these outposts, +even though you don't actually occupy it yet. +It also prevents your neighbor from discovering where YOUR capital is. +In Empire, it's very important to protect the location of your capital; +likewise, it's quite nice to know the location +of the neighboring capitals \*Qjust in case\*U! +.s1 +If any of your neighbors attacks your outposts, +that gives you a valuable clue to their intentions, +while not costing you much in the way of resources. +Also, an attack on a remote outpost may give you enough time +to prepare your country for the possible invasion to follow. +You may not want to claim too much land though, +or the outposts will get overrun by people +who are fed up with your obvious land-grabbing. +.s1 +Basically, try and be fair about land distribution, +but make sure you get a good deal for yourself. +.s1 +Empire players go to war for many reasons. +One is lack of resources; +you have land, and they want it. +Another is safety; +your troops or ships are perceived as menacing, +so they are destroyed by your adversary. +Another is because the attacking player +really enjoys attacking people! +Still another is boredom and/or curiosity -- +\*QJust how do nukes work anyway? +Hey, I know, I'll try them out on Freedonia!\*U +.s1 +In Empire, wars are generally won by people who attack first. +Because mobility can be saved up +your attacks can proceed while the hapless enemy is asleep. +Many Empire attacks have happened over the weekend, +or at 2:00 in the morning. +It is quite difficult to defend your country when you're not logged in. +The auto-defense features of the game are minimal at best. +.s1 +The whole philosophy of \*QFirst Strike\*U holds true from early land +warfare, to naval warfare, to the philosophy of Mutual Assured +Destruction. +If you strike first and your attack is well-planned, +any retributive strike of the enemy's will be ragged at best. +If it's a land war, +all of the fighting will be on the enemy's territory, +not on yours. +Your industries will be fine, and the battleground will be the enemy's. +.s1 +Having mentioned the advantages of pre-emptive strikes, +I must caution against spur-of-the-moment attacks. +I've noticed that many wars tend to occur because +some country sinks your battleship; +you get mad and decide to attack. +I'm just as guilty of this as anyone. +Spending a few days marshaling your forces +can mean the difference between a long, drawn-out slugfest, +and an overwhelming 2:00 blitzkrieg +that blows away half the enemy's army and navy +within the first few hours. +While it's nice to have instant gratification +(seeing enemy troops die right after you read the telegram +describing the destruction of your poor, defenseless battleship +feels SO good), +a hasty counterattack will alert your enemy +who will mobilize forces and retaliate accordingly. +Things will escalate, and you'll be in a full-scale shooting war +before you can say \*QGulf of Tonkin Resolution!\*U +And you will have lost the advantage. +.s1 +Going first only counts if you have marshaled your forces. +A scattered, ill-planned attack will net you nothing +but a little instant gratification, +at the cost of a long drawn-out war in which +your neighbors who aren't fighting are the only winners. +Once two countries are at war, +it's much harder to win \*Qovernight\*U. +Vietnam is a good example of what you shouldn't do. +Gradual escalation just gives the enemy time to prepare. +A sudden, overwhelming attack is far better +and will achieve your goals much more cheaply. +.s1 +Knowing where the enemy is located is absolutely critical +to the planning of a successful attack. +.s1 +War takes up a lot of resources; +your personal time is the most precious resource of all. +In a war, your time, energy, and creativity will be devoted +towards destroying your adversary. +This leaves little time for economic development. +In war, the home front stagnates, or goes to seed. +Only the bare necessities are produced for the civilians at home, +technological innovation and new land development ceases, +and your country will generally fall behind in the global race +for technology. +.s1 +Therefore, if you decide to go to war, +you'd better win quickly +or else it will take a lot of time, +and your country will go downhill fast. +If you're just punishing someone for doing something \*Qnasty\*U, +offer \*Qnice\*U peace terms after you've meted out +appropriate punishment. +If you aren't attacking because you're bored, +other players are likely to agree to peace +because losing a war is unpleasant. +I've turned enemies into allies often enough; +they are happy to survive, +and if your attack was relatively justified, +they are happy to have you as a friend. +.s1 +You'll notice I didn't give any advice to responding to an attack. +I think being attacked is generally a losing proposition +because in Empire the attacker generally has the advantage +unless fighting with greatly lower tech equipment. +.s1 +As soon as ships start appearing on the power chart, +make sure each sector bordering water +has at least five to ten military. +When more ships come around, beef up the coastline defenses even more. +Put tons of military in your capital. +.s1 +To summarize, +if you go to war, strike the first blow -- preferably at 0200. +.s1 +Remember the cost in your own personal time investment. +Once the ball starts rolling, +you won't be able to call it all off and go for a vacation. +Your enemy will want to kill you, +so you'd better be prepared to spend plenty of time in solid play. +.s1 +.ce 3 +\*(iFHumble Additions to the +Treatise of Advice\*(pF +by Tom Tedrick +.s1 +In addition, keep mobility in mind. +In many of my low-tech wars, superior mobility was decisive. +.s1 +Combining these ideas gives you my basic opening strategy: +take as many sectors as is possible, as quickly as possible +(I will take 300 sectors the first day if I can), +and designate them highways, leaving one civilian in each sector. +(You may need to leave one food in sectors with zero fertility.) +.s1 +When my country first reaches 100% efficiency, +roughly two-thirds of my sectors will be 100% efficient highways. +This allows me to shift my forces all the way +from one border to another in a single move. +I once had great fun smashing three countries +that attacked me simultaneously from three sides +by shifting all my forces from border to border to border, +achieving local superiority in each case, +and annihilating the enemy forces in turn at updates +(this is related to the theory of the +advantages of interior lines worked out by the Germans). +.s1 +If the enemy runs out of mobility you can sometimes catch +the main invasion force helplessly immobilized on the front lines +and annihilate it. +.s1 +.ce 2 +\*(iFHints to the Wise\*(pF +by Shelley Louie +.s1 +Since this is an advice note, +I'll refrain from being too specific about tactics. +You'll just have to learn them yourself. +.s1 +Building the Perfect Beast: (Country Construction) +.in +0.3i +.s1 +The first thing you want is land. +Lots of land. +A whole hell of a lot of land. +You should try to expand your country from the very beginning. +From there, you'll meet your neighbors who are doubtlessly +doing the same thing you're doing. +Expanding wildly. +Now comes the first of a series of decisions you have to make. +Do you want to become a raging power-mad warmonger? +If you do, be sure to have built your army beyond the basic 100 troops. +The earlier in the game you find someone, +the easier it is to crush them into oblivion. +If you feel peaceful, see the diplomatic section of the text. +.s1 +Another difficult decision is designating your sectors. +A good beginning mix is two mines per light construction and +heavy construction factory, +about 20% agribusinesses +(later dropping to 10%, 5%, or even none at all!), +and a few schools, research, parks, etc. +to fill up some of the other space. +The most important thing to have is a good transportation system +in the form of your highways. +Anywhere from 20-40% of your country should be highways. +You'll find them infinitely useful +in moving food to a starving sector, +taking people to a new settlement, +or transporting troops to a local revolution, highways are vital! +.s1 +Another important consideration is \*Qdo you want really want to win?\*U +This implies the idea of competing +in terms of building technology and research, +and being able to get supplies to continue to produce +both of these vital products plus happiness, +a high (greater than 10) education, maintaining a military force, etc. +Winning means succeeding on all fronts. +I play to win, but find that I can't devote the time or effort +to winning, so I usually end up playing for the pure enjoyment +of the game. +Ask Tom [Tedrick] how many hours he puts into playing, +and you can figure that is what you're going to have to do to win. +A final warning, if you play seriously, your grades will drop. +No if's, and's, or but's about this. +You can't just throw three to five hours a day away +and not have your schoolwork suffer. +.in +.s1 +Happiness is a Warm Gun: (The Art of Diplomacy) +.in +0.3i +.s1 +No one trusts anybody in this game unless you know them personally +outside of the limited scope of Empire. +Of course, this limits you a lot, +so you break the rules and make alliances +with people who you have no relation to. +And they in turn backstab you and devastate the country +you so meticulously built for the last few weeks. +Oh well, that's what you deserve... +.s1 +Just kidding. +Most of the people you will play with are rather trustworthy souls. +At least they are until it becomes burdensome to them. +A good relationship (as all those sex manuals will tell you) +is based on trust and respect for the other person. +What does this mean to you? +Build enough military to be a pain to invade. +Military power insures respect. +Trust is up to the two people involved. +.in +.s1 +Night Moves: (The Art of Empire) +.in +0.3i +.s1 +Empire is a skill. +Never forget that. +You will learn as you play that you may have to stay up +for that 3:00 AM update to completely surprise your unknowing victim +or even just to maximize your country's potential. +Also never forget that someone may be up at that time +waiting to pounce all over you too. +Pleasant dreams. +.in +.s1 +Running on Empty: (Losing and still having fun) +.in +0.3i +.s1 +Okay, you've tried to keep up with Tom [Tedrick], Chris [Guthrie], +and all those other experienced people, +but it just isn't going to happen. +You are not going to win the big win (i.e., become world dictator). +What do you do? +Give up and watch your country go to pot? +Give all your stuff away to another country and resign? +.s1 +No! +You can have fun even after you can't win. +Make small wars with other small countries. +Try to get a hold of nukes to devastate them. +Form a cartel with other small nations +and try to run over a big country. +As in real life, the possibilities are endless! +Look at the Middle East, they're having fun, right? +.s1 +This is just a game, and from this point on, +you don't have to worry about watching over your nation too closely. +Play for the enjoyment of playing. +.s1 +Which, of course, is the intention of Empire in the first place. +.in +.s1 +.ce 2 +\*(iFOn the Distribution of All Things\*(pF +by David Bleckmann +.s1 +The reader here is assumed to have read the information pages +on distribute, threshold, and level. +.s1 +To use distribute, it is a good idea to have a warehouse. +You don't have to, but this is how the command usually works. +If for some odd reason you don't use a warehouse, +you will have to use some other sector as your +\*Qdestination sector\*U, as mentioned in \*Qinfo level\*U. +For novices, just build a warehouse. +I will refer to warehouse instead of distribution sector +for the rest of this text. +.s1 +You should place your warehouse in a spot +that can be reached by all your sectors via a low mobility path. +That is, for each sector you own, +there should be a path along which you could move goods +at very little mobility cost. +Since 100% efficient highways don't cost any mobility to move across, +roads that come close to each of your sectors +and lead to your warehouse are a good idea. +.s1 +Now for each of your sectors you must set up a distribution path. +Use the distribute command. +This is a path from each of your sectors to your warehouse, +along a low mobility path as described above. +For example, if you have a nation that looks like this: +.NF + j j m + c + m + g * + + h + w + k + m + + g +.FI +And you wanted to set up a path from your capital, +you would give the command +.EX dist 0,0 bbg +.s1 +Note: the path can only be so long, +and as your country gets larger you will +need more than one warehouse. +.s1 +Once you have done this for all of your sectors, +you are ready to start distributing. +.s1 +Now you will probably want to have food on all your sectors, +and if one sector has a lot of people on it, +you may want to have a bit more on it. +You will not want to have to monitor the food levels +for all of your sectors. +This is the process that is automated by distribute. +.s1 +Using food as an example, +you can go through all of your sectors and issue a threshold command, +such as: +.EX thresh f 0,0 40 +.s1 +This will set the threshold for food at your capital at 40. +You can do this for all of your sectors using a command like +.EX thresh f # +.s1 +And give a threshold for each of your sectors as prompted. +.s1 +Now at each update, +Empire will move food to and from your warehouse +in an attempt to satisfy all your threshold requirements. +If for example a certain sector +has more than its allotted threshold of a certain product +(e.g., an agribusiness producing food), +food will be moved off it to the warehouse. +If a sector has less than its threshold, +and the warehouse has any of that commodity, +the product will be moved from the warehouse +to the needy sector in an attempt to satisfy its threshold. +If a certain sector has a threshold of 0 for a certain product, +no distribution takes place. +.s1 +Therefore if you wished to move as much iron as possible +from an iron mine every update, +you would set its threshold for iron to one. +If somewhere else you had a lcm factory that can use 45 iron a turn +(found out through the prod command) +you would set its threshold for iron to 45 (or greater) +and its threshold for lcm's to one. +Then, on each update, +Empire would move all iron off your iron mine (except for one unit), +try to put 45 iron on your lcm factory and take all lcm's +(except for one) +off your lcm plant +(possibly to be used somewhere else). +.s1 +Note: the order in which this happens is predictable, +but not always desirable. +Thus, if you have no iron on your warehouse to start with +and your lcm factory gets updated first, +it won't get any iron even though there will be some in the warehouse +in a few seconds. +It is always a good idea to keep surplus goods in your warehouse. +.s1 +The end result is that you can set up your country to move your products +around without you logging in. +It also doesn't cost as many mobility points +to move things as distribute, and it costs no BTU's! +.s1 +.ce 3 +\*(iFSome Further Clarifications +on Distribution versus Delivery\*(pF +by David Muir Sharnoff +.s1 +.in +0.3i +\*(iFSecondly, I am still a little confused +about distribution and delivery. +When I designate a distribution route, +does that mean that things will be delivered +from the point of distribution to the warehouse? +Or do I also have add the delivery route +on top of the distribution route in order to get things moving? +And how do I get the visual route of the distribution route? +I can get delivery routes by doing the route command. +Thanks.\*(pF +.in +.s1 +The two methods of moving commodities +(distribute/threshold/level and deliver/cutoff/route) +are completely independent. +.s1 +Delivery is most useful for short, one-sector, movement of commodities. +Distribute can be used in conjunction with highways and distribution +sectors to provide low-cost, long-range movement of commodities. +There is no analog to the route command in the distribute paradigm. +.s1 +Here are some examples of commands: +.s1 +.EX distribute -2,0 jjjh +This command sets up a distribution path from the distribution sector +in -2,0 to sector 4,0. +.s1 +.EX thresh food 4,0 400 +This command sets the threshold on sector 4,0. +Sector -2,0 (the distribution sector for 4,0) +will attempt to keep 400 units of food in 4,0 +by importing or exporting as necessary. +.s1 +.EX thresh oil 4,0 100 +This command is the same as above, +but will instead attempt to keep 100 units of oil. +.s1 +.EX level -2,0 +This command will report the distribution routes +and thresholds for sector -2,0. +.s1 +.EX deliver food -2,0 (384) y +This command will deliver all food from -2,0 +in excess of 384 units to -3,-1. +.s1 +.EX deliver lcm -2,0 b +This command will deliver all lcm's from -2,0 to -3,1. +.s1 +.EX deliver lcm -2,0 +30 +This command will deliver lcm's in excess of 24 +(deliver uses multiples of eight). +.s1 +.EX cutoff -2,0 +This command will report what commodities are being delivered +from -2,0 and what their cutoffs are. +.s1 +.EX route food -20:20,-10:10 +This command will graphically report the food delivery paths +in the sectors from -20:20 to -10:10. +.s1 +.ce 2 +\*(iFSome More Hints for the Novice\*(pF +by Jeff Trim +.s1 +Tech levels are very important in this game. +You cannot produce uranium, guns or shells +until you achieve a tech level of 40. +.s1 +Choose your friends carefully. +I was talking to Lewis from Cornell College +and his comment was the best I'd heard in a while: +\*QNever ally with someone that doesn't have a definite +interest in seeing you survive.\*U +Don't be deceived by the treaty command; +treaty violations will show up in the news, +but that is not going to stop the aggressor from wiping you out, +no matter how bad it looks in the news. +.s1 +Nuclear attacks can cause a lot of damage, +but no one has ever been taken out of the game by a nuclear attack. +The damage from a purely nuclear attack is recoverable. +It takes conventional forces combined with nukes to really do damage. +(Of course I won't fool you either; +it doesn't hurt to have a few nukes either.) +.s1 +Beware of running low on BTU's. +I will recount one story of a player on this site +that was running low on BTU's. +His enemies launched a nuclear attack and hit his capital! +Unfortunately, he didn't have enough BTU's +to redesignate a new capital. +The moral of the story is that you should +plan an alternate capital at some point in the game. +These are generally not needed at the beginning of the game, +because you need to effectively deploy your sectors in the early going. +But later, it wouldn't hurt to have one or more alternate capitals. +.s1 +Empire is a game of perception. +If your adversaries think you're tough, +they're probably going to pass you and head for easier prey. +But the reverse is also true; +if you look weak they might try a few tactics on you -- +and depending upon your response, +they'll either back down or fight it out. +Bargain from a position of strength. +You could be the weakest country on the planet but still look +so tough that no one would bother you. +It's all perception. +.s1 +Weak countries have an added advantage: gun running! +If a country is heading out with his fleet +to attack another country and you happen to be along the way, +you could cut a deal with him and +you could make a deal and allow that country to attack a coastal +sector and turn it into a harbor. +You've now placed an obligation on that country, +who will be very careful to keep you happy so you won't +grant similar privileges to that country's enemy. +Weak nations can be quite powerful if you handle the diplomacy right. +The tough players like blowing away their tough adversaries +and as long as you stand idly by +and watch those two countries blow each other to little pieces, +you'll be left intact and growing richer off their little war. +.s1 +.ce +.s1 +.SA "Overview, Hints, Expert, Introduction" diff --git a/info/Introduction/Overview.t b/info/Introduction/Overview.t new file mode 100644 index 00000000..c06bf655 --- /dev/null +++ b/info/Introduction/Overview.t @@ -0,0 +1,236 @@ +.TH Introduction "An Overview of Empire" +.NA Overview "An Overview of the Game" +.LV Basic +What is Empire? +.in +0.3i +.s1 +Empire is an military/economic simulation of make-believe +countries in a make-believe world. +The military part is emphasized. +The economic part is still there, +but as a prerequisite to a working military. +.in +.s1 +What part do I play? +.in +0.3i +.s1 +Each player is the ruler of a country. +As leader of your country, +you give commands that affect your country +(e.g., move people around, +re-designate sectors, etc). +You also handle all of your country's foreign policy. +.s1 +Empire lets you get reports on the status of your country +(``info census'' and others), +find out what's going on in other parts of the world +(``info news''), +and communicate with other countries +(``info telegram''). +.s1 +Although no goal is explicitly stated, +most players rapidly derive their own, +ranging from the mundane desire to be the biggest, +strongest country in the game, +to the more refined goals of +having the most efficient land use possible, +or having the lowest ratio of military to civilians while +still surviving. +.in +.s1 +The World of Empire +.in +0.3i +.s1 +Empire is played on a hexagonal map +partitioned into a rectangular grid of \*(iFM\*(pF\ \(mu\ \*(iFN\*(pF +sectors (where \*(iFM\*(pF and \*(iFN\*(pF are typically, +but not necessarily, +powers of two, usually 64, 128, or 256). +The world is made up of approximately +50% sea, 45% habitable land and 5% uninhabitable mountains. +.s1 +Sectors can be assigned a specific sector type. +These types range from banks to nuclear fuel processing plants. +See ``info Sector-types'' for more detail. +.s1 +Your personal coordinate system is based on your capital, +which is a type of sector. +Your capital is generally marked by the coordinates 0,\ 0. +.in +.s1 +The Empire Time Scale +.in +0.3i +.s1 +The Empire world both does and does not match the real-time world. +To better explain this, let us examine the concept of an update. +.s1 +At regular intervals (usually once per day), +the entire Empire world is updated. +When the world updates, new population is added, +ores are dug up and added to stockpiles, +food and other commodities are distributed to sectors, +the educational and technological levels are updated, +and so on. +It can be thought of as the minimum quantum for growth. +.s1 +On this time scale, an update could be considered +to be approximately one generation. +Thus the difference from the time scale of the real world. +.s1 +However, certain commands are issued in real-time, +such as attacks. +These commands have instantaneous effects on the state of your country. +Dedicated (or merely experienced) Empire players will often +log on to monitor their country. +And most attackers will wait until the small hours of the morning +to carry out their attacks, for obvious reasons. +.s1 +If you do not log in to Empire, +any automatic policies you have set up will be carried out. +However, Empire will not try to fix any mistakes you have made; +unless you are very careful, +it's probably not a good idea to rely on these automatics. +.in +.s1 +Bureaucratic Time Units (BTU's) +.in +0.3i +.s1 +To prevent the more fanatical Empire players +from staying logged on all the time, +Empire places a limit on the amount of time you may be logged in +per day. +This limit is settable by the deity, usually 1000 minutes. +If you run out of time, too bad! +You can't log in again until the counter resets itself +(usually at midnight). +.s1 +The other control on the number of commands that you may issue +are called ``Bureaucratic Time Units'' or BTU's. +A BTU is an arbitrary amount of bureaucratic bookkeeping that +your government must spend to perform a certain function. +Most commands that are not merely informative cost BTU's. +.s1 +BTU's are generated by your country's capital. +The more efficient your capital, the more BTU's that are generated. +The number of BTU's also depend on the game's settings.. See the +output of the 'version' command for an estimate of BTU generation speeds. +However, you may have a maximum of 512 BTU's at any one time. +And once your BTU's reach zero, you may not issue any commands +that use BTU's. +.s1 +Three things to note about BTU's: +.in +\w'00)\0\0'u +.s1 +.L 1) +Since commands use up BTU's, +this limits the number of commands +that a player may issue over a particular time period. +This has the effect of preventing the Empire fanatic +from overruning other players with less free time to log on. +.s1 +.L 2) +The build-up of BTU's is constant and does not depend on being +logged in. +This allows players to participate when it is convenient rather +than at some fixed time +(such as most board games, or the stock market). +.s1 +.L 3) +The BTU concept helps compensate for the fact that, +in concept, the governments of each country are always +``playing'' although the player representing that country +may only log in periodically. +.in -\w'00)\0\0'u +.in 0 +.s1 +How long will a game take? +.in +0.3i +.s1 +Probably from one to four months. +You should expect to spend one to four hours a day playing. +Also expect that if you do spend this amount of time playing, +your grades or work will suffer. +You just can't spend that much time playing and either +study or be productive. +.in +.s1 +What should I do now? +.in +0.3i +.s1 +When a new country enters the game, +it starts out with an amount of money and two sectors. +These sectors are sanctuaries +and have an initial amount of people and commodities. +Until you \*Qbreak sanctuary\*U, +your country is effectively in stasis. +Nothing will change until you actually log in and +force a change +(such as designating a capital to begin accumulating BTU's). +.s1 +The absolutely minimal set of information pages you should read are: +break, map, ann, wire, tel, read, expl, move, res, cen, dist, thresh, lev, +com, prod, budget, Sector-types. +.in +.s1 +A Comment from Peter S. Langston (the author of the original Empire game) +.in +0.3i +.s1 +It should be remembered that Empire is merely an interesting pastime; +in the vernacular, \*Qit's just a game\*U. +There are many amusing stories of people +that took the game too seriously; +one tells of a corporate Vice President +who walked into the computer room and flipped the main +circuit breaker in order to stop an attack on his country; +another tells of the Harvard student +that refused to go to bed until everyone logged out of Empire +and of the other players who took turns staying up late.... +.s1 +While many players take Empire very seriously, +an equal number of players use it as a safe environment +in which they can act out their fantasies. +On occasion the fantasies involved are remarkably aggressive or hostile. +It has been my experience that the people with the most belligerent +countries are often the people with the kindest hearts; +anti-social game play doesn't necessarily reflect the \*Qtrue\*U +being underneath +(or else I have some VERY weird friends). +.in +.s1 +A Brief History +.in +0.3i +.s1 +The game \*QEmpire\*U is the most recent in a series +of territorial conquest, political/economic simulation games +initially inspired by a board game of the same name +played at Reed College (Portland, Oregon). +Earlier versions were written at Reed by Peter Langston +and at The Evergreen State College (Olympia, Washington) +by Chas Douglas, Peter Langston, Ben Norton, Mike Rainwater and others; +of particular note are the games \*QGalaxy\*U (Langston) +and \*QCivil\*U (Norton). +The previous version was written in 1985 partly on the HRSTS Unix system at +the Harvard Science Center, (Cambridge, Mass.), +partly on the Unix system at Commercial Union +Leasing Corporation, (New York, N.\ Y.) +and partly on the Unix system at Davis Polk & Wardwell, +(New York, N.\ Y.) +by Peter Langston with invaluable goading from +Joe Stetson, Robert Bradbury, Nat Howard, Brian Redman, Adam Buchsbaum, +and a myriad of others. +Since Langston never released source code for his version, +Dave Pare and friends de-compiled it in that same year and have +created this version +which is very different. Since then many re-writes and fixes have been +put in and none of the original code exists anymore. +Many people have enhanced the +code, most notably, Dave Pare added plane units in 1986, Jeff Bailey +added many configurable options in the KSU distribution, Thomas +Ruschak added land units and missions in 1992-1993 and released the +"Chainsaw" server, and Ken Stevens rewrote much of the server code in +1995 and released the "Empire2" server, and Steve McClure and the Wolfpack +made lots +of other changes and released the "Empire4" server in August of 1996. +.in +.s1 +.SA "Novice, Expert, Introduction" diff --git a/info/Introduction/Suggestions.t b/info/Introduction/Suggestions.t new file mode 100644 index 00000000..47a2fd96 --- /dev/null +++ b/info/Introduction/Suggestions.t @@ -0,0 +1,46 @@ +.TH Introduction SUGGESTIONS +.NA Suggestions "Suggestions for enhancements to the game" +.LV Expert +.nf + + Whenever I think about new things for empire, I evaluate them in this +order: + + 1) Is it fun? + + This is subjective, of course. The real question should be "Will the +majority of Empire players find this enjoyable?" + + 2) Is is complicated? + + What sorts of new commands are needed? How will the player use the new +feature? Do new commands need to be added? How much will this change impact +the user? + + 3) Is is code-able? + + How difficult is it to do? Does it involve minor changes, or a major +re-write? Many ideas have merit, but are prohibitively difficult to implement. + + 4) Is it realistic? + + In general, realism is good, in that it makes the game more intuitive, +and easier for new players to learn. + + 5) Is it play-balanced? + + It is important that the delicate balance between offense and +defense not be tipped one way or the other. For example, a stacking +limit for land units would tip the balance too far in favour of the +defender. Or, allowing more than one ship to assault at a time would +tip the balance in favour of the attacker. + + 6) Is it important? + + If the change involves adding detail to the game, is the detail +important enough? Does the change go beyond the general level of Empire +abstraction? For example, a change to allow you to name each of your mil +would obviously be beyond Empire's general detail level. A command to name +ships is stretching it. +.fi +.SA "Introduction" diff --git a/info/Makefile b/info/Makefile new file mode 100644 index 00000000..45573a1e --- /dev/null +++ b/info/Makefile @@ -0,0 +1,53 @@ +# +# Empire - A multi-player, client/server Internet based war game. +# Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, +# Ken Stevens, Steve McClure +# +# 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 2 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, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# --- +# +# See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the +# related information and legal notices. It is expected that any future +# projects/authors will amend these files as needed. +# +all: + @echo "Making automated Subjects." + @echo "If this fails, you may not have perl5 installed." + -perl info.pl + @echo "Done making automated Subjects." + (cd Commands ; make) + (cd Concepts ; make) + (cd Introduction ; make) + (cd Server ; make) + (cd Subjects ; make) + -(cd ../info.nr ; ls -CF > all) + @echo Done making info files. + +html: + @echo "Making automated Subjects." + @echo "If this fails, you may not have perl5 installed." + -perl info.pl + @echo "Done making automated Subjects." + @echo "Building HTML info files." + (cd Commands ; make html) + (cd Concepts ; make html) + (cd Introduction ; make html) + (cd Server ; make html) + (cd Subjects ; make html) + (cp ls2html.pl ../info.html) + -(cd ../info.html ; ls -CF *.html | perl ls2html.pl > all.html) + @echo Done making HTML info files. + diff --git a/info/README b/info/README new file mode 100644 index 00000000..f0ce4b92 --- /dev/null +++ b/info/README @@ -0,0 +1,135 @@ + --- How to build the info pages 0--- + +It is very easy to build the info pages. Note that you need prel5 installed to +build the Subject info pages. The default ones are supplied, but if you want +to build new ones yourself, you need perl5. + +To build the info pages, just type "make" at the high level info directory. +This will build you the text info pages that the game uses and put them into +the info.nr directory. + +To build the html info page, just type "make html" at the high level info +directory. This will build you the html info pages (thanks Drake!) and put +them into the info.html directory. Use the "TOP.html" or the "all.html" as +the first html pages you reference (TOP.html is better.) + + + --- How to add a new info page --- + +NOTE: info.pl requires perl5. If you don't have perl5, your Subject.t +files will have to be built for you by someone who has perl5. + +==EASY INSTALL== + +To create a new info page, follow these five easy steps: +1. Copy an existing info page and change the relevant stuff. +2. The .SA ("SEE ALSO") line at the bottom must contain at + least one Subject (see the Subjects subdirectory). +3. Make sure that the entire .SA line is on one line (i.e. no line-breaks + inside the quotes). +4. Type "info.pl". +5. Type "make". + +==SECURE INSTALL== + +If something goes wrong, or if you like doing things carefully, then +follow these more elaborate directions: + +1. Decide which subdirectory to put your info page in: + Commands - Empire Commands + Concepts - Game concepts + Introduction - General info about playing Empire + Server - Info about the server + +2. Decide what to call your info page: + - If it's an Empire command, give it the same name as the command + as listed in lib/player/empmod.c + - You may not name your info page any of the following: + "Command", "Commands", "Concept", "Concepts", "Introduction", "Server" + - Make sure there isn't another info page with the same name in a + different subdirectory. + - Make sure your info page doesn't have the same name as an existing + Subject name (see the "Subjects" subdirectory). + +3. Format your info page. + +Copy the same format as a similar file in the same directory. +The first "Title Header" line must be: +.TH arg1 arg2 + - arg1 should be one of: Command, Concept, Introduction, Server + - arg1 should match the directory the info page is in + - If arg2 contains more than one word, make sure it's in double quotes + - if the info page is for an Empire command, then arg2 must be the + command name in ALL UPPERCASE. + +The second "NAME" line must be: +.NA arg1 arg2 + - arg1 must be the name of the file + - arg2 must be in quotes + - arg2 is a one-line description of the info page which info.pl will + put on the Subject page that your info page belongs to. + +The last "SEE ALSO" line should be: +.SA "item1, item2, ..., subject1, subject2" + - the stuff in quotes is a list of other info pages which are + related to this page and info Subjects to which this page belongs. + - the stuff in quotes must all be on the same line + - You must include at least one subject (see the Subjects + subdirectory) in the list (at the end of the list by convention). + +The lines in between can contain the following formatting characters: + +Empire command syntax: +.SY "command " + +An Empire command example: +.EX "command args" + +No Formatting: +.NF +this stuff +won't be formatted +.FI + +Begin paragraph: +.s1 + +4. Run "info.pl" + Type "info.pl" at the unix prompt. + If there are any problems with your info page, info.pl will abort + with a clear error message explaining what went wrong. + +5. Type "make" + This will compile your info pages into ../info.nr + + +==APPENDIX A - What exactly info.pl does== + +info.pl reads all of the info pages and creates a table of contents +for them organized by subject. An info page belongs to a subject if +that subject appears as an entry in the .SA ("SEE ALSO") field of the +info page _and_ that entry is not the name of another info page. + +For example, the .SA field of headlines.t contains the entries +"newspaper" and "Communication". Since there's already an info page +called "newspaper.t", but there is no "Communication" info page, then +the headlines info page is considered to be a member of the +Communication +subject. + +The output of this script is a bunch of files in the "Subjects" +subdirectory. The file Subjects/TOP.t is the toplevel table of +contents and lists all of the subjects. Then for each subject, a +Subjects/Subject.t file is created, listing all of the info pages that +belong to it. + + +==APPENDIX B - The checklist.pl script== + +This little perl script compares the "list" of legal Empire commands in your +server with the Empire commands documented in the Commands +subdirectory. To run it, login to your game and type: + + [##:##]% list > list.out + +Then, move the list.out file to this directory and run checklist.pl. diff --git a/info/Server/Bugs.t b/info/Server/Bugs.t new file mode 100644 index 00000000..92b408ba --- /dev/null +++ b/info/Server/Bugs.t @@ -0,0 +1,169 @@ +.TH Server Bugs +.NA Bugs "Known bugs in the Empire Server" +.LV Expert +.s1 +NOTE: This file is dramatically out of date. +.S1 +The classification scheme used by report is dumb. +.s1 +You can make a sector temporarily useless by filling up all its +fields with delivery and distribution information. +This is useful when an enemy is trying to capture the sector +(his mil don't have room to move in :-) +You have to halt some of the deliveries or distributions +to make room for the military to move in. +(Mostly fixed by changing the number of available fields) +.s1 +Warehouses can't distribute all commodities simultaneously, +due to limited fields for this information. +This becomes a problem if you have a countrywide network +of warehouses distributing to each other. +(Mostly fixed by changing the number of available fields) +.s1 +You can sometimes build planes in non-airport sectors, +deliberately or accidentally. FIXED +.s1 +You can sometimes move small quantities of certain items +from warehouses at no mobility cost, even into mountains +(this is my favorite bug, I'd hate to see it fixed :-) +.s1 +Guerrillas don't seem to carry the plague. +.s1 +You can get information about enemy sectors +by attacking with 0 military. +This costs 0 BTU's currently +(this is another of my favorite bugs :-) +This is a good way to flood the enemy mailbox with junk mail +at no cost in BTU's. FIXED +.s1 +You can sometimes trick someone into paying a huge price for +commodities by changing the price suddenly. +Therefore one should always check prices when buying commodities. +.s1 +When two countries are attacking each other simultaneously, +you can sometimes move into a sector he is in the process of attacking. +If you get the timing right, +he will take the sector but you will get it back, +along with all his military. +.s1 +If a plane is out to trade, and gets shot down, +it can still be bought until the next update. +If another country builds a new plane +that gets the number of the plane that was shot down, +the new plane will go on the trading market automatically. +Then if that plane is bought, +the money goes to the country whose plane was shot down, +not the country that built the plane. +I stole numerous planes +(including nuclear missiles :-) +this way +(by deliberately putting low numbered planes up for trade, +then having them shot down). +.s1 +If a plane has negative mobility, then gets traded, mobility +goes to 0. +.s1 +Firing on sectors with land-locked sunken ships does strange things. +.s1 +If two countries are cooperating, +its possible to raid an enemy airport and steal the planes +by putting them out to trade. +.s1 +You can also strip enemy sectors of commodities using \*Qsell\*U, +if you have military control temporarily. +.s1 +One can raid an enemy harbor and use up all the raw materials +by building useless ships. FIXED +.s1 +One can make work go back to 100 everywhere in a country by +moving all civilians in low-work sectors onto a bridge, +then collapsing the bridge. +Work then goes to 100 at the next update, +if you leave some mil in the vacated sectors. +Or you can move mil out too, +letting the sector ownership change to the Deity, +then move back in from a 100% working sector, +and work goes immediately to 100. +.s1 +Two cooperative countries can move commodities around at no +mobility cost using the market. +.s1 +You can depopulate an enemy sector in a raid by converting +all civs to uws and selling them. +This can make it hard for the victim to get back in the game +even with a rapid & successful counterattack. FIXED, convert takes mob now. +.s1 +Sometimes sector ownership doesn't change when the last civ starves, +so you may get census information about sectors with 0 civs. +Later this same sector may get its ownership +switched to the Deity without your doing anything. FIXED +.s1 +You can only have so much of a commodity in a sector. +If you went over 32,000 and something, units of food, for example, +bizarre things might happen. +I think that has been fixed. FIXED +.s1 +Treaty had bugs +(for example, firing on any ships was considered a treaty violation, +not just the ships of the country you had a treaty with). +I think Jeff might have fixed this. FIXED +.s1 +Also air attacks were not considered treaty violations. +This may have been fixed. FIXED +.s1 +You can collapse enemy bridges by making a lightning raid on +his bridgeheads and redesignating them, +even if you only hold the bridgehead for a short time. +(In this games, bridges work differently, see info build, info bridges") +.s1 +You can map out enemy territory by raiding his radar stations. +.s1 +Condition checking is very treacherous. +Global commands with conditions are unreliable. +I never figured out exactly what was wrong, +although I think your method of putting conditions +towards the front of the line helped sometimes. +.s1 +You can have more than 26 ships in a fleet, +but only the first 26 will move when you navigate the fleet +(I think 26 is the right number, but I'm not certain. +It might be 32). +.s1 +\*QLook\*U only spots subs (from destroyers) at a certain distance. +If you are too close you won't see them +(unless you are in the same sector). +.s1 +You can only fly as many planes on a mission as +you can fit on the command line +(so low numbered planes have an advantage this way). +USE WINGS +.s1 +I never managed to load more than 1 warhead on a missile, +but I didn't have time to investigate this thoroughly. FIXED +.s1 +Wilderness sectors that you own don't appear as \*Q?\*U on enemy maps, +so you can sometimes hide information by leaving sectors +as wilderness. FIXED +.s1 +When a sector has a visible ship, +radar doesn't show whether the sector is land or sea, just the ship. +This has interesting possibilities for exploitation +(like land-locking a battleship +in your capital in order to deceive the enemy :-) +.s1 +I don't think you can land planes on a land-locked aircraft carrier +anymore. +.s1 +Its common to mistakenly set the price of a plane or ship incorrectly +so one should check trade after using set. +.s1 +Torpedo isn't random, but always works within range +(another of my favorite bugs :-) FIXED +.s1 +Transporting nukes costs 0 mobility. FIXED +.s1 +The \*Qmust be accepted by\*U date on offered loans is bogus. +.s1 +\*QTurn off\*U doesn't stop updates. +.s1 +.SA "list, Innards, Server" diff --git a/info/Server/CHANGES.CHAINSAW.t b/info/Server/CHANGES.CHAINSAW.t new file mode 100644 index 00000000..1aa13653 --- /dev/null +++ b/info/Server/CHANGES.CHAINSAW.t @@ -0,0 +1,663 @@ +.TH Server "Chainsaw Changes" +.NA CHANGES.CHAINSAW "Changes from KSU Empire to Chainsaw code" +.LV Expert +.s1 +CHANGES.CHAINSAW.1.0 +.s1 +Changes to the Chainsaw code in version 1.0 +.s1 +This file enumerates some of the more important changes between +BBN Empire 1.0 & BSD Empire 1.1.5, KSU, & MERC empire. BBN Empire 1.0 +is a superset of the other versions, including all MERC code, which includes +all KSU code, which include the BSD 1.1.5 code. +.s1 +.L Bug-fixes & Changes +.s1 +Scrap and scuttle will now ask for confirmation before scrapping or scuttling +wing or fleets. The will also ask before scrapping or scuttling ALL planes or +ships (when a '*' is given as an argument) +.s1 +Bomb has been changed to allow planes with the P_T (tactical bomber) flag to +bomb, even if they are also cargo planes. This fixes the problem with Zeppelins +not being allowed to bomb. +.s1 +Power has been modified to not report on all deity countries (as opposed to just +ignoring country 0) +.s1 +The plane functions have been extensively modified to calculate and enforce +the ship plane-capacity limits. In previous versions, this was enforced only +in the load command, and incorrectly maintained. (In some situations, the # +could go negative, and wrap around to 255, causing much disbelief) +.s1 +The telegram command was changed so that bulletins from a deity include the +name of the deity country that sent them. (Useful for multiple deity games) +.s1 +The nation files are re-read for the report and country commands. Before, +the program would use the in-memory nation stuff, which meant that it was out +of date if it changed (i.e. people logging in/out after you would not be shown +as logged in in the country output, report would be out of date, esp in blitzes, +etc) With this option, the nation file is closed and re-opened, which updates +the in-memory stuff to be current. This is still not perfect, as when people +exit incorrectly, they are still shown as logged on, until they telnet and +kill the process, or the transaction manager is restarted. +.s1 +Also, the init_nats function was changed. Previously, if a country did not +receive a BTU delta when logging in, its last login time was not set. +.s1 +.L OPTIONS +.s1 +Many new options have been defined for BBN 1.0. +.s1 +.L CHOPPER-STEALTH +.s1 +Choppers have a chance of evading interception. It isn't as good as +stealth, which is why it's listed as half-stealth. I'm not telling +the exact numbers... figure them out for yourself. +.s1 +.L BABY_NUKES +.s1 +Credit for this idea goes to Tom Tedrick. Damage/effects are the same, +but blast effects are confined to the target hex. This also automatically turns +of MISSING MISSILES. Note that launch will still ask about air/ground burst. +.s1 +.L SUPER_BARS +.s1 +Gold bars cannot be pin bombed, and are not hurt by firing. There are still +ways to kill them, but not by shelling or bombing. +.s1 +.L EASY_BRIDGES +.s1 +A bridge can be built in any sector adjacent to one of yours, providing +that the target sector is adjacent to a non-sea, non-bridge sector. Since +bridgeheads are not required, you can't collapse bridges by killing the head. +(You can still kill them by taking the bridge below 20%) This also fixes a +problem with planes on bridges not dying when the bridge dies. (This was partly +fixed before, but the fix didn't work all the time) +.s1 +Note that the sector building the bridge may be a bridge, providing the sector +that the bridge is being built in is adjacent to a non-sea, non-bridge sector. +For example, this is legal: + + . . . . . . . => . . . . . . . +. . . . . . . => . . . . . . . + . - = . - . . => . - = = - . . +. . . . . . . => . . . . . . . + . . . . . . . => . . . . . . . + +.s1 +This is not legal: + . . . . . . . => . . . . . . . +. . . . . . . => . . . . . . . + . - = . . - . => . - = = . - . +. . . . . . . => . . . . . . . + . . . . . . . => . . . . . . . + +.s1 +Also, the sector building the bridge must be at least 60% efficient. +.s1 +.L BETTERARMOR +.s1 +Ship's armor factors now more greatly affect both shelling and bombing. BB's are +much harder to kill. Smaller ships are more fragile.\ +.s1 +.L ALL_BLEED +.s1 +When this option is enabled, countries receive tech leakage from ALL tech +producers, not merely allies. Tech leakage is 33% by default. The leak is +calculated as 33% of the average tech made by all those making tech. For +example, if there are 10 players, making 3, 4, 0, 0, 3, 0, 2, 0, 2, 1 tech, +the total tech made is 15 by 6 countries, for an average of 2.5 tech. All 10 +countries would get .833 tech leak (33% of 2.5), for total tech production of: +3.833, 4.833, 0.833, 0.833, 3.833, 0.833, 2.833, 0.833, 2.833, 1.833 +.s1 +.L DRNUKE +.s1 +You need research to build nukes. (1/4 the tech value, so a tech 300 nuke +needs 100 research) +.s1 +.L SLOW_WAR +.s1 +You cannot attack someone's land unless you are at war with them. (You can +still blow up their ships with fire, board, torp, etc) When you declare war on +someone, your relation goes to Mobilizing. You still can't attack them. After +the next update, your relation goes to Sitzkrieg, and you still can't attack +them. After the NEXT update, you're at war with them, and anything goes. +.s1 +If someone is Mobilizing or in Sitzkrieg, or At War with you, and you +declare war against them, your relation is set to be the same as theirs, so +there is no way to gain any advantage through this stuff. It just means that +you can't sneak-attack people. +.s1 +The restrictions do not apply if you are the old_owner of the sector. If you +are the old_owner, you may bomb/shell/attack at will. +.s1 +Note that while ships are freely attackable, regardless of war status, even +if they are in a harbor of a nation you are not at war with. +.s1 +The first person who declares war pays $1000. Return declarations are free. +.s1 +.L NOMOBCOST +.s1 +Ships do not use mobility when firing. Torpedo mobility cost is reduced to be +equal to 1/2 the mobility the firing ship would use to move a sector. +.s1 +.L NEWSUBS +.s1 +This option encompasses several small changes in sub-warfare. A new flag, sub-t, +is added. Only ships with the sub-t flag are allowed to torpedo subs. Also, +ships with depth-charge capability can now use them to their full gun range. +Depth charges are more affected by sub armor value. Torpedo damage is increased. +.s1 +.L OTHER-CHANGES +.s1 +Most of the ships have had their firing ranges bumped up significantly. + +Thomas Ruschak, The_Scum +.s1 +CHANGES.CHAINSAW.2.0 +.s1 +Changes to the Chainsaw code in version 2.0 +.s1 +This file enumerates some of the more important changes between +the code used for BBNII (Chainsaw Empire 1.0) & Chainsaw 2.0. +.s1 +.L Bug-fixes +.s1 +You can no longer map by attempting to land planes on unknown sectors. +The replies have been standardized to give no information. +.s1 +The radar command is fixed to eliminate 'ghost' images at high tech. +.s1 +Planes can now land on carriers that happen to be in bridge sectors. +.s1 +You can no longer find out if any enemy subs are under your bridges by +trying to load things on them. +.s1 +You can no longer load things onto non-allied ships, even +if they are in a harbor you own. +.s1 +'break' now breaks ALL sanctuaries you own, even if some are not adjacent +to 0,0. +.s1 +When specifying a flight path, the terminating 'h' is no longer counted as +a sector for purposes of range. +.s1 +Qorder is now documented, and works as described in the document. +.s1 +.L CHANGES +.s1 +When scrapping or scuttling groups of ships/planes or wings of +ships/planes, you will be asked to confirm that you want to do it. +(Also when doing scrap * or scuttle *) +.s1 +Ships that assault will always retain 1 food. +.s1 +You may now specify a "number to build" parameter for build. +.s1 +The deity can now make declaration on another country's behalf. +.s1 +Minesweepers now take less damage from mines (1/2 the normal amount). +.s1 +A plane unloaded in an ally's harbor now becomes his plane. A plane loaded +onto an ally's ship also becomes his plane. +.s1 +Your planes may now land on an ally's sectors or ships. Once there, they become +his planes. +.s1 +Ships will fire back in defense of sectors being attacked, +assaulted, or shelled. +.s1 +Your ships/sects will no longer shoot themselves in defense. +You can cheerfully blast your own ships/sects without fear of +retaliation from your own forces. You can also torp your own +ships, and they will resignedly watch as the torps slam into them. +.s1 +Gun ranges are no longer truncated. Instead, there is a % chance equal to the +decimal portion of the range of gaining a hex. For example, with a range of +2.50, there is a 50% chance of being able to fire at range 3. With a range of +6.33, there is a 33% chance of being able to fire at range 7. +.s1 +The power report has been changed to be more realistic. The relative worth +of most commodities has been changed, and a country's total is multiplied by +a tech factor to arrive at a final value. +.s1 +There is no longer a minimum maintenance cost of $1/ETU for planes and ships. +The new minimum is $1. +.s1 +The torpedo command is changed. Surface ships may now have the torpedo ability, +as well as subs. When surface ships torpedo, they are fired at by defending +ships BEFORE they fire their torpedos. +.s1 +An "escort" flag was added for planes. Planes with the escort flag may escort +missions. (Formerly, only planes with the intercept flag could escort) +.s1 +Fighter aircraft being used as tactical bombers are now at a greater penalty +in air-to-air combat. +.s1 +Ships with no mobility may now be nav'd. This allows fishing boats and oil +derricks to check resource values without having mob. (Of course, you can't +move with no mob, and an attempt to do so kicks you out) +.s1 +The load command will now allow you to load wings/groups of planes. +.s1 +You may now give things to allied ships using the tend command. (You may not +take things from allied ships, only give) (If ALLYHARBOR is used) +.s1 +You may now upgrade allied ships. (If ALLYHARBOR is used) +.s1 +Your civs will work on allied ships in your harbors. (If ALLYHARBOR is used) +.s1 +You may assault your own sectors. Mil assaulting are simply added to the +number in the sector. +.s1 +You may now land planes on a carrier in an allied harbor. (If ALLYHARBOR is +used) +.s1 +Conventional non-tactical missiles will now be intercepted by ABM's. +.s1 +.L Options +.s1 +.L Trade-Ships +.s1 +Trade ships simulate internal or external trade. In the real world, you make +goods someplace where they're cheap, ship them somewhere they're expensive, and +sell them, making a profit. +.s1 +For empire purposes, you make a trade ship, which uses many cm's, and costs +$2500. You then sail it somewhere and scuttle it. You get money back, more than +you put into building the ship. The return rate depends on several factors. +.s1 +The primary factor is distance. The distance is calculated as straight-line +distance from the sector the ship is scuttled in to the sector in which it was +built. You have to sail it at least 8 sectors to get any profit at all. If you +sail it more than eight, the profit rises steadily. +.nf + dist < 14: +3.5% * dist + dist < 25: +5.5% * dist + otherwise: +7.5% * dist +.fi +.s1 +Another factor is the sector in which you scuttle it. If you scuttle it in a +harbor you own, you get normal cash. If you scuttle it in the harbor of +an ally, you get a 20% bonus, AND your ally gets 10% of the cash you make as +a bonus (you still get the full amount) +.s1 +For example, using the numbers from above, if you sailed 15 sectors, and +scuttled in an allied harbor, you'd get $4562 * 1.2 = $5.5K, and your ally +would get $4562/10 = $456. +.s1 +The last factor is the efficiency of the trade ship. The cash return is +multiplied by the efficiency of the ship when it is scuttled. +.s1 +Note that captured trade ships can be scuttled by pirates, who receive cash +as if it was their own. +.s1 +.L FUEL +.s1 +Each ship has a fuel capacity, and a fuel usage rate. During an update, ships +use fuel at a rate of 10 mob for every units of fuel. Ships with +a fuel usage of 1 get 10 mob for every 1 fuel, ships with 2 fuel usage get 10 +mob for 2 fuel, etc. Ships with no fuel do not get mobility. Ships with a fuel +usage of 0 do not need fuel. (Sailing ships & nuc ships/subs) +.s1 +A new command, "fuel" is added. It allows fueling from a harbor sector, or a +ship or ships with the "oiler" flag. When fueling, petrol and/or oil in the +harbor or on the oiler is exchanged for fuel points, which are loaded on the +ship. Petrol is used first, if available, at a rate of 1 pet = 10 fuel. If +there is not enough petrol, oil is used, at a rate of 1 oil = 50 fuel. +.s1 +Ships of allies can be fueled, if the ALLYHARBOR option is in use, either at a +harbor, or with an oiler. +.s1 +.L SEMILAND +.s1 +This option adds a flag, "semi-lander", which allows the ship to use 25% of its +mil in an assault. +.s1 +.L SHIPCHOPPERS +.L XLIGHT +.s1 +These two flags are similar. They establish new plane flags, "helo" (ship +helicopter), and "x-light" (extra light). Each ship is then rated on it's +ability to carry those types, +independently of it's ability to carry normal planes. This allows deities +to let non-carriers carry sams, for example, or to let ships carry anti-sub +helicopters or transport helos. +.s1 +.L ASW_PLANES +.s1 +A new plane flag is added "asw". This allows planes with the flag to spot +subs on recon missions. (Detection chance is +(100-accuracy)-(4-sub visibility)*10) +Planes with this flag may be informed (depending on detection ability) when +pin-bombing a sea-sector of the presence of subs. They then have the option of +bombing the subs. Each plane on such a mission rolls separately to find the +subs, and can only bomb the ones it can find. +.s1 +.L PARAFLAG +.s1 +A "para" flag is added for planes. Only planes with the para flag can be used +to paratroop. +.s1 +.L STEALTHV +.s1 +This option adds a new statistic for planes, stealth percentage. Use of this +option effectively disables stealth planes and the CHOPPER_STEALTH option, as +the stealth and half-stealth flags are ignored. +.s1 +With this option, each plane is rated as to its percentage chance to evade +ground-fire and interception. The stealth rating of a group of planes is equal +to the rating of the plane in the group with the lowest stealth rating. +.s1 +.L MULTIFIRE +.s1 +When this option is used, both fire and torpedo accept multiple ships/sectors. +Each firing ship/sector may be used against a separate target, or all may fire +together. +.s1 +Return fire is distributed evenly over the firing ships/sectors, with each +defending ship/sector firing once. The spreading of damage also applies to +subs being depth-charged after torping, and for torpedo boats being fired at +prior to torping. +.s1 +.L RETREATS +.s1 +Each ship/fleet may be given a retreat path, and retreat conditions. Conditions +are: retreat when damaged at all, retreat when torped, retreat when sonared, +retreat when fired upon from beyond max range, retreat if bombed, retreat if +depth-charged. +.s1 +Retreat conditions are assigned to ships, and may be assigned to entire fleets +at once. When a ship's retreat condition is satisfied, things happen. +.s1 +If the ship's fleet has a retreat path, all ships in the fleet that are in the +affected sector attempt to retreat 2 sectors along the path, using mobility as +if they were navigating. +.s1 +If the ship's fleet does not have a retreat path, then the ship checks to see +if it has it's own retreat path. If so, it retreats 2 sectors along it, as +above. +.s1 +Note that retreating ships can hit mines, and could be blocked by new bridges, +or by an ally changing to non-allied status (which would make them unable to +retreat into a harbor) +.s1 +Retreat paths are wiped from a ship when the ship moves. Retreat paths are wiped +from fleets only at the player's request. +.s1 +.L HARBOR_POLICE +.s1 +With this option, the board command is extended to allow boarding of enemy +ships in your harbors. The harbor sector must have mobility, but the command +does not use any mobility. +.s1 +.L MINE_PLANES +.s1 +With this option, planes with the \*Qmine\*U ability are allowed to use +the drop command to drop shells as mines in sea sectors. (see info drop) +.s1 +.L SWEEP_PLANES +.s1 +With this option, planes with the \*Qsweep\*U ability will automatically +attempt to sweep mines while on recon missions. See info recon for more +details. +.s1 +.L BUDGET +This option changes the update ordering a bit, and allows you to set +priorities for production, for those situations where money is tight. +A new command, \*Qbudget\*U, is added, that shows financial information, +and allows setting of priorities. +.s1 +.L DAVYJONES +.s1 +When this option is used, nukes striking wasteland or sanctuary sectors do +not detonate. Nukes striking water sectors affect only their impact sector. + +.s1 +Thanks go to all the people who've helped me with ideas and playtesting: +Jorge Diaz (Ansalon), Tom Tedrick (Afrika Korps), Keith Graham (DreamLands), +Dave Nye (Evil_Empire), Sasha Mikheev (Dolgopa), Baldric, Elsinore, Brett Reid +(Resvon), Kazzadur \ystein Tvedten (Flipper's evil twin), Tharkadia, Yikes, and +many more I'm forgetting. The good things are mostly ideas contributed by these +people. The bugs, I'm afraid, are my own. +.nf + + Thomas Ruschak (The_Scum) +.fi +.s1 +CHANGES.CHAINSAW.2.1 +.s1 +Changes to the Chainsaw code in version 2.1 +.s1 +Chainsaw 2.1 has some minor differences from Chainsaw 2.0. +.s1 +Now, when navigating, sonar or radar commands will +default to the current ship, or the first (lowest +numbered) ship in a group. You may override this by +specifying the desired ship on the command line. +(I.e. "r 12" or "radar 212", etc) +.s1 +The chance of a plane aborting is changed to +(100-eff)%. This means that if a 100% plane +takes a hit for 30% damage, it has a 30% chance to abort. +If it then takes another hit for 20% more, a total of 50% damage, +it has a 50% chance to abort. +.s2 +Also, when bombing ships, rolls are not made for +aborting until after all ships have fired, rather +than rolling every time the plane takes a flak +hit from a ship. +.s1 +A new command has been added, the 'payoff' command. +It shows the value of trade ships if scuttled at +the current sect (check info payoff). +.s1 +Constants have been added to control ship & plane +efficiency growth rate. It is now possible to allow +2xETUS growth in efficiency, 3x, etc. +.s1 +Subs may no longer shell.. they may only torpedo. +.s1 +A WIRE option has been added that activates the +'wire' command. The wire command reads only +announcements. The normal read command then +reads only telegrams & bulletins. +.s1 +When assaulting, troops will always leave at least 1 food on the ship. +.s1 +You may now build multiples of an item by adding a build count at the +end of your build command. (see info build) +.s1 +You may now give comments in the hours file. Comment lines start with a +'#' character. (Players do not need to care about this.. it's for deities) +.s1 +The report command has been changed to not include countries +that are not active. (i.e. visitor or in sanctuary) +.s1 +The version command now show the ship/sector/plane mobility max/gain, +as well as the ship/plane growth constants. +.s1 +CHANGES.CHAINSAW.2.2 +.s1 +Changes to the Chainsaw code in version 2.2 +.s1 +Chainsaw 2.2 has some minor differences from Chainsaw 2.1. +.s1 +A new option, SNEAK_ATTACK is included. It can only be used in +conjunction with SLOW_WAR. It allows you to attack a sector of +someone you're not at war with. Once attacked, the attacker +automatically declares war against the defender, and pays $5K. +At that point, the attacker has to go through the normal SLOW_WAR +procedure before attacking again. See info attack, info assault. +SNEAK_ATTACKs may not be done by parachute. +.s1 +The 'list of commands' command now puts a 'c' in front of commands +that require you to have a capital to use, and a '$' in front of +commands that require you to be non-broke for use. +.s1 +CHANGES.CHAINSAW.3.0 +.s1 +Changes to the Chainsaw code in version 3.0 +.s1 +Chainsaw 3.0 has some major differences from Chainsaw 2.2. +.s1 +Ships that don't carry enough crew lose effic when at sea. See +info build (the ship building section) +.s1 +The BUDGET option has been removed. Budget is now standard. +The NEWSUBS option has been removed. NEWSUBS is now standard. +The MULTIFIRE option has been removed. MULTIFIRE is now standard. +.s1 +I took out the 'too much traffic for workers' thing, because it was dumb. +.s1 +Ships of tech 310 or better can detect mines with sonar. +.s1 +Conventional missiles launched from subs are anonymous. The +victim is not notified of the launching country's identity, +and the news knows naught. +.s1 +In order to export something from a sector, you must have +military control of the sector. In order to import something from a +distribution sector, you must have military control of the distribution +sector. +.s1 +The chances to hit a mine are changed. See info mine and info lmine. +.s1 +Two new deity commands have been added, 'disable' and 'enable', +which disable and enable updates. The 'update' command will mention +it if updates are disabled. +.s1 +When you capture a sector, all distribution info is wiped (distribution +sector, thresholds). Sectors just taken over are stopped (see start and stop). +.s1 +The criteria for sector ownership have been changed slightly. See +info sector-ownership for information. +.s1 +Countries still in sanctuary can now get telegrams and announcements. +.s1 +Fishing boats and oil derricks only work in open ocean sectors. +.s1 +Civs & mil may be distributed. No sector will export its last civ. +.s1 +A new command, bdesignate, has been added. It allows you to manually +modify your bmap. +.s1 +When navigating a ship or marching a unit, you get a map of the sectors around +your ship or unit, without using BTU's. +.s1 +When using map or bmap, giving the number of a ship you own instead +of an area will give you a map centered around that ship. For example, +.s1 +.EX map 1 +.s1 +will give you a map centered on ship 1. Lmap works similarly, except +you can get a map around a land unit, and pmap gives a map around a plane. +.s1 +When loading/unloading, you can give a desired level as a negative number +instead of an amount to load/unload. For example: +.s1 +.EX load 4 -10 food +.s1 +will attempt to load or unload food as necessary to get ship 4 to 10 food. +(Similar to the syntax for enlist) See info load for details. +.s1 +Land units have been added. There are many new commands for dealing with them. +Look at info Land-units for a general overview. +.s1 +Sectors that don't have enough food at the update will now attempt to +draw food from supply sources. (see info supply for details on supply sources. +Conquered sectors will not draw food) +Other sectors/ships/units will now draw supplies (mostly shells) when they +need them. +.s1 +You can now give destination sectors instead of paths for all movement +commands. For example, +.s1 +.EX move c 0,0 10 5,-1 +.s1 +will move 10 civs from 0,0 to 5,-1 via the most efficient path, the +one that uses the least mobility. +.s1 +Ships/planes/units now use lcms/hcms as they gain efficiency, rather than using +them all at once. See info build for more details. +.s1 +Distribution has been changed. Each sector now has a distribution sector +rather than a distribution path (during the update, the least-cost path +is found and used) Also, importing & exporting via distribute now happen +in separate phases, rather than being mingled. See info distribute +and info update-sequence for a full description. +Read info distribute, or don't cry. +.s1 +There is a document that details the update sequence. (info update-sequence) +.s1 +Civs/mil/uw's are much harder to kill (how much harder is deity-settable) +with shelling or bombing or nuking. +.s1 +Air to air combat is changed. Check info interception for an explanation +of the interception process and a description of air combat. +.s1 +Fully efficient roads now have a small mob cost to move through. +.s1 +Fort gun range is now (7*tech factor). Damage from fort shelling now +depends on the number of guns firing. Forts get a +1 range bonus if at +least 60% efficient. +.s1 +Sectors can cost money to designate, and may cost extra to build. They +may also take lcms or hcms to build. Show sector build will show this. +.s1 +A new command, cede, allows you to give a sector or ship to a neighbor. See +info cede for more details. +.s1 +There are several new information commands, such as neweff and +starvation. See the info pages for details. +.s1 +Sectors are damaged by combat occurring in them. See info attack for details. +.s1 +Missions may be given to ships/planes/units, allowing them to interdict +enemy movement, support friendly attacks & defense, and other things. +See info mission for details. +.s1 +Forts automatically fire at enemy ships coming within range. +.s1 +Mountains can be used (poorly) as capitals. See info capital. +.s1 +New options: +.s1 +RES_POP: when RES_POP is enabled, the maximum number of civilians, mil, +or uw's that can be in a sector is determined by research. See info +research for exact details. +.s1 +NEW_STARVE: when NEW_STARVE is enabled, the starvation ordering is changed. +Instead of losing equal numbers of each type of population (uws, civs, mil), +you first lose uw's, then civs, then mil. As before, no more than 1/2 the total +population of a sector can starve in one update. Example: if you have 200 uw's, +100 mil, and 500 civilians, and no food, normally you'd have 100 uw's, 50 mil, +and 250 civs after the update. With NEW_STARVE in effect, you'd have 0 uw's, +300 civilians, and 100 mil. +.s1 +NEW_WORK: When moving civs to or from a sector with low work, the new loyalty +and work percentage of the destination sector is computed proportionally. +For example, of you move 100 people from a 0% work sector to a 100% work +destination sector with 100 people in it, the destination sector will have 200 +50% work people in it. If you then moved in 100 people with a 100% work +percentage, the sector would have 300 67% work people in it. +.s1 +CARRIER_WORK: carriers will now work on damaged planes on board. It's not much, +but it's something. +.s1 +STOP: there are now 2 new commands, stop & start. If you stop a sector, it +will not gain efficiency or produce for 1 update. Start counteracts stop. +Census is also changed to report the production status of a sector. +.s1 +CHANGES.CHAINSAW.3.3 +.s1 +Changes to the Chainsaw code in version 3.3 +.s1 +Sectors taken over have the their production stopped. +This should prevent the "redesignate a dozen tech centers" update attack. +If STOP is not defined, the new sector designation is set to be the +same as the current sector designation. + +.s1 +The 'file' utility now creates an all-sea world instead of not creating a world. +.SA "Server" diff --git a/info/Server/Empire2.t b/info/Server/Empire2.t new file mode 100644 index 00000000..b8f69f7c --- /dev/null +++ b/info/Server/Empire2.t @@ -0,0 +1,652 @@ +.TH Server "Empire2 Changes" +.NA Empire2 "Changes from the Chainsaw server to the Empire2 Server" +.LV Expert +.s1 +There have been several changes/fixes made to the Chainsaw code in the +new Empire2 Server. This outlines the various changes and how +they will affect you, the player. Most of these changes were coded by +Ken Stevens and any bug-reports in the new +server should be directed to him. +.s1 +.in 0 +.\" ----------------------------------------------------------- + +Ships +.in 0.6in +.L - +Ships now have three letter abbreviations. +.L - +"load" syntax has been changed to make it the same as the "move" +syntax. +.nf +- The following changes were made to the sonar command: + - will only work from ships at sea + - will only detect ships at sea + - will now detect the shoreline + - will only detect things if there is a straight line of water + between the detector and the detected + - now displays a map and changes your bmap + - for ships with tech > 310, shows mines on the map with an X and + puts the X on your bmap +.fi +.L - +All ships (including subs) in harbors are now visible via the \Q*lookout\U* +command by all ships (including subs) in adjacent sectors +.L - +If a NEUTRAL (or worse) ship sails within your coastwatch range, +then you will receive a telegram like this: +.nf +TheBorg lc2 light cruiser 2 (#666) sighted at -9,-1 +.fi +This telegram is sent before any interdiction is done. If you +want to turn this feature off, then type "toggle coastwatch off". +Note that you can also now turn off those nuisance sonar ping +detection telegrams by typing "toggle sonar off". +.L - +You may now tend land units which have +"assault" capability (see info tend). +.L - +"build" syntax has been simplified. You no longer need to specify tech +level to build at (the default is your current tech level). Also, the + arg now comes before the arg: + +.EX build s 4,0 fb1 +builds a fishing boat at current tech level. + +.EX build s 4,0 fb1 5 +builds 5 fishing boats at current tech level. + +.EX build s 4,0 fb1 2 99 +builds 2 fishing boats at tech level 99. +.L - +"show" output now shows you the total amount of avail used to build something. +.L - +The Autonav code has been completely rewritten and is dramatically +improved. Thanks Chad! +.L - +You now get a telegram if someone loads something onto your ship or if +someone unloads into your harbour. +.L - +Load/Unload now tell you exactly how much stuff got loaded/unloaded +from each ship. +.L - +You can now only unload into a sector if you are friendly towards them. +.L - +The "coastwatch" command now shows ship names! (Empire invents the +telescope!) +.L - +The "payoff" command now shows the distance your ship has +traveled--handy for making sure you pass those critical distances. +.L - +The tech level required to build aegis cruisers has been increased +from 150 to 260. +.L - +The following ships: "mc missile cruiser", "aac aa cruiser", "agc +aegis cruiser", and "ncr nuc cruiser" have been given a new ship +capability called "anti-missile" This means that they will use their +anti-missile systems to attempt to +intercept enemy missiles aimed at any ship within a 1 sector radius. +Note that just like abm & a-sat missile interception, only missiles +belonging to countries you are "Hostile" or "At War" with will be intercepted. +Thanks Chad! +.L - +Ship damage now always factors the armor value of the ship, no matter +where the damage comes from. Also, whenever a ship is hit, the player +is told exactly how hard that particular ship was hit. +.L - +The "scuttle", "scrap", "mission", and "fuel" commands will now accept +"l" for the unit type. (You are no longer required to type "la".) +.L - +Now when you load land units onto a ship, the code will automatically +try to supply them, and if they are out of supply, you will get a warning. +.in 0 +.\" ----------------------------------------------------------- + +Subs +.in 0.6in +.L - +ASW planes will now fly out to track any non-FRIENDLY (including +NEUTRAL) sub movement. +.L - +However there is a chance that the plane won't even leave the ground +and notice any sub movement at all. The chance of detection is +identchance = (1 - (1 - hitchance)^2). +.L - +ASW planes will no longer detect subs they fly over while flying an +interdiction mission. +.L - +Once the planes have arrived at the sector where the sub movement +was detected, then identchance is checked again. If success, then +the plane is able to identify the owner of the sub. If the owner +is neutral, then the player gets the message: +.nf + np1 naval plane 1 #2 tracks TheBorg subs at 2,-6 +.fi +If the plane is unable to identify the owner of the sub, then the +player gets the message: +.nf + np1 naval plane 1 #2 detects sub movement in -3,-3 +.fi +If the ship was identified as HOSTILE or AT_WAR, then the plane will +drop depth charges. +.L - +If depth-charges miss, then the ship owner will get +the message: +.nf +RUMBLE... your sub in 24,0 hears a depth-charge explode nearby +.fi +.L - +torp and fire will now only tell the victim that a "sub" torped +them, or that return fire damaged a "sub" (rather than giving out +detailed information about the sub number, type, and owner...) +.L - +max sonar range has been reduced to 7 and sonar output no longer +prints blank lines. +.L - +sonar has been changed in the following way: +detection = (source "spy" value) + (target "vis" value) +If the detection value is less than 8, then sonar will just print +.nf + Sonar detects sub #12 +.fi +If the detection value is above 7, then sonar will report the type of sub. +Only if the detection value is above 9 will the owner of +the sub be revealed. +.L - +For ASW planes flying "sonar" or "recon" missions, a similar change +has been made. The plane needs to pass one identchance check to see +the type of sub, and needs to pass two identchance checks to see the +owner of the sub. +.L - +Note in both of the above cases, owner and type of FRIENDLY and +ALLIED subs will always be revealed. +.in 0 +.\" ----------------------------------------------------------- + +Navigation +.in 0.6in +.L - +When you "nav" or "order" your ships, they will automatically avoid "x" and "X" +sectors on your bmap. +.L - +now when you navi (or march), any new sector designations +automatically appear on your nav map and get added to your bmap (you +no longer need to do a "look" to find out their designation. Note +that subs will only see sea, harbors, and bridges and will have to +look" (and risk detection) to see anything else. +.L - +If you hit the wrong character, navi will now display all possible navi +commands. +.L - +You can now draw a 'M' map or a 'B' bmap while navigating. +.L - +You can list the ship you are navigating using 'i' and you can change +your flagship using 'f'. +.L - +Navigating using "nav", "order" or "sail" now calls exactly the same +code and will thus result in exactly the same risks (mines & interdiction). +.L - +Now you can type commands like this: +.EX nav 72 jlsruMluBursh +That is, you can mix directions with other navigation commands. +.L - +Interdiction of navigating ships now works as follows: +.NF +1. Forts interdict. +2. If there are any ships left, ships, land, planes interdict. +3. If there are any ships left, marine missiles on interdiction fire one at a + time until there are no ships left. +.FI +.L - +There is now a new kind of diplomatic relation that you can have with +a country: "Friendly" which falls between "Neutral" and "Allied". +This basically splits "Allied" into two steps: anything to do with +ships is available to "Friendly" nations (nav, load, unload, tend, +upgrade, order, sail, follow), whereas anything to do with planes or +military support is reserved for Allies. This allows you to +establish trading relationships without the necessity of a military +relationship. See info relation for full details. +.L - +If the BIG_CITY option is enabled, then small ships may navigate, +load, and unload in 2% cities. +.in 0 +.\" ----------------------------------------------------------- + +Planes +.in 0.6in +.L - +Planes which are less than 40% efficient can not fly. +.L - +If you're tech is higher than 290, then you may not build planes with +tech lower than 150. +.L - +Planes will only abort if they have been damaged below 80% (it used to +be that they could abort at anything below 100%). +.L - +The range of marine missiles and SAM's has been reduced. +.L - +Air combat reports are now succinct tables with headers. Much easier +to read. Thanks Waffen! +.L - +New command "skywatch" scans your skies overhead for satellites. +Works very much like "coastwatch". +.L - +You can now filter your satellite output to list, for example, only +banks owned by country #7 which are over 60% efficient. The selectors +available are exactly the same as those used by the "census", "ship", +and "land" commands. See "info satellite" for more details. +.L - +A 75% satellite now only sees 75% of sectors (the rest are blank). +It's always the same 25% that are blank. +.L - +All missiles are now VTOL. In particular, this means that missiles on +missions will now fire from anywhere (including on subs). +.L - +Surface missiles can now be put on interdiction mission. To +distinguish surface missiles from anti-ship missiles, the latter have +been given a new capability called "marine". Surface missiles on +interdiction will keep firing on the enemy until at least 100 damage +has been done. +.L - +Interdicting marine missiles will also fire on ships when they "fire". +.L - +Missiles and planes flying interdiction missions will now detonate +any nuclear warheads that they are carrying. +.L - +When you "arm" a missile or plane, you will be asked whether you +would like to program the warhead to airburst or groundburst. +.L - +Missiles and planes are now limited to a maximum of one warhead +apiece. +.L - +A-sats will now automatically attempt to intercept any satellites +launched by a country you're "Hostile" or "At War" with. This works exactly the same +way as ABM defense. Also, if you launch a satellite over a sector +which is owned by a non-ally then they will get a message telling them +that you have positioned a satellite over their sector. In the age of +advanced telecommunication such things don't go unnoticed. +.L - +There is now only one formula for determining whether a plane/missile +hits its target and how much damage it does (including abm's and +a-sat's). See "info bomb" for the formula. In particular, +planes/missiles flying missions will now have exactly the same +hitchance as those flown by hand. +.in 0 +.\" ----------------------------------------------------------- + +Land Units +.in 0.6in +.L - +Land units now have three letter abbreviations. +.L - +Artillery must be at least 20% efficient before it can fire. +.L - +The "lmine" command now allows you to lay as many land mines as you +want. If the unit can't carry as many mines as you asked it to lay, +then it will just keep resupplying itself until it finishes the job. +Also, it now costs engineers 1 point of mobility per mine laid. +.L - +If land units are accompanied by engineers, then their chance of +hitting a land mine is reduced by a factor of 3. E.g. if there +are 25 mines in the sector, then a land unit has a 33% +chance of hitting a land mine. If it is accompanied by an +engineer, then that chance drops to 11%. +.L - +If an engineer sweeps a land mine that it cannot carry, it drops +it as a shell into the sector. +.L - +Engineers now sweep a number of times equal to 2 times the number +of shells they can carry. +.L - +The chance of an engineer finding a land mine in a sector is now +50% time the "att" value of the unit: +.nf + # of sweeps chance of finding a mine +old system 5 66% +eng1 130 6 60% +eng2 165 8 75% +meng 260 8 90% +.fi +.L - +You can now draw a 'M' map or a 'B' bmap while marching. Also, if +you hit the wrong character, navi will now display all possible march +commands. +.L - +Fortifying a land unit no longer clears the unit's mission. +.L - +You can list the units you are marching using 'i' and you can change +your leader using 'f'. +.L - +Now you can type commands like this: +.EX mar 72 jlruMluBurh +That is, you can mix directions with other march commands. +.\" ----------------------------------------------------------- +.in 0 + +Forts +.in 0.6in +.L - +Forts now get their range bonus for return fire if they're > 60%. +.L - +Forts now do not cost anything to designate. +.L - +You may not fire a fort which is less than 5% efficient. +.L - +Forts will now only automatically interdict ships that the country +would be able to see using the "coastwatch" command. Ships out of +visual range will not be interdicted by forts. Note that +ship/ship, unit/ship, plane/ship interdiction was not changed, +and also the "fire" command was not changed. _only_ fort/ship +interdiction was changed. +.in 0 +.\" ----------------------------------------------------------- + +Sectors +.in 0.6in +.L - +Bank interest is now scaled by efficiency rather than simply turning +off below 60%. +.L - +Shoot syntax has changed from "shoot 2,0 c 400" to "shoot c 2,0 400". +.L - +Harbors now have the same packing bonus as a warehouse. +.L - +You can now build bridges all on one line as in: +.EX build b 2,2 j +.L - +You are now only allowed to cede to nations which are Friendly towards you. +.L - +The new Empire command "strength" will show you the defense strength +of all your sectors (including number of land mines and reacting units +from nearby sectors). +.L - +The "test" command no longer requires there to be the commodity in +the sector (useful if you want to use that sector as a temporary +stopover and you don't want the stuff to get stranded there). +.L - +Shelling now factors in the efficiency of the sector into its +defensive bonus, so now a 0% bank defends the same as a 0% fort which +defends the same as a 0% road. The formula for calculating the new +defense value of a sector is: +((defense - 2)*eff/100) + 2 +.L - +The "neweff" command now checks to see if a sector has been stopped. +.L - +xdist and ydist are now in player coordinates. +.L - +Any interdiction of things being moved will also damage the sector +being moved into. Note: this will slow down bridge attacks! +.L - +Deliver now gets the same 4x bonus that distribute gets. +.L - +The "spy" command now gives you much more useful information: +.in 0 +.NF +SPY report +Wed Jul 26 21:10:13 1995 + sect type own oldown eff civ mil shl gun pet food bars units planes + 29,5 c+ 4 4 90 980 0 940 10 0 0 0 2 0 +.FI +.in 0.6in +.L - +A new option has been added to the server called BIG_CITY. +When the BIG_CITY option is turned on, it +takes lcm's, hcm's, and money to create a city ('c' sector), but they +can hold ten times as many civs, and get a 10x packing bonus for moving civs. +.L - +It used to be that a gold mine could not hold more than 999 dust. Now +all sectors are allowed to hold 9999 of anything, but it is now only +_production_ which is limited to 999 per update. +.L - +Now the "starvation" command will let you check for starvation on land +units or ships. +.in 0 +.\" ----------------------------------------------------------- + +Info +.in 0.6in +.L - +The info pages are now organized into subjects. Type "info" for a list. +.L - +The budget command has been changed so that now you may choose not to +pay maintenance costs. Also, "mil" on ships/planes/units has been +moved from the maintenance costs for those items to the "Military" section +of the budget. +.in 0 +.\" ----------------------------------------------------------- + +Commands +.in 0.6in +.L - +Broke countries are now allowed to use all commands except for the +following: +.s1 +arm assault attack board bomb build convert disarm drop enlist explore +fire fly grind harden launch lmine mine paradrop recon satellite scrap +shoot sweep torpedo treaty upgrade work +.L - +Broke countries used to be prevented from using the following +commands, but will now be allowed to use them: +.s1 +demobilize lload llookout load lookout lradar lrange lretreat ltend +lunload march mission morale mquota navigate order qorder radar range +retreat sail sonar sorder spy supply tend transport unload unsail +.in 0 +.\" ----------------------------------------------------------- + +Update +.in 0.6in +.L - +If you can not afford to maintain your ships/planes/units or you +choose not to maintain them using the "budget" command, then they will +lose ETU/5 % efficiency at the update. Also, if you are broke at the +point of the update when it comes time to build something, then that +thing will not be built. In short, the only way you can go broke now +is by having lots of mil to pay. +.in 0 +.\" ----------------------------------------------------------- + +Communication +.in 0.6in +.L - +The new commands "flash" and "wall" permit instant communication +between friends and allies respectively. Type "info flash" and "info +wall" for more details. +.L - +The new command "toggle" can be used to instantly inform you when +you receive a new telegram. You can also use "toggle" to temporarily +block flash messages. To find out which clients support this, type +"info Clients". +.L - +The server will now correctly report how many telegrams you have +waiting. +.L - +The new command "pray" lets you send a telegram to the Deity. Also +a telegram from the deity is no longer called a BULLETIN, it is now +called a TELEGRAM. +.L - +The new command "motd" lets you see the "message of the day" (login +message) again. +.L - +The buggy commands "mail" and "wmail" have been removed from the +server. If you want to use them, you'll have to use pei. +.L - +You can now specify which countries you'd like to see in your "power" +report. +.L - +New "report" command lists number ranges rather than "advanced", +"superior", etc... +.in 0 +.\" ----------------------------------------------------------- + +Combat +.in 0.6in +.L - +Defense against attack, assault, and paradrop is now exactly the same. +.L - +If attack odds are > 90%, then defensive support is no longer called. +This will put a stop to most shell-draining techniques. +.L - +You can now specify how many troops you want to board with. Also, the +code now always forces you to leave at least 1 mil on your ship when +boarding. You can also board from any sector type and with land units +having "assault" capability. You may not board with more mil or units +than the boarded ship can hold. +.L - +You may not attack with supply, security, artillery, or +anti-aircraft (flak capability) land units. +.L - +Attacking land units & mil used to be taken out of the sectors/ship +they were attacking/assaulting/boarding from. This caused endless problems +(including stranded units). In the new code, mil and units stay where +they were until they have finished attacking. The battle is assumed +to take place along the "border" between the two sectors. Thus, the +attacking mil & land units will be vulnerable to shelling and +attacking while you are answering the attack prompts. +.L - +If, while you are answering the attack prompts, anything happens to +either the sector you are attacking, or the mil & units you are attacking +with, then you will be notified ("land unit #3 damaged from 80% to 50%", +"Your mil in 3,1 damaged from 180 to 12", "defending mil has been increased +from 10 to 250"). +You will also be notified in this way if a bridge collapses, one of your +attacking sectors was taken, you were shelled, your enemy abandoned +the sector you were attacking, your land units reacted to fight another battle, +...) You will be notified if any of these things change before the +battle and given a chance to abort your attack. If for some reason it +is no longer possible to attack (e.g. you now own the sector, or a +bridge collapses) then the attack will be automatically aborted. +.L - +The sub-prompt for both the "attack with" and the "move in" questions +has changed to [ynYNq?]. The meanings of these 6 answers are: +.NF +y - yes this unit +n - no this unit +Y - yes all units in this army +N - no all units in this army +q - quit attack +? - print this help message +.FI +.L - +The server will now add up the mil you saw and the enemy land units your +scouts saw, and based on this info, it will estimate a defense strength of the +enemy. If your scouts didn't see the efficiency of the enemy units, then +it will assume that they were at 100%. Based on this estimated defense +strength, the server will calculate an estimate of your success odds for +you and if these +estimated odds are less than 50%, then the server will ask you if you're +sure you want to continue with the attack. These estimates are +made before support is calculated, and before the enemy reacting +units have reacted, so it will not be particularly accurate. However, if +by the time you've finished answering all the attack prompts something has +happened which has made your odds much worse than you expected (e.g. your +cavalry got shelled or your enemy beefed up his mil), then this will give +you a chance to abort the attack. +.L - +Immediately after a battle is won (i.e. before any move-in sub-prompts +are asked), 1 mil (first choice) or 1 land unit (second choice) is +automatically moved into the taken sector. Not only does this put a +definitive stop to shell-draining tricks, but it also resolves what was a +big problem in the old code of the taken sector being owned but not +occuppied for a period. This problem resulted in, among other things, +stranded land units. It is impossible to strand a land unit in the new +code. +.L - +I have added a new option to the server called INTERDICT_ATT, +which, when enabled, calls the usual interdiction routines against +mil & land units moving into the victim sector after an attack. +The same chances of interdiction apply as in "move" and +"march". The mil get interdicted sector by sector, and the +land units all at once. +.L - +In the new attack code, it is much harder for a unit to fail a morale check. +The new chance (recalculated after each hit) is (retreat% - unit efficiency). +Thus, a land unit which has a retreat percentage of 60% and is now 50% +efficient, will have a 10% chance of retreating with each hit. +.in 0 +.\" ----------------------------------------------------------- + +Important bugfixes +.in 0.6in +.L - +Missiles on subs will now fly missions against enemy planes (in +chainsaw, the missiles simply vanish). +.L - +Subs now only interdict subs if they have sub-torp ability (in +chainsaw, sb1's will interdict sb1's). +.L - +Missiles will no longer hit subs. +.L - +Your airport now needs to be at least 60% eff in order to fly bombing +runs from it (in chainsaw you can bomb from 40% airports, but only fly +and recon to 60% airports). +.L - +You can't sweep, hit, or lay sea mines in a harbour. You can't sweep, +hit, or lay land mines on a bridge. (In chainsaw, your ally can hit +your land mines in your harbour.) +.L - +It is no longer possible to accidently go broke through any of the +following commands: build, convert, demob, des, harden, upgrade. (In +chainsaw it's easy to accidentally go broke through one of these commands.) +.L - +Much of the "attack" function was rewritten to check for "special +cases" which can result in lost military and units. Thanks Chad! +.L - +The range of missiles on interdiction mission was half +of what it should be. this is now fixed. +.L - +If you typed "realm #2 0:10,0:10", it would change realm +#0. This is now fixed +.L - +If you downgraded your relations from Allied to Neutral, +then the other country would downgrade their relations towards you to +Hostile. This is now fixed. +.L - +You used to have to log out and back in again to stop being broke. +Now your status will be updated as soon as you get the money (well, +one command after to be exact). +.in 0 +.s1 +Options +.NF +The following options have been made standard: +DROPANY: you can drop things on sectors belonging to allies +REJECTS: you can reject announcements and teles from annoying countries +BMAP: map info gained is saved in a big world map (bmap command) +AUTONAV: ships can move automatically +SCUTTLE: you can sink your own ships automatically +CONVASAT: anti-satellite missiles don't need nuclear warheads +ABM: anti-missile missiles exist +GRIND: you can grind gold bars back into dust +NONUKESUB: nukes don't affect submarines +RANGEDIT: you can modify the range of your planes +MISSDEF: ships with tactical missiles will fire them in defense +SHIPSAM: ships can carry and use SAMSs +BIND: network stuff, no interest to players (NITP) +MERC: a collection of bug fixes +TACARGO: planes that are cargo AND tactical can bomb (zeppelins) +NOGODS: deity countries don't show up on power reports +BETTERARMOR: armor has more of an effect on ship damage +GODNAMES: bulletins are identified by which deity sent the +MULTIFIRE: multiple ships/sects can fire at once +SHIPTORP: ships can have torp ability +SWEEP_PLANES: some planes can sweep mines +MINE_PLANES: some planes can lay mines +ASW_PLANES: some planes can detect/kill subs +HARBOR_POLICE: you can board ships in your harbor using mil from the harbor +WING_LOAD: you can load groups of planes on ships with 1 command +ALLYUPGRADE: allies can upgrade your ships in their harbors +ALLYHARB(etc): allies will increase your ships' efficiency in their harbors +RETREAT: ships can automatically retreat, under conditions you set +STEALTHV: stealth is a % chance to evade, all planes are rated 0-100% +SEMILAND: some ships can land 20% of mil instead of 10% or 100% +WIRE: announcements are seperated from teles/bulletins +STOP: Sectors taken over must be started. Start and stop are enabled + +The following options have been permanently turned off +REALM_IN_NAT: realms are displayed by the nation command +DAVYJONES: nukes hitting sea affect 1 sect, hitting waste/sanct don't det +BABY_NUKES: Nukes affect only 1 sector +.FI +.s1 +.SA "strength, tend, toggle, flash, relations, arm, starvation, Damage, report, power, Clients, Attack, Server" diff --git a/info/Server/Empire3.t b/info/Server/Empire3.t new file mode 100644 index 00000000..56c4cfbc --- /dev/null +++ b/info/Server/Empire3.t @@ -0,0 +1,174 @@ +.TH Server "Empire3 Changes" +.NA Empire3 "Changes from the Empire2 server to the Empire3 Server" +.LV Expert +.s1 +There have been several changes/fixes made to the Empire2 code in the +new Empire3 Server. This outlines the various changes and how +they will affect you, the player. Most of these changes were coded by +Ken Stevens and any bug-reports in the new +server should be directed to him. +.s1 +Sectors +.in 0.6in +.L - +The delivery and distribution stuff was removed from the output of +"commodity" and each column was widened to 5 characters (to accomodate +the new system where sectors are now allowed to hold up to 9999 of +stuff) +.L - +Mountains will now mine gold at 3/4 the rate that gold mines do (thar's +gold 'n them thar hills!) +.L - +Mountains can now only hold 1/10th the population of normal sectors. +.L - +The mobility cost to move into a sector has been changed from: +.nf + cost = (mcost - eff) / 5 + to: + if (mcost < 25) + cost = (2 + (3 - mcost) * eff) / 5 + else + cost = (mcost - 20 * eff) / 5 + +OLD SYSTEM: eff 0% 100% NEW SYSTEM: eff 0% 100% + + 0.2 0.0 + 0.4 0.0 + m 0.4 0.2 m 0.4 0.2 + ^ 5.0 4.8 ^ 5.0 1.0 +.fi +Note that this means land units can attack 100% mountains now, so +there will be a tradeoff for the defender--either they can have a low +efficiency mountain that costs more mobility to attack but gets a +lower defense bonus, or they can have a high efficiency mountain that +costs less mobility to attack but gets a higher defense bonus. +.L - +New conditional query "coastal" which gets set when you take a +"census" of the sector. Type "cens * ?coast=1" to get a list of all +of your sectors which are adjacent to water (and thus vulnerable to +assault). +.\" ----------------------------------------------------------- +Ships +.in 0.6in +.L - +- The size of "ts1 trade ship 1" was reduced to 100 lcm, 50 hcm, $1500 +(from 200 lcm, 100 hcm, $2500). Most players were waiting for ts2 +so this is a nice way to deal with that. +.in 0 +.\" ----------------------------------------------------------- +Planes +.in 0.6in +.L - +In the old system, planes would be charged either 10 mobility +(interceptors), 12 mobility (escorts) or 20 mobility (the rest) per +flight. This cost was then multiplied by (100 / eff) with the +restriction that plane mobility could not go below -32. Planes flying +missions were charged only 1/4 of this. In the new system, planes are +charged a base rate of 5 mobility to prepare for takeoff. On top of +this, they are charged a flight cost which is either 10 (interceptors +and escorts) or 20 (the rest), however this flight cost is scaled down +according to the length of the flight--it is multiplied by (flight +length) / (max plane range). The flight cost is then scaled by +(100/eff) with the restriction that a plane can't go below -32 +mobility. Planes flying missions are charged 1/2 of this. +.L - +The mobility of a plane will now go down by one point for every two +points of damage it took from air-to-air combat, to a limit of -32 +mob. This is to simulate the high mobility cost of air-to-air combat, +and the fact that air-to-air combat is more effort for low tech planes. +.L - +SAM interception is now separate from plane interception; for each +attacking plane, if it cost at least $1000 to build, then one SAM will +be launched at it. After SAMs have been fired, fighter planes will +intercept what's left over. +.L - +The restriction that high tech nations can not build low tech planes +has been removed (the above changes address the f1 SAM-soaking problem). +.L - +Marine missiles on interdiction now fire at a single ship rather +than the whole fleet. They pick the ship which is the most valuable +according to (cost to build) * efficiency. Furthermore, marine +missiles will only launch at a ship if the ship cost >= $1000 to build +or if it can carry land units or planes. +.L - +Sectors which your planes fly over when they fly missions will now be +added to your bmap. +.in 0 +.\" ----------------------------------------------------------- +Land Units +.in 0.6in +.L - +There are three new land units: 'cavalry 2', 'light infantry', and 'aau1'. Here's the basic scheme. The old cavalry are an average +between the somewhat weaker cav1 and somewhat stronger cav2. +light infantry are half the size of and slightly fastar than inf1's. 'aau1' come at the same tech as Zepplins and let low tech countries +try to throw rocks at low tech planes... +.in 0 +.\" ----------------------------------------------------------- +Maps +.in 0.6in +.L - +You now have 50 realms. +.L - +Each country now has two bmaps, their 'working' bmap and their 'true' bmap. The true bmap contains only information put there by the +server. The working bmap also contains information put there by the +bdes and sharebmap commands. The 'bmap' command usually displays the +working bmap unless the player specifies 'bmap true'. +If the players working bmap becomes corrupted somehow, then they can +type 'bmap revert' to revert their working bmap back to their +true bmap. This change was necessary to prevent abuse of the new 'sharebmap' command (which compares the players true bmaps when +determining whether they overlap). +.L - +There is a new command "sharebmap ". If +is friendly towards you and your 'true' bmaps already share enough information +in common, then your bmap will be added to their bmap. For more details +see 'info sharebmap'. +.in 0 +.\" ----------------------------------------------------------- +Information +.in 0.6in +.L - +The new info page "info Mobility" gives the formulas for all +mobility costs in the game. +.in 0 +.\" ----------------------------------------------------------- +Communication +.in 0.6in +.L - +If someone else was the last person to use your country, then when you +login you will get a message like: +.NF +Last connection from: Mon Nov 13 04:48:04 1995 + to: Mon Nov 13 05:13:12 1995 + by: children@RedDragon.Empire.Net +.FI +.L - +If the game is a blitz, then the 'players' command will list other +countries which are logged on. This will cut down on the 'is anybody +else logged on?' announcements. Note that for players, 'last command' +and 'user@hostname' are not printed (only deities get to see this stuff). +.L - +You can now read old announcements which you've already thrown away by +typing: +.SY "wire " +This works much in the same way as news. The server automatically +deletes all announcements older than 7 days. +.L - +New server commands 'toggle sync', 'toggle async', and 'sync' permit +client-server database synchronization. +.L - +Before you type a telegram, you will now see: +.nf + Enter telegram for Fodderland + undo last line with ~u, print with ~p, abort with ~q, end with ^D or . + 1024 left: +.fi + The new tilde escapes work very nicely. + +.\" ----------------------------------------------------------- +.in 0 +.s1 +Options +.nf +The following options have been made standard: +NEWPAF: Plane combat is in nice easy-to-read columns +.fi +.s1 +.SA "toggle, sharebmap, Clients, Server" diff --git a/info/Server/Empire4.t b/info/Server/Empire4.t new file mode 100644 index 00000000..5e68f2bc --- /dev/null +++ b/info/Server/Empire4.t @@ -0,0 +1,1306 @@ +.TH Server "Empire4 Changes" +.NA Empire4 "Changes from the Empire3 server to the Empire4 Server" +.LV Expert +.s1 +There have been several changes/fixes made to the Empire3 code in the +new Empire4 Server. This outlines the various changes and how they +will affect you, the player. These were coded as the Wolfpack project, +and bug-reports should be sent to . +.NF +Changes to Empire 4.2.12 - Mon Aug 18 16:54:21 MDT 2003 + * Corrected contact information for Wolfpack. + * Sector isn't abandoned until move or explore is complete. + * Fixed multiple cases where return value of getstarg() was + used without being checked which crashed the server. + * Used stdarg.h instead of varargs.h. + * Call only_subs and save result before mission frees attacker + list. Call with free list could cause server crash. + * Fixed spy sat map for units on opposite side of world wrap. + * Don't sleep in main thread when called from signal handler. + * Fixed error checking in pthreads. + * Properly detach pthreads. + * Pass unlocked mutex to pthread_mutex_unlock. + * Cope with interrupted sleep in pthread empth_sleep to prevent + double update. + * Added server configurable update window. + * Initialized variables passed to setsockopt in accept.c. + * Fixed bug where sharing bmap with uncontacted country crashes + server. + +Changes to Empire 4.2.11 - Sun Sep 1 09:54:59 MDT 2002 + * Added compile option for the Mac OSX architecture. + * Fixed bug in cargo where unit array was indexed by shp_maxno + instead of lnd_maxno. + * Fixed bug in reject where aborting the command crashes the + server. + * Can't buy land units into enemy headquarters. + * Added sabotage command and commando unit. + * Spies moving by themselves will not trigger interdiction. + * Fixed error in map distance calculation that caused errant + interdiction. + * Ships going under -127 mobility will be set to -127 mob and + not roll over to positive mobility. + * Corrected plane cost in info Maintenance. + * Changed error message for loans rejected for being too big. + * Land units will take casualty damage proportional to their + ability to carry mil. + * Fixed bug where "route i *" crashes server. + * Cannot upgrade planes in orbit. + * Fixed bug in declare with deity aborting command at last + prompt crashes the server. + * Coastwatch notify works with NO_FORT_FIRE option. + * Thread that kills idle connection will charge player for + minutes the player was logged on. + * Removed separate sendeof at end of execute from emp_client + that logged players off on certain platforms. + * Updated player idle counter during read prompt so players + wouldn't be kicked off during long flashes or writing telegrams. + * LOSE_CONTACT will work as advertised. + * Allied units marching through 0 mobility conquered sectors + are charged at least LND_MINMOBCOST. + +Changes to Empire 4.2.10 - Fri Aug 10 17:25:05 MDT 2001 + * Assault can reinforce own sector when SLOW_WAR is enabled. + * emp_client no longer converts lines into tags but still verifies executes, + pipes, and file redirect match players input. + * Added pboard command to capture enemy planes in your territory. + * Declaring war when at Sitzkrieg won't return relations to Mobilizing. + * Declaring war won't charge money if you're already Mobilizing. + * Added multiple territory fields. + * "show nuke build" displays the proper avail. + * retreating land units will only retreat to sectors owned by the player + that owns the unit. + * added hard cap of "250 + easy" to limit_level. + * education p.e. calculation divides edu constant by etu per update. + * Added patch for Linux for the PowerPC. + +Changes to Empire 4.2.9 - Sun Jan 7 15:49:13 PST 2001 + * Fixed data corruption when bogus target gets fired upon. + * Increased size of ancillary stacks to prevent stack overflow. + * Changed all references to empire.cx. + * Ships, planes, and land units lost to lack of maintenance will now be + lost. + * No longer allowed to sack deity's capital. + * Accuracy calculation in land unit support was backwards. + * Corrected formula for likelihood of plague in info Plague. + * Fixed files to correctly size map and bmap files from econfig file. + * No longer allowed to add country 0. It corrupts deity country. + +Changes to Empire 4.2.8 - Mon Oct 9 17:35:35 MDT 2000 + * Fixed range in radar.t and Sector-types.t. Maximum range at infinite + tech is 16. + * Changed so that player can't drop civilians into occupied sectors. + * Fixed bug that crashes update if etus/update is less than 8. + * Fixed sometimes not reporting overflights + * Fixing flak for units/ships to be in all sectors as they should be + * Updated order of firing flak in Flak.t. + * Fixed 80% efficient planes on ships must be maintained. + * Fixed initial MOB_ACCESS check thread sleep time was set by an uninitialized + variable. + * Removed "TEMPORARILY DISABLED" message from mission command for escort + missions. Escort missions have been re-enabled since 4.0.15. + * Using sonar from the navigate command will print the sonar map. + * Eliminated annoying error messages when using navigate with conditionals. + * Fixed Technology.t to correctly add 1 before taking the logarithm. + * Fixed bug that allowed players to steal opponents maps. + * Put time limit for bidding on market and trade in econfig file. + * Moved hours file information into econfig file. + * Added comments on setting update policy in econfig file. + * Added logging of cases where write extends data file by more than one id. + * Option MARKET is turned off by default. + +Changes to Empire 4.2.7 - Fri Mar 10 18:41:04 PST 2000 + * Added new NF_SACKED flag to indicate when a country has had it's + capital sacked. This flag is only cleared when the country actively + redesignates it's capital using the "capital" command, and changed + capital.t to reflect this (no more re-sacking after an update if the + country doesn't reset and repeating until they are out of cash.) + * Added land unit to edit command for planes. + * Added nuketype to edit command for planes. + * Changed so that if the leader of a group of units is a train, the + railways are used for bestpath instead of roadways. + * Changed mission command to also print reaction radius of reserve + missions when set for land units. + * Changed Flak.t to reflect guns having to be loaded onto a land unit + for flak to fire. + * Changed so that visitor countries cannot change their name or password. + * Changed so that you cannot upgrade deity planes, ships or units. + * Changed so that you know where missions are flown from. + * Changed so that the airport owner you fly a mission from is informed. + * Changed so that preperations for takeoff are reported to the owner of + the sector, ship or unit a plane is taking off from if it is not owned + by the owner of the plane. + * Changed so that when a sector reverts during a guerrilla revolt, the + mobility is not reset. When MOB_ACCESS is not enabled, this used to mean + you would always get at least an updates worth of mobility. With + MOB_ACCESS, sectors that reverted during the update were useless, since you + got no mobility for a long time. This fixes that problem, and makes che + more useful as well. + * Changed so that air defense missions don't always send up every plane in the + area, but instead always send up at most two times the number of incoming + planes (for each interdicting country.) This helps to stop 1 plane from + stripping the mobility from 25 air defense planes all at once, but doesn't + limit it to n+1 as there is for regular interception. + * Clarified deity reversion of sectors in Sector-ownership.t + * Clarified production efficiency and added pointer to "show sector cap" + in Product.t + * Clarified nuketype selector for planes in Selector.t + * Clarified that fortifying units does not affect mission status in info + pages for mission and fortify. + * Clarified fuel syntax upon error in fuel command in empmod.c. + * Cleaned up comments causing minor complaints in some builds. + * Fixed bug in loans where you could collect on proposed loans. + * Fixed production command to be more accurate (though it *still* has some + rounding errors, it's better.) + * Fixed potential memory leak in air defense missions. + * Fixed bug where you couldn't pinbomb some commodities if other commodities + didn't already exist in the sector. + * Fixed bug where you couldn't build 0 crew planes without military in the + sector. (This is different from needing at least 1 military to build all + planes that need a crew which introduced another related bug earlier.) + * Fixed bug where scrapping land unit 0 could cause erroneous transfer + messages to be displayed for deity owned planes. + * Fixed bug where land units on ships in a sector taken over were blown + up or captured. + * Fixed bug where planes on ships in a sector taken over were blown up + or captured. + * Fixed bug in sdump printing origx and origy in deity coordinates. + * Fixed bug in satellites showing wrong sectors (sometimes) when using the + optional arguments. + * Fixed bug in launch showing wrong satellite target (showed asat instead + of the target satellite.) + * Fixed bug where you could gain information not normally available using + the "fire" command to determine sector type information. + * Fixed bug in market/trade creating extra money when loans are taken out. + * Fixed problem with land units not being reported sunk after being sunk + on a ship that was nuked or wastelanded in a sector. + * Fixed problem with Spies.t using "llook" instead of "llookout". + * Fixed problem in lwp/arch.c including jmp_buf.h instead of setjmp.h + on some Linux boxes. + * Fixed problem with plague infection being way too high in cities when + the BIG_CITY option is enabled. + * Fixed bug in edit command getting confused with arguments. + * Fixed bug in ask_move_in_off asking you to move in a negative number of + troops (hey, it could happen. :) ) + * Fixed bug in add command not keeping flags or relations initially correct. + * Fixed bug in torpedo command sometimes telling victim about torpedo + sightings even when way out of range. + * Fixed bug in spy command not reporting planes in adjacent sectors, as well + as not formatting them properly when reporting them. + * Fixed bug in satellite with noisy transmission causing a potential + crash of the server with non-100% efficient satellites. + * Fixed potential crashing of the server during satellite display when not + calculating distances to ships and units correctly. + * Fixed bug where planes in non-allied sectors, ships and units could be + used on missions. + * Fixed bug where planes on the trading block could be used on missions. + * Fixed bug where planes and units that get traded don't have mobility set + correctly when using MOB_ACCESS option. + * Fixed bug which made security units virtually useless. + * Fixed access times and mobility not being set right when building planes, + ships, units, bridges and bridge towers when MOB_ACCESS is enabled. + * Fixed minor formatting problem with launch of satellites. + * Fixed minor formatting problem with planes with greater than 999 tech. + * Fixed minor formatting problem with ships with greater than 999 tech. + * Fixed problem with "llook" showing up in TOP info file. + * Fixed problem with lwp Makefile choking on NT builds with clean target. + * General cleanup of potentially ambiguous statements. + +Changes to Empire 4.2.6 - Fri Jun 4 05:55:20 PDT 1999 + * Added "TECH_POP" as an option where technology costs more to make + as your population grows past 50K civilians. It is disabled by + default. + * Changed "produce" command to accurately print what the true p.e. is. + * Changed "update" command to display if mobility updating is enabled for + MOB_ACCESS option. + * Fixed bug where toggling off the coastwatch flag also turned off + forts firing on hostile ships coming into range. + * Fixed bug where assaulting your own land would violate any treaties + you have where assaults are a violation. + * Fixed bug where all planes (even those without need for a crew, such + as missiles) needed at least 1 military to build. + * Fixed bug where when a ship sinks during the update due to lack of maint, + land units and planes on it were left stranded. + * Fixed bug where when a land unit dies during the update due to lack of + maint, land units and planes on it were left stranded on it. + * Fixed bug where nukes could be lost due to MOB_ACCESS updating mobility + while arming. + * Fixed bug in "show sector capabilities" not showing products correctly. + * Fixed bug in "show tower build" printing "bridges" instead of "bridge + towers". + * Fixed bug in sectors that don't revolt not showing up as lost items. + * Fixed bug where maps with an X of exactly 200 is not drawing third line. + * Fixed bug where MOB_ACCESS was not updating the mobility just before + the update. + * Fixed bug in the way treaties are examined and sometimes produce + wrong results. + * Fixed edit to allow creating negative mobility for sectors. + * Fixed setsector to allow creating negative mobility for sectors. + * Fixed bug where when writing out the value of a sector that had + negative mobility and was damaged in combat, mobility was being + set back to 0. + * Fixed Taxes.t info page to reflect that captured civvies only pay + 1/4 taxes. + * Fixed Technology.t info page to reflect TECH_POP option. + * Fixed navigate.t info page to reflect that only ships in the fleet + in the same sector that are fired upon have damage divided up. + * Made techlists toggle on by default (so things are shown in order of + technological advances.) + +Changes to Empire 4.2.5 - Mon Mar 1 06:42:24 PST 1999 + * Added optimization to increasing mobility to check if an object is + already at max mob, just return since it can't be increased. + * Added "-ltermcap" for client libs for hp build (it was already in + hpux build.) + * Added clearing of telegram flags after the update so that the next + telegram is flagged as new and not part of the update. + * Fixed Update-sequence.t to reflect MOB_ACCESS. + * Fixed bug where fortification amount was not being limited to + maximum mobility for land units (land_mob_max). + * Fixed bug where land unit fortification strength was being calculated + by using 127 instead of land_mob_max. + * Fixed bug where scrapping land units was creating military. + * Fixed description of sect_mob_neg_factor in econfig file. + * Increased speed of PT boats. + +Changes to Empire 4.2.4 - Tue Feb 2 05:47:44 PST 1999 + * Added check to make military values match up correctly for land + units. + * Fixed bug in doconfig not putting ipglob.c in the right place. + * Fixed bug where attacking deity sectors will violate a treaty. + * Fixed newspaper.t information file. + * Fixed potential bug in fixing up timestamp information when restarting a + game with MOB_ACCESS turned on. + * Fixed bug in explore command not setting mobility to correct + value when MOB_ACCESS was enabled. + * Fixed bug in enlist setting mobility incorrectly sometimes. + * Added doc/backup file for deities which recommends how backups and + restores of the data directory should be done. + +Changes to Empire 4.2.3 - Wed Jan 13 06:02:35 PST 1999 + * Added linux-pthreads target and build for using pthreads under Linux. + * Added NO_FORT_FIRE option which disables the ability of forts to + fire when enabled. + * Added more error checking and recovery for corrupt data files. + * Changed alphapos target to alpha-pthreads for better clarity. + * Changed fairland to allow 0 sector distance to other islands and + continents (James Risner) + * Changed "frg" and "dam" land unit stats to "rng" and "fir" so they + match the way ships are described (since this is how they really work.) + * Changed Unit-types.t to now describe "rng" as firing range of a unit, + and "fir" as the number of guns that a land unit fires. + * Cleaned up misc. build warnings. + * Changed artillery damage to be 5 + d6 per gun firing from just d6 + per gun firing and updated Damage.t to reflect this change. + * Changed artillery firing ranges to be like ships ranges - divided + by two, and modified them to make more sense. + * Changed artillery units to be "slightly" :) more powerful. + * Changed "cavalry" unit to tech 30 and lowered mil content to 20. + * Changed "artillery" unit to tech 35. + * Changed so that guns are no longer required to build units, and + that guns must be loaded onto artillery units for them to fire. + Client developers note: the show command has not changed yet to + remove the 'guns' column (since guns are no longer required) but + will in a future revision (possibly 4.2.4) so "be prepared" for + "show land build" to change. :) + * Fixed landunitgun to handle all the damage calculations like it should. + * Fixed bug sinking planes when the ship they are on sinks. + * Fixed bug destroying planes when the land unit they are on is destroyed. + * Fixed bug where land units could fire support without enough military. + * Fixed bug in abandoning sectors by marching out a land unit where it + would not let you sometimes (uninitialized variable problem.) + * Fixed gets problem in files.c (James Risner) + * Fixed bug in determinig operations range of a ship. + * Fixed bug in building planes where you could manufacture military. + * Fixed warnings in threading package(s). + * Fixed fire.t to reflect new firing changes. + * Fixed lstat.t to reflect new firing changes. + * Fixed sstat.t to reflect the way things really work. + * Fixed Ship-types.t to reflect the way things really work. + * Fixed the way shutdowns work to hopefully better protect data files. + * Fixed bug in attacking when sector mobility is less than 0 and it would + prompt for attacking with a negative amount of military. + * Fixed typo in fire.t stating wrong parameters for firing from a sector. + * Fixed bug in client when it prompts for country name it was putting + an extraneous end of line on the end that needed to be stripped off. + * Fixed problems running on Linux running on an Alpha machine. Thanks + to Rocky Mountain Internet and Jeremy A. Cunningham for giving us time + on a machine to work out the bugs. (Note that the only build that + works on Linux/Alpha is the linux-pthreads) + +Changes to Empire 4.2.2 - Sun Dec 27 12:46:34 PST 1998 + * Added some code optimizations into the update code when building paths. + * Added some new cacheing for building paths to help speed up updates. + * Added so that you can use "name" and "password" with the change command + as well as "country" and "representative". + * Added flag to power command so that if you are a deity and enter + a negative number of countries you want to see, you see the power chart + for that many countries without power numbers on the next line. Only + useful for deities that want to see the chart un-broken up by that line. + * Added new functionality to fortify command. You can now use a negative + fortification value to cause the unit to be fortified and leave at + least that much mobility on the unit. I.E. "fort * -67" will fortify + all units and make sure the mobility of each unit doesn't go below + 67. If the mobility is already below that level (or equal) the unit + is left unchanged. + * Added that the realm command prints "Realm #n is x:x,y:y" after + you set a new realm. + * Added TREATIES option and enabled it by default. + * Added "no depth-charging subs" and "no new land units" treaty + clauses. + * Added Trannie Carter's basic client fix to use fgets instead of gets. + * Changed market and command to only print the lowest priced lot of + each given commodity by default. If you specify "all" it shows + all lots on the market, and if you specify a specific item, it shows + all lots of that item type. + * Changed start command to only write out sector if it changed. + * Changed stop command to only write out sector if it changed. + * Changed how plane names were changed on server startup if the + PLANENAMES option was enabled. + * Changed move command to use standard askyn function for abandoning + sector prompt. + * Changed plane overlight sightings to take stealth into account, + and if the planes managed to evade all flak and interceptors, they + are not marked as "spotted" over enemy sectors. + * Changed all units with the supply flag to have their marching speeds + based on efficiency since that is their purpose. What this means is + that supply units and trains are more effective at 100% than at 10% + (just as fighting units are more effective at 100% than at 10%, but + their effectiveness is determined by how well they fight, not how well + they "run away, run away!" :) ) + * Changed so that flash toggle is on by default for POGO at setup + time. + * Changed so that when a sector is taken, all land units owned by the + current owner are treated as planes are during takeovers (i.e. there + is a pretty good chance they are blown up, and if not, they change owner + to the attacker and are beat up pretty good.) + * Fixed treaties to work again. + * Fixed bug in taking over land units not using correct pointer (can + cause a crash or data corruption.) + * Fixed collect command to wipe deliver and distribution information + correctly. + * Fixed potential bug in bmap not working when destination bmap has + blank spaces in it. + * Fixed bug in shark command not getting right nation structure. + * Fixed bug in server where empty commands (for example, all spaces + or tabs) were being reported as bogus commands. They are now just + ignored. + * Fixed bug in scrap not dropping land units off of scrapped units carrying + them. + * Fixed bug in news where boarding of land units was reported backwards. + * Fixed bug in calculating new people when growing them during an update. + * Fixed missing -ltermcap in HP/UX build. + * Fixed setsector to limit mobility to 127 not 255 (255 was being caught + later and being reset to 0 anyway) + * Fixed Sector-types.t to show a '\' instead of a '/' for wasteland, + since that is what it really is. + * Fixed retreat.t documentation to reflect the "retreat upon failed + boarding" flag. + * Fixed bug where satellites were not orbiting the world during the + update. + * Fixed bug in torpedos being too smart. They knew how to jump over + land! :) Now the "line_of_sight" routine is used to determine if a + torpedo has a straight path to the destination. If it doesn't, the + torpedo no longer jumps over land, but instead slams into it. This was + an interesting bug because you could torp ships on the other side of + a very skinny island as long as they were in range, even if there was + no sea route possible. + * Fixed bug when pinbombing and you run out of an object to pinbomb (land + units for example) but you still have to pick something to bomb. For + ships it worked ok (just aborted that it couldn't find any more ships) + and this was fixed for land units and planes. + * Fixed server crashing bug when flying a plane and not carrying + any cargo. + * Fixed bug in move losing commodities when it runs out of room in the + destination sector. Goods are now attempted to be returned to the + start sector, and apporpriate steps taken if the start sector is no + longer available. + * Fixed march to prompt you before you abandon a sector you own by + marching out the last land unit. + * Fixed check functions to only check the relevant portions of the structure + and not the timestamp info that doesn't affect how the object functions. + * Fixed bug in spy command that always told you if a spy unit was in a + non-owned sector. + * Fixed bug in displaying of land unit missions not showing correct land + unit range. + * Fixed bug in wire command where new announcements that you read at + the last second don't get wiped out properly. + * Fixed bug where announcement file could be corrupted by very long lines. + * Fixed bug where bmap was not set when player was told what kind of + sector they were attacking (this was an old abusable bug that was + removed long ago to fix the abuse, and it's been fixed in a non-abusable + way finally.) + * Fixed bug where change command would warn you about monetary and + BTU costs, but not prompt you to break out if you didn't want to really + change your country name. + * Fixed bug in sub-launched nukes that are intercepted being reported in + the news incorrectly. + * Fixed bug in load where you could abandon a sector and not know it by + loading your last civilians or military onto a ship. + * Fixed potential memory leak in autonav code. + * Fixed potential bug where you could possibly determine if a sector is + owned or not using one way plane missions. + * Fixed Damage.t info page to properly show damages for planes and + land unit shelling. + * Fixed deliver.t to include syntax for command. + * Fixed country.t to include syntax for command. + * Fixed bug where ships on orders were not adding radar information to + the bmap during an update. + * Fixed bug where ships on sail were not adding radar information to + the bmap during an update. + * Fixed bestownedpath code to use the bmap properly. Note this is a very + important bug fix. When navigating a ship, players are no longer given + free information that they would not normally know. For example, if you + try sailing your ship off into uncharted areas of your bmap, the bestpath + code will only use as much information as you have on-hand (i.e. your + bmap) to plan out your path for you. If you have no information on an + area, it just keeps forging on, until bumping into something. Of course, + after the initial exploration through an area, the bmap will be set and + used for all future sailings through that area. Harbors and bridges + are still checked for construction worthiness if you know where they + are (i.e. they are on your bmap.) (Overall, what happened before + was that the bestpath code would route your ship around islands that + you didn't even know were there, and you could use various commands + to see how that ship was going to sail during the update and thus you + gained information that you wouldn't normally know.) + * Merged bestpath and bestownedpath and wrote new wrappers, "BestShipPath" + and "BestAirPath" to use it properly. It is also good to note that + bestownedpath is used to determine paths for ships and for planes, + and that best_path (which uses the A* algorithm) is used for all land + based paths, and that the two are never interchanged. + * Removed "jet recon" plane (it slipped in during the PLANENAMES conversion, + and RECON was never used before.) + * Removed extraneous "resnoise" and "resbenefit" functions and combined + the two for setresource and setsector commands. + +Changes to Empire 4.2.1 - Tue Nov 3 12:56:20 PST 1998 + * Fixed problem with global/plane.c not defining last structure element + properly, and thus causing crashes when accessing certain plane + routines. This happened during the move to make the PLANENAMES option + run-time configurable. + +Changes to Empire 4.2.0 - Thu Oct 29 06:27:15 PST 1998 + * Bumped rev to 4.2.0 since this is a major release (the server is now + run-time configurable for just about everything and is released under + the GNU GPL.) + * Put in official licensing information. + * Re-arranged and commented the econfig (Empire Configuration) file. The + auto-generated "data/econfig" file is now pumped out chock full of + comments (which may or may not be useful.) Since the server is + pretty much fully run-time configurable (MAXNOC is not, but it gets + a default of 99 anyway) deities will probably be spending more time + in the config file. + * Added server support for building under NT, including mods from + Doug Hay and Steve McClure to get the server building and running + under NT. (This was built using MSVC++ 5.0 on NT 4.0 and command + line "nmake nt") + * Added Doug Hay's ntthread.c implementation for NT threading. + * Added max pop column to "show sector stats" output. + * Added lboard command for boarding land units from sectors. Only raw + mil can board land units, and only mil and land units aboard the unit + being boarded fight back. + * Added GODNEWS option. When enabled, the deity giving people stuff + is shown in the news. + * Added bridge tower sector ('@') + * Added BRIDGETOWERS option. When enabled you can build bridge towers + from a bridge span. You can then build bridge spans from the tower. + If the tower is destroyed ( <20% eff) bridges connected fall unless + supported on the other side. You can only build bridge towers in open + water not adjacent to land and other towers. Expensive. + * Added plains sector ('~') - Max pop is 1/40th regular sectors, and + it is deity creatable only (can't redesignate unless you wasteland it + with a nuke :) ) + * Changed "info all" to no longer use printdir, instead it just uses the "all" + info page which contains this information. + * Changed so you can now load up to 2 spy units onto non-land unit carrying + submarines if the LANDSPIES option is enabled. Useful for sneaking up + to shore and spying on your neighbors. + * Changed so spies unloaded from ships are not given as gifts, they are just + unloaded quietly. + * Changed build command to handle building towers ("build t") + * Changed show command to show tower stats ("show t b") + * Changed reject so you can now reject things from any country except + deity countries (this now includes sanctuary countries and visitor + countries you don't want to deal with) + * Changed ndump to dump nuclear stockpile ID as well. + * Changed flash so that if someone allied to you is either not logged on or + not accepting flashes, you are notified. This is info you could gain + otherwise since you can see other countries that are allied to you via + players. + * Fixed bug in news command when HIDDEN mods are enabled. + * Fixed distribute command to only write out to the database if we + actually changed the sector (i.e. if we really moved the dist + center, we write. Otherwise, it makes no point.) + * Fixed threshold command to only write out to the database if + we actually changed the sector (i.e. if we really changed the + threshold, we write. Otherwise, it makes no point.) + * Fixed - population growth and truncation in "Update-sequence.t" info + file is now clearer + * Fixed the way fortify takes mobility away from a land unit if + engineers are present. + * Fixed bug in buying commodities at the last minute not resetting the + time correctly in all situations. + * Fixed bug in building nukes where it would always ask if you tried + building more than one at a time. + * Fixed bug where if you put (either by building or by transporting) + more than 127 of one type of nuke in a sector, they all got lost. A + negative wrapover sort of thing. + * Fixed ndump to print # of stockpiles dumped. + * Fixed ndump.t to reflect changes + * Fixed bug in build command that didn't account for EOL characters. + * Fixed bug where you could use planes to drop conquered populace + * Fixed bug in distribute command in how it checked for current distribution + sector. + * Fixed pr_flash and pr_inform to no longer send messages if the player + is still in the process of logging in (i.e. not in the PLAYING state) + * Fixed report command output for deities. + * Fixed bug in nuclear damage either taking out submarines when it + shouldn't, or not taking them out when it should. + * Fixed bug in loading units that are carrying units onto other units + (note that it doesn't happen since only HEAVY units can carry other + units and that check works, but that might change some day, and we + don't want units carrying units to be carried by other units, etc. :) ) + * Fixed info pages to reflect new sector types. + * Fixed info pages to reflect new spy unit capabilities. + * Fixed show commands to only show trade ships if the TRADESHIPS option + is enabled. + * Fixed build command to only allow building of trade ships if the + TRADESHIPS options is enabled. + * Fixed up some definitions located in many places used for checking + sectors for navigation rights. + * Fixed power.t to correctly describe NEW_POWER formula. + * Made HIDDEN option run time configurable. + * Made LOSE_CONTACT option run time configurable. + * Made ORBIT option run time configurable. + * Made SAIL option run time configurable. + * Made MOB_ACCESS option run time configurable. + * Made FALLOUT option run time configurable. + * Made SLOW_WAR option run time configurable. + * Made SNEAK_ATTACK option run time configurable. + * Made WORLD_X and WORLD_Y run time configurable. + * Made MARKET option run time configurable. + * Made LOANS option run time configurable. + * Made BIG_CITY option run time configurable. + * Made TRADESHIPS option run time configurable. + * Made SHIPNAMES option run time configurable. + * Made DEMANDUPDATE option run time configurable. + * Made UPDATESCHED option run time configurable. + * Made LANDSPIES option run time configurable. + * Made NONUKES option run time configurable. + * Made PLANENAMES option run time configurable. + * Removed SMALL_SERVER stuff (unused baggage) + * Removed trading post sector ('v') + +Changes to Empire 4.0.18 - Thu Sep 24 06:54:27 PDT 1998 + * Fixed bug in aircombat where planes in flight could intercept air + defense planes and take no damage (i.e. they got to fight twice, + once for free.) + * Fixed bug in freeing memory after performing missions that could crash + the server (it mainly happened after an interdiction mission using + planes and escorts, where some escorts came from airports that didn't have + bombers going up. Freeing the leftover escorts was crashing the server.) + * Fixed bug where you could load non-existant units if you were allied + with country #0. + * Fixed bug where you could pin-bomb a plane with itself. + * Fixed bug where satellites over a bridge may get killed if the bridge + is sunk. + * Fixed bug where land units on a ship in the same sector as a bridge + that is splashed may get sunk. + * Fixed bug where planes on a ship in the same sector as a bridge + that is splashed may get sunk. + * Fixed doconfig with correct empire site text. + * Fixed major problem with abms not firing, and sometimes crashing + server. + * Fixed bug in land units counting up loaded units wrong. + * Fixed doconfig makefile to have doconfig.c as a dependency. + * Fixed bug in resetting commodities (the comm_uid was not being + properly set.) + * Fixed bug in repaying loans not working correctly (the l_uid was not + being properly set.) + * Fixed bug in buying items from the trading block not allowing you + to due to a perceived change in item status. + * Fixed bug in mfir.c where a bogus input to a target could crash + the server. + * Fixed bug that after you read telegrams new telegrams may not send + an inform message (the old telegram flags were not cleared.) + * Fixed bug where fort support distance calculations are calculated + twice instead of just once. This bug caused a lower percentage + of support fire than designed. + * Fixed bomb.t to reflect land unit changes. + * Put in some integrity checking for planes returing from bombing runs. + * Added ability to edit land unit that a land unit is loaded on in + edit command. + * Consolidated bridgefall code into "knockdown" function (this code + existed in at least 3 places, and was different in all of them.) + * Subs returning fire are no longer reported in the news. + * Visitor countries can now use the 'motd' command. + * When trying to use a visitor country, if it is in use, you are not told + by whom, just that it is in use. + * Optimized (slightly) support fire from forts not getting supply and + shells if not needed (out of range) + * Updated Education.t + * Modified (increased) chances of hitting mines slightly. + * Removed unused variables from shp_check_mines. + +Changes to Empire 4.0.17 - Fri Jul 31 06:12:21 PDT 1998 + * Added ability in edit to change coastal flag for sectors. + * Added ability in edit to edit plague values for ships. + * Added ability for "spy" to report all units/planes not owned by you + that exist in the sector you are spying from. + * Modified naval planes and anti-sub planes. + * Changed so that missiles and bombs that miss their targets cause + collateral damage in the target sector (they have to land somewhere!) + * Changed llook so that non-spy units are required to have at least 1 + military personnel on board to see anything. + * Fixed "llookout.t" to reflect change for military requirement. + * Updated Plague.t + * Updated upgrade.t + * Added "lmine" flag for deities to see what sectors have mines in them + (works for sea and land mines, used "lmine" to distinguish it from "min" + which determines mineral (iron) content of a sector.) + * No longer able to pin bomb land units on a ship. + * Land units are required to have at least one military loaded to perform + a mission. + * Firing land units are required to have at least on military loaded to + be able to fire (or return fire.) + * Spies are not always seen when being pinbombed. You have to look very + carefully for them (as you usually would.) + * Fixed typo in "Spies.t" + * Added new info about spy ability to spy.t. + * Updated tax information in Innards.t and Update-sequence.t + * Fixed typo in fire.t information about units firing on ships. + * Loading military onto land units now resets fortification. (You gotta + re-fortify the new guys.) + * Fixed bug where planes that were mine capable could not drop mines if + they were not cargo capable. + * Fixed bug in potentially crashing in update code for nations tech/research. + * Fixed bug in execute putting you into execute mode incorrectly. + * Fixed bug in board not allowing land units to board from 0 mobility + sectors. + * Fixed bug where interdicted land units that were missed displayed + a "SPLASH! Bombs miss your ships" message. + * Fixed bug in minesweeping sectors where, even with mobility or + having the sweep ability, ships would get hit by mines for doing + nothing. + * Fixed bug in count_land_planes always writing out land units unnecessarily. + * Fixed bug in count_planes always writing out ships unnecessarily. + * Fixed bug in lnd_count_units always writing out land units unnecessarily. + * Fixed bug in count_units always writing out ships unnecessarily. + * Fixed bug in llook that reported units on ships. + * Fixed bug in llook that reported satellites launched over the unit. + * Fixed bug in llook that always reported spies (it should be a 10-100% + chance) + * Fixed bug in anti possibly not saving lost items correctly. + * Fixed bug in planes getting extended range when on missions and the + op center is not where the plane is located. + * Fixed bug in land unit defensive strength not being based on the eff of + the unit when calculating odds of a battle. + * Fixed bug in board not reporting consistant information. + * Fixed bug in the way land unit casualties were being taken. + * Fixed bug where land units on ships could return fire. + * Fixed bug where land units on other land units could return fire. + * Fixed bug where land units on other land units could fire. + * Fixed bug in attacks/assaults/boardings spreading plague incorrectly. + * Fixed bug in updating plague for ships. + * Fixed bug in updating plague for land units. + * Fixed bug in updating plague for attacking/defending land units. + * Fixed bug where you couldn't pin-bomb land units that were < 20% eff. + * Fixed bug which revealed the owner of torping subs when on a mission. + +Changes to Empire 4.0.16 - Fri Jun 12 08:52:06 EDT 1998 + * Added patches sent in by Steve McClure, Sverker Wiberg and Curtis + Larsen. They are described with other changes below. + * Fixed bugs in the following commands that allowed two cooperating + countries to create infinite numbers of any commodity and/or cash + at any time (race conditions in the server): build, board, deliver, + designate, distribute, explore, fuel, improve, load, ltend, mobquota, + move, name, order, reset, sail, sell, set, tend, territory, test, + threshold, torpedo, transport, unload + * Fixed bug in board command giving out too much information about a + non-owned sector when it shouldn't be. + * Fixed bug in board command when firing on a sector in defense before + checking mobility. + * Fixed bug in rangeedit allowing plane(s) to possibly be stored wrong. + * Fixed bug in launch allowing plane to possibly be stored wrong after + launch. + * Fixed bug in lrangeedit allowing land unit(s) to possibly be stored wrong. + * Fixed bug in morale allowing land unit(s) to possibly be stored wrong. + * Fixed bug in arm/disarm allowing a plane to possibly be stored wrong. + * Fixed bug in loan sometimes not writing database correctly. + * Fixed bug in collect. + * Fixed bug in dropping mines from land units. + * Fixed crashing bug in sector_strength routine when oceans take + collateral damage. + * Fixed bug in transport possibly decrementing too much mobility when + moving a nuke. + * Fixed some little warning type messages building with gcc -Wall. + * Fixed problem compiling lwp threads with glibc6 under Linux. + * Changed flash so that players can always flash deities. + * Changed players command to always show deities and visitor countries + that are logged on, and only show allied countries for normal player + countries. + * Fixed bug in anti command not stopping sectors when they revolt. + * Fixed bug in set_coastal function not counting bridge spans as + water based sectors (after all, the land is still a coastal sector, + even if next to a bridge span.) + * "flash" and "players" is re-enabled for visitor accounts. + * Fixed bug in bleeding of technology and research to other players. + * Fixed bug in explore not spreading plague correctly. + * Fixed bug in move not spreading plague correctly. + * Fixed bug in deliver not spreading plague correctly. + * Fixed bug in distribute not spreading plague. + * Included "postresults" script in the scripts directory which can be + used to auto-post daily power chart/announcements to rec.games.empire. + * Updated Plague.t + * Updated Innards.t + * Removed OVCONFIG from build.conf, and patched doconfig to match. + * doconfig is only run if needed + * emp_client and emp_server are only linked if needed + * Added list of disabled options to the version command. + * Fixed bug in survey allowing you to see hidden variables. + * Re-enabled escort missions due to above bug fix most likely the problem. + * Changed one instance of "restrict" to "restricted" in bestpath.c. For + some reason, this was causing a problem on one of the Linux builds (??). + * Added "show sector capabilities" functionality (this didn't exist + before.) + * Fixed bug in neweff not reporting stopped sectors. It now (correctly) + reports them as not changing eff. + +Changes to Empire 4.0.15 - Wed May 20 12:35:53 EDT 1998 + * Fixed the spelling of Markus' name in CHANGES4.0 files. + * Added Markus' patches/fixes. Some are detailed below. + * Added 'mipsultrix.gxx' build target. + * Fixed doconfig to write ipglob.c in the correct target area. + * Fixed a bunch of type casting that needed to be done correctly. + * Only print out last connect by for non-visitor accounts. + * 'players' command is only useable by non-visitor accounts. + * Fixed ask_off in attsub.c to not print out allied sector mil counts + when attacking from neighboring sectors. + * Fixed targetting of che when taking over sectors. + * 'anti' command only fights che that are targetted at you. + * Fixed update not updating timestamps of objects (ships, planes, land + units, sectors.) + * Fixed bug delivering conquered populace. + * Fixed potential bug scuttling ship with land units on it. + * Moved heavy bombers to tech 90. + * Fixed bug in setsector telling the deity coordinates of sectors being + granted/taken away. + * Fixed bug in setting budget of enlistment sectors to 0. + +Changes to Empire 4.0.14 - Wed Apr 8 08:47:54 EDT 1998 + * Fixed time_t problem in common/log.c + * Fixed bug in headlines + * Replaced vaxultrix build flags with proper vanilla ones. + * Fixed bug in update/prepare.c (sometimes not getting charged for + mil on units and ships) + * Fixed bug in printing of "No ship(s)" twice in cargo command when no + ships were selected. + * Temporarily disabled escort missions until a fix is found. They are + randomly crashing the server. + * Fixed morale.t to reflect that retreat percentage is based off of + morale_base and not 75. + * Fixed bug in bridgefall where planes and units on ship in a sector + that has a bridge collapse are being sunk. + * Fixed bug in update/produce.c when a sector overflows it's capacity + on production. + * Fixed bug in produce command reporting incorrect costs (sometimes). + * Land units on ships will now try to draw supply from the ship they + are on. + +Changes to Empire 4.0.13 - Mon Mar 2 11:04:28 EST 1998 + * Fixed bug in distribute when world sizes are other than 64x32 + * Fixed bug in getcommand (not really a bug, just made it work like + it used to so that the players command is useful for deities + again) + * Fixed building of POSIX threads on Alpha running Digital Unix. + * Fixed line_of_sight prototype in sona.c + * Fixed fairland not to conuse stupid C++ compilers. + +Changes to Empire 4.0.12 - Tue Feb 24 11:27:31 EST 1998 + * Fixed client build on linux (whoops) + +Changes to Empire 4.0.11 - Tue Feb 10 10:53:10 EST 1998 + * AIX build seems to only work with gcc right now (but at least that works) + * Vax Ultrix (vaxultrix) build should work now (hopefully) out of the box. + * Took out autosupply of airports when bombing or dropping shells. + (This was the only commodity this was done for, and it was creating + problems since supply is still somewhat broken somewhere) + * Included Curtis Larsen's, Markus Armbruster's and Sverker Wiberg's + submitted patches, which collectively included cleaning up most + of the server prototypes and bogus declarations. Many thanks. + * Increased incoming command buffer to 1024 from 512 bytes + * Increased the # of parsed arguments from 64 to 100 + * Fixed bug where spies were not dying when damaged. + * Fixed bug in HIDDEN mods in declare command not printing country # of + uncontacted country correctly (or at all as a matter of fact) + +Changes to Empire 4.0.10 - Mon Aug 18 12:34:58 EDT 1997 + * Fixed bug where fleets were being interdicted but the damage was being + spread to ships not in the same sectors. + * Fixed but in market when buying goods without enough cash. + * Planes in orbit over airports are no longer fixed up during updates. + * Planes in orbit are no longer damaged when the sectors they are over + are damaged. + * Planes on ships are no longer damaged when the sectors they are in are + damaged, unless the ship is damaged. + * Fixed problem with no newline after partisan activity telegram in + anti.c + * Fixed problem in chan.c printing out change costs incorrectly. + * Fixed problem in dispatch.c screwing things up on redirection. + * financial should now handle 6 and 7 digit loans. + * Planes on ships that are in sectors that revolt are no longer taken + over. + * Fixed bug in powe.c where the power report was mis-calculating the + efficiency of planes. + * Fixed doconfig.c to use STDC instead of multi-level #ifdefs. + * Fixed bug in parse.c that was screwing up double quotes in conditional + arguments. + * Military in a sector now only produce up to maxpop, just like civvies + and uw's. No more stuffing 6K mil into a mountain to max it out. You + can still hold more mil there over the updates, but the extras just + won't produce anymore. + * Fixed bug in shark that allowed you to shark up loans even if you couldn't + cover the debt. + * Fixed bug in day of week calculation for server up time in common/keyword.c + that is used for gamedays. + * Documented what happens to standing military in collect.t when you collect + a sector. + * Documented mountains only holding and using 1/10th of the normal sector + population in Sector-types.t. + * Fixed documentation on ship's firing ranges in fire.t to be less + ambiguous. + * Updated nukes in nuke.t + * Added apropos command (thanks to Mike Wise) + * Added case-insensitivity to the info command (thanks to Mike Wise). If + there are two files of the same name, and you don't get a complete match, + then whichever file is found first in the directory is used. + * Changed documentation in wantupd.h + +Changes to Empire 4.0.9 - Sat Apr 19 23:01:51 EDT 1997 + * Fixed dump info pages that were getting formatted funny. + * Fixed improve info page. + * Fixed bug in allied planes/units not moving when the carriers move. + * Fixed bug in satellite output for <100% satellites. + * Fixed bug in load/unload not putting a newline after some unloadings + in allied sectors. + * Fixed bug in harden not printing correct values. + * Fixed bug in creating/moving/etc. nuclear stockpiles. + * Fixed bug where subs were trying to torp commodities moving on land when + on interdiction. (This was funny ;-) ) + * Fixed bug in "move" where you could keep a sector even after someone else + took it from you. + * Budget now correctly reports the # of units being built. + * Mil on units & ships are now reported as normal military costs, not + ship or unit maintainence costs in budget. + * Fixed bug in update code where taxes could potentially be initialized + incorrectly (affected budgets too.) + * Fixed bug in nat.h header so that it uses SCT_MAXDEF instead of a fixed + number (that was incorrect.) + * Fixed bug with trains - they needed the xlight flag to carry planes. + * Revamped and improved flak. + * Added "Flak" info page. + * Added "Fallout" info page. + * Fixed repay/offer/consider to all need a capital to be used. + * Fixed bug with air defense missions not running when not AT WAR. They now + fly when HOSTILE. + * plane/ship/unit short names are all now 4 characters, padded if needed. + * pdump/sdump/ldump/ndump now just print the short name for the type. + * sdump now has ship name at very end in quotes. + These were done at the request of some client developers for ease of use. + * Fixed extra space in the dump output. + * Fixed fallout - not quite so nasty anymore. + * Fixed fallout - things on ships/units are damaged now. + * Fixed and balanced planes/ships/units/nukes in conjunction with each other. + * Fixed bug in doconfig.c calculating wrong s_p_etu sometimes. + * Fixed bug where harbors weren't being used to resupply. + * Fixed bug where selling units loaded with planes and units wouldn't take + the loaded planes or units - they are now dropped. + * Fixed bug in arm/disarm where you could arm/disarm planes on the trading + block. + * Deities can now remove things from the trading block/market. + * Fixed bug in "work" not charging engineers enough mob. + * Fixed bug in "work" not adding teardown and buildup avail costs together. + * Subs no longer need mobility to return fire when fired upon. + * Fixed "reset". + * Fixed bug in "trade" allowing 2 players to pay for the same item, but only + the last player gets it. + * Fixed bug where you couldn't launch missiles from allied ships or sectors. + * Fixed bombing so that pin-bombing can cause collateral damage too. + * Fixed sector damage to damage planes there too. + * Fixed flag in lload so that it doesn't always print if not needed. + * Fixed "sell.t" info page. + * Fixed bug in "buy" where not entering the price correctly could cause + a crash. + * Fixed "sell" so that at least 1 mobility is required to sell goods. Keeps + the midnight "raid and sell" abuse down. :) + * Fixed "show plane cap" to move the last column over 1 more where it should + be. + * Fixed timestamps to be updated for units/planes on ships/units that move, + since those units/planes move too. + +Changes to Empire 4.0.8 - Wed Feb 26 23:00:51 EST 1997 + * Fixed bug in nstr_exec that was wiping out the previous conditional. + This was major because it affected timestamp values which are more + than 65535. + * Fixed bug in sdump.c for typo in reporting the trade ships origin. + +Changes to Empire 4.0.7 - Mon Feb 24 22:48:54 EST 1997 + * Fixed bug in aircombat.c when calculating the air combat odds. Negative + numbers were screwing things up good... + * Fort sector's coordinates are no longer printed when auto-firing at + ships. + * Subs can now surface and fire deck guns (again) They can also be + hit by return fire when doing so. + * Fixed bug in setting of plane attack and defensive values so that + negative numbers don't keep going further negative. + * Fixed incorrect military control calculation in the sell command. + * Trading posts are no longer required to sell goods from. You can sell + from harbors and warehouses now too. + * Spy now prints out the owner of land units you see when spying. Before + this was assumed to be sector owner, which is no longer true. + * Loading land units now prints out what was loaded onto each unit, + just as loading ships do. + * Added fallout, coast, c_del, m_del, c_cut and m_cut to dump output. + * Added "GO_RENEW" option. This option means that gold and oil resources + are renewable. + * Added "lost_items_timeout" config variable, and set the default to + 48 hours. This determines how long lost items stay in the lost items + database. + * Fixed land unit names to be more consistent. + * Fixed mission.t info page. + * Fixed bug in that if mission_mob_cost was set to 0, even negative + mob units should be able to be put on missions. + * Removed restriction on things needing to be at least 60% to be put + on a mission. Note that while you can put them on missions at < 60% + now, when trying to do the mission, it still checks the eff. This + is to help in automatic setup (build, put on mission, forget) instead + of having to come back repeatedly. + * Spies caught in Neutral or Friendly countries cause the Neutral or + Friendly country to go Hostile towards the owner of the spy. + * Tweaked ammunition numbers for artillery units. + * No more automatic declarations of War should be made. You will go + hostile, but since going to war doesn't increase your countries + defenses, and is purely political, it is left to the player to go + that final step. + * Fixed bug in trade that wasn't incrementing the time if last second bidding. + * Fixed bug in "lmine" that was crashing the server if the land unit was + out of mobility. + * Fixed buy so that if you specify a product, you can only bid on that + type of product. + * Added "lost.t" info page. + * Added "lost items" database (EF_LOST) + * Fixed bug where you could move in allied forces after an attack if they + bordered the victim area. + * Fixed nstr_comp to deal with values > 16 bits coming in from + client for comparisons. + * Changed last minute market/trade timers to increment 5 minutes. 2 minutes + was too quick. + * Fixed decode in lib/common/nstr_subs.c to deal with NSC_TIME better. + * Commented out the logging of the market checking in server/marketup.c, + lib/commands/buy.c and lib/commands/trad.c It was generating lots of + pretty much useless data that made parsing the server.log file more + more difficult than it needed to be. + * Fixed crashing bug in ldump. + * sdump, ldump, ndump, pdump and dump now print out the current + timestamp on the "DUMP XXX" line. + * Fixed denial of service bug in lib/player/accept.c in + player_find_other function. + * Fixed bug in shark reporting incorrect buyer of the loan. + * Fixed bug in sdump.c (case 0 should have been case 10) + * ldump and sdump now always print the fuel column if asked for, + even if opt_FUEL is turned off. In the case that it is turned + off, the fuel is listed as 0. + * Added "timestamp" field, which is updated every time an item is + changed. + * Fixed up the Clients.t info page. + * sdump now prints trade ship building origin. + * sdump now always prints name even if SHIPNAMES isn't defined. If + it is not defined, then the name is empty. + * Added "timestamp" to info/Concepts/Selector.t + * Added some more relevant info to info/Server/Empire4.t + * Fixed Infrastructure.t info page to reflect the fact that infrastructure + is no longer torn down when a sector is re-designated. + * Fixed sell.t to more accurately reflect the time-delay market. + * Fixed read.t and wire.t to reference accept and reject. + * Fixed reject.t not referencing accept command. + * Fixed collect.t to more accurately reflect what goes on when collecting + sectors. + * Fixed financial.t to reflect defaulted loans. + * Fixed dump.t, sdump.t, ldump.t, ndump.t, pdump.t to reflect new + timestamp info. + * Fixed "census.t" (had incorrect reference to "info syntax" instead + of "info Syntax". + +Changes to Empire 4.0.6 - Thu Jan 16 11:33 EST 1997 + * Increased damage from depthcharges because on increased damage from + torpedos. Sub frange decreased to be more balanced with destroyer frange. + * Intelligence reports (spy) on units will now report the estimated number + of mil on the unit. + * Fixed equation for ship visibility so it will drop as tech increases. + * Added new commands sdump, ldump, pdump, and ndump to dump data on ships, + land units, planes, and nukes. + * If fields are provided, dump will only supply those fields requested. + * Decreased speed of subs. + * When options NO_LCMS or NO_HCMS are set, those commodities are no longer + required for infrastructure improvements. + * Units that lose an assault or a boarding attempt from a ship will no + longer swim back to the ship they came from. + * Units that take extra casualties will no longer lose all their mil at + once. + * Infrastucture is retained when redesignating a sector. + * Dieing spies will no longer crash the server. + * Units, planes, and ships must have mobility to perform missions. + * Units on ship being scrapped are transferred to harbor. + * Food is no longer autoloaded onto units when they are built. + * Fixed show plane stat to show correct range. + * Infantries now take damage at same rate as casualties. + * Fixed bug with hap_fact. Having more happiness now helps with fighting + che. + * Fixed anti to write back target country so che will continue to fight + when they survive. + * Fixed llookout to show correct estimate on number of mil on unit. + * Added buildable architecture "hp". This type will build the server on + a HP/UX machine using the standard compiler instead of gcc. + +Changes to Empire 4.0.5 - Thu Dec 12 10:28:48 EST 1996 + * Fixed bug in update/distribute.c where pathcost was not being called with + the MOB_ROAD argument (and thus distribution costs could be GREATLY + affected.) - Thanks Ice! + +Changes to Empire 4.0.4 - Mon Dec 9 11:00:00 EST 1996 + * Fixed Solaris port using gcc. + * Fixed doconfig.c to create directories with right modes. + * Fixed install macros in makefiles to move binaries to the right + places. + +Changes to Empire 4.0.3 - Wed Dec 4 22:46:53 EST 1996 + * Added HP/UX port. + * Fixed doconfig.c (put exit(0) at the end of main.) + * Fixed improve.c (moved the prompt[] string outside the fcn.) + +Changes to Empire 4.0.2 - Mon Oct 14 12:26:40 EDT 1996 + * Put in LND_MINMOBCOST in land.h + * Put in change in lnd_mobcost in lndsub.c + * Put in new nuke costs in nuke.c + * Put in fix so that total work can only be done by the max pop. No more extra + civvies tossed in will do it anymore in human.c. + * Put in fix for src/util/Makefile - beefed it up. + * Put in fix to show where your ship is when it gets shelled in mfir.c. + * Changed infrastructure of roads from .040 to .020 (122 instead of 150 in + common/move.c) + * Fixed Update-sequence.t. + * Put in fix for mobcost bonus for 0% highways. + * Fixed stop.t + * Fixed commodity.t + * Spruced up torpedo damage somewhat. :) :) + * Fixed "assault bmap bug" in attsub.c + * Fixed Produce.t (bars cost) + * Changed mountains to get an automatic "2" for defensive bonus in attsub.c + * Fixed consider.t + * Fixed repay.t + * Fixed offer.t + * Fixed "offer" and "consider" not being legal commands in player/empmod.c + * Fixed Damage.t + * Fixed sstat.t + * Fixed lstat.c, pstat.c and sstat.c + * Fixed cutoff command in cuto.c + * Fixed attack value in attack_val in lndsub.c + * Fixed lload in commands/load.c + * Fixed defense_val in lndsub.c - Made it a minimum of 1, so that units will + always fight until dead or retreating. 0 makes them get stuck. + * Fixed update/deliver.c - no delivery of non-oldowned civvies (or anything + else for that matter.) + * Fixed llook in commands/look.c + * Fixed che bug in subs/nstr.c + * Fixed bug in strv.c by overcompensating by 1 food per sector (minute amounts + of people would starve.) + * Fixed update/human.c - feed_people rounding problems (I hope.) + * Fixed morale problem in update/land.c + * Fixed count_bodies in attsub.c + * Fixed lnd_mobcost. + * Fixed subs/land,plane,ship.c to handle sunken units and planes correctly. + * Fixed interest rate in commands/offe.c + * Fixed bug in buy.c. + * Put in DEFENSE_INFRA soption o you can turn on/off the use of the defensive + infrastructure. When off, the defensive infrastructure is the same + as the sector efficiency, and you can't improve it. This is OFF by + default. + * Fixed Empire4.t + * Added Wolfpack.t + * Land units are now built with a default reaction radius of 0. + * Changed name of lt artilleries to "lat" from "lart" so you can now build + "lar"s again. + * Lowered the speed and firing range of pt boats. + * Lowered the initial att strength of cavs from 1.5 to 1.3 (they were TOO + powerful.) + * Changed the max mob gain defaults of units/planes to 1.0 and ships to 1.5 + (This is * ETU_RATE, so it is equal to ETU_RATE for units/planes and + 1.5 * ETU_RATE for ships.) + * Conquered civvies only pay 1/4 taxes. + * Railways don't get torn down when you rebuild sectors anymore (but roads + and defenses do (if enabled.) + +Changes to Empire 4.0.1 - Wed Aug 28 11:35:40 EDT 1996 + * Added "extern double tradetax" to check_trade in trad.c + * Improved description of data directory in build.conf + * Fixed bug in attacking land units that retreat so they now get + charged mobility for attacking. + * Fixed dump to report road, rail and defense of a sector at the end. + * Fixed doconfig bug in not checking the right directory to see if the + "data" directory existed or not before trying to create it. + * "change" now works for sanctuary countries. + * Fixed the description of "sinfrastructure". + * Added more info to "Infrastructure". + * Units/planes are no longer reduced to 75% when bought from the trading + block. + * Supply units were slowed down to the speed of infantry units. + * Trade-ship payoffs have been lowered to 2.5, 3.5 and 5.0 + * Bars interest is up to $250 per 1K again. + * Civ taxes were raised back up to a 10:1 mil/civ tax ratio (was 20:1) + * Fixed various info pages. + * Fixed bug in people not getting truncated when broke (this was thought + to be fixed, but wasn't. Now it is, dammit!) + * Fixed bug with units marching across oceans (scuba gear not included. ;-) ) + * Market/trade taxes and trade ship payoff figures were added to version. + * "cede" has been removed as a default command. + * Makefile rule was fixed for depend build. + * Fixed bug in mapdist not taking world edges into account nicely enough. + * Added a "scuttle" order for autoscuttling trade ships. Makes using them + easier. Cleaned up scuttle code while in there. + * Fixed bug with scuttling a ship with units on it not scuttling the units + too. + +Changes to Empire 4.0.0 - Initial release + * Initial Wolfpack release - Long live the Wolfpack!!!! + * Cleaned up the build environment. Now all that is needed is to edit the + build.conf file, answer the questions there and type "make " to + build for a specific architecture. Thus, no more reliance on gnumake + or special shell scripts. + * We are now shipping the pre-built info pages with the server for those who + Don't want to build them. You can also still just type "make" and have + the info pages build, but it doesn't completely work (i.e. rebuild new + Subjects) if you don't have perl5 installed. + * Put in the "help" command that does the same thing as "info". + * Removed C_SYNC. This is done for 2 reasons. 1) None of us like it or + wish to support it. 2) We envision a better scheme for doing similar + things will come along. + * Put in MOB_ACCESS - This allows real-time updating of mobility. + * Put in MARKET - This is the time-based market (yes, still teleports, + but it's not as bad as it was.) + * Lots of the documenation has been updated, but there is more to do. + * Added NO_LCMS, NO_HCMS and NO_OIL options. When any of these options are + enabled, you don't need any of that type of material to build things. + If NO_HCMS is enabled, you don't need HCMS to build bridges, you need + lcms. If both NO_HCMS and NO_LCMS are enabled, then you don't need + any materials to build a bridge. + * There is no mobility cost for assigning missions. But, there is also + no longer any benefit for being on a mission either. + * Damage is the same for all commodities (people too.) This means you + can deity shell/bomb sectors again. + * Units are now dependant on tech. What this means is that their statistics + now increase with tech. In addition, there is only 1 type of each basic + unit now (i.e. just "cavalry" instead of "cavalry 1", "cavalry 2", etc.) + This reflects the idea that as you learn more, you learn how to not only + build better units, but you learn to build units better. :) This also + opens the door for a "lupgrade" command along the same lines as the + "upgrade" command for ships. + * Units now have a minimum mob cost for attacking a sector. Marching + mob costs have not changed. + * Starting units have been removed. This means that at the beginning, people + may live a little longer since their neighbor can't come visiting quite + as quick. + * Shells are no longer required to build units. + * Mil are no longer required to build units. + * Mil are no longer an intrinsic part of a unit. They are now a loadable + commodity. The way a unit's defense/att bonuses work now are + attack = (att * mil * eff) + defense = (def * mil * eff) + In addition, when a unit takes damage, both the eff and the mil go + down. You can quickly toss in new hacks, but you need to wait to repair + the unit at the update. Thus, you can now look at unit's efficiency + as their training. + * You need at least 1 mil on a unit to march it (spies are the exception.) + * Units always react if in range and they have the mobility, no matter + what their efficency. + * Units may now march anywhere - in your own sectors, deity owned sectors + or allied sectors, with 1 exception, spies. Also, your units can get + trapped if your ally declares non-alliance with you while your units + are still in his country.) + * Units always march at their speed, efficiency doesn't matter. + * LANDSPIES was added - This creates land unit based spies. Spies may march + anywhere, with a chance of getting caught (except in allied territory.) + See "info Spies" for more info on them. + * Planes may now be based out of allied airports. Landing planes on + ships/sectors you do not own no longer changes thier owner. You can only + land on owned/allied sectors/ships, and you may only + fly/bomb/para/recon/drop from owned/allied sectors. So, if a country + you are allied with goes hostile at you, your planes are now stuck there. + Note that if you are using an allied airport, their commodities get + sucked up, not yours (obviously.) + * Planes are now tech-based. Their statistics increase as their tech + increases. Deleted extraneous planes. + * There is a new toggle, "techlists", which allows you to see what you + can build/stats/capabilities sorted by tech instead of groupings. + * Ships are now tech-based. Their statistics increase as their tech + increases. Deleted extraneous ships. + * Che can now be lessened by making happiness. If you have more happiness + than your conquered populace, they don't fight as hard or recruit as + much. If you have less than them, they fight harder and recruit more. + It's not much though - it ranges from 2.0 in your favor to only 0.8 + against you (whereas it was always 1.0 before.) So, it definitely + favors the attackers to make lots of happy now. + * Bridgeheads can only be built on coasts. + * Players command was fixed so you only see allies, and don't get + approx #'s of players anymore. + * POSIX threads support has been added. + * The attack bmap bug has been fixed. + * BTUs regenerate 3 times faster now. + * GRAB_THINGS is off by default. + * Big nuclear bombs are back, and FALLOUT has been fixed and enabled + as a default (you couldn't make wasteland before with FALLOUT, now + you can.) + * You can now deliver military and civilians. + * Added SHIP_DECAY option - off by default (turns off ships decaying out + at sea if not enough mil.) + * The reverting owner bug has been fixed in territory, thresh, dist + and deliver. There are probably more, and when found, will be fixed. + * The "sectors don't starve when stopped or broke" bug has been fixed. + * The "people never get truncated" bug has been fixed. + * Added infrastructure to sectors. What this means is that a sector + can now have it's mobility improved by building both roads and + railways. It also means that a sectors defense is now based on the + defensive infrastructure you build into the sector (no more intrinsic + better defenses based on the sector, you determine which sectors are + defended heavily, and which aren't.) + * The defensive value of a sector no longer relies on the efficiency of + the sector. Instead, it relies on the defensive efficiency of the sector. + Thus, the "production" and "defensive" aspects of sectors have been + separated. + * "show sect stats" now shows the maximum defensive value for sectors. + * Changed sector structure to take floats for off/def values so we can use + a base of 1 instead of 2. + * Added "improve" and "sinfrastructure" to support the infrastructure + concepts. + * Added L_TRAIN units which can only travel along railways. Very fast on + efficient railways, slow on non-efficient ones. + * Added the ability for units to carry other units. + * Fixed census (shortened up "fallout" and "coast" to "fall" and "coa".) + * Forts only cost $500 to build and 100 hcms now (since they don't get any + better defenses automagically.) + * Modified "show sect build" to show the costs for building up the + infrastructure of a sector. + * Changed "spy" and the satellite recon stuff (which shows sector stuff for + spyplanes too) to show the new infrastructure stuff, rounded of course. + * Added Drake's info->html scripts, with some modifications, so you can + now type "make html" and have your info pages built as html files too. + This adds a new directory, "info.html", to the build tree. + * Modified upgrade so that planes and land units may now be upgraded. + * Added pstat command to list the statistics of your planes. + * Added lstat command to list the statistics of your land units. + * Added sstat command to list the statistics of your ships. + * Added nmap command to show a map of your sectors after their new + designations have taken place. + +.FI +.s1 +.SA "Clients, Server, Infrastructure, Sectors, LandUnits, Planes, Ships" diff --git a/info/Server/God.t b/info/Server/God.t new file mode 100644 index 00000000..ab967698 --- /dev/null +++ b/info/Server/God.t @@ -0,0 +1,101 @@ +.TH Server "How to be a good God" +.NA God "Tips on being God" +.LV Expert +.s1 +The following commands act differently or require different +parameters when used as deity: +wire, read, des, zdone, nav, march, transport, move, build, country. +.s1 +Comments from Dave Pare +.s1 +I've been deity of seven or eight games, +and each time I learn something new about how far I should go, +and how active a role I should take. +.s1 +There are several things a deity should take into account. +.in +\w'00)\0\0'u +.s1 +.L 1) +Bug policy. +When a player says that a bug bit him, how do you handle it? +Since I used to hack on the game at the same time players would play, +I used to have a \*Qnasty\*U bug policy. +That is, if a bug bites a player, he loses. +It is very difficult to verify if a player +\*Qreally did lose those 1000 gold bars\*U from that bank +because of a bug. +Also, whenever a player had something bad happen to him, +he'd yell \*QBUG\*U. +All too often, the player just did something stupid. +.s1 +If a player ever found a \*Qgood\*U bug +(and reported it in a timely fashion), +I'd give him some kind of reward. +The reward was generally material enough +to encourage them to report bugs, +but not too much so the other players complained. +If through use of this bug the player manufactured +\*Qtoo many\*U goodies for himself, +I acted to redress the balance immediately. +.s1 +This whole case is only interesting +when the Deity knows the Empire code, +and can identify bugs as such. +.s1 +.L 2) +Unskilled players. +It's tough watching your friends lose in an Empire game. +Helping \*Qjust a little\*U by giving information, +or by giving a teensy bit of assistance is BAD. +Empire is NOT a game of socialist care for the needy; +it's more like survival of the fittest. +Players should sink or swim on their own. +If you help a novice, you're deliberately hurting his opponent. +Some players will lose, +and as Deity you'll have to stand by and watch this happen. +.s1 +.L 3) +Answering random prayers. +If you DO help someone, help them in relatively minor ways. +Do things like fill in some ocean, etc. +Don't give away commodities -- except perhaps food. +Whatever you do, don't give tech, military hardware, +civilians, military, or any information at all! +The game is very stingy with information, and you should be too. +.s1 +.L 4) +Security. +Make SURE that nobody else has access to the data directories. +There are always players who will do anything to win. +If you help them control themselves +by making the data completely unavailable -- +watch those dump tapes too -- +you'll be doing their moral fiber and everyone else a favor. +.in +.s1 +Remember, as Deity your job is to make the game fair. +Don't hose players +(unless they cheat -- and you catch them!) +and don't give out information. +Information is very important in Empire, +and as Deity you've got access to all of it. +Be careful in what you say, +and how you leave your terminal at night! +.s1 +Unless you've got nothing else to do, +a Deity should keep player communications to a minimum. +Handling special player requests gets tedious after a while; +make players pay for Deity assistance. +One game I suggested that the only way players could get the Deity +to fill in ocean sectors, zap plague, etc, +was to offer a real-life sacrifice to the deity -- +a few bottles of good beer, for example! +I got perhaps a dozen bottles, +and managed to greatly curtail player requests at the same time! +.s1 +In summary, an Empire game should be between players. +Any time the Deity helps anyone, +Deity intervention starts becoming a factor in the game. +As a Deity, you absolutely can't go wrong +if you do nothing at all except routine game maintenance. +.SA "Deity" diff --git a/info/Server/Hidden.t b/info/Server/Hidden.t new file mode 100644 index 00000000..e3f07e4e --- /dev/null +++ b/info/Server/Hidden.t @@ -0,0 +1,36 @@ +.TH Server "The HIDDEN Option" +.NA Hidden "The HIDDEN option" +.LV Expert +.s1 +The following commands are restricted when the HIDDEN option is +in play: +.NF +power: Will only display your country's power. Other nations never show up. +report: Will only report on contacted countries, and no status (active/flux). +relat: Will only display contacted countries. +news: Will only show news about contacted countries (except for headlines). +accep: Will only display contacted countries. +tele: Only allowed with contacted and deity countries. +.FI +.s1 +A country is 'contacted' with a successful spy, look, coastwatch, +or recon, when an attack is made, or when you are the victom of an attack +or if you receive a telegram. +.s1 +It possible for contact to be one sided. If you contact someone, they must +also contact you in order to obtain information from you. If you want someone +to be able to contact you, you can send them a telegram. +.s1 +Tech and research bleed only comes from contacted countries, so it's in your +best interest to explore as much as possible. +.s1 +Because of the difficulty of tracking past news, news cannot be used +with an argument under this option. Once the news is read, it cannot be +read again. This may change in the future. +.s1 +If the LOSE_CONTACT option is in play, contact is lost after three +update of no contact. Contact can be maintained by the same methods described +above. It's important to note, however, that contact is retained by RECEIVING +a telegram, not sending one. + +.SA "Options, Server" diff --git a/info/Server/History.t b/info/Server/History.t new file mode 100644 index 00000000..c980b591 --- /dev/null +++ b/info/Server/History.t @@ -0,0 +1,229 @@ +.TH Server "A Brief History of the Different Versions of Empire" +.NA History "Empire Revision History" +.LV Expert +.NF + +1985 PSL Empire, Peter Langston + +Naturally, the original creator (or at least the last surviving +implementor) of Empire is Peter Langston. He distributed the +game that we all wanted to hack on, but naturally enough he +didn't give out the source! (he wasn't dumb...he probably knew +what we'd do to his code) + + +1986 UCSD Empire 0.x, Dave Pare + +Made Empire multiplayer with fixed update times. Added hexmap, planes, nukes, +satellites, ships, market, distribute, and updates. + +Jim Reuter (and his PDP/11 decompiler) provided Dave Pare with a large +quantity of amazingly readable decompiled code. His contribution +came at a time when Dave's interest in reverse-engineering was +flagging, and it provided what was necessary to create the +original UCSD Empire. + +David Muir Sharnoff was responsible for promoting the early +development of Empire 0.X. Without David it is unlikely if Empire +would have escaped UCSD! He took on the onerous task of managing +the source, creating mailing lists, applying patches, and generally +making the early versions of UCSD Empire releasable -- they +sure weren't when they left Dave Pare's hands... + +The rest of the folks who contributed to the early versions did +so with code and/or ideas. (If I've forgotten anyone, let me know!) +They appear in chronological order. + + Keith Muller + James Anderson + Julian Onions + Lewis Jansen + Peter Vukovich + Jeff Anton + Jeff Wallace + Gregory Paris + Edward Rynes + Sean Casey + Phill Everson + Kurt Pires + Jeff Okamoto + Nick Lai + Steven Grady + Jim Griffith + Chris Metcalf + Steven Grimm + Mike St. Johns + + +1986 BSD Empire 1.1, Dave Pare + +The following people (listed in alphabetical order) have contributed +to the development of BSD Empire 1.1. Without these people, BSD +Empire would never have happened. Thanks also go to the XCF at the +University of California, Berkeley, for providing the facilities on +which we performed this herculean task. + + David Davis + Steven Grady + Jim Griffith + Beorn Johnson + Phil Lapsley + Jonathan Lee + Kurt Pires + Jeff Wallace + + +198? UCB Empire 1.2, ?? + +Added announcements, food, removed weather, parks, petrol, +edu, terrorists, shoot, many new ships. + + +198? BSD Empire -- KSU Distribution (1.04), Jeff Bailey + +One of the goals of the KSU team was to make the server as +configureable as possible. As such, they added many OPTIONS, and +global constants. Added abms, asats, bmap, autonav, scuttle, +NUKEFAILDETONATE, MISSINGMISSILES, SHIPNAMES, NEUTRON, RANGEEDIT, +MISSDEF, NOFOOD, UPDATESCHED, DEMANDUPDATE, ORBIT, FALLOUT, SAIL, +ALLYHARBOR, and fixed many bugs. Other contributers were: + Yaser Doleh + Robert Forsman + Doug Hay + Alex Shatsky + + +198? Merc Empire ?.?, ?? + +Fixed many bugs and removed loans, added grind, starvation, and prod. + + +1992 Chainsaw Empire 1.0, Thomas Ruschak + +Added land units, SUPER_BARS, EASY_BRIDGES, SLOW_WAR. + + +1992 Chainsaw Empire 2.0, Thomas Ruschak + +Added trade ships, fuel, semiland ships, ASW planes, payoff, wire, SNEAK_ATTACK +retreat paths, sweep planes, budget. Tom thanks the following people +for helping him with ideas and playtesting: + + Jorge Diaz (Ansalon) + Tom Tedrick (Afrika Korps) + Keith Graham (DreamLands), + Dave Nye (Evil_Empire) + Sasha Mikheev (Dolgopa) + Baldric + Elsinore + Brett Reid (Resvon) + Sam Tetherow (Kazzad'ur) + Tharkadia + Yikes + + +1993 Chainsaw Empire 3.0, Thomas Ruschak + +Added land units, missions, bestpath, people take less damage from shelling, +1 +range bonus for 60% forts, cede, neweff, starva, forts interdict +ships, mountain caps, RES_POP, NEW_STARVE, NEW_WORK, uncrewed ship +decay, anonymous sublaunched missiles, stop & start, bdes. + + +1995 Empire 2.0, Dave Pare + +emp_player, emp_tm, and emp_update, were consolidated into one program +called emp_server. A threads package called "lwp threads" was used to +manage the player threads. Many options were made standard. Kevin Klemmick +added HIDDEN and NEWPAF options. Many options were made standard. +These are the people who submitted patches for Empire 2.0: + Chad Zabel (3 letter abbrev's, & autonav) + Ken Huisman + Scott Ferguson (linux port) + Kevin Klemmick + Doug Hay (threads debugging) + Bill Canning (AIX port) + Julian Onions + + +1995 Empire 2.1 beta, Ken Stevens + +Organized info pages, wrote a "configure" script, made minor +improvements to many commands, rewrote missile, navigation, and march +code. Consolidated launch/bomb and missile/plane interdiction so that +hitchance and damage is the same whether it's a mission or done "by +hand". Added collateral damage, interdiction nuke detonation, +"friendly" trade relations, BIG_CITY, ATT_INTERDICT, +Consolidated sail, navi, and order. Added toggle, flash, wall, +shutdown, strength. Other contributers: + Chad Zabel (ship anti-missile defense) + Julian Onions (runtime configuration) + Sasha Mikheev (linux port) + +1995 Empire 2.2 beta, Ken Stevens + +Completely rewrote attack, assault, board, and paradrop. Added +"players", "skywatch", "disarm", tend land units. Other contributers: + Craig Leres + Janjaap van Velthooven (IRIX port) + Ken Huisman (RCS source managemant) + + +1995 Empire 2.3, Ken Stevens + +After running a series of playtest games, Ken fixed all known bugs in +the server, organized and rewrote alot of documentation (including +this info page) and released the Empire2 server out of beta. + +1995 Empire 3.0, Ken Stevens + +Empire 3.0 implemented the C_SYNC RFC, a powerful platform independent +client-server protocol for synchronizing the client database with the +server database. The Empire 3.0 server was released with the Empire +Toolkit written by Kevin Morgan, a portable C library which parses the +C_SYNC messages from the server into a database for the client. Thus, +clients can link with the Empire Toolkit and be confident that when +the server gets upgraded, their client will still work. Note that the +C_SYNC protocol is asynchronous so, in particular, players will be +able to watch their neighbours sail ships past their coast etc... + +1996 Empire 4.0, Wolfpack (http://www.wolfpackempire.com) + +A group of people got together to form a new server project. This project +is a new project, and is a complete takeoff from the Empire 3.0 server +project. There are many additions and some subtractions from the 3.0 +code base. The Wolfpack is headed up by Steve McClure and consists of the +following people: + + Mark Ballinger + Geoff Cashman + Bill Frolick + William S. Kaster + Pat Loney + Steve McClure + Richard Moss + Walter Smith + Sam Tetherow + Yannick Trembley + John Yockey + +1998 Empire 4.2, Wolfpack (http://www.wolfpackempire.com) + +The above authors (Dave Pare, Jeff Bailey, Thomas Rushack, Ken Stevens +and Steve McClure) agreed to re-release the source code under the GNU +GPL. The source was already freely released to the public, but any +copyright issues (such as gaining permission from Phil Lapsley for the +A* code and removing any other copyrighted code which would violate +the GPL) were cleared up, and the licensing information was put in +place to keep the server source free forever. Yee-haw! + +In addition, the server was made run-time configurable (yes, including +WORLD_X and WORLD_Y) so that you didn't have to re-build an entire server +each time you changed an option (you just have to rebuild the world +sometimes. ;-) ) + +The source is still managed by the Wolfpack team, and still headed +up by Steve McClure. + +.FI +.SA "Server" diff --git a/info/Server/MakeSrcs b/info/Server/MakeSrcs new file mode 100644 index 00000000..f7997b1d --- /dev/null +++ b/info/Server/MakeSrcs @@ -0,0 +1 @@ +INFOSRCS=Bugs.t CHANGES.CHAINSAW.t Empire2.t Empire3.t Empire4.t God.t Hidden.t History.t Merc.t Old-empire.t Options.t Wolfpack.t diff --git a/info/Server/Makefile b/info/Server/Makefile new file mode 100644 index 00000000..d2224a61 --- /dev/null +++ b/info/Server/Makefile @@ -0,0 +1,62 @@ +# +# Empire - A multi-player, client/server Internet based war game. +# Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, +# Ken Stevens, Steve McClure +# +# 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 2 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, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# --- +# +# See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the +# related information and legal notices. It is expected that any future +# projects/authors will amend these files as needed. +# +SRCDIR = ../.. +NROFF = nroff +TROFF = troff + +INFOSRCS = empty + +INFOOBJS = $(INFOSRCS:.t=) + +HTMLOBJS = $(INFOSRCS:.t=.) + +include MakeSrcs + +.SUFFIXES: .t + +all: + @echo INFOSRCS=`echo *.t` > MakeSrcs + @make nroffs + @echo Done. + +html: + @echo INFOSRCS=`echo *.t` > MakeSrcs + @make htmlfiles + @echo Done. + +htmlfiles: $(HTMLOBJS) + +nroffs: $(INFOOBJS) + +$(INFOOBJS): + @$(NROFF) $(SRCDIR)/info/CRT.MAC $@.t | awk -f $(SRCDIR)/info/Blank.awk > $(SRCDIR)/info.nr/$@ + @echo Created $(SRCDIR)/info.nr/$@ + +$(HTMLOBJS): + @perl $(SRCDIR)/info/emp2html.pl $@t > $(SRCDIR)/info.html/$@html + @echo Created $(SRCDIR)/info.html/$@html + + diff --git a/info/Server/Merc.t b/info/Server/Merc.t new file mode 100644 index 00000000..24c8d81a --- /dev/null +++ b/info/Server/Merc.t @@ -0,0 +1,92 @@ +.TH Server "Merc Empire Changes" +.NA Merc "Changes from KSU code to Merc code" +.LV Expert +.s1 +There have been several changes/fixes made to the KSU code for +the Merc V game. This will outline the various changes and how +they will affect you. + +Bridges + +There was a bug which allowed planes that were on bridges that collapsed +to remain in the sea sector and could be retrieved by either rebuilding +the bridge or moving them onto a 100% highway. This has been fixed so +that any planes upon a bridgespan which falls will be destroyed. + +Uncompensated Workers + +Uncompensated workers were not paying taxes, even though the version command +provided a tax rate for them. They now pay the taxes that are shown. + +.SY "reject reject announcements *" + +This command now works, so that you can reject announcements from +everybody. This is not recommended though... + +Technology + +The tech formula has been fixed so that all increases in material +result in an increase in the amount of tech produced. + +.NF + if(breakthroughs > 0.75) { + above = breakthroughs - 0.75; + tech = 0.75 + log2(1 + above); + } + else { + tech = breakthroughs; + } +.FI + +Grind + +The grind command now requires available work to grind up bars. +It takes 5 avail to grind up a gold bar. + +Loans + +Loans have been removed from Merc V. This is an experiment to see +how things go without loans being available. + +Country Names + +Certain commands only worked with country numbers, but they now work +with country names as well. The primary command that this affects for +Merc V is report. + +Production + +The production of dust/oil/rads is now limited to the resource content +of the sector. It used to be possible to get more out of a sector., + +Starvation + +Sectors that have a very large number of civilians that starve will +have at most 499 civilians after the update unless there was enough food +to feed more than 499 civs. + +Attack + +The attack command now uses at least 1 mobility point per sector that +participates in any attack. + +Pinpoint Bombing + +Pinpoint bombing now lists all the commodities in a sector that can +be bombed. + +Production Report + +The production report now contains a report of what will actually be produced +by your sectors at the next update. Since some of the rounding done by the +update code uses a random percentage chance, it is possible that you will get +1-2 units more of some of the items. The production report command is +conservative, and assumes that all rounding will be down. + +Version + +The information in the version command was modified so that the information +that was printed out would reflect the actual parameters of the game. + + +.SA "Server" diff --git a/info/Server/Old-empire.t b/info/Server/Old-empire.t new file mode 100644 index 00000000..4248cafd --- /dev/null +++ b/info/Server/Old-empire.t @@ -0,0 +1,331 @@ +.TH Server "Differences from Old Empire" +.NA Old-empire "Differences from 1.2 to UCB Empire" +.LV Expert +.s1 +.ce +\*(bFUCB Empire Version 0.9.24 - Update for Version 1.2 Players\*(pF +.s1 +So you want to try the New Empire Huh? +.s1 +Okay, I have written this document with YOU in mind! +Welcome to the University of California at Berkeley's Empire! +(From now on called UCB Empire). +There are a whole bunch of changes in the game +since we last played, so I need to bring you up to date. +.s1 +Our OLD EMPIRE game was Version 1.2 - +written way back in the 70's by Peter Langston, +when he was going to College like we are! +But Empire has come along way since then - +and what many have considered the REAL EMPIRE was released in 1985 - +containing the final version of Peter Langston's Empire game. +It still is considered the \*QStandard\*U. +But in 1986 the \*Qcomputer brains\*U at Berkeley +decided to play around with the Source Code +and create their own \*Qenhanced\*U version of the game. +Hence \*QBerkeley Empire\*U was created.... +.s1 +.ce +\*(bFChanges from Version 1.2\*(pF +.s1 +(Please keep in mind that these are only a FEW on the changes - +you're going to have to read the Manual and use the INFO command +to get a REAL good idea on what you should read up on - +DON'T depend on this list to tell you everything you need to know) +.s1 +There is an \*Qannounce\*U command - +this command sends a Telegram to EVERYONE in the game - +and you can make an \*Qannouncement\*U to the World. +.s1 +In the OLD game - +you simply dug up ORE and sent it to the Shell, Defense, etc. +factory to have it processed into something else +(make guns, shells, etc). +.s1 +But in the NEW game - sectors are a lot more complex. +For one thing curtain sectors CAN'T even PRODUCE +until your country has reached a given TECH level. +These sectors are currently: +.s1 +Shell Factories (need at least 20 TECH) +Gun Factories (need at least 20 TECH) +Petroleum Plants [ for Airplane Fuel ] (need at least 20 TECH) +Uranium Mines (need at least 40 TECH) +.s1 +Other sectors can produce normally, +even though your TECH level is still 0. +Keep in mind that you CAN DESIGNATE the ABOVE sectors - +but they won't produce until you reach the desired TECH LEVEL. +.s1 +Also, it takes more \*QMaterials\*U +to make 1 Unit of a finished product. +By this I mean that to make approximately \*Q1 SHELL\*U +at your shell factory, you'd have to have: +3 Dollars (in the treasury), +2 LCM, 1 HCM, and at least 20 TECH Level. +.s1 +LCM is Light Construction Materials, +HCM is Heavy Construction Materials, +and I discussed the TECH Level problem (above). +To fully understand this concept - +please see \*Qinfo Products\*U and \*Qinfo Sector-types\*U. +.s1 +FORTS - have been improved. +It used to be in OLD Empire that you had to use the DEFEND command +to say which sectors you wanted to DEFEND with the guns from your fort. +But in the NEW Empire - +your forts will fire on ANY enemy attacker +as long as the attacker is within the guns' +range when the \*Qattack\*U was made. +Hence - no more DEFEND command. +.s1 +FOOD - In the OLD Empire you didn't have to worry about it - +the people fed themselves. +But in the NEW Empire - +there is a new sector designation called \*Qa\*U for agribusiness. +These are farms that make food and you have to transport that food +to other sectors that don't grow food or those sectors will starve. +**NOTE** that in the \*QFERTILITY\*U rating in the \*QCENSUS\*U report - +only those with HIGH Fertility ratings can successfully grow food. +If the FERTILITY rating is in the 10-30% - BE CAREFUL - they +may not be able to grow enough food to sustain even themselves! +Food is also a great Commodity to \*QSELL\*U (hint,hint!) +.s1 +WEATHER - There ISN'T ANY! +(no more rainy days :-) +Although judging from the way Berkeley has been improving the game - +it won't be long till they do fix it. +Can you imagine what weather will be like if they update it +like the did the \*Qplanes\*U! +Thunderstorms, tornadoes, hurricanes, earthquakes, volcanos, etc. +BUT FOR NOW - THERE IS NO WEATHER - Atmosphere is stuck at +\*Q0\*U - clear days! +.s1 +NEXT UPDATE (how will I know when it is supposed to Happen?) - +EMPIRE will always tell you when the NEXT UPDATE is scheduled +by using the VERSION command. +VERSION will also tell you how much food will grow per-update and +also things like - how much food you people eat per update - etc. +.s1 +MAP CHANGES - +in the OLD Empire you could move u)p, l)eft, r)ight, d)own, etc - +but now you have to move in DIAGONALS - +you'll get used to it - +the world is set up like this so the game can handle +more SECTORS per world. +Basically means that the MAP display is more condensed - +and you'll be able to see more sectors on a MAP display +than ever before. +.NF +0.2i +A few new SECTOR-DESIGNATIONS have been added: + + BASICS INDUSTRIES MILITARY / SCIENTIFIC + . sea d defense plant t technical center + ^ mountain i shell industry f fortress + s sanctuary m mine r research lab + / wasteland g gold mine n nuclear plant + - wilderness h harbor l library/school + c capital w warehouse e enlistment center + p park u uranium mine ! headquarters + COMMUNICATIONS * airfield FINANCIAL + + highway a agribusiness b bank + ) radar installation o oil field + j light manufacturing + # bridge head k heavy manufacturing + = bridge span % refinery +.FI +PLEASE! +Fully READ the \*Qinfo Sector-types\*U +.s1 +I haven't got time to go through all of them - +but I will point out a few of them that might be unfamiliar to you. +.s1 +PARKS - these are special because they convince your people that +they should ENLIST and go out and fight for you! +Lots of fun - gotta have one of these to keep the ENLISTMENT rate high. +.s1 +URANIUM MINE - I forgot to add this above with the other Commodities - +with the Commodities \*QFERTILITY\*U, \*QOIL\*U, \*QGOLD\*U, +\*QMINE\*U - +there is also \*QURANIUM\*U. +Uranium is the most UNCOMMON natural resource +and hence those that have a deposit of it +should be careful to guard it well. +When URANIUM is dug up it becomes \*Qradioactive Matter\*U - +you then deliver the Radioactive Matter to the Nuclear Plant +and have it converted into - you guessed it - NUKES! +Be aware, however, that you must have a HIGH Tech level +to make nukes - +and it is going to take you a LONG TIME to get to this point. +.s1 +REFINERY SECTORS: These are where the OIL you make +is turned into PETROL(-eum) for your various AIRPLANE needs. +Planes run on PETROL and the refinery sectors make PETROL out of OIL. +You then have to deliver the PETROL to your Airports for use... +.s1 +LIBRARY/SCHOOL: Obviously your people aren't very smart :-) +As it is your going to need to educated them. +Education will increase CROP yields and also help with TECHNOLOGY. +see \*Qinfo education\*U. +.s1 +.ce 1 +\*(bFWorld Updates\*(pF +.s1 +In the OLD EMPIRE - updates weren't handled in a FAIR way. +If you created a 0% FORT before you logged out of Empire - +it would REMAIN a 0% FORT until you logged back into Empire - +and if your on a LONG weekend that could have meant +that you would be WIPED OUT!!!! +.s1 +In the NEW EMPIRE - +updates are handled by an independent program +called the \*QTransaction Manager\*U. +This program runs independently of EMPIRE +and runs at 4 hours intervals, +updating the game constantly. +That means that you enemies will be updated just as often as you ARE - +and may make them think a little more carefully about attacking you. +The CURRENT update times are: +.s1 +2am, 6am, 10am, 2pm, 6pm, 10pm (In the local time zone) +.s1 +NO OTHER UPDATES ARE POSSIBLE - except at these times. +What is updated is all Mobility, Food Production, +Shell & Factory Production, Ship Plane and Sector Efficiency, +and EVERYTHING that \*Qupdate\*U used to do. +(hence there is NO Update Command). +Everyone is updated at the SAME TIME! +.s1 +.ce +\*(bFOther Things That Might be of Interest\*(pF +.s1 +Terrorists! - +(real trouble makers, but great for setting on your enemies - +they blow up things and convert followers!) +.s1 +SHOOT - it is now possible to SHOOT your civilians +(captured enemy ones) or your own :-) +God knows why you would but... +sometimes the conquered people are REAL radical +and it DOES become necessary +.s1 +SELL - you can sell your goods on the OPEN Market - +and set PRICE MULTIPLIERS so that your enemies +HAVE to buy at a BIG mark up - +but your friends can still buy your good cheap! +.s1 +Okay - you've been waiting for it - so here it is! +The new line of Ships, Planes and Nukes for Empire: +.ce +\*(bFThe Ships\*(pF +.NF + $$$ lcm hcm tec def spd vis spy rng fir + 350 20 10 40 30 50 10 4 1 1 patrol boat + 200 25 15 0 10 20 15 2 0 0 fishing boat + 550 25 25 20 60 30 20 3 1 1 minesweep + 1100 25 35 20 80 35 20 4 3 2 destroyer + 2200 40 30 70 30 25 2 3 2 2 submarine + 4000 40 40 50 40 25 60 3 0 0 tanker + 3000 40 50 40 100 30 30 5 6 3 heavy cruiser + 600 60 40 0 50 25 35 3 0 0 cargo ship + 2000 50 50 120 20 10 80 4 0 0 oil derrick + 4400 70 65 60 80 30 35 8 2 2 aircraft carrier + 4000 55 65 50 127 30 35 6 8 4 battleship + 1500 60 30 120 15 40 15 5 0 0 fishing trawler + 4000 90 60 320 30 40 1 3 0 8 nuclear sub + 1200 40 40 70 30 30 30 2 0 0 landing ship + 2500 40 40 220 20 70 17 5 0 0 hydrofoil + 6000 80 30 280 20 30 20 10 0 0 radar center +.FI +.s1 +.NF + food civ mil sh gun pln dst pet oil + 30 0 10 10 2 0 0 0 0 patrol boat + 100 30 5 0 0 0 0 0 0 fishing boat + 25 0 25 60 2 0 0 0 0 minesweep + 80 0 80 40 4 0 0 0 0 destroyer + 25 0 25 25 4 0 0 0 0 submarine + 200 30 5 0 0 0 0 990 990 tanker + 100 0 120 60 6 0 0 0 0 heavy cruiser + 900 50 50 300 50 0 900 0 0 cargo ship + 300 80 80 0 0 0 0 0 200 oil derrick + 180 0 350 350 4 8 0 500 0 aircraft carrier + 300 0 200 100 8 0 0 0 0 battleship + 120 25 5 0 0 0 100 25 0 fishing trawler + 500 30 30 25 4 8 0 60 0 nuclear sub + 300 0 400 0 0 0 0 0 0 landing ship + 20 60 30 0 0 0 0 0 0 hydrofoil + 60 0 20 0 0 0 0 0 0 radar center +.FI +.s1 +The column headings have the following meanings: +.in \w'food\0\0'u +.L $$$ +money required to build it +.L lcm +light construction materials required to build it +.L hcm +heavy construction materials required to build it +.L tec +technology required to build it +.L def +defensive armament of the ship +.L spd +the distance/mu for moving (in relative units) +.L vis +how visible the ship is, (relative units) +.L spy +how far the ship can see, +(i.e. how good the communication equipment is), +again in relative units +.L rng +twice the distance the guns can fire, +(assuming a high technology level) +.L fir +the number of guns the ship can fire at once +.L food +the amount of food the ship can carry +.L civ +the number of civilians the ship can carry +.L mil +the number of military the ship can carry +.L sh +the number of shells the ship can carry +.L gun +the number of guns the ship can carry +.L pln +the number of planes the ship can carry +.L dst +the amount of gold dust the ship can carry +.L pet +the amount of petrol the ship can carry +.L oil +the amount of oil the ship can carry +.L aml +the amount of lcms the ship can carry +.L amh +the amount of hcms the ship can carry +.in +.s1 +Note that some ship differences are not listed in these tables. +.s1 +Only fishing boats and fishing trawlers accumulate food by fishing. +.s1 +Only oil derricks accumulate oil at sea. +.s1 +Only destroyers will drop depth charges, +and only destroyers can see and fire at submarines. +.s1 +Only submarines can fire torpedos. +.s1 +Only destroyers and heavy cruisers can lay mines. +.s1 +Only minesweeps can reclaim mines from the sea. +.s1 +Only nuclear submarines can carry nuclear missiles. +.s1 +Only aircraft carriers can launch and retrieve air strikes. +.s1 +Only cargo ships can carry lcms (1400) and hcms (900). +.s1 +.SA "coastwatch, fire, load, lookout, mine, navigate, tend, torpedo, fly, Server" diff --git a/info/Server/Options.t b/info/Server/Options.t new file mode 100644 index 00000000..728f7460 --- /dev/null +++ b/info/Server/Options.t @@ -0,0 +1,70 @@ +.TH Server OPTIONS +.NA Options "Server options" +.LV Expert +.nf +The following options are from KSU code: + +SHOWPLANE: planes/units on ships/units up for trade are shown +PINPOINT(etc): Missile exist which target ships instead of sectors +SAIL: another wait to automatically move ships (may also be buggy) +NUKEFAIL(etc): nukes on missiles that explode in launching may detonate +SHIPNAMES: ships may be named +DEMANDUPDATE: updates may be allowed on player demand +UPDATESC(etc): updates can be controlled by the 'hours' file. NITP + +The following options were introduced in the Chainsaw server: + +EASY_BRIDGES: bridges can be built from any sector +SUPER_BARS: gold bars aren't destroyed by shelling or bombing +ALL_BLEED: you get tech bleed from all countries, not just allies +DRNUKE: research is required to make nukes +SLOW_WAR: War declaring takes time. No land attacks unless at war. +SNEAK_ATTACK: If SLOW_WAR, allows you to pay money and sneak one attack. +NOMOBCOST: ships pay 0 mob to fire. Subs pay 1/2 a sect's movement cost +TRADESHIPS: you can build/nav/scuttle trade ships to make money +FUEL: ships need fuel to gain mobility +RES_POP: Research affects max sector population. +NOFOOD No food is required. +BLITZ: Turns NOFOOD option on and players get infinite BTU's. +NONUKES: No nuclear weapons +NEWPOWER: New power formula. See "info power". +NO_PLAGUE: Plague is disabled. +NEW_STARVE: UW's starve, then civs, then mil +NEW_WORK: Work is changed in proportion to the # of civs moved +GRAB_THINGS: Units will grab things they need to build +NEUTRON: Enables neutron bombs +FALLOUT: Sectors are damaged by radiation for a few updates after blast + +The following options were introduced in the Empire2 Server: + +HIDDEN: Hides information about countries you haven't contacted +LOSE_CONTACT: In HIDDEN, lose contact after a few updates +ORBIT: Satellites can orbit the planet +BIG_CITY: 'c' sectors cost $, lcm, hcm to build and hold 10x civs +INTERDICT_ATT Interdict units & mil as they move in after an attack + +The following options were introduced in the Empire4 Server: +BRIDGETOWERS: You can build bridge towers, which allow you to build + bridges from them. +DEFENSE_INFRA: Use the new defensive infrastructure. Otherwise, use + sector efficiency for defensive values. +GODNEWS: The world is told via news when deities are giving or taking + things from players. +GO_RENEW: Gold and Oil are renewable resources. +MOB_ACCESS: Allows real-time updating of mobility. +MARKET: Time-delay market and trade. +LOANS: Allows S&L type interaction between countries. +LANDSPIES: Creates land unit style spies. +PLANENAMES: Shows real names for planes. +NO_FORT_FIRE: Forts cannot fire. +NO_LCMS: The game doesn't need lcms to be played. +NO_HCMS: The game doesn't need hcms to be played. +NO_OIL: The game doesn't need oil to be played. +SHIP_DECAY: Allows ships to decay when at sea with not enough crew. +TECH_POP: Technology costs more to make as your civilian population + grows past 50,000 civilians. +TREATIES: Sign treaties with your friends and enemies, and breaking of + them is reported in the news. +.fi + +.SA "Hidden, Server" diff --git a/info/Server/Wolfpack.t b/info/Server/Wolfpack.t new file mode 100644 index 00000000..3e11b209 --- /dev/null +++ b/info/Server/Wolfpack.t @@ -0,0 +1,13 @@ +.TH Server "Wolfpack Code" +.NA Wolfpack "The Wolfpack project" +.LV Expert +.s1 +There have been several changes/fixes made to the Empire3 code in the +new Empire4 Server. This outlines the various changes and how they +will affect you, the player. These were coded as the Wolfpack project, +and bug-reports should be sent to . +.s1 +See the "info Options" "info Empire4" for more detailed information on +the Wolfpack project. +.s1 +.SA "Options, Empire4, Server" diff --git a/info/Subjects/MakeSrcs b/info/Subjects/MakeSrcs new file mode 100644 index 00000000..1ff4c6eb --- /dev/null +++ b/info/Subjects/MakeSrcs @@ -0,0 +1 @@ +INFOSRCS=Combat.t Commodities.t Communication.t Deity.t Detection.t Diplomacy.t Distribution.t Introduction.t LandUnits.t Loans.t Maps.t Market.t Missions.t Moving.t Nation.t Obsolete.t Occupation.t Planes.t Playing.t Populace.t Production.t Sectors.t Server.t Ships.t TOP.t Update.t diff --git a/info/Subjects/Makefile b/info/Subjects/Makefile new file mode 100644 index 00000000..032035e5 --- /dev/null +++ b/info/Subjects/Makefile @@ -0,0 +1,62 @@ +# +# Empire - A multi-player, client/server Internet based war game. +# Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, +# Ken Stevens, Steve McClure +# +# 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 2 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, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# --- +# +# See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the +# related information and legal notices. It is expected that any future +# projects/authors will amend these files as needed. +# +SRCDIR = ../.. +NROFF = nroff +TROFF = troff + +INFOSRCS = empty + +INFOOBJS = $(INFOSRCS:.t=) + +HTMLOBJS = $(INFOSRCS:.t=.) + +include MakeSrcs + +.SUFFIXES: .t + +all: + @echo INFOSRCS=`echo *.t` > MakeSrcs + @make nroffs + @echo Done. + +html: + @echo INFOSRCS=`echo *.t` > MakeSrcs + @make htmlfiles + @echo Done. + +htmlfiles: $(HTMLOBJS) + +nroffs: $(INFOOBJS) + +$(INFOOBJS): + @$(NROFF) $(SRCDIR)/info/CRT.MAC $@.t | awk -f $(SRCDIR)/info/Blank.awk > $(SRCDIR)/info.nr/$@ + @echo Created $(SRCDIR)/info.nr/$@ + +$(HTMLOBJS): + @perl $(SRCDIR)/info/subj2html.pl $@t > $(SRCDIR)/info.html/$@html + @echo Created $(SRCDIR)/info.html/$@html + + diff --git a/info/TROFF.MAC b/info/TROFF.MAC new file mode 100644 index 00000000..40c5e68e --- /dev/null +++ b/info/TROFF.MAC @@ -0,0 +1,41 @@ +.\" EMPIRE MACRO FILE FOR TROFF +.\" normal Font - Times Roman +.ds nF \\fR +.\" Normal font name: must match value of nF! +.ds N R +.\" example Font - Times Roman +.ds eF \\fC +.\" Example Font name (used with .cs requests): must match value of eF! +.ds EF C +.\" bold Font - Times Bold +.ds bF \\fB +.\" italic Font - Times Italic +.ds iF \\fI +.\" large Font - Times Roman +.ds lF \\fR +.\" previous Font - A special way to switch +.ds pF \\fP +.\" Character spacing string +.ds cS 26 +.\" Start out correctly +.nr CS 0 +.\" Special strings for special characters, including smart quotes. +.ds <= \(<= +.ds >= \(>= +.ds Q `` +.ds U '' +.pl 11i \" Page length - environment 0 +.ll 6i \" Line legnth +.lt 5i \" Title length +.po 0.9i \" Page offset +.ev 1 +.ll 6i \" Line legnth - environment 1 +.lt 5i \" Title length +.po 0.9i \" Page offset +.ev +.ev 2 +.ll 6i \" Line legnth - environment 2 +.lt 5i \" Title length +.po 0.9i \" Page offset +.ev +.so INFO.MAC \" Read in INFO.MAC macros diff --git a/info/checklist.pl b/info/checklist.pl new file mode 100644 index 00000000..7a2471dc --- /dev/null +++ b/info/checklist.pl @@ -0,0 +1,69 @@ +#!/usr/local/bin/perl +# +# checklist.pl +# +# By Ken Stevens +# +# HOW TO RUN IT: +# In empire, redirect the output of the player "list" command to a file called +# "player.list". Similarly, make a file listing deity commands and call it +# deity.list. Put both these files in this directory, and then run this script +# to check which Empire commands need to be documented. +# + +open(LIST, ") { + last if /^ /; +} + +while() { + last if /^For further info on command syntax see/; + $_ = substr($_, 5); + ($com) = split; + push (@list, $com); +} +close LIST; + +push(@list, "break"); + +open(LIST, ") { + last if /^ /; +} + +while() { + last if /^For further info on command syntax see/; + $_ = substr($_, 5); + ($com) = split; + push (@list, $com); +} +close LIST; + +open(OBSOLETE, ") { + push(@obsolete, $1) if /^.L (\S+)$/; +} + +close OBSOLETE; + +open (LS, "ls Commands|"); + +while () { + chop; + next unless /^(\S+).t/; + push(@Commands, $1); +} +close LS; + +print "In list but not Commands:\n"; +for $l (@list) { + print " $l\n" unless grep (/^$l$/, @Commands); +} +print "In Commands but not list:\n"; +for $c (@Commands) { + print " $c\n" unless grep(/^$c$/, @list) || grep(/^$c$/, @obsolete); +} diff --git a/info/deity.list b/info/deity.list new file mode 100644 index 00000000..61a79d7f --- /dev/null +++ b/info/deity.list @@ -0,0 +1,111 @@ +list + Current EMPIRE Command List + ------- ------ ------- ---- +Initial number is cost in B.T.U. units. +Next 2 chars (if present) are: +$ - must be non-broke c -- must have capitol +Args in [brackets] are optional. +All-caps args in have the following meanings: + :: a number in unspecified units + :: a commodity such as `food', `guns', etc + :: a commodity such as `food', `guns', etc + :: an item type such as `ship', `plane', etc +0 accept [as-COUNTRY] +0 add +0 announce {message} +0 army +0 bdes +0 bestpath +0 bestdistpath +0 bmap +1 budget [ ] +1 buy [ ] +0 bye {log-off} +0 capitol +0 cargo +1 cede +0 census +0 change +2 collect +0 commodity +1 consider +0 country +0 cutoff +1 deliver <[+|-]thresh> +1 designate +0 disable +0 dissolve +1 distribute +0 dump +0 edit +0 enable +0 execute +0 financial +0 flash [] +0 fleetadd +0 force +1 fortify +1 fuel [TENDER] +0 give +0 headlines [days] +0 hidden +0 info +0 land +0 lcargo +0 ledger +0 level +0 list of commands +0 lmap +0 mail +0 market [COMM] +0 map +1 mult [COUNTRY] +0 name +0 nation +0 newcap [] +0 neweff +0 newspaper [days] +0 nuke +1 offer [ ] +0 offset +1 origin +0 path +0 payoff +0 plane +0 pmap +0 power [["new" []] | ["country" ]] +0 production +0 quit +0 read +0 realm [] +0 relations [as-COUNTRY] +2 reject +1 repay +0 report +0 resource +1 route +0 sect +1 sell +1 set +0 setsector +0 setresource +0 ship +0 show <"build"|"stats"|"cap"> +0 shutdown [] +0 smap +0 starvation +0 telegram +0 territory +1 threshold +1 trade +0 turn <"on"|"off"|"mess"> +0 update +0 version +0 wait +0 wall [] +1 wingadd +1 wipe +0 wire +0 wmail +0 zdone +For further info on command syntax see "info syntax". diff --git a/info/emp2html.pl b/info/emp2html.pl new file mode 100644 index 00000000..249c4180 --- /dev/null +++ b/info/emp2html.pl @@ -0,0 +1,167 @@ +#!/usr/local/bin/perl + + +$[ = 1; # set array base to 1 + +line: while (<>) { + chop; # strip record separator + @Fld = split(' ', $_, 9999); + +procline: + if (/^\.TH/) { + $str=$Fld[3]; + for ($i=4;$i <= $#Fld; $i++) { + $str .= " " . $Fld[$i]; + } + $str = &htmlify($str); + printf("%s : %s

%s : %s

\n", + $Fld[2],$str,$Fld[2], $str); + next line; + } + + if (/^\.SY/) { +# $i = $_ =~ "\"" && ($RLENGTH = length($&), $RSTART = length($`)+1); +# $str = substr($_, $i + 1, length($_) - $i - 1); + $str = substr($_,5); + $str = &htmlify($str); + printf "[##:##] %s

\n", $str; + next line; + } + + if (/^\.EX/) { + $str = substr($_, 5); + printf "
[##:##] %s

\n", &htmlify($str); + next line; + } + + if (/^\.L/) { + $str = substr($_, 4); + printf "

%s

\n", &htmlify($str); + next line; + } + + if (/^\.(NF|nf)/) { printf (("

\n")); next line;    }
+    if (/^\.(FI|fi)/) {	printf (("

\n")); next line; } + if (/^\.s3/) { printf (("

\n")); next line; } + if (/^\.s1/) {printf (("


\n")); next line; } + if (/^\.br/) { printf "
\n"; next line; } + if (/^\.SA/) { + @a = split('[: ",.]+'); + + printf("See also : %s\n",&anchor($a[3]) ); + for ($i = 4; $i <= $#a ; ($i)++) { + printf(", %s\n",&anchor($a[$i])); + } + + while (<>) { + chop; # strip record separator + @a = split('[: ,.]+'); + @Fld = split(' ', $_, 9999); + if (/^\./) { goto procline; } + for ($i = 1; $i <= $#a ; ($i)++) { + printf(", %s\n",&anchor($a[$i])); + } + } + + exit(0); + } + + if (/^\./) { next line; } + + if (/^(See also|See Also|see also)/) { + @a = split('[: ,.]+'); + + printf("See also : %s\n",&anchor($a[3]) ); + for ($i = 4; $i <= $#a ; ($i)++) { + printf(", %s\n",&anchor($a[$i])); + } + + while (<>) { + chop; # strip record separator + @a = split('[: ,.]+'); + @Fld = split(' ', $_, 9999); + if (/^\./) { goto procline; } + for ($i = 1; $i <= $#a ; ($i)++) { + printf(", %s\n",&anchor($a[$i])); + } + } + + exit(0); + } + + printf "%s\n", &htmlify($_); +} + +#sub anchor { +# local($_) = @_; +# $file = $_ . ".t"; +# if (-r $file) { +# return ("" . $_ . ""); +# } else { +# return ( " " . $_ . " "); +# } +#} + +sub anchor { + local($_) = @_; + local(@file,$file); + $file = $_ . ".t"; +# if (-r $file) { + if (1) { + $file =~ s/.t$/.html/; + return ("$_"); + } else { + @file = <$_*t>; + if (@file) { + warn "Expanding $_ to $file[$[]\n"; + $file[$[] =~ s/.t$/.html/; + return ("$_"); + } else { + warn "Unable to link $_\n"; + return ( "$_"); + } + } +} + + +# Translate HTML special characters into escape sequences +sub htmlify { + local($_) = @_; + s/^\"(.*)\"$/$1/; + s/\\&//g; # a nothing character + s/\&/&/g; + s/\/>/g; + while (@a = /(\\\*Q)([A-Za-z0-9\-\.]+)(\\\*U)/) { + /(\\\*Q)([A-Za-z\-]+)(\\\*U)/; + $_ = $` . &anchor($a[2]) . $'; + } + while (@a = /(\\\*Q)(\"info )([A-Za-z0-9\-\.]+)(\\\*U)/) { + /(\\\*Q)(\"info )([\w\-\.]+)(\\\*U)/; + $_ = $` . "\"info " . &anchor($a[3]) . $'; + } + while (@a = /(\"info )([A-Za-z0-9\-\.]+)/) { + /(\"info )([\w\-\.]+)/; + $_ = $` . "\"info " . &anchor($a[2]) . $'; + } + s/\\\*Q//g; + s/\\\*U/<\/em>/g; + s/\\fI//g; + s/\\fR/<\/em><\/em>/g; + s/\\fB//g; + s/\\fP/<\/strong><\/em>/g; + s/\\\*\(bF//g; # bold font + s/\\\*\(pF/<\/strong><\/em>/g; # pica font + s/\\\*\(nF/<\/strong><\/em>/g; # normal font + s/\\\*\(iF//g; # italic font + s/\\\(mu/x/g; # multiply symbol + s/\\ / /g; # should be non breaking space + return $_; +} + +#sub htmlify { +# local($str) = @_; +# $str; +#} + + diff --git a/info/info.pl b/info/info.pl new file mode 100644 index 00000000..1b51ba4b --- /dev/null +++ b/info/info.pl @@ -0,0 +1,329 @@ +#!/usr/local/bin/perl +# +# info.pl +# +# Create Subjects/Subject.t files from the Info Pages. +# +# written by Ken Stevens +# +# +# DESCRIPTION: +# info.pl reads all of the info pages and creates a table of contents +# for them organized by subject. An info page belongs to a subject if +# that subject appears as an entry in the .SA ("SEE ALSO") field of the +# info page _and_ that entry is not the name of another info page. +# +# For example, the .SA field of headlines.t contains the entries +# "newspaper" and "Communication". Since there's already an info page +# called "newspaper.t", but there is no "Communication" info page, then +# the headlines info page is considered to be a member of the +# Communication subject. +# +# An info page may belong to more than one subject, and if it belongs +# to no subject, then its subject will be set to the name of the subdirectory +# it is in (e.g. the Server and Information info pages work this way). +# +# The output of this script is a bunch of files in the "Subjects" +# subdirectory. The file Subjects/TOP.t is the toplevel table of +# contents and lists all of the subjects. This is what the player +# sees when they type "info". Then for each subject, a +# Subjects/Subject.t file is created, listing all of the info pages that +# belong to that subject. +# +# INSTALLATION: +# info.pl requires perl5 to run. If you don't have version 5 of perl, then +# you'll either have to install it, or you'll have to get someone to create +# your Subjects.t files for you. +# +# HOW TO RUN IT: +# Type "info.pl" at the unix prompt. +# +# BUG REPORTS: +# mail your bug-reports and comments to: +# Ken Stevens + +# --- Glossary --- +# item.t An info page file +# item An info page +# Subject An entry in a SEE ALSO entry which is not an item +# subdirectory Where the info files are kept +# +# --- Global variables --- +# @dirs Subdirectories of info directory containing item.t files +# @Subjects Subjects which already exist (as Subjects/Subject.t) +# $dir The current subdirectory we're working in +# $filename The name of an item.t file +# $filedir{$filename} +# The subdirectory item.t is in +# F Filehandle for item.t +# $desc{$filename} +# A one line description of the item (second arg to .NA) +# $level{$filename} +# The difficulty level of the page. At present either +# Basic or Expert. +# $see_also{$filename} +# A list of SEE ALSO items for the file (.SA argument) +# $subj A subject +# SUBJ Filehandle for Subject.t +# $subject{$subj}{$dir} = "item1\nitem2\n..." +# Items in that subject organized by directory. +# $largest{$sub} The largest item in that subject (used for column formatting) +# TOP Filehandle for Subjects/TOP.t +# @rowsubj List of subjects +# @colsubj List of subjects organized into 3 columns +# +# --- Functions --- +# +# read_subjects Get list of current subjects +# parse_files Parse all the item.t files in one $dir +# parse_file Check the .TH, .NA, and .SA fields & parse them +# parse_see_also Create %subject from %see_also +# set_subject Add a new entry to %subject and possibly to %largest +# create_subj Create a Subject.t file +# create_subjects Remove the old Subject.t files and create new ones +# flush_subj Print a row of Subjects to TOP +# error Print an integrity error to STDERR and exit with code 1. + +eval("require 5"); # Test for perl version 5 +die "info.pl requires version 5 of perl.\n" if $@; + +# These are the directories which contain item.t files: +@dirs = ('Commands', 'Concepts', 'Server', 'Introduction'); + +# Get list of current subjects +&read_subjects; + +# Parse the item.t files in each info directory +for $dir (@dirs) { + &parse_files; +} + +# Create %subject from %see_also +for $filename (sort keys %filedir) { + &parse_see_also; +} + +# Create the Subject.t files +&create_subjects; + +exit 0; + +# Get list of current subjects +sub read_subjects { + open (LS, "ls Subjects|"); + + while () { + chop; + next unless /^(\S+).t/; + push(@Subjects, $1); + } + close LS; +} + +# Parse all the item.t files in one $dir with lots of integrity checks +sub parse_files { + local ($type) = $dir; + chop($type) unless $type eq "Server" || $type eq "Introduction"; + + if (defined $filedir{$dir}) { + $filename = $dir; + &error("Illegal filename (it is a directory name)."); + } elsif (defined $filedir{$type}) { + $filename = $type; + &error("Illegal filename (it is a type name)."); + } + + open (LS, "ls $dir|"); + + while () { + chop; + next if /^GNUmakefile$/; + next if /^Makefile$/; + next if /^MakeSrcs$/; + $filename = $_; + &parse_file; + } + close LS; +} + +# Check the .TH, .NA, and .SA fields. +# Parse .NA into %desc and .SA into %see_also +sub parse_file { + $filename =~ s/\.t$//; + + if (grep (/^$filename$/, @dirs)) { + &error("Illegal filename. $filename is a name of a subdirectory of the info directory."); + } + if ($filedir{$filename}) { + &error("$filename.t is in both $filedir{$filename} and $dir"); + } elsif (grep (/^$filename$/, @Subjects)) { + &error("Illegal filename. $filename is already a Subject name."); + } else { + $filedir{$filename} = $dir; + } + + die "Can't open $dir/$filename.t\n" unless open(F, "<$dir/$filename.t"); + + $_ = ; + if (/^\.TH (\S+) (\S.+\S)$/) { + if ($1 ne $type) { + &error("First argument to .TH was '$1' but it should be '$type'"); + } + if ($type eq "Command" && $2 ne "\U$filename") { + &error("Second argument to .TH was '$2' but it should be '\U$filename'"); + } + } else { + &error("The first line in the file must be a .TH entry"); + } + $_ = ; + if (/^\.NA (\S+) "(\S.+\S)"$/) { + if ($filename ne $1) { + &error("First argument to .NA was '$1' but it should be '$filename'"); + } + $desc{$filename} = $2; + } else { + &error("The second line in the file must be an .NA entry"); + } + $_ = ; + if (/^\.LV (\S+)$/) { + if ($1 ne 'Basic' && $1 ne 'Expert') { + &error("The argument to .LV was '$1' but it must be either 'Basic' or 'Expert'"); + } + $level{$filename} = $1; + } else { + &error("The third line in the file must be a .LV entry"); + } + while () { + last if /^\.SA/; + } + if ($_) { + if (/^\.SA "([^\"]*)"/) { + $see_also{$filename} = $1; + } else { + &error("Incorrect .SA Syntax. Syntax should be '.SA \"item1, item2\"'"); + } + while () { + &error("Multiple .SA entries. Each file may contain at most one .SA entry") if /^\.SA/; + } + } + close F; +} + +# Create %subject from %see_also +sub parse_see_also { + local (@see_also) = split(/, /, $see_also{$filename}); + local ($dir) = $filedir{$filename}; + local ($found); # Does this item belong to any Subject? + + for (@see_also) { + if (!(defined $filedir{$_})) { # is this entry a subject? + &set_subject; + $found = 1; + } + } + + &error("No Subject listed in .SA field") unless $found; +} + +# Add a new entry to %subject and possibly to %largest +sub set_subject { + $subject{$_}{$dir} .= "$filename\n"; + $largest{$_} = $filename if length $filename > length $largest{$_}; + $largest{$_} = $dir if length $dir > length $largest{$_}; +} + +# Create a Subject.t file +sub create_subj { + print " Creating Subjects/$subj.t\n"; + print "WARNING: $subj is a NEW subject\n" unless + grep(/^$subj$/, @Subjects); + die "Unable to write to Subjects/$subj.t\n" unless + open(SUBJ, ">Subjects/$subj.t"); + + print SUBJ '.\" DO NOT EDIT THIS FILE. It was automatically generated by info.pl'."\n"; + print SUBJ ".TH Subject \U$subj\n"; + $largest{$subj} =~ s/-/M/g; + print SUBJ ".in \\w'$largest{$subj}XX\\0\\0\\0\\0'u\n"; + for $dir (keys %{$subject{$subj}}) { + print SUBJ ".s1\n"; + for (split(/\n/, $subject{$subj}{$dir})) { + print SUBJ ".L \"$_ "; + if ($level{$_} eq 'Basic') { + print SUBJ "* \"\n"; + } else { + print SUBJ " \"\n"; + } + print SUBJ "$desc{$_}\n"; + } + } + print SUBJ <" where is +one of the subjects listed above. Subjects marked by * are the most +important and should be read by new players. +EOF + close SUBJ; +} + +# Remove the old Subject.t files and create the Subject.t files and TOP.t +sub create_subjects { + print " Removing Subjects/*.t\n"; + `rm -f Subjects/*.t`; + print " Creating Subjects/TOP.t\n"; + die "Can't open Subjects/TOP.t" unless open(TOP, ">Subjects/TOP.t"); + print TOP < 1; + } + &flush_subj; + print TOP <" where is one of the subjects listed above. +For a complete list of all info topics, type "info all". +EOF + close TOP; +} + +# Print a row of subjects to TOP +sub flush_subj { + return unless $#subj >= 0; + print TOP " "; + for (@subj) { + printf TOP "%-25s", $_; + } + print TOP "\n"; + @subj = (); +} + +# Print an integrity error message and exit with code 1 +sub error { + local ($error) = @_; + + print STDERR "Error on line $. of $filedir{$filename}/$filename.t:\n"; + print STDERR "$_"; + print STDERR "\n" unless /\n$/; + print STDERR "$error\n"; + exit 1; +} diff --git a/info/ls2html.pl b/info/ls2html.pl new file mode 100644 index 00000000..6a5be1b6 --- /dev/null +++ b/info/ls2html.pl @@ -0,0 +1,8 @@ +#!/usr/local/bin/perl + +printf("
\n");
+while (<>) {
+    s/([\w\.\-]+)\.html/$1<\/a>/g;
+    print;
+}
+printf("
\n"); diff --git a/info/player.list b/info/player.list new file mode 100644 index 00000000..f3bef86b --- /dev/null +++ b/info/player.list @@ -0,0 +1,148 @@ +list + Current EMPIRE Command List + ------- ------ ------- ---- +Initial number is cost in B.T.U. units. +Next 2 chars (if present) are: +$ - must be non-broke c -- must have capitol +Args in [brackets] are optional. +All-caps args in have the following meanings: + :: a number in unspecified units + :: a commodity such as `food', `guns', etc + :: a commodity such as `food', `guns', etc + :: an item type such as `ship', `plane', etc +0 accept [as-COUNTRY] +0 announce {message} +3 $c arm +0 army +3 $c assault [ ] +3 $c attack [ ] +0 bdes +0 bestpath +0 bestdistpath +0 bmap +3 $c board +2 $c bomb +1 budget [ ] +1 $c build +0 bye {log-off} +0 capitol +0 cargo +0 census +0 change +1 c coastwatch +0 commodity +2 $c convert +0 country +0 cutoff +2 c declare +1 deliver <[+|-]thresh> +1 $c demobilize +1 designate +1 distribute +1 $c drop +0 dump +2 $c enlist +0 execute +1 $c explore +1 $c fire [TO-SECT | SHIP] +0 flash +0 fleetadd +2 $c fly +1 $c follow +1 fortify +1 fuel [TENDER] +1 $c grind +2 $c harden +0 headlines [days] +0 info +0 land +3 $c launch +0 lcargo +0 level +0 list of commands +1 $c lload +1 $c llookout +0 lmap +2 $c lmine +1 $c load +1 $c lookout +1 $c lradar +1 $c lrange +1 $c lretreat [i|h|b|c] +1 $c ltend +1 $c lunload +0 mail +0 map +1 $c march +2 $c mine +2 $c mission [] +1 $c morale +1 c move +2 $c mquota +1 mult [COUNTRY] +0 name +0 nation +1 $c navigate +0 neweff +0 newspaper [days] +0 nuke +1 $c order +1 origin +3 $c paradrop +0 path +0 payoff +0 plane +0 pmap +0 power ["new"] +0 production +0 $c qorder +0 quit +1 $c radar +1 $c range +0 read +0 realm [] +3 $c recon +1 $c retreat [i|t|s|h|b|d|c] +0 relations [as-COUNTRY] +2 reject +0 report +0 resource +1 route +1 $c sail +1 $c satellite +2 $c scrap +5 c scuttle +0 sect +0 ship +3 $c shoot +0 show <"build"|"stats"|"cap"> +0 smap +1 $c sonar +0 $c sorder +1 $c spy +1 c start +0 starvation +1 c stop +1 $c supply +0 c survey +3 $c sweep +0 telegram +1 $c tend +0 territory +1 c test +1 threshold +3 $c torpedo +1 $c transport <"nuke"|"plane"> [nuketype] +0 $c treaty +1 $c unload +1 $c unsail +0 update +1 $c upgrade +0 version +1 wingadd +1 wipe +0 wire +0 wmail +1 $c work +0 zdone +For further info on command syntax see "info syntax". diff --git a/info/subj2html.pl b/info/subj2html.pl new file mode 100644 index 00000000..034e09ef --- /dev/null +++ b/info/subj2html.pl @@ -0,0 +1,198 @@ +#!/usr/local/bin/perl + + +$[ = 1; # set array base to 1 +$dome = 0; + +line: while (<>) { + chop; # strip record separator + @Fld = split(' ', $_, 9999); + +procline: + if (/^\.TH/) { + $str=$Fld[3]; + for ($i=4;$i <= $#Fld; $i++) { + $str .= " " . $Fld[$i]; + } + $str = &htmlify($str); + printf("%s : %s

%s : %s

\n", + $Fld[2],$str,$Fld[2], $str); + next line; + } + + if (/^\.SY/) { +# $i = $_ =~ "\"" && ($RLENGTH = length($&), $RSTART = length($`)+1); +# $str = substr($_, $i + 1, length($_) - $i - 1); + $str = substr($_,5); + $str = &htmlify($str); + printf "[##:##] %s

\n", $str; + next line; + } + + if (/^\.EX/) { + $str = substr($_, 5); + printf "
[##:##] %s

\n", &htmlify($str); + next line; + } + + if (/^\.L/) { + @a = split('[: ",.]+'); + $str = &anchor($a[3]); + $str = ("$str $a[4]"); + printf("
%s\n", $str); + next line; + } + + if (/^\.s3/) { printf (("

\n")); next line; } + if (/^\.s1/) {printf (("


\n")); next line; } + if (/^\.br/) { printf "
\n"; next line; } + + if (/^\.(FI|fi)/) { printf (("

\n")); $dome = 0; next line; } + if (/^\.(NF|nf)/) { printf (("

\n")); $dome = 1; next line;    }
+
+    if ($dome == 1) {
+	@a = split('[: ",.]+');
+
+	for ($i = 2; $i <= $#a ; ($i)++) {       
+	    printf("%s",&anchor($a[$i]));
+	    for ($j = 0; $j < 20 - length($a[$i]); $j++) {
+		printf(" ");
+	    }
+	}
+        printf("\n");
+	while (<>) {
+	    chop;	# strip record separator
+	    @a = split('[: ,.]+');
+	    @Fld = split(' ', $_, 9999);
+	    if (/^\./) { goto procline; }
+	    for ($i = 2; $i <= $#a ; ($i)++) {       
+		printf("%s",&anchor($a[$i]));
+		for ($j = 0; $j < 20 - length($a[$i]); $j++) {
+		    printf(" ");
+		}
+	    }
+	    printf("\n");
+	}
+	next line;
+    }
+
+    if (/^\.SA/) {
+	@a = split('[: ",.]+');
+
+	printf("See also : %s\n",&anchor($a[3]) );
+	for ($i = 4; $i <= $#a ; ($i)++) {       
+	    printf(", %s\n",&anchor($a[$i]));
+	}
+
+	while (<>) {
+	    chop;	# strip record separator
+	    @a = split('[: ,.]+');
+	    @Fld = split(' ', $_, 9999);
+	    if (/^\./) { goto procline; }
+	    for ($i = 1; $i <= $#a ; ($i)++) {       
+		printf(", %s\n",&anchor($a[$i]));
+	    }
+	}
+	    
+	exit(0);
+    }
+	    
+    if (/^\./) {	next line; }
+
+    if (/^(See also|See Also|see also)/) {
+	@a = split('[: ,.]+');
+
+	printf("See also : %s\n",&anchor($a[3]) );
+	for ($i = 4; $i <= $#a ; ($i)++) {       
+	    printf(", %s\n",&anchor($a[$i]));
+	}
+
+	while (<>) {
+	    chop;	# strip record separator
+	    @a = split('[: ,.]+');
+	    @Fld = split(' ', $_, 9999);
+	    if (/^\./) { goto procline; }
+	    for ($i = 1; $i <= $#a ; ($i)++) {       
+		printf(", %s\n",&anchor($a[$i]));
+	    }
+	}
+	    
+	exit(0);
+    }
+	    
+    printf "%s\n", &htmlify($_);
+}
+
+#sub anchor {
+#    local($_) = @_;
+#    $file = $_ . ".t";
+#    if (-r $file) {
+#	return ("" . $_ . "");
+#    } else {
+#	return ( " " . $_ . " ");
+#    }
+#}
+
+sub anchor {
+    local($_) = @_;
+    local(@file,$file);
+    $file = $_ . ".t";
+#    if (-r $file) {
+    if (1) {
+      $file =~ s/.t$/.html/;
+      return ("$_");
+    } else {
+	@file = <$_*t>;
+	if (@file) {
+	  warn "Expanding $_ to $file[$[]\n";
+	  $file[$[] =~ s/.t$/.html/;
+	  return ("$_");
+	} else {
+	  warn "Unable to link $_\n";
+	  return ( "$_");
+	}
+    }
+}
+
+    
+# Translate HTML special characters into escape sequences
+sub htmlify {
+        local($_) = @_;
+	s/^\"(.*)\"$/$1/;
+	s/\\&//g;		# a nothing character
+        s/\&/&/g;
+        s/\/>/g;
+	while (@a = /(\\\*Q)([A-Za-z0-9\-\.]+)(\\\*U)/) {
+	    /(\\\*Q)([A-Za-z\-]+)(\\\*U)/;
+	    $_ = $` . &anchor($a[2]) . $';
+	}
+	while (@a = /(\\\*Q)(\"info )([A-Za-z0-9\-\.]+)(\\\*U)/) {
+	    /(\\\*Q)(\"info )([\w\-\.]+)(\\\*U)/;
+	    $_ = $` . "\"info " . &anchor($a[3]) . $';
+	}
+	while (@a = /(\"info )([A-Za-z0-9\-\.]+)/) {
+	    /(\"info )([\w\-\.]+)/;
+	    $_ = $` . "\"info " . &anchor($a[2]) . $';
+	}
+        s/\\\*Q//g;
+        s/\\\*U/<\/em>/g;
+        s/\\fI//g;
+        s/\\fR/<\/em><\/em>/g;
+        s/\\fB//g;
+        s/\\fP/<\/strong><\/em>/g;
+	s/\\\*\(bF//g;	# bold font
+	s/\\\*\(pF/<\/strong><\/em>/g; # pica font
+	s/\\\*\(nF/<\/strong><\/em>/g; # normal font
+	s/\\\*\(iF//g;	# italic font
+	s/\\\(mu/x/g;		# multiply symbol
+	s/\\ / /g;		# should be non breaking space
+        return $_;
+}
+
+#sub htmlify {
+#    local($str) = @_;
+#    $str;
+#}
+
+
diff --git a/man/emp_client.6 b/man/emp_client.6
new file mode 100644
index 00000000..b7093ea8
--- /dev/null
+++ b/man/emp_client.6
@@ -0,0 +1,77 @@
+.TH EMP_CLIENT 6 "19 Oct 1998" "empire client version 2.8"
+.UC
+.SH NAME
+empire \- Empire client
+.SH SYNOPSIS
+.B empire
+[
+.IR country
+[
+.IR password
+]
+]
+[
+.BI \-k
+]
+[
+.BI \-2 outfile
+]
+.br
+.SH DESCRIPTION
+.I empire
+is a bare bones client to connect to the Empire server.  Empire is a
+global economic/political/military simulation game wherein players,
+representing national governments, make "real-time" decisions
+concerning resource allocation, national goals, international
+diplomatic efforts, etc.  Extensive records are kept for all players.
+.PP
+WARNING -- This game is not only addictive but often peels back
+the thin veneer of civilization that hides the maniac within.
+.SH OPTIONS
+.TP
+.IR country
+the name of your country in the game
+.TP
+.IR password
+the password for your country in the game
+.TP
+.BI \-k
+if someone else is connected to your country, kill their connection
+.TP
+.BI \-2 outfile
+redirect output to 
+.I outfile
+.SH ENVIRONMENT VARIABLES
+setenv EMPIREHOST server-machine to access the game on server-machine.
+.PP
+setenv EMPIREPORT port-number to access the game on port-number.
+(the person running the game should tell you what this is... if not, 
+you should have the right default already.)
+.PP
+setenv COUNTRY country-name (optional)
+.PP
+setenv PLAYER representative-name (optional)
+.SH AUTHORS
+.nf
+Primary Author is Dave Pare (mr-frog@scam.berkeley.edu)
+Secondary authors/contributors may include:
+James Anderson (jwa@k.cs.cmu.edu)
+Jeff Anton (anton@postgres.berkeley.edu)
+Phill Everson (everson@compsci.bristol.ac.uk)
+Steven Grimm (koreth@ucscb.UCSC.EDU)
+Lewis R. Jansen (lrj@helios.tn.cornell.edu)
+Mike St. Johns (stjohns@edn-vax.arpa)
+Nick Lai (lai@cs.ucla.edu)
+Shelley Louie (slouie@cory.berekely.edu)
+Steve McClure (ionica@empire.cx)
+Chris Metcalf (metcalf-christopher@yale.arpa)
+Dave Muir Sharnoff (muir@cogsci.berkeley.edu)
+Keith Muller (muller@sdcc7.ucsd.edu)
+Chuck Musciano (chuck@trantor.harris-atd.com)
+Jeff Okamoto (okamoto%hpccc@hplabs.hp.com)
+Julian Onions (jpo@computer-science.nottingham.ac.uk)
+Kurt Pires (kjpires@ic.berkeley.edu)
+Jim Reuter (reuter@decwrl.dec.com)
+Peter Vukovich (peterv@monet.berkeley.edu)
+Jeff Wallace (jeffw@scam.berkeley.edu)
+John Yockey (johny@verinet.com)
diff --git a/man/emp_server.6 b/man/emp_server.6
new file mode 100644
index 00000000..4f45f8f9
--- /dev/null
+++ b/man/emp_server.6
@@ -0,0 +1,64 @@
+.TH EMP_SERVER 6 "19 Oct 1998" "emp_server Version 4.20"
+.UC
+.SH NAME
+emp_server \- Empire server
+.SH SYNOPSIS
+.B emp_server
+[
+.BI \-dhps
+]
+[
+.BI \-D datadir
+]
+[
+.BI \-e configfile
+]
+[
+.IR name
+]
+.br
+.SH DESCRIPTION
+.I emp_server
+is a demon which listens to the Empire port for players connecting to
+the game.  When a player connects, a thread is created for that player
+within the server.  For more information on the game of Empire, see
+the
+.I info
+pages within the game.
+.SH OPTIONS
+.TP
+.B \-d 
+Debug mode.  This will prevent the server from forking itself into the
+background.  It will also cause the server to dump core if it crashes.
+You must run with this flag if you are running
+.I emp_server
+from within a debugger.
+.TP
+.B \-h 
+Help.  Print a usage line showing the command line options.
+.TP
+.B \-p
+Lwp Print mode.  This is used for debugging lwp-threads.
+.TP
+.B \-s
+Lwp stack check mode.  This will report if any of the lwp thread stack
+spaces overflow.  It forces lwp print mode on.
+.TP
+.BI \-D datadir
+causes the server to use the data files in 
+.I datadir
+.TP
+.BI \-e configfile
+causes the server to use the game configuration specification in 
+.I configfile
+(by default, the file "econfig" in the data directory is used)
+.TP
+.IR name
+This argument does nothing.  It is used by scripts to locate the
+server to kill it.
+.SH BUGS
+Please report all bugs to the Wolfpack 
+.SH AUTHORS
+Dave Pare, Jeff Bailey, Thomas Ruschak, Ken Stevens and Steve McClure
+ are principle authors.
+The list of secondary authors is too long to mention.
diff --git a/man/fairland.1 b/man/fairland.1
new file mode 100644
index 00000000..3ff8ad02
--- /dev/null
+++ b/man/fairland.1
@@ -0,0 +1,106 @@
+.TH FAIRLAND 1 "7 Aug 1995" "fairland 1.6"
+.UC
+.SH NAME
+fairland \- Empire land generator
+.SH SYNOPSIS
+.B fairland
+[
+.BI \-aieoq
+]
+[
+.BI \-s scriptout
+]
+[
+.BI \-e configfile
+]
+.IR nc
+.IR sc
+[
+.IR ni
+]
+[
+.IR is
+]
+[
+.IR sp
+]
+[
+.IR pm
+]
+[
+.IR di
+]
+[
+.IR id
+]
+.br
+.SH DESCRIPTION
+.I fairland
+is a program which creates land and ore for Empire.  It
+should be run after 
+.I files 
+has been run and before 
+.I emp_server
+has been started.  This is a land generator for empire that creates a
+specified number of continents, and spaces them evenly accross the
+map.  It tries to make all of them the same size, and makes sure that
+they don't meet.  It gives each start island exactly the same
+distribution of resources and the same number of mountains.  You can
+get nearly any kind of map you want by choosing the right arguments.
+.SH OPTIONS
+.TP
+.B \-a 
+mark the continents with a * so that you can tell them from the islands
+.TP
+.B \-i
+islands will crash into each other and merge
+.TP
+.B \-o
+do not set the resources.  If you use this flag, then you will need to
+run some other program (for example the 
+.I ore 
+program) to set the resources.
+.TP
+.B \-q
+run quietly without printing anything to the terminal
+.TP
+.BI \-s scriptout
+writes a script for placing capitol to the file
+.I scriptout
+(If you don't specify this argument, then the script will be written
+to "newcap_script".)
+.TP
+.BI \-e configfile
+causes
+.I fairland
+to use the game configuration specified in 
+.I configfile
+(by default, the file "econfig" in the data directory is used)
+.TP
+.IR nc 
+number of continents
+.TP
+.IR sc 
+continent size
+.TP
+.IR ni 
+number of islands (optional, default = nc)
+.TP
+.IR is 
+average size of islands (optional, default = sc/2)
+.TP
+.IR sp 
+spike percentage: 0 = round, 100 = snake (default = 10)
+.TP
+.IR pm 
+the percentage of land that is mountain (default = 0)
+.TP
+.IR di 
+the minimum distance between continents (default = 2)
+.TP
+.IR id 
+minimum distance from islands to continents (default = 1)
+
+.SH AUTHOR
+Ken Stevens 
+
diff --git a/man/files.1 b/man/files.1
new file mode 100644
index 00000000..d939ea2b
--- /dev/null
+++ b/man/files.1
@@ -0,0 +1,24 @@
+.TH FILES 1 "7 Aug 1995" "files"
+.UC
+.SH NAME
+files \- Empire file initialization
+.SH SYNOPSIS
+.B files
+[
+.BI \-e configfile
+]
+.br
+.SH DESCRIPTION
+.I files
+creates all of the files which are required by 
+.I emp_server
+to run a game.  It will destroy all previous game data, so excercise
+caution when running this program.
+.SH OPTIONS
+.TP
+.BI \-e configfile
+causes
+.I files
+to use the game configuration specified in 
+.I configfile
+(by default, the file "econfig" in the data directory is used)
diff --git a/man/land.1 b/man/land.1
new file mode 100644
index 00000000..d95c95c5
--- /dev/null
+++ b/man/land.1
@@ -0,0 +1,35 @@
+.TH LAND 1 "7 Aug 1995" "land"
+.UC
+.SH NAME
+land \- Empire land generator
+.SH SYNOPSIS
+.B land
+[
+.IR sectrange
+.IR mincontdist
+.IR chunksize
+.IR numchunks
+.IR numisle
+]
+.br
+.SH DESCRIPTION
+While most deities prefer to use
+.I fairland
+to generate their land, this program is included as an alternative for
+creating the geography for a game.
+.SH OPTIONS
+.TP
+.IR sectrange
+smoothing area (default = 3)
+.TP
+.IR mincontdist
+minimum distance between continents (default = 2)
+.TP
+.IR chunksize
+basic land block size (default = 2)
+.TP
+.IR numchunks
+number of chunks per continent (default = 70)
+.TP
+.IR numisle
+number of islands (default is based on world size)
diff --git a/man/ore.1 b/man/ore.1
new file mode 100644
index 00000000..984e7557
--- /dev/null
+++ b/man/ore.1
@@ -0,0 +1,31 @@
+.TH ORE 1 "7 Aug 1995" "ore"
+.UC
+.SH NAME
+ore \- Empire resource generator
+.SH SYNOPSIS
+.B ore
+[
+.BI \-e configfile
+]
+[
+.BI \-s sectfile
+]
+.br
+.SH DESCRIPTION
+While most deities prefer to use
+.I fairland
+to generate their ore, this program is included as an alternative for
+creating the resources for a game.
+.SH OPTIONS
+.TP
+.BI \-e configfile
+causes
+.I ore
+to use the game configuration specified in 
+.I configfile
+(by default, the file "econfig" in the data directory is used)
+.TP
+.BI \-s sectfile
+give resources to the sectors in 
+.I sectfile
+(default is the "sector" file in the data directory)
diff --git a/man/pconfig.1 b/man/pconfig.1
new file mode 100644
index 00000000..1fb8482b
--- /dev/null
+++ b/man/pconfig.1
@@ -0,0 +1,29 @@
+.TH PCONFIG 1 "7 Aug 1995" "pconfig"
+.UC
+.SH NAME
+pconfig \- Print configuration
+.SH SYNOPSIS
+.B pconfig
+[
+.IR configfile
+]
+.br
+.SH DESCRIPTION
+.I pconfig
+creates an "econfig" file which may be used with the \-e argument with
+most Empire programs.  By default, Empire programs look for a file
+called "econfig" in the data directory, but the 
+.I pconfig
+program may be used to create an alternate Empire configuration file.
+After you have created an "econfig" file, you can edit the game
+configuration data in the file which the server uses to control
+various parameters for the game.
+.SH OPTIONS
+.TP
+.BI configfile
+causes
+.I pconfig
+to use the game configuration specified in 
+.I configfile
+.SH AUTHOR
+Julian Onions 
diff --git a/man/perfect.1 b/man/perfect.1
new file mode 100644
index 00000000..f51265e0
--- /dev/null
+++ b/man/perfect.1
@@ -0,0 +1,31 @@
+.TH PERFECT 1 "7 Aug 1995" "perfect"
+.UC
+.SH NAME
+perfect \- create perfect resources
+.SH SYNOPSIS
+.B perfect
+[
+.BI \-e configfile
+]
+[
+.BI \-s sectfile
+]
+.br
+.SH DESCRIPTION
+While most deities prefer to use
+.I fairland
+to generate their resources, this program is included as an alternative for
+creating the resources for a game.  It sets all resources to 100.
+.SH OPTIONS
+.TP
+.BI \-e configfile
+causes
+.I perfect
+to use the game configuration specified in 
+.I configfile
+(by default, the file "econfig" in the data directory is used)
+.TP
+.BI \-s sectfile
+give resources to the sectors in 
+.I sectfile
+(default is the "sector" file in the data directory)
diff --git a/scripts/README b/scripts/README
new file mode 100644
index 00000000..0f649467
--- /dev/null
+++ b/scripts/README
@@ -0,0 +1,41 @@
+The files in this directory are various utility scripts/programs
+submitted by various people for doing routine maintainence on the
+server, such as keeping it alive, making maps, posting to newsgroups,
+starting blitzes, etc.
+
+While we provide these files for your convenience, they are not an
+"official" part of the server.  Therefore, you can e-mail us with
+problems with them, but we may or may not know the answers and/or how
+to fix any problems.  Some of the files have the author's e-mail in
+them, and others are anonymous submissions, so you may want to try
+to contact the authors if all else fails (but try us first, as we might
+know.)
+
+Wolfpack!
+
+------
+
+keepitup
+	Automatically reboots your Empire server if it crashes.
+	No configuration necessary.  See the comments at the top of
+	the file for syntax.  See crontab.config for an example of
+	what to add to your crontab.
+
+saveass
+	Makes automatic backups of your game data.  See crontab.config.
+	To configure, change two paths at the top of the file.
+
+bigstart
+	Handy for blitzes.  Fill start islands with sanctuaries and
+	fill the sanctuaries with civs.  To configure, change the
+	value of "height" and "width" in teh BEGIN routine.
+
+postresults
+	Useful for posting canned results to a newsgroup.
+
+blitz/
+	Scripts for running an auto-resetting blitz.
+
+mapper/
+	Scripts for making mpeg videos of your game.  See mapper/README
+	for configuration details.
diff --git a/scripts/bigstart b/scripts/bigstart
new file mode 100644
index 00000000..4d7d04a5
--- /dev/null
+++ b/scripts/bigstart
@@ -0,0 +1,86 @@
+#!/bin/awk -f
+#
+#  IMPORTANT: You must change "height" and "width" by hand below.
+#
+#	A deity tool to parse a dump file and generate edit commands
+#	to build larger start sanctuaries.
+#		dump * | bigstart >bigstart.out
+#		exec bigstart.out
+#	-Drake (dld@chem.psu.edu)
+
+
+function sanctuary(x,y,o,nsect)
+{
+  if (x>=width/2) x -= width;
+  if (y>=height/2) y -= height;
+  if (x<-width/2) x += width;
+  if (y<-height/2) y+= height;
+
+  nsect = x "," y;
+  if ((nsect in newown) && !(nsect in own)) {
+    printf("des %s s\n",nsect);
+    printf("give civ %s 550\n",nsect);
+    printf("setsector oldowner %s %d\n",nsect,o);
+    printf("setsector owner %s %d\n",nsect,o);
+    printf("setsector work %s 100\n",nsect);
+    own[nsect]=o;
+    delete newown[nsect];
+    added++;
+  }
+}
+
+
+BEGIN {
+  SUBSEP=",";
+  sects=0;
+  begin=0;
+  width=64;
+  height=32;
+}
+
+
+{
+
+  if (begin==1) {
+    for (i=1;i<=NF;i++) header[i]=$i;
+    nheader=NF;
+    begin=2;
+    break;
+  }
+
+  if (NF != nheader) {
+    begin=0;
+  }
+
+  if (begin==2) {
+    for (i=1;i<=nheader;i++) {
+      val[header[i]] = $i;
+    }
+    if (val["own"]==0 && val["des"]=="-") {
+      newown[val["x"],val["y"]]=0;
+    }
+    if (val["own"]>0) {
+      own[val["x"],val["y"]]=val["own"];
+    }
+  }
+}
+
+/ *DUMP SECTOR/ { begin=1; }
+
+END {
+  do {
+    added=0;
+    for (sect in own) {
+      split(sect,a,",");
+      x=a[1];
+      y=a[2];
+      
+      sanctuary(x+2,y,own[sect]);
+      sanctuary(x-2,y,own[sect]);
+      sanctuary(x+1,y+1,own[sect]);
+      sanctuary(x+1,y-1,own[sect]);
+      sanctuary(x-1,y+1,own[sect]);
+      sanctuary(x-1,y-1,own[sect]);
+    }
+  } while (added);
+}
diff --git a/scripts/blitz/README b/scripts/blitz/README
new file mode 100644
index 00000000..cd39dde5
--- /dev/null
+++ b/scripts/blitz/README
@@ -0,0 +1,6 @@
+These are the scripts that we use to run the Cheetah and Vampire
+blitzes.  If you want to use them, then you should copy them to the
+bin directory, change the pathnames where appropriate and install the
+crontab.config using the crontab command.
+
+Wolfpack! 1996
diff --git a/scripts/blitz/crontab.config b/scripts/blitz/crontab.config
new file mode 100644
index 00000000..2b26cbb5
--- /dev/null
+++ b/scripts/blitz/crontab.config
@@ -0,0 +1,3 @@
+8,18,28,38,48,58 * * * * /empire/wolfpack/cheetah/bin/keepitup -check vampire /empire/wolfpack/cheetah 6667 Lurker password 1>>/empire/wolfpack/logs/keepitup 2>&1
+00 6 * * * /empire/wolfpack/cheetah/bin/setup-blitz 1>>/empire/wolfpack/logs/setup-blitz 2>&1
+25 6 * * * /empire/wolfpack/cheetah/bin/start-blitz 1>>/empire/wolfpack/logs/start-blitz 2>&1
diff --git a/scripts/blitz/motd b/scripts/blitz/motd
new file mode 100644
index 00000000..1879be90
--- /dev/null
+++ b/scripts/blitz/motd
@@ -0,0 +1,18 @@
+turn on
+                      Welcome to the Wolfpack
+                           Cheetah Blitz
+
+                    Empire 4.0.0 (Wolfpack) code
+
+New players should start by typing "info".
+
+All players should check "info Empire4" and "info Infrastructure".
+
+The Wolfpack home page is:  http://www.wolfpackempire.com, and has
+    complete info pages on-line with cross-links.
+
+The blitz resets at 6:00pm EDT every day.  Updates start at 6:30pm EDT.
+
+Please email all comments and bug reports to wolfpack@wolfpackempire.com
+
+.
diff --git a/scripts/blitz/setup-blitz b/scripts/blitz/setup-blitz
new file mode 100644
index 00000000..22f78ea5
--- /dev/null
+++ b/scripts/blitz/setup-blitz
@@ -0,0 +1,37 @@
+#!/bin/csh
+
+echo '================Setup begin================='
+date
+
+cd /empire/wolfpack/cheetah/bin
+/empire/wolfpack/cheetah/bin/keepitup -kill cheetah
+\rm -f /empire/wolfpack/cheetah/data/server.log
+./files < bigstart.out
+bye
+EOF
+
+/empire/wolfpack/cheetah/bin/emp_client POGO peter < bigstart.out >> /dev/null
+
+/empire/wolfpack/cheetah/bin/emp_client POGO peter < motd
+
+/empire/wolfpack/cheetah/bin/emp_client POGO peter << EOF
+change coun Wolf
+change rep password
+realm 0 0:-1,0:-1
+add 13 Lurker password v i
+add 14 Mapmaker password g i
+bye
+EOF
+
+echo '================Setup end================='
diff --git a/scripts/blitz/start-blitz b/scripts/blitz/start-blitz
new file mode 100644
index 00000000..ca86e2f3
--- /dev/null
+++ b/scripts/blitz/start-blitz
@@ -0,0 +1,14 @@
+#!/bin/csh
+echo '================Start begin================='
+date
+
+/empire/wolfpack/cheetah/bin/keepitup -check cheetah /empire/wolfpack/cheetah 6667 Lurker password
+cd /empire/wolfpack/cheetah/bin
+/empire/wolfpack/cheetah/bin/emp_client Wolf password << EOF
+enable
+ann
+Updates are enabled.  Have a blast!
+.
+bye
+EOF
+echo '================Start end================='
diff --git a/scripts/crontab.config b/scripts/crontab.config
new file mode 100644
index 00000000..23dfb273
--- /dev/null
+++ b/scripts/crontab.config
@@ -0,0 +1,2 @@
+2,12,22,32,42,52 * * * * /home/wolfpack/bin/keepitup -check howitzer /home/wolfpack/howitzer 7778 Lurker password 1>>/home/wolfpack/logs/keepitup 2>&1
+01 18 * * * /home/wolfpack/emp4/scripts/saveass 1>>/home/wolfpack/logs/saveass 2>&1
diff --git a/scripts/keepitup b/scripts/keepitup
new file mode 100644
index 00000000..93ac18e0
--- /dev/null
+++ b/scripts/keepitup
@@ -0,0 +1,156 @@
+#!/bin/sh
+#
+# keepitup
+# This is a hacked version of "isempireup" by Dave Nye
+# Modified for use with the Empire2 server by Ken Stevens 1995
+#
+# Usage:
+# keepitup -kill 
+# keepitup -start  
+# keepitup -check     
+#
+# Portability:
+# You may need to put a '-' in front of the ps flags below
+
+_verbose=true
+tbase=/tmp/empcheck.$$
+
+trap 'rm -f $FNAMES ; exit' 0 1 2 3 15
+
+putmsg() {
+    if [ "$_verbose" = "true" ]; then
+	echo "`date` $*"
+    fi
+}
+
+ERR0="Server EOF"
+ERR1="connect: Connection refused"
+ERR2="Expecting 2, got unix socket connect: No such file or directory"
+MDOWN="The game is down"
+FLAGS="-d"
+
+killit() {
+    FK=${tbase}.kill
+    FNAMES="$FNAMES ${FK}.L ${FK}.P"
+    rm -f ${FK}.L ${FK}.P
+
+    ps auxw >${FK}.L
+    egrep "emp_server $FLAGS $1" ${FK}.L | egrep "$USER" >${FK}.P
+
+    SZ="`wc -l ${FK}.P | awk '{print $1}' -`"
+    if [ $SZ -gt 0 ]; then
+	PIDS=`awk '{rec = rec " " $2} END {print rec}' ${FK}.P`
+	putmsg "Found pids $PIDS to kill for emp_server $FLAGS"
+	kill $PIDS
+    fi
+    rm -f ${FK}.L ${FK}.P
+}
+
+kill9it() {
+    PROC=$1
+
+    FK=${tbase}.kill
+    FNAMES="$FNAMES ${FK}.L ${FK}.P"
+    rm -f ${FK}.L ${FK}.P
+
+    ps auxw >${FK}.L
+    egrep "$PROC" ${FK}.L | egrep "$USER" >${FK}.P
+
+    SZ="`wc -l ${FK}.P | awk '{print $1}' -`"
+    if [ $SZ -gt 0 ]; then
+	PIDS=`awk '{rec = rec " " $2} END {print rec}' ${FK}.P`
+	putmsg "Found pids " $PIDS " to kill for" $PROC
+	kill -9 $PIDS
+    fi
+    rm -f ${FK}.L ${FK}.P
+}
+
+restartgame() {
+    DIR=$1
+    UNIQ=$2
+
+    killit $UNIQ
+    sleep 1
+    cd $DIR/bin
+    ./emp_server $FLAGS $UNIQ &
+    echo "restarted $UNIQ"
+    cd $HOME
+}
+
+checkgame() {
+    DIR=$1
+    PORT=$2
+    COUN=$3
+    PASS=$4
+
+    EMPIREHOST=`/bin/hostname`
+    EMPIREPORT=$PORT
+    COUNTRY=$COUN
+    PLAYER=$PASS
+    export EMPIREHOST EMPIREPORT COUNTRY PLAYER
+
+    FN=${tbase}.client
+    rm -f ${FN}.I  ${FN}.1 ${FN}.2
+    FNAMES="$FNAMES ${FN}.I ${FN}.1 ${FN}.2"
+    echo "quit" >${FN}.I
+    echo "quit" >${FN}.I
+
+    kill9it emp_client
+    $DIR/bin/emp_client >${FN}.1 2>${FN}.2  <${FN}.I
+    STAT=$?
+    ER=`head -1 ${FN}.2`
+    NORM=`head -1 ${FN}.1`
+
+    if [ "$STAT" = "0" ]; then
+	ALLOK=true
+#	putmsg "All Ok"
+    elif [ "$ER" = "$ERR0" ]; then
+	ALLOK=true
+#	putmsg "All Ok, but bad return status"
+    elif [ "$ER" = "$ERR1" ]; then
+	ALLOK=false
+	putmsg "emp_server is down"
+    elif [ "$ER" = "$ERR2" ]; then
+	ALLOK=false
+	putmsg "emp_server is down"
+    else
+	ALLOK=false
+	putmsg "Something is wrong"
+    fi
+    rm -f ${FN}.I  ${FN}.1 ${FN}.2
+}
+
+while [ $# -gt 0 ]; do
+    case "$1" in
+	# -kill game
+	"-kill") shift
+	    if [ $# -lt 1 ]; then
+		echo "Expecting -kill "
+		exit 1
+	    fi
+	    killit $1
+	    shift ;;
+	# -start game dir
+	"-start") shift
+	    if [ $# -lt 2 ]; then
+		echo "Expecting -start  "
+		exit 1
+	    fi
+	    restartgame $2 $1
+	    shift ;shift;;
+	# -check game dir port country user
+	"-check") shift
+	    if [ $# -lt 5 ]; then
+		echo "Expecting -check     "
+		exit 1
+	    fi
+	    checkgame $2 $3 $4 $5
+	    if [ "$ALLOK" != "true" ]; then
+		restartgame $2 $1
+	    fi
+	    shift ; shift ; shift ; shift ; shift ;;
+	*) echo "Unknown parameter found in: $*."
+	    echo "Aborting."
+	    exit 1 ;;
+    esac
+done
diff --git a/scripts/mapper/Makefile b/scripts/mapper/Makefile
new file mode 100644
index 00000000..3e513cfe
--- /dev/null
+++ b/scripts/mapper/Makefile
@@ -0,0 +1,24 @@
+#
+#	Riverworld Blitz mpeg makefile.  Assumes the netpbm programs are
+#	somewhere in the path.  map.m2v is an mpeg2 file-- unfortunately
+#	it's 15x the size of the mpeg1 (.mpg) file.  If you modify map.par
+#	to generate a smaller file, or find another mpeg2 encoder, let
+#	me know.
+#		-Drake (dld@chem.psu.edu)
+
+
+.SUFFIXES: .pgm .gif .ppm .pov .jpg
+
+all: map.mpg final.gif
+
+map.param: param.pl default.param frames
+	param.pl default.param >map.param
+color.ppm: randppm.awk
+	randppm.awk >$@
+map.mpg: map.param 
+	mpeg_encode map.param
+final.gif: frames color.ppm
+	makeframe map-`cat frames`.gif | ppmtogif -interlace >final.gif
+
+clean:
+	rm -f map-*.gif overmap-*.gif frames census report version over.pbm power wire final.gif over.mask color.ppm map.mpg
diff --git a/scripts/mapper/README b/scripts/mapper/README
new file mode 100644
index 00000000..06cf7938
--- /dev/null
+++ b/scripts/mapper/README
@@ -0,0 +1,66 @@
+To install mapper, edit makempeg and mapper and
+(1) fix paths
+(2) change names of countries to exclude
+(3) add a crontab similar to the one in the file crontab.config
+
+When starting, type:
+make clean
+make color.ppm
+
+-children
+
+   This directory contains a number of scripts which output PPM format
+files suitable for conversion to gif with the PBM utilities or MPEG
+with mpeg_encode.  mpeg_encode is available from
+	http://s2k-ftp.cs.berkeley.edu:8000/multimedia/mpeg/
+PBMPLUS is available from 
+	ftp://ftp.ee.lbl.gov/
+Some of the scripts (mapper in particular) depend on a country
+"mapper" being defined that can be logged into automatically using the
+Empire client eif.  Modify to use the client and country name of your
+choice.
+
+-harmless
+
+
+
+pgmmap.awk
+   A simple map making program.  Reads a deity dump file and produces
+a grayscale .pgm file as output, with each color corresponding to a
+country number.  To make a color coded map, scramble the colors.
+
+pgmfallout.awk
+   Convert a deity census file into a PGM file with fallout levels.
+
+randppm.awk
+   Generates random colors in a ppm file.  Useful for remmapping colors
+from pgmmap.awk
+
+over.awk
+   Reads in a report file and generates a text overlay of country names.
+Requires pbmtext (part of netpbm) to work.
+
+param.pl
+   Modify an mpeg parameter file to use map-*.gif files as input.
+Reads the highest level file from the file 'frames' and skips over any
+file not 300-500 bytes long (in a 64x32 blitz, the .gif files should
+be ~400 bytes).  Larger worlds may require different size limits.
+Disabling the size limits is not advised, as this is the only way
+corrupt frames are eliminated.
+
+makempeg
+   Log into the mapper country, capture new report files, and generate
+a new .mpg file.  Also copies map.mpg and final.gif into the web space
+directories so others can view them.  The web copy may be commented
+out or modified to meet your local needs.
+
+mapper
+   Log into mapper country and capture a map of the current owners of
+the world (.gif format).  Games without fallout should comment out the
+fallmap producing line.
+
+archive.pl
+   Pushes the archived blitz records down the stack (in web space) and
+prints out a new .html index.
+
+-Drake (dld@chem.psu.edu)
diff --git a/scripts/mapper/archive.pl b/scripts/mapper/archive.pl
new file mode 100644
index 00000000..8d77a09a
--- /dev/null
+++ b/scripts/mapper/archive.pl
@@ -0,0 +1,51 @@
+#!/usr/local/bin/perl
+
+
+#   Run by cron at 7:50 to archive (in web space) the current blitz mpeg
+#   and to generate a new html index file.  Outputs html.
+#	-Drake (dld@chem.psu.edu)
+
+require 'ctime.pl';
+
+chdir '/home/children/html/howitzer';
+
+@file = ("Blitz-0", "Blitz-1","Blitz-2","Blitz-3","Blitz-4", "Blitz-5","Blitz-6", "Blitz-7");
+unlink("$file[$#file].mpg","$file[$#file].gif","$file[$#file].txt","$file[$#file]Ann.txt");
+
+
+for ($i=$#file;$i>0;$i--) {
+    rename($file[$i-1] . '.mpg',"$file[$i].mpg");
+    rename($file[$i-1] . '.gif',"$file[$i].gif");
+    rename($file[$i-1] . '.txt',"$file[$i].txt");
+    rename($file[$i-1] . 'Ann.txt',"$file[$i]Ann.txt");
+}
+
+if (-s 'Blitz.mpg') { system('cp -p Blitz.mpg Blitz-0.mpg'); }
+if (-s 'Blitz.gif') { system('cp -p Blitz.gif Blitz-0.gif'); }
+if (-s 'Blitz.txt') { system('cp -p Blitz.txt Blitz-0.txt'); }
+if (-s 'Blitz.txt') { system('cp -p BlitzAnn.txt Blitz-0Ann.txt'); }
+
+print " \n";
+print "Howitzer Blitz Archive\n";
+print "\n\n";
+print "

Archived Blitzes

\n"; +print "
    \n"; + +foreach $base (@file) { + $file = $base . '.mpg'; + + if (-s $file) { + ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size, + $atime,$mtime,$ctime,$blksize,$blocks) + = stat($file); + chop($m=&ctime($mtime)); + print "
  • $m \n"; + } +} + +print "
\n"; +print " \n"; diff --git a/scripts/mapper/cleanup b/scripts/mapper/cleanup new file mode 100644 index 00000000..5790f222 --- /dev/null +++ b/scripts/mapper/cleanup @@ -0,0 +1,6 @@ +#!/bin/sh + +# add any paths necessary for eif, netpbm, and mpeg_encode. + +cd /home/children/howitzer/map +make clean diff --git a/scripts/mapper/crontab.config b/scripts/mapper/crontab.config new file mode 100644 index 00000000..a2457b84 --- /dev/null +++ b/scripts/mapper/crontab.config @@ -0,0 +1,4 @@ +4,14,24,34,44,54 * * * * /home/children/howitzer/map/mapper 1>>/dev/null 2>&1 +51 18 * * * /home/children/howitzer/map/makempeg 1>>/dev/null 2>&1 +58 18 * * * /home/children/howitzer/map/archive.pl > /home/children/html/howitzer/index.html +27 19 * * * /home/children/howitzer/map/cleanup 1>>/home/children/logs/cleanup 2>&1 diff --git a/scripts/mapper/default.param b/scripts/mapper/default.param new file mode 100644 index 00000000..7c64fc9e --- /dev/null +++ b/scripts/mapper/default.param @@ -0,0 +1,41 @@ +# default parameter file for encoding empire games. P frames are +# very cheap since most pixels remain exactly the same color. +# I frames (complete pictures) are expensive, so they are infrequent. +# Inidividual maps are stored as gifs (a very compact storage format for +# this sort of data) and enlarged and converted on the fly to ppm format +# using various netpbm tools. +# This file is modified by param.pl to generate the real .param file +# with the correct input filenames. +# -Drake (dld@chem.psu.edu) + +PATTERN IPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP +OUTPUT map.mpg + +BASE_FILE_FORMAT PPM +GOP_SIZE 60 +SLICES_PER_FRAME 1 + +PIXEL HALF +RANGE 8 +PSEARCH_ALG LOGARITHMIC +BSEARCH_ALG SIMPLE +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +REFERENCE_FRAME DECODED + +# +# This takes two files, fallmap*.gif and map*.gif. Both are converted to ppm +# and enlarged by a factor of 4. fallmap*.gif is also smoothed. The two are +# then added together (causing sectors with high fallout to be brighter). +# Finally, the country names in over.mask and over.pbm are overlaid. +# + +INPUT_CONVERT makeframe `basename *` + +INPUT_DIR . + +# This files actual are substituted here by param.pl +INPUT +END_INPUT diff --git a/scripts/mapper/makeframe b/scripts/mapper/makeframe new file mode 100644 index 00000000..36d410e1 --- /dev/null +++ b/scripts/mapper/makeframe @@ -0,0 +1,7 @@ +#!/bin/sh + +# giftopnm fall$* | pnmgamma 2 | pnmscale 2 | pnmsmooth | pnmscale 2 | pnmsmooth | pnmdepth 255 >fall.ppm +giftopnm over$* >over.pbm +pbmmask -expand over.pbm >over.mask +giftopnm $* | pgmtoppm -map color.ppm | pnmscale 4 | pnmcomp -invert -alpha over.mask over.pbm + diff --git a/scripts/mapper/makempeg b/scripts/mapper/makempeg new file mode 100644 index 00000000..abde651b --- /dev/null +++ b/scripts/mapper/makempeg @@ -0,0 +1,27 @@ +#!/bin/sh + +# add any paths necessary for eif, netpbm, and mpeg_encode. +PATH=/home/children/bin/netpbm:${PATH}:/usr/local/bin:${HOME}/bin:. +export PATH + +cd /home/children/howitzer/map +touch version power wire census +eif mapper <!version +census * >!census +report * | egrep -v '(Frey|pea|Lurker|Mapmaker|Visitor|visitor)' >report +power new >!power +wire Mapmaker y >!wire +exit +EOF + +cat power report >>/home/children/html/howitzer/Blitz.txt +cat wire >>/home/children/html/howitzer/BlitzAnn.txt +echo >>/home/children/html/howitzer/Blitz.txt +echo >>/home/children/html/howitzer/Blitz.txt + +make final.gif map.mpg + +cp map.mpg /home/children/html/howitzer/Blitz.mpg +cp final.gif /home/children/html/howitzer/Blitz.gif + diff --git a/scripts/mapper/map.param b/scripts/mapper/map.param new file mode 100644 index 00000000..c9bec415 --- /dev/null +++ b/scripts/mapper/map.param @@ -0,0 +1,180 @@ +# default parameter file for encoding empire games. P frames are +# very cheap since most pixels remain exactly the same color. +# I frames (complete pictures) are expensive, so they are infrequent. +# Inidividual maps are stored as gifs (a very compact storage format for +# this sort of data) and enlarged and converted on the fly to ppm format +# using various netpbm tools. +# This file is modified by param.pl to generate the real .param file +# with the correct input filenames. +# -Drake (dld@chem.psu.edu) + +PATTERN IPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP +OUTPUT map.mpg + +BASE_FILE_FORMAT PPM +GOP_SIZE 60 +SLICES_PER_FRAME 1 + +PIXEL HALF +RANGE 8 +PSEARCH_ALG LOGARITHMIC +BSEARCH_ALG SIMPLE +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +REFERENCE_FRAME DECODED + +# +# This takes two files, fallmap*.gif and map*.gif. Both are converted to ppm +# and enlarged by a factor of 4. fallmap*.gif is also smoothed. The two are +# then added together (causing sectors with high fallout to be brighter). +# Finally, the country names in over.mask and over.pbm are overlaid. +# + +INPUT_CONVERT makeframe `basename *` + +INPUT_DIR . + +# This files actual are substituted here by param.pl +INPUT +map-0.gif +map-1.gif +map-2.gif +map-3.gif +map-4.gif +map-5.gif +map-6.gif +map-7.gif +map-8.gif +map-9.gif +map-10.gif +map-11.gif +map-12.gif +map-13.gif +map-14.gif +map-15.gif +map-16.gif +map-17.gif +map-18.gif +map-19.gif +map-20.gif +map-21.gif +map-22.gif +map-23.gif +map-24.gif +map-25.gif +map-26.gif +map-27.gif +map-28.gif +map-29.gif +map-30.gif +map-31.gif +map-32.gif +map-33.gif +map-34.gif +map-35.gif +map-36.gif +map-37.gif +map-38.gif +map-39.gif +map-40.gif +map-41.gif +map-42.gif +map-43.gif +map-44.gif +map-45.gif +map-46.gif +map-47.gif +map-48.gif +map-49.gif +map-50.gif +map-51.gif +map-52.gif +map-53.gif +map-54.gif +map-55.gif +map-56.gif +map-57.gif +map-58.gif +map-59.gif +map-60.gif +map-61.gif +map-62.gif +map-63.gif +map-64.gif +map-65.gif +map-66.gif +map-67.gif +map-68.gif +map-69.gif +map-70.gif +map-71.gif +map-72.gif +map-73.gif +map-74.gif +map-75.gif +map-76.gif +map-77.gif +map-78.gif +map-79.gif +map-80.gif +map-81.gif +map-82.gif +map-83.gif +map-84.gif +map-85.gif +map-86.gif +map-87.gif +map-88.gif +map-89.gif +map-90.gif +map-91.gif +map-92.gif +map-93.gif +map-94.gif +map-95.gif +map-96.gif +map-97.gif +map-98.gif +map-99.gif +map-100.gif +map-101.gif +map-102.gif +map-103.gif +map-104.gif +map-105.gif +map-106.gif +map-107.gif +map-108.gif +map-109.gif +map-110.gif +map-111.gif +map-112.gif +map-113.gif +map-114.gif +map-115.gif +map-116.gif +map-117.gif +map-118.gif +map-119.gif +map-120.gif +map-121.gif +map-122.gif +map-123.gif +map-124.gif +map-125.gif +map-126.gif +map-127.gif +map-128.gif +map-129.gif +map-130.gif +map-131.gif +map-132.gif +map-133.gif +map-134.gif +map-135.gif +map-136.gif +map-137.gif +map-138.gif +END_INPUT diff --git a/scripts/mapper/mapper b/scripts/mapper/mapper new file mode 100644 index 00000000..77318443 --- /dev/null +++ b/scripts/mapper/mapper @@ -0,0 +1,41 @@ +#!/bin/sh + +# This script may be run from cron before each update make +# a map of the world. It increments the number in the file "frames" +# each time it is run, and uses this number to determine the map +# file names. Creates a country map and an overlay with country names. +# -harmless + + +# edit these to the location of the map files and the utilities +cd /home/children/howitzer/map +PATH=/home/children/bin/netpbm:${PATH}:/usr/local/bin:${HOME}/bin:. +export PATH + +if test ! -s frames +then + echo 0 >frames.new +else + awk '{ print $1 + 1; }' frames > frames.new +fi + + +FILE=map-`cat frames.new`.gif +OVERMAP=overmap-`cat frames.new`.gif +touch census report version +eif mapper <${FILE} +report * | egrep -v '(Frey|Lurker|pea|Mapmaker|Visitor|visitor|report)' >report +census * >! census +version >!version +exit +EOF + +./over.awk scale=4 version report census +/home/children/bin/netpbm/ppmtogif over.pbm >${OVERMAP} + +if test -s "$FILE" +then + cp frames.new frames + rm frames.new +fi diff --git a/scripts/mapper/over.awk b/scripts/mapper/over.awk new file mode 100644 index 00000000..46741a58 --- /dev/null +++ b/scripts/mapper/over.awk @@ -0,0 +1,85 @@ +#!/bin/awk -f + +# Parse report and generate pbmtext commands for each country +# Now generates new positions as an average of all sectors. + +BEGIN { + if (scale=="") scale=1; + FS="[ \t\n,]+"; +} + +/^World size is [0-9]+ by [0-9]+./ { + width = $4; + height= $6; + system("ppmmake white " (width+1)*scale " " height*scale " | ppmtopgm | pgmtopbm >over.pbm"); +} + +/.*#.*name.*tech.*research.*education.*happiness.*cap-location/ { + getline; + while (NF>4) { + if ($2>0 && $2<90) { + name[$2]=substr($0,8,15); + capx[$2]= $(NF-1); + capy[$2]= $NF; + } + getline; + } +} + +/own +sect/ { + getline; + while (NF>2) { + if ($2 in name) { + if (!count[$2]) { + cx[$2] = $3; + cy[$2] = $4; + } else { + dx = $3 - cx[$2]; + dy = $4 - cy[$2]; + if (dx>=width/2) dx -= width; + if (dy>=height/2) dy -= height; + if (dx<-width/2) dx += width; + if (dy<-height/2) dy += height; + cx[$2] += dx/(1+count[$2]); + cy[$2] += dy/(1+count[$2]); + } + count[$2]++; + } + getline; + } +} + + +END { + for (i in name) { + if (count[i]) { + system("pbmtext \"" name[i] "\" | pnmcrop >text.pbm"); + system("pnmfile text.pbm >text.size"); + getline < "text.size"; + close("text.size"); + h=$NF; + w=$(NF-2); + x = cx[i] + width/2; + y = cy[i] + height/2; + + while (x<0) x += width; + while (y<0) y += height; + while (x>=width) x -= width; + while (y>=height) y -= height; + + x = int(x*scale); + y = int(y*scale); + + x -= w/2; + y -= h/2; + if (x<0) x=0; + if (y<0) y=0; + if (x+w>=width*scale) x=width*scale-w-1; + if (y+h>=height*scale) y=height*scale-h-1; + + + system("pnmpaste text.pbm " x " " y " over.pbm > over2.pbm"); + system("cp over2.pbm over.pbm"); + } + } +} diff --git a/scripts/mapper/over2.pbm b/scripts/mapper/over2.pbm new file mode 100644 index 00000000..0397c9ed --- /dev/null +++ b/scripts/mapper/over2.pbm @@ -0,0 +1,3 @@ +P4 +260 128 +À`l diff --git a/scripts/mapper/param.pl b/scripts/mapper/param.pl new file mode 100644 index 00000000..eb03f2bc --- /dev/null +++ b/scripts/mapper/param.pl @@ -0,0 +1,41 @@ +#!/usr/local/bin/perl + +open(FRAMES_FH, 'frames') || die 'Cannot open file "frames".'; + + +# modify the INPUT stanza of a mpeg param file to reflect the actual input + +$[ = 1; # set array base to 1 +$, = ' '; # set output field separator +$\ = "\n"; # set output record separator + +line: while (<>) { + chop; # strip record separator + @Fld = split(' ', $_, 9999); + if (/^INPUT$/ .. /^END_INPUT$/) { + next line; + } + + print $_; +} + +printf (("INPUT\n")); +$_ = &Getline2('FRAMES_FH'); +$frames = $Fld[1]; +for ($i = 0; $i <= $frames; $i++) { + $file = sprintf('map-%d.gif', $i); + $size = -s $file; + if ($size>300 && $size<10000) { + printf "%s\n", $file; + } +} +printf (("END_INPUT\n")); + +sub Getline2 { + ($fh) = @_; + if ($getline_ok = (($_ = <$fh>) ne '')) { + chop; # strip record separator + @Fld = split(' ', $_, 9999); + } + $_; +} diff --git a/scripts/mapper/pgmmap.awk b/scripts/mapper/pgmmap.awk new file mode 100644 index 00000000..f551021b --- /dev/null +++ b/scripts/mapper/pgmmap.awk @@ -0,0 +1,66 @@ +#!/bin/awk -f + +# +# Convert a deity dump file into a Portable GreyMap of country numbers +# + +function abs(x) { + if (x>0) return x; + return -x; +} + +/own +sect/ { + getline; + while (NF>2) { + own[$2]=$1; + des[$2]=substr($3,0,1); + if ($1>max) max=$1; + getline; + } +} + +/own x y des/ { + getline; + while (NF>2) { + own[$2,$3]=$1; + des[$2,$3]=$4; + if ($1>max) max=$1; + if ($2 < left) left=$2; + if ($2 > right) right=$2; + if ($3 < top) top=$3; + if ($3 > bottom) bottom=$3; + getline; + } +} + +/^World size is [0-9]+ by [0-9]+./ { + width = $4; + height= $6 + 0; + left=-width/2; + right=width/2-1; + top= -height/2; + bottom = height/2-1; +} + +END { + printf("P2\n%d %d\n255\n",right-left+2,bottom-top+1); + for (y=top;y<=bottom;y++) { + printf("\n"); + if (y%2) { + color=own[right,y]; + if (color==0 && des[right,y]!=".") color=254; + printf("%d\n",color); + } + for (x=left + abs(y%2);x<=right;x+=2) { + color=own[x,y]; + if (color==0 && des[x,y]!=".") color=254; + printf("%d %d\n",color,color); + } + if (!(y%2)) { + color=own[left,y]; + if (color==0 && des[left,y]!=".") color=254; + printf("%d\n",color); + } + } +} + diff --git a/scripts/mapper/randppm.awk b/scripts/mapper/randppm.awk new file mode 100644 index 00000000..88111df6 --- /dev/null +++ b/scripts/mapper/randppm.awk @@ -0,0 +1,15 @@ +#!/bin/awk -f + +# Create random colors for colormap files + +BEGIN { + printf("P3\n16 16\n255\n"); + srand(); + printf("0 192 255\n"); + for (i=1;i<253;i++) { + printf("%d %d %d\n",32*int(rand()*6)+32,32*int(rand()*6)+32,32*int(rand()*6)+32); + } + printf("255 255 255\n"); + printf("128 128 128\n"); + printf("0 0 0\n"); +} diff --git a/scripts/mapper/text.pbm b/scripts/mapper/text.pbm new file mode 100644 index 00000000..bcb7abc7 --- /dev/null +++ b/scripts/mapper/text.pbm @@ -0,0 +1,3 @@ +P4 +24 9 +ü€F diff --git a/scripts/mapper/text.size b/scripts/mapper/text.size new file mode 100644 index 00000000..b35171ab --- /dev/null +++ b/scripts/mapper/text.size @@ -0,0 +1 @@ +text.pbm: PBM raw, 24 by 9 diff --git a/scripts/postresults b/scripts/postresults new file mode 100644 index 00000000..448978a1 --- /dev/null +++ b/scripts/postresults @@ -0,0 +1,66 @@ +#!/bin/csh +# +# postresults - Steve McClure (ionica@empire.cx), 1998 +# Do an automated post to rec.games.empire of a game's power chart +# and the last day's annoucements. +# +# To use, you need to create a visitor country in your game. For example, +# use "News" and "reporter" for the country name/rep of a special country +# used to get the power chart and annos. +# +# Also, this file references a "visitor" account. If you don't have one, +# you may want to take that line out. +# +# Note that this uses 'inews' to post. It's also very crude. But, it +# works great when used from a cronjob. +# +# You will also want to change the messages below to more accurately +# reflect your game. +# +# Note this is the same script I used to post results for the Winterfest +# '98 Tourney. I'm submitting it to wolfpack for inclusion with the +# server. + +# Change the following variables depending on where your binaries/game +# is located +setenv INEWS /usr/local/news/inews +setenv TMPDIR /empire/ionica/Tourney +setenv TMPFILE rd3game1.txt +setenv CLIENT /usr/local/bin/empire +setenv EMPIREHOST 149.84.128.9 +setenv EMPIREPORT 6641 +setenv EMPCOUNTRY News +setenv EMPREP reporter +setenv EMPTITLE "Winterfest '98 Tourney Round 3, Game #1" +setenv DEITYMAIL ionica@empire.net +# + +cd $TMPDIR + +echo '' > $TMPFILE +echo "This is the daily power chart and announcements for the" >> $TMPFILE +echo $EMPTITLE >> $TMPFILE +echo '' >> $TMPFILE +echo "This is the Final Round of the Winterfest '98 Tourney\!" >> $TMPFILE +echo '' >> $TMPFILE +echo "This game has a visitor account (Country 'visitor' Representative 'visitor')" >> $TMPFILE +echo "and can be found at host '$EMPIREHOST' and port '$EMPIREPORT'." >> $TMPFILE +echo '' >> $TMPFILE +echo "For more questions about this game, send e-mail to '$DEITYMAIL'" >> $TMPFILE +echo '' >> $TMPFILE +echo '------' >> $TMPFILE +echo '' >> $TMPFILE +$CLIENT $EMPCOUNTRY $EMPREP << EOF +pow new >> $TMPFILE +EOF +echo '' >> $TMPFILE +echo '------' >> $TMPFILE +echo '' >> $TMPFILE +$CLIENT $EMPCOUNTRY $EMPREP << EOF +wire 1 >> $TMPFILE +EOF +echo '' >> $TMPFILE +echo '------' >> $TMPFILE +echo '' >> $TMPFILE + +$INEWS -t "$EMPTITLE" -n "rec.games.empire" -r "$DEITYMAIL" "$TMPFILE" diff --git a/scripts/saveass b/scripts/saveass new file mode 100644 index 00000000..c5f6796b --- /dev/null +++ b/scripts/saveass @@ -0,0 +1,42 @@ +#! /bin/sh +#! This is a script that will probably end up saving your ass more times +#! then you'll probably want to admit. I wrote this back when I was co-deity +#! of the first empire tourney in December of 1990. This is a basic script +#! run from cron usually 15 miniutes before the update and keeps three copies +#! of the binaries and empire data on hand in tared and compressed format. +#! If you run faster games increase the frequency of the calls from cron. +#! 45 7,15,23 * * * /home/evil/EMP/bin/saveass +#! Above is a sample cron entry that does the backup three times a day. +#! This script should run on most all UNIX computers with all you'll have +#! to do is change the $BACKUPSDIR variable at the top. +#! +#! Dave 'TheEvilOne' Nye, evil@bbn.com +#! +#! Change these to your site specific directories. + +EMPIREDIR=/home/bughunt/navy +BACKUPSDIR=/home/bughunt/navy/backups + +cd $BACKUPSDIR +rm -rf data.old.old +rm -rf bin.old.old +mv data.old data.old.old +mv bin.old bin.old.old +mv data.new data.old +mv bin.new bin.old +mkdir data.new +mkdir bin.new + +#! Enough set up..let's do some work... + +cd $EMPIREDIR +tar -cf data.tar data +tar -cf bin.tar bin +mv $EMPIREDIR/data.tar $BACKUPSDIR/data.new +mv $EMPIREDIR/bin.tar $BACKUPSDIR/bin.new + +#! This will send you mail telling you that the backup went okay. + +/usr/local/bin/gzip $BACKUPSDIR/data.new/data* +ls -l $BACKUPSDIR/data.new +/usr/local/bin/gzip $BACKUPSDIR/bin.new/bin* diff --git a/src/client/Makefile b/src/client/Makefile new file mode 100644 index 00000000..dae6bb1b --- /dev/null +++ b/src/client/Makefile @@ -0,0 +1,99 @@ +# +# Empire - A multi-player, client/server Internet based war game. +# Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, +# Ken Stevens, Steve McClure +# +# 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 2 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, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# --- +# +# See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the +# related information and legal notices. It is expected that any future +# projects/authors will amend these files as needed. +# +# +# Empire front end Makefile +# (server mode) +# + +include ../../build.conf +include ../make.src +include ../make.defs + +CFILES = bit.c dtable.c expect.c globals.c handle.c host.c \ + hpux.c ioqueue.c ipglob.c login.c main.c queue.c saveargv.c \ + servcmd.c serverio.c tags.c termio.c termlib.c +OFILES = bit.o dtable.o expect.o globals.o handle.o host.o \ + hpux.o ioqueue.o ipglob.o login.o main.o queue.o saveargv.o \ + servcmd.o serverio.o tags.o termio.o termlib.o +OBJFILES = bit.obj dtable.obj expect.obj globals.obj handle.obj host.obj \ + hpux.obj ioqueue.obj ipglob.obj login.obj main.obj queue.obj saveargv.obj \ + servcmd.obj serverio.obj tags.obj termio.obj termlib.obj + +CLIENTLIBS= -ltermlib + +# +# Change this line to the compiler you are going to use. +# + +all: emp_client + +osx: emp_client + +emp_client: $(OFILES) + $(CC) -o emp_client $(OFILES) $(LFLAGS) $(CLIENTLIBS) -lc + +nt: emp_client.exe + +emp_client.exe: $(OBJFILES) $(CFILES) + link /OUT:emp_client.exe \ + /PDB:emp_client.pdb /NOLOGO \ + /NOD /DEBUG:full /DEBUGTYPE:cv /MACHINE:IX86 /NOLOGO \ + $(OBJFILES) \ + kernel32.lib \ + wsock32.lib \ + libcmt.lib \ + oldnames.lib + +# cl /D_WIN32 /Feemp_client.exe $(CFILES) wsock32.lib + +dgux: $(OFILES) + $(CC) $(CFLAGS) -dn -o emp_client $(OFILES) -lsocket -lnsl -ltermcap -lc + +solaris: + $(MAKE) emp_client CLIENTLIBS="-lsocket -lnsl -ltermcap -lc" + +hpux: + $(MAKE) emp_client CLIENTLIBS=-ltermcap + +clean: + -(rm -f $(OFILES)) + -(rm -f emp_client) + -(del /q $(OBJFILES)) + -(del /q emp_client.exe) + -(del /q emp_client.ilk) + -(del /q emp_client.pdb) + +install: + -(mkdir $(EMPDIR)/bin) + cp emp_client $(EMPDIR)/bin + +ntinstall: + -(mkdir $(NTINSTDIR)\bin) + copy emp_client.exe $(NTINSTDIR)\bin + +include ../make.rules +include Makedepend + diff --git a/src/client/Makefile.server b/src/client/Makefile.server new file mode 100644 index 00000000..272f842f --- /dev/null +++ b/src/client/Makefile.server @@ -0,0 +1,96 @@ +# +# Empire - A multi-player, client/server Internet based war game. +# Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, +# Ken Stevens, Steve McClure +# +# 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 2 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, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# --- +# +# See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the +# related information and legal notices. It is expected that any future +# projects/authors will amend these files as needed. +# +# +# Empire front end Makefile +# (server mode) +# + +include ../../build.conf +include ../make.src +include ../make.defs + +CFILES = bit.c dtable.c expect.c globals.c handle.c host.c \ + hpux.c ioqueue.c ipglob.c login.c main.c queue.c saveargv.c \ + servcmd.c serverio.c tags.c termio.c termlib.c +OFILES = bit.o dtable.o expect.o globals.o handle.o host.o \ + hpux.o ioqueue.o ipglob.o login.o main.o queue.o saveargv.o \ + servcmd.o serverio.o tags.o termio.o termlib.o +OBJFILES = bit.obj dtable.obj expect.obj globals.obj handle.obj host.obj \ + hpux.obj ioqueue.obj ipglob.obj login.obj main.obj queue.obj saveargv.obj \ + servcmd.obj serverio.obj tags.obj termio.obj termlib.obj + +CLIENTLIBS= -ltermlib + +# +# Change this line to the compiler you are going to use. +# + +all: emp_client + +emp_client: $(OFILES) + $(CC) -o emp_client $(OFILES) $(LFLAGS) $(CLIENTLIBS) -lc + +nt: emp_client.exe + +emp_client.exe: $(OBJFILES) $(CFILES) + link /OUT:emp_client.exe \ + /PDB:emp_client.pdb /NOLOGO \ + /NOD /DEBUG:full /DEBUGTYPE:cv /MACHINE:IX86 /NOLOGO \ + $(OBJFILES) \ + kernel32.lib \ + wsock32.lib \ + libcmt.lib \ + oldnames.lib + +# cl /D_WIN32 /Feemp_client.exe $(CFILES) wsock32.lib + +dgux: $(OFILES) + $(CC) $(CFLAGS) -dn -o emp_client $(OFILES) -lsocket -lnsl -ltermcap -lc + +solaris: + $(MAKE) emp_client CLIENTLIBS="-lsocket -lnsl -ltermcap -lc" + +hpux: + $(MAKE) emp_client CLIENTLIBS=-ltermcap + +clean: + -(rm -f $(OBJS)) + -(rm -f emp_client) + -(del /q $(OBJFILES)) + -(del /q emp_client.exe) + -(del /q emp_client.ilk) + -(del /q emp_client.pdb) + +install: + -(mkdir $(EMPDIR)/bin) + cp emp_client $(EMPDIR)/bin + +ntinstall: + copy emp_client.exe $(EMPDIR)\bin + +include ../make.rules +include Makedepend + diff --git a/src/client/Makefile.standalone b/src/client/Makefile.standalone new file mode 100644 index 00000000..8cb19edb --- /dev/null +++ b/src/client/Makefile.standalone @@ -0,0 +1,81 @@ +# +# Empire - A multi-player, client/server Internet based war game. +# Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, +# Ken Stevens, Steve McClure +# +# 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 2 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, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# --- +# +# See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the +# related information and legal notices. It is expected that any future +# projects/authors will amend these files as needed. +# +# +# Empire front end Makefile +# (standalone mode) +# + +CFILES = bit.c dtable.c expect.c globals.c handle.c host.c \ + hpux.c ioqueue.c ipglob.c login.c main.c queue.c saveargv.c \ + servcmd.c serverio.c tags.c termio.c termlib.c +OFILES = bit.o dtable.o expect.o globals.o handle.o host.o \ + hpux.o ioqueue.o ipglob.o login.o main.o queue.o saveargv.o \ + servcmd.o serverio.o tags.o termio.o termlib.o +OBJFILES = bit.obj dtable.obj expect.obj globals.obj handle.obj host.obj \ + hpux.obj ioqueue.obj ipglob.obj login.obj main.obj queue.obj saveargv.obj \ + servcmd.obj serverio.obj tags.obj termio.obj termlib.obj + +CFLAGS= -g +LIBS= -ltermlib + +# +# Change this line to the compiler you are going to use. +# +CC=cc + +empire: $(OFILES) + $(CC) -o empire $(OFILES) $(LIBS) + +linux: $(OFILES) + $(CC) -o empire $(OFILES) -lcurses + +nt: + cl /DWIN32 /Feempire.exe $(CFILES) wsock32.lib + +dgux: $(OFILES) + $(CC) $(CFLAGS) -dn -o empire $(OFILES) -lsocket -lnsl -ltermcap -lc + +solaris: + make empire LIBS="-lsocket -lnsl -ltermcap -lc" + +hpux: + make empire LIBS=-ltermcap + +clean: + rm -f $(OFILES) empire + +# created using mkmf +bit.o: bit.h +expect.o: fnlist.h +globals.o: fnlist.h proto.h +ioqueue.o: queue.h ioqueue.h +login.o: misc.h proto.h +main.o: misc.h proto.h queue.h ioqueue.h bit.h +queue.o: queue.h +servcmd.o: misc.h proto.h queue.h ioqueue.h +serverio.o: misc.h queue.h ioqueue.h +tags.o: tags.h +termio.o: tags.h diff --git a/src/client/README b/src/client/README new file mode 100644 index 00000000..a05f1ea6 --- /dev/null +++ b/src/client/README @@ -0,0 +1,47 @@ + +This is the basic Empire Client version 2.8. + +See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the +related information and legal notices. It is expected that any future +projects/authors will amend these files as needed. + +For questions and comments, please contact "wolfpack@wolfpackempire.com". + +Note that this client is the same client that is shipped with the +server. The only difference is the Makefile is copied from the +"Makefile.standalone" for the standalone distributions, and +from the "Makefile.server" for the server distributions. + +If you are building this with the server, it is built automatically. + +If you are building this standalone, continue reading to see how +to build the client. + +To make the program, edit ipglob.c and change empirehost[] to +point at the machine where the game is running (although this is +not necessary.) + +Also, if you are going to use "gcc", you need to change the Makefile +line "CC=cc" to "CC=gcc". + +To build for a Linux macihne, type "make linux". + +To build for a HP/UX machine, type "make hpux". + +To build for a DG/UX machine, type "make dgux". + +To build for a Solaris machine, type "make solaris". + +To build for a Windows machine, type "nmake win32". + (Note that the Windows port was built with MSVC 5.0) + +For other machines, type "make". + +You can change hosts on-the-fly by using environment variables -- see +the man page for details. But, for a short version, you can set the +EMPIREHOST and EMPIREPORT environment variables to the host and +port of the server you wish to connect to, and the client will +automatically use them instead of the built in ones. + +Also note that pipes do not work on the Windows versions. + diff --git a/src/client/bit.c b/src/client/bit.c new file mode 100644 index 00000000..500b13de --- /dev/null +++ b/src/client/bit.c @@ -0,0 +1,232 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * bit.c: Bit field manipulation routines + * + * Known contributors to this file: + * + */ + +#include "misc.h" + +/* + * bits.c + * + * allocate and search select-style bitfields + * + */ + +#include "bit.h" + +int bit_nfile; +int bit_nbytes; + +int getfdtablesize(); +void bit_zero(bit_fdmask); + +bit_fdmask +bit_newfdmask() +{ + extern s_char *malloc(); + bit_fdmask mask; + + if (bit_nfile == 0) { + bit_nfile = getfdtablesize(); + bit_nbytes = (bit_nfile + (BIT_BITSPERMASK-1)) / BIT_NBBY; + } + mask = (bit_fdmask) malloc(bit_nbytes); + (void) bit_zero(mask); + return mask; +} + +/* + * zero the bitfield + */ +void +bit_zero(bitp) + bit_fdmask bitp; +{ + bit_mask *mask; + register int i; + register int nwords; + + mask = bitp; + nwords = bit_nbytes / sizeof(*mask); + for (i=0; i +#endif +#ifdef _WIN32 +#include +#endif + +/*ARGSUSED*/ +void +setfdtablesize(min, start) + int min; + int start; +{ +#ifdef sequent + extern int errno; + + while (start >= min) { + if (setdtablesize(start) < 0) + break; + start -= 16; + } + errno = 0; +#endif +} + +int +getfdtablesize() +{ +#ifdef hpux + return _NFILE; +#else +#ifdef _WIN32 + return _NFILE; +#else + int getdtablesize(); + + return getdtablesize(); +#endif +#endif +} diff --git a/src/client/empire.6 b/src/client/empire.6 new file mode 100644 index 00000000..b7093ea8 --- /dev/null +++ b/src/client/empire.6 @@ -0,0 +1,77 @@ +.TH EMP_CLIENT 6 "19 Oct 1998" "empire client version 2.8" +.UC +.SH NAME +empire \- Empire client +.SH SYNOPSIS +.B empire +[ +.IR country +[ +.IR password +] +] +[ +.BI \-k +] +[ +.BI \-2 outfile +] +.br +.SH DESCRIPTION +.I empire +is a bare bones client to connect to the Empire server. Empire is a +global economic/political/military simulation game wherein players, +representing national governments, make "real-time" decisions +concerning resource allocation, national goals, international +diplomatic efforts, etc. Extensive records are kept for all players. +.PP +WARNING -- This game is not only addictive but often peels back +the thin veneer of civilization that hides the maniac within. +.SH OPTIONS +.TP +.IR country +the name of your country in the game +.TP +.IR password +the password for your country in the game +.TP +.BI \-k +if someone else is connected to your country, kill their connection +.TP +.BI \-2 outfile +redirect output to +.I outfile +.SH ENVIRONMENT VARIABLES +setenv EMPIREHOST server-machine to access the game on server-machine. +.PP +setenv EMPIREPORT port-number to access the game on port-number. +(the person running the game should tell you what this is... if not, +you should have the right default already.) +.PP +setenv COUNTRY country-name (optional) +.PP +setenv PLAYER representative-name (optional) +.SH AUTHORS +.nf +Primary Author is Dave Pare (mr-frog@scam.berkeley.edu) +Secondary authors/contributors may include: +James Anderson (jwa@k.cs.cmu.edu) +Jeff Anton (anton@postgres.berkeley.edu) +Phill Everson (everson@compsci.bristol.ac.uk) +Steven Grimm (koreth@ucscb.UCSC.EDU) +Lewis R. Jansen (lrj@helios.tn.cornell.edu) +Mike St. Johns (stjohns@edn-vax.arpa) +Nick Lai (lai@cs.ucla.edu) +Shelley Louie (slouie@cory.berekely.edu) +Steve McClure (ionica@empire.cx) +Chris Metcalf (metcalf-christopher@yale.arpa) +Dave Muir Sharnoff (muir@cogsci.berkeley.edu) +Keith Muller (muller@sdcc7.ucsd.edu) +Chuck Musciano (chuck@trantor.harris-atd.com) +Jeff Okamoto (okamoto%hpccc@hplabs.hp.com) +Julian Onions (jpo@computer-science.nottingham.ac.uk) +Kurt Pires (kjpires@ic.berkeley.edu) +Jim Reuter (reuter@decwrl.dec.com) +Peter Vukovich (peterv@monet.berkeley.edu) +Jeff Wallace (jeffw@scam.berkeley.edu) +John Yockey (johny@verinet.com) diff --git a/src/client/expect.c b/src/client/expect.c new file mode 100644 index 00000000..96dac3c9 --- /dev/null +++ b/src/client/expect.c @@ -0,0 +1,175 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * expect.c: Read from the socket, expecting to see a particular code. + * + * Known contributors to this file: + * Steve McClure, 1998 + */ + +#include "misc.h" +#include "fnlist.h" + +#include +#include +#include +#include +#ifndef _WIN32 +#include +#include +#else +#include +#endif + +int +expect(s, match, buf) + int s; + int match; + s_char *buf; +{ + int size; + s_char *p; + int n; + int code; + int newline; + s_char *ptr; + int cc; + + size = 1024; +#ifndef _WIN32 + (void) alarm(30); +#endif + ptr = buf; + n = recv(s, ptr, size, MSG_PEEK); + if (n <= 0) { + fprintf(stderr, "Expecting code %d\n", match); +#ifdef _WIN32 + errno = WSAGetLastError(); +#endif + perror("recv"); + return 0; + } + size -= n; + buf[n] = '\0'; + if ((p = strchr(ptr, '\n')) == 0) { + do { +#ifndef _WIN32 + cc = read(s, ptr, n); +#else + cc = recv(s, ptr, n, 0); +#endif + if (cc < 0) { +#ifdef _WIN32 + errno = WSAGetLastError(); +#endif + perror("expect: read"); + return 0; + } + if (cc != n) { + fprintf(stderr, + "expect: short read (%d not %d)\n", + cc, n); + return 0; + } + ptr += n; + if ((n = recv(s, ptr, size, MSG_PEEK)) <= 0) { + fprintf(stderr, "Expecting %d, got %s\n", + match, buf); + return 0; + } + size -= n; + ptr[n] = '\0'; + } while ((p = index(ptr, '\n')) == 0); + newline = 1 + p - buf; + *p = 0; + } else + newline = 1 + p - ptr; +#ifndef _WIN32 + cc = read(s, buf, newline); +#else + cc = recv(s, buf, newline, 0); +#endif + if (cc < 0) { +#ifdef _WIN32 + errno = WSAGetLastError(); +#endif + perror("expect: read #2"); + return 0; + } + if (cc != newline) { + fprintf(stderr, "expect: short read #2 (%d not %d)\n", + cc, newline); + return 0; + } + buf[newline] = '\0'; +#ifndef _WIN32 + (void) alarm(0); +#endif + if (!isxdigit(*buf)) { + fprintf(stderr, "Expecting %d, got %s\n", match, buf); + return 0; + } + if (isdigit(*buf)) + code = *buf - '0'; + else { + if (isupper(*buf)) + *buf = tolower(*buf); + code = 10 + *buf - 'a'; + } + if (code == match) + return 1; + return 0; +} + +void +sendcmd(s, cmd, arg) + int s; + int cmd; + s_char *arg; +{ + extern struct fn fnlist[]; + s_char buf[128]; + int cc; + int len; + + (void) sprintf(buf, "%s %s\n", fnlist[cmd].name, arg != 0 ? arg : ""); + len = strlen(buf); +#ifndef _WIN32 + cc = write(s, buf, len); +#else + cc = send(s, buf, len, 0); +#endif + if (cc < 0) { +#ifdef _WIN32 + errno = WSAGetLastError(); +#endif + perror("sendcmd: write"); + } + if (cc != len) { + fprintf(stderr, "sendcmd: short write (%d not %d)\n", cc, len); + } +} diff --git a/src/client/fnlist.h b/src/client/fnlist.h new file mode 100644 index 00000000..5de58300 --- /dev/null +++ b/src/client/fnlist.h @@ -0,0 +1,45 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * fnlist.h: function list structure + * + * Known contributors to this file: + * Dave Pare, 1986 + * Steve McClure, 1998 + */ + +#ifndef _FNLIST_H_ +#define _FNLIST_H_ + +struct fn { + int (*func)(); + s_char *name; + int value; +}; + +#endif _FNLIST_H_ + diff --git a/src/client/globals.c b/src/client/globals.c new file mode 100644 index 00000000..9f754f7f --- /dev/null +++ b/src/client/globals.c @@ -0,0 +1,51 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * globals.c: Globals for the client + * + * Known contributors to this file: + * Dave Pare, 1986 + */ + +#include +#include +#include "misc.h" +#include "fnlist.h" +#include "proto.h" + +struct fn fnlist[] = { + { NULL, "user", USER,}, + { NULL, "coun", COUN,}, + { NULL, "quit", QUIT,}, + { NULL, "pass", PASS,}, + { NULL, "play", PLAY,}, + { NULL, "list", LIST,}, + { NULL, "cmd", CMD,}, + { NULL, "ctld", CTLD,}, + { NULL, "kill", KILL,}, + { NULL, "", 0,}, +}; diff --git a/src/client/h.h b/src/client/h.h new file mode 100644 index 00000000..014f10ef --- /dev/null +++ b/src/client/h.h @@ -0,0 +1,39 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * h.h: Simple typedef + * + * Known contributors to this file: + * Steve McClure, 1998 + */ + +#ifndef _H_H_ +#define _H_H_ + +typedef char s_char; + +#endif diff --git a/src/client/handle.c b/src/client/handle.c new file mode 100644 index 00000000..e9e4ccd8 --- /dev/null +++ b/src/client/handle.c @@ -0,0 +1,52 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * handle.c: Interrupt handler + * + * Known contributors to this file: + * Dave Pare, 1989 + * Steve McClure, 1998 + */ + +#if !defined(_WIN32) +#include +#endif + +int +handleintr(s) + int s; +{ + extern int interrupt; + + if (interrupt) { + /* tacky, but it works */ + if (write(s, "\naborted\n", 1+7+1) <= 0) + return 0; + interrupt = 0; + } + return 1; +} diff --git a/src/client/host.c b/src/client/host.c new file mode 100644 index 00000000..ab3da133 --- /dev/null +++ b/src/client/host.c @@ -0,0 +1,133 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * host.c: make stream connection to empire + * + * Known contributors to this file: + * Dave Pare, 1989 + * Steve McClure, 1998 + */ + +#include +#include +#ifndef _WIN32 +#include +#include +#include +#include +#else +#include +#endif +#include +#include "misc.h" + +int +hostaddr(name, addr) + s_char *name; + struct sockaddr_in *addr; +{ +#ifndef _WIN32 + extern u_long inet_addr(); +#endif + struct hostent *hp; + + if (name == 0 || *name == 0) + return 0; + if (isdigit(*name)) { + addr->sin_addr.s_addr = inet_addr(name); + } else { + hp = gethostbyname(name); + if (hp == NULL) { + fprintf(stderr, "%s: No such host\n", name); + return 0; + } + bcopy(hp->h_addr, (s_char *)&addr->sin_addr, + sizeof(addr->sin_addr)); +#ifdef _WIN32 + printf("Trying to connect to '%s'\n", inet_ntoa(addr->sin_addr)); + fflush(stdout); +#endif + } + return 1; +} + +int +hostport(name, addr) + s_char *name; + struct sockaddr_in *addr; +{ + struct servent *sp; +#ifndef _WIN32 + int atoi(); +#endif + + if (name == 0 || *name == 0) + return 0; + if (isdigit(*name)) { +#ifndef _WIN32 + addr->sin_port = htons(atoi(name)); +#else + addr->sin_port = atoi(name); + addr->sin_port = htons(addr->sin_port); +#endif + } else { + sp = getservbyname(name, "tcp"); + if (sp == NULL) + return 0; + addr->sin_port = sp->s_port; + } + return 1; +} + +int +hostconnect(addr) + struct sockaddr_in *addr; +{ + int s; + + s = socket(AF_INET, SOCK_STREAM, 0); + if (s < 0) { +#ifdef _WIN32 + errno = WSAGetLastError(); +#endif + perror("socket"); + return -1; + } + addr->sin_family = AF_INET; + if (connect(s, (struct sockaddr *)addr, sizeof(*addr)) < 0) { +#ifdef _WIN32 + errno = WSAGetLastError(); +#endif + perror("connect"); +#ifdef _WIN32 + printf("Check that your EMPIREHOST and EMPIREPORT are correct.\n"); +#endif + (void) close(s); + return -1; + } + return s; +} diff --git a/src/client/hpux.c b/src/client/hpux.c new file mode 100644 index 00000000..422b20cb --- /dev/null +++ b/src/client/hpux.c @@ -0,0 +1,95 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * hpux.c: hpux dependencies + * + * Known contributors to this file: + * + */ + +#ifdef hpux +#include +#define NULL 0 +#include "misc.h" + +s_char * +rindex(sp, c) + register s_char *sp; + register int c; +{ + register s_char *r; + + r = NULL; + do { + if (*sp == c) + r = sp; + } while (*sp++); + return r; +} + +s_char * +index(sp, c) + register s_char *sp; + register int c; +{ + do { + if (*sp == c) + return (sp); + } while (*sp++); + return NULL; +} + +int +ffs(marg) + register unsigned marg; +{ + register unsigned bval; + register int i; + + if (marg == 0) + return 0; + for (bval=1, i=1; i <= 32; i++, bval <<= 1) + if (marg & bval) + return i; + return 0; +} + +bzero(ptr, len) + s_char *ptr; + int len; +{ + memset(ptr, 0, len); +} + +bcopy(src, dst, len) + s_char *src; + s_char *dst; + int len; +{ + memcpy(dst, src, len); +} +#endif diff --git a/src/client/ioqueue.c b/src/client/ioqueue.c new file mode 100644 index 00000000..b1eecb33 --- /dev/null +++ b/src/client/ioqueue.c @@ -0,0 +1,322 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * ioqueue.c: Manage an i/o queue + * + * Known contributors to this file: + * Steve McClure, 1998 + */ + +#include +#include +#ifndef _WIN32 +#include +#include +#endif +#include "misc.h" +#include "queue.h" +#include "ioqueue.h" + +#ifdef _WIN32 +typedef struct iovec { + char *iov_base; + int iov_len; +} iovec_t; +#endif + + +static int ioqtobuf(); +static int ioqtoiov(); +static void enqueuecc(); +static int dequeuecc(); + +void insque(); +void remque(); +void initque(); +struct qelem *makeqt(); +void free(); + +void +ioq_init(ioq, bsize) + struct ioqueue *ioq; + int bsize; +{ + extern s_char num_teles[]; + + initque(&ioq->queue); + ioq->cc = 0; + ioq->bsize = bsize; + *num_teles = '\0'; +} + +/* + * copy batch of pointers into the passed + * iovec, but don't actually dequeue the data. + * return # of iovec initialized. + */ +int +ioq_peekiov(ioq, iov, max) + struct ioqueue *ioq; + struct iovec *iov; + int max; +{ + if (ioq->cc <= 0) + return 0; + return ioqtoiov(ioq, iov, max); +} + +/* + * Copy the specified number of characters into the buffer + * provided, without actually dequeueing the data. Return + * number of bytes actually found. + */ +int +ioq_peek(ioq, buf, cc) + struct ioqueue *ioq; + s_char *buf; + int cc; +{ + return ioqtobuf(ioq, buf, cc); +} + +int +ioq_dequeue(ioq, cc) + struct ioqueue *ioq; + int cc; +{ + if (dequeuecc(ioq, cc) != cc) + return 0; + return cc; +} + +int +ioq_read(ioq, buf, cc) + struct ioqueue *ioq; + s_char *buf; + int cc; +{ + int n; + + n = ioqtobuf(ioq, buf, cc); + if (n > 0) + dequeuecc(ioq, n); + return n; +} + +void +ioq_write(ioq, buf, cc) + struct ioqueue *ioq; + s_char *buf; + int cc; +{ + enqueuecc(ioq, buf, cc); +} + +int +ioq_qsize(ioq) + struct ioqueue *ioq; +{ + return ioq->cc; +} + +void +ioq_drain(ioq) + struct ioqueue *ioq; +{ + struct io *io; + struct qelem *qp; + + while ((qp = ioq->queue.q_forw) != &ioq->queue) { + io = (struct io *) qp; + free(io->data); + (void) remque(&io->queue); + (void) free(io); + } + ioq->cc = 0; +} + +s_char * +ioq_gets(ioq, buf, cc) + struct ioqueue *ioq; + s_char *buf; + int cc; +{ + register s_char *p; + register s_char *end; + int nbytes; + + nbytes = ioqtobuf(ioq, buf, cc); + if (nbytes < cc) + cc = nbytes; + end = &buf[cc]; + for (p = buf; p < end && *p; p++) { + if (*p == '\n') { + *p = '\0'; + dequeuecc(ioq, (p - buf) + 1); + return buf; + } + } + return 0; +} + +/* + * all the rest are local to this module + */ + + +/* + * copy cc bytes from ioq to buf. + * this routine doesn't free memory; this is + * left for a higher level. + */ +static +int +ioqtobuf(ioq, buf, cc) + register struct ioqueue *ioq; + s_char *buf; + int cc; +{ + register struct io *io; + struct qelem *qp; + s_char *offset; + int nbytes; + int nleft; + + nleft = cc; + offset = buf; + for (qp = ioq->queue.q_forw; qp != &ioq->queue; qp = qp->q_forw) { + io = (struct io *) qp; + if ((nbytes = io->nbytes - io->offset) < 0) { + fprintf(stderr, "ioqtobuf: offset %d nbytes %d\n", + io->offset, io->nbytes); + continue; + } + if (nbytes > 0) { + if (nleft < nbytes) + nbytes = nleft; + bcopy(io->data + io->offset, offset, nbytes); + offset += nbytes; + nleft -= nbytes; + } + } + return offset - buf; +} + +/* + * translate "around" max bytes to an iovec + * array. The limit max is only advisory, + * and more may get buffered. It is an attempt to limit + * really silly sends -- like sending 40k on a socket + * with one writev for example. This makes the processing + * of a full ioqueue still be quick. + */ +static +int +ioqtoiov(ioq, iov, max) + register struct ioqueue *ioq; + register struct iovec *iov; + register int max; +{ + register struct io *io; + register int cc; + register int niov; + struct qelem *qp; + + cc = 0; + niov = 0; + qp = ioq->queue.q_forw; + for (qp = ioq->queue.q_forw; qp != &ioq->queue; qp = qp->q_forw) { + io = (struct io *) qp; + if (niov >= MAXIOV || cc >= max) + break; + iov->iov_base = io->data + io->offset; + iov->iov_len = io->nbytes - io->offset; + cc += io->nbytes - io->offset; + niov++; + iov++; + } + return niov; +} + +/* + * append a buffer to the end of the ioq. + */ +static void +enqueuecc(ioq, buf, cc) + struct ioqueue *ioq; + s_char *buf; + int cc; +{ + struct io *io; + + io = (struct io *) malloc(sizeof(*io)); + io->nbytes = cc; + io->offset = 0; + io->data = buf; + insque(&io->queue, ioq->queue.q_back); + ioq->cc += cc; +} + +/* + * remove cc bytes from ioqueue ioq + * free memory, dequeue io elements + * which are no longer used. + */ +static +int +dequeuecc(ioq, cc) + register struct ioqueue *ioq; + register int cc; +{ + register struct io *io; + register struct qelem *qp; + register int nbytes; + register int there; + + nbytes = 0; + while ((qp = ioq->queue.q_forw) != &ioq->queue) { + io = (struct io *) qp; + there = io->nbytes - io->offset; + if (there < 0) { + fprintf(stderr, "dequeuecc: nbytes %d, offset %d\n", + io->nbytes, io->offset); + continue; + } + if (cc > there) { + cc -= there; + nbytes += there; + (void) remque(&io->queue); + free(io->data); + } else { + io->offset += cc; + nbytes += cc; + break; + } + } + ioq->cc -= nbytes; + return nbytes; +} diff --git a/src/client/ioqueue.h b/src/client/ioqueue.h new file mode 100644 index 00000000..4fe67dc8 --- /dev/null +++ b/src/client/ioqueue.h @@ -0,0 +1,49 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * ioqueue.h: stores and frees data associated with a file descriptor. + * uses writev to write, and read to read. + * + * Known contributors to this file: + * + */ + +#define MAXIOV 16 + +struct ioqueue { + struct qelem queue; /* queue fwd/back */ + int bsize; /* basic block size */ + int cc; /* character count */ +}; + +struct io { + struct qelem queue; /* list of ioqueue elements */ + int nbytes; /* number of data bytes present */ + int offset; /* offset into current entry */ + s_char *data; /* pointer to start */ +}; + diff --git a/src/client/login.c b/src/client/login.c new file mode 100644 index 00000000..b3ca3609 --- /dev/null +++ b/src/client/login.c @@ -0,0 +1,126 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * login.c: Log into an empire server + * + * Known contributors to this file: + * Dave Pare, 1989 + * Steve McClure, 1998 + */ + +#include "misc.h" +#include "proto.h" + +#include +#include +#if !defined(_WIN32) +#include +#endif + +int expect(); +int atoi(); +void sendcmd(); + +int +login(s, uname, cname, cpass, kill_proc) + int s; + s_char *uname; + s_char *cname; + s_char *cpass; + int kill_proc; +{ + s_char tmp[128]; + s_char buf[1024]; + s_char *ptr; + s_char *p; + + if (!expect(s, C_INIT, buf)) + return 0; + (void) sendcmd(s, USER, uname); + if (!expect(s, C_CMDOK, buf)) + return 0; + if (cname == 0) { + (void) printf("Country name? "); + cname = fgets(tmp, 128, stdin); + if (cname == 0 || *cname == 0) + return 0; + } + if (cname[strlen(cname) - 1] == '\n') + cname[strlen(cname) - 1] = 0; + if (cname[strlen(cname) - 1] == '\r') + cname[strlen(cname) - 1] = 0; + (void) sendcmd(s, COUN, cname); + if (!expect(s, C_CMDOK, buf)) { + (void) fprintf(stderr, "empire: no such country\n"); + return 0; + } + if (cpass == 0) { +#ifndef _WIN32 + cpass = (s_char *)getpass("Your name? "); +#else + printf("Note: This is echoed to the screen\n"); + printf("Your name? "); + cpass = tmp; + *cpass = 0; + fgets(cpass, 128, stdin); +#endif + if (cpass == 0 || *cpass == 0) + return 0; + } + (void) printf("\n"); + (void) sendcmd(s, PASS, cpass); + bzero(cpass, strlen(cpass)); /* for core dumps */ + if (!expect(s, C_CMDOK, buf)) { + (void) fprintf(stderr, "Bad password\n"); + return 0; + } + if (kill_proc) { + (void) sendcmd(s, KILL, (s_char *)0); + (void) printf("\n\t-=O=-\n"); + (void) expect(s, C_EXIT, buf); + fprintf(stderr, "%s\n", buf); + return 0; + } + (void) sendcmd(s, PLAY, (s_char *)0); + (void) printf("\n\t-=O=-\n"); + if (!expect(s, C_INIT, buf)) { + fprintf(stderr, "%s\n", buf); + return 0; + } + for (ptr = buf; !isspace(*ptr); ptr++) + ; + ptr++; + p = index(ptr, '\n'); + if (p != 0) + *p = 0; + if (atoi(ptr) != CLIENTPROTO) { + printf("Empire client out of date; get new version!\n"); + printf(" this version: %d, current version: %d\n", + CLIENTPROTO, atoi(ptr)); + } + return 1; +} diff --git a/src/client/main.c b/src/client/main.c new file mode 100644 index 00000000..cb539c60 --- /dev/null +++ b/src/client/main.c @@ -0,0 +1,362 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * main.c: client main function + * + * Known contributors to this file: + * Dave Pare, 1986 + * Steve McClure, 1998 + */ + +#ifdef _NTSDK +#undef _NTSDK +#endif + +#include "misc.h" +#include "proto.h" +#include "queue.h" +#include "ioqueue.h" +#include "bit.h" + +#include +#ifndef _WIN32 +#include +#endif +#include +#include +#include +#ifndef _WIN32 +#include +#include +#include +#else +#include +#include +#include +#endif + +#ifdef _WIN32 +HANDLE hStdIn; +#endif + +extern int errno; + +#define RETRY 3 + +int interrupt; +int sock; + +void saveargv(); +void getsose(); +int hostport(); +int hostaddr(); +int hostconnect(); +int login(); +void ioq_init(); +void io_init(); +void bit_copy(); +int handleintr(); +int termio(); +int serverio(); +void servercmd(); +void ioq_drain(); + + +#ifdef _WIN32 +s_char * +index(str, c) +s_char *str; +char c; +{ + static s_char *p; + + p = str; + while (p && *p) { + if (*p == c) + return (s_char *)p; + p++; + } + return (s_char *)0; +} + +bzero(ptr, size) +s_char *ptr; +int size; +{ + int i; + + for (i = 0; i < size; i++) + ptr[i] = 0; +} + +bcopy(src, dest, size) +unsigned char *src, *dest; +int size; +{ + int i; + unsigned char *d = dest, + *s = src; + + for (i = 0; i < size; i++) + *d++ = *s++; +} +#endif + +int +main(ac, av) + int ac; + s_char *av[]; +{ +#ifdef _WIN32 + WSADATA WsaData; + int err; + fd_set readfds; + struct timeval tm; + INPUT_RECORD InpBuffer[10]; + DWORD numevents; + DWORD stdinmode; + SECURITY_ATTRIBUTES security; + void intr(void); +#endif + extern s_char *getenv(); + extern s_char empireport[]; + extern s_char empirehost[]; + bit_fdmask mask; + bit_fdmask savemask; + struct ioqueue server; + s_char *argv[128]; + int i, j; + s_char *ptr; + s_char *auxout_fname; + FILE *auxout_fp; +#ifndef _WIN32 + struct passwd *pwd; + void intr(); +#endif + struct sockaddr_in sin; + int n; + s_char *cname; + s_char *pname; + int retry = 0; + int send_kill = 0; + +#ifdef _WIN32 + err = WSAStartup (0x0101, &WsaData); + if (err == SOCKET_ERROR) { + printf ("WSAStartup Failed\n"); + return FALSE; + } +#else + mask = bit_newfdmask(); + savemask = bit_newfdmask(); +#endif + bzero((s_char *)argv, sizeof(argv)); + saveargv(ac, av, argv); + auxout_fname = 0; + auxout_fp = 0; + for (i = j = 1; i < ac; ++i) { + ptr = argv[i]; + if (strcmp(ptr, "-2") == 0) { + if (i + 1 >= ac) { + fprintf(stderr, "-2: Missing filename!\n"); + exit(1); + } + auxout_fname = argv[i+1]; + ++i; + continue; + } + else if (strcmp(ptr, "-k") == 0) { + send_kill = 1; + continue; + } + argv[j] = argv[i]; + ++j; + } + ac = j; + if (auxout_fname && (auxout_fp = fopen(auxout_fname, "a")) == NULL) { + fprintf(stderr, "Unable to open %s for append\n", auxout_fname); + exit(1); + } +#ifndef _WIN32 + pwd = getpwuid(getuid()); + if (pwd == NULL) { + fprintf(stderr, "You don't exist. Go away\n"); + exit(1); + } +#endif + getsose(); + if (!hostport(getenv("EMPIREPORT"), &sin) && + !hostport("empire", &sin) && + !hostport(empireport, &sin)) { + fprintf(stderr, "No empire port\n"); + exit(1); + } + if (!hostaddr(getenv("EMPIREHOST"), &sin) && + !hostaddr(empirehost, &sin)) { + fprintf(stderr, "No empire host\n"); + exit(1); + } + if ((sock = hostconnect(&sin)) < 0) + exit(1); + cname = getenv("COUNTRY"); + pname = getenv("PLAYER"); + if (ac > 1) + cname = argv[1]; + if (ac > 2) + pname = argv[2]; +#ifndef _WIN32 + if (!login(sock, pwd->pw_name, cname, pname, send_kill)) { +#else + if (!login(sock, "win-empcl2.8", cname, pname, send_kill)) { +#endif + close(sock); + exit(1); + } + ioq_init(&server, 2048); + io_init(); + mask = bit_newfdmask(); +#ifndef _WIN32 + BIT_SETB(0, savemask); + BIT_SETB(sock, savemask); +#endif + (void) signal(SIGINT, intr); +#ifndef _WIN32 + (void) signal(SIGPIPE, SIG_IGN); + while (BIT_ISSETB(sock, savemask)) { + bit_copy(savemask, mask); + n = select(sock+1, (fd_set *)mask, (fd_set *)0, (fd_set *)0, + (struct timeval *)0); + if (interrupt) { + if (!handleintr(sock)) + break; + errno = 0; + } + if (n <= 0) { + if (errno == EINTR) { + perror("select"); + (void) close(sock); + BIT_CLRB(sock, savemask); + } + } else { + if (BIT_ISSETB(0, mask)) { + if (!termio(0, sock, auxout_fp)) { + if (retry++ >= RETRY) { + BIT_CLRB(0, savemask); + } + } else { + retry = 0; + } + } + if (BIT_ISSETB(sock, mask)) { + if (!serverio(sock, &server)) + BIT_CLRB(sock, savemask); + else + servercmd(&server, auxout_fp); + } + } + } +#else + tm.tv_sec = 0; + tm.tv_usec = 1000; + + security.nLength = sizeof(SECURITY_ATTRIBUTES); + security.lpSecurityDescriptor = NULL; + security.bInheritHandle = TRUE; + hStdIn = CreateFile("CONIN$", + GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + &security, + OPEN_EXISTING, + (DWORD)NULL, + NULL); + + if (hStdIn == INVALID_HANDLE_VALUE) { + printf("Error getting hStdIn.\n"); + fflush(stdout); + } + err = GetConsoleMode(hStdIn, &stdinmode); + if (!err) { + printf("Error getting console mode.\n"); + fflush(stdout); + } + stdinmode |= ENABLE_LINE_INPUT|ENABLE_ECHO_INPUT; + err = SetConsoleMode(hStdIn, stdinmode); + if (!err) { + printf("Error setting console mode.\n"); + fflush(stdout); + } + while (1) { + FD_ZERO(&readfds); + FD_SET(sock, &readfds); + n = select(sock+1, &readfds, (fd_set *)0, (fd_set *)0, + (struct timeval *)&tm); + if (n < 0) { + if (errno == EINTR) { + errno = WSAGetLastError(); + perror("select"); + (void) close(sock); + break; + } + } else { + if (WaitForSingleObject(hStdIn, 10) != WAIT_TIMEOUT) { + if (!termio(-1, sock, auxout_fp)) { + if (retry++ >= RETRY) { + ; + } + } else { + retry = 0; + } + FlushConsoleInputBuffer(hStdIn); + } + if (FD_ISSET(sock, &readfds)) { + if (!serverio(sock, &server)) + break; + else + servercmd(&server, auxout_fp); + } + } + } + CloseHandle(hStdIn); +#endif + ioq_drain(&server); + (void) close(sock); + exit(0); + return 0; /* Shut the compiler up */ +} + +void +#ifdef _WIN32 +intr(void) +#else +intr() +#endif +{ + interrupt++; +#ifdef hpux + signal(SIGINT, intr); +#endif +} diff --git a/src/client/misc.h b/src/client/misc.h new file mode 100644 index 00000000..b5f3de6b --- /dev/null +++ b/src/client/misc.h @@ -0,0 +1,136 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * misc.h: Misc client definitions + * + * Known contributors to this file: + * Steve McClure, 1998 + */ + +#ifndef _MISC_H_ +#define _MISC_H_ + +#include +#include +#include + +#ifdef hpux +#include +#else +#ifdef _WIN32 +#include + +typedef unsigned char u_char; +typedef unsigned short u_short; +#else +#include +#endif +#endif + +#define MAXNOC 100 + +#define WORLD_X 32 +#define WORLD_Y 16 + +#define ETUS 60 /* Defined here.. may be overridden later, + but things still use this define */ +typedef u_char natid; /* also change NSC_NATID in nsc.h */ +#if !defined(aix) && !defined(sgi) +#ifndef ultrix /* already defined in ultrix */ +typedef char s_char; /* change to signed char for aix */ +#endif ultrix +#else +typedef signed char s_char; +#endif /* !aix && !sgi */ +typedef short coord; /* also change NSC_COORD in nsc.h */ +/* + * watch it; your compiler might not like this. + * If you think this is bogus, look at /usr/include/struct.h + */ +#define OFFSET(stype, oset) ((int)(&(((struct stype *)0)->oset))) +#define SETOFF(sinst, oset) ((s_char *) (sinst) + (oset)) + +#ifndef bit +#define bit(x) (1<<(x)) +#endif + +#define minutes(x) (60*(x)) +#define hours(x) (60*60*(x)) +#define days(x) (60*60*24*(x)) + +typedef void (*voidfunc)(); + + /* return codes from command routines */ +#define RET_OK 0 /* command completed sucessfully */ +#define RET_FAIL 1 /* command completed unsucessfully [?] */ +#define RET_SYN 2 /* syntax error in command */ +#define RET_SYS 3 /* system error (missing file, etc) */ + +#define MAX_DISTPATH_LEN 10 /* Has to go somewhere */ + +/* + * references to library functions which aren't related to any + * particular object, and are of general interest + */ +extern long random(); + +extern double dmax(); +extern double dmin(); + +extern s_char *fmt(); +extern s_char *copy(); +extern s_char *numstr(); +extern s_char *esplur(); +extern s_char *splur(); +extern s_char *iesplur(); +extern s_char *plur(); +extern s_char *getstarg(); +extern s_char *getstring(); + +/* + * frequently used libc functions + */ + +#ifndef _WIN32 +extern s_char *malloc(); +extern s_char *calloc(); +#endif + +#if (!defined (aix) && !defined (sgi)) +extern s_char *ctime(); +extern s_char *strncpy(); +extern s_char *strcpy(); +#ifndef NeXT +extern s_char *index(); +extern s_char *rindex(); +#endif /* NeXT */ +#endif /* !aix && !sgi*/ + +extern time_t time(); +extern double atof(); + +#endif diff --git a/src/client/proto.h b/src/client/proto.h new file mode 100644 index 00000000..c7903565 --- /dev/null +++ b/src/client/proto.h @@ -0,0 +1,68 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * proto.h: Protocol for client + * + * Known contributors to this file: + * Dave Pare, 1986 + */ +/* + * The master copy of this is in the standard include directory. + * A copy is placed in the client directory to allow client + * to be compiled independently of the rest of the game. + */ + +#define CLIENTPROTO 2 /* if new things are added, bump this */ + +#define USER 0 +#define COUN 1 +#define QUIT 2 +#define PASS 3 +#define PLAY 4 +#define LIST 5 +#define CMD 6 +#define CTLD 7 +#define WAT 8 +#define KILL 9 +#define GKILL 10 /* kill even if process stuck --ts */ + +#define C_CMDOK 0x0 +#define C_DATA 0x1 +#define C_INIT 0x2 +#define C_EXIT 0x3 +#define C_FLUSH 0x4 +#define C_NOECHO 0x5 +#define C_PROMPT 0x6 +#define C_ABORT 0x7 +#define C_REDIR 0x8 +#define C_PIPE 0x9 +#define C_CMDERR 0xA +#define C_BADCMD 0xB +#define C_EXECUTE 0xC +#define C_FLASH 0xD +#define C_INFORM 0xE +#define C_LAST 0xE diff --git a/src/client/queue.c b/src/client/queue.c new file mode 100644 index 00000000..896035b8 --- /dev/null +++ b/src/client/queue.c @@ -0,0 +1,80 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * queue.c: implementation of various queuing routines + * + * Known contributors to this file: + * Steve McClure, 1998 + */ + +#if !defined(_WIN32) +#include +#endif +#include "misc.h" +#include "queue.h" + +void +insque(p, q) + struct qelem *p; + struct qelem *q; +{ + p->q_forw = q->q_forw; + p->q_back = q; + q->q_forw->q_back = p; + q->q_forw = p; +} + +void +remque(p) + struct qelem *p; +{ + p->q_back->q_forw = p->q_forw; + p->q_forw->q_back = p->q_back; +} + +void +initque(p) + struct qelem *p; +{ + p->q_forw = p; + p->q_back = p; +} + +struct qelem * +makeqt(nelem) + int nelem; +{ + extern s_char *malloc(); + struct qelem *table; + struct qelem *qp; + int i; + + table = (struct qelem *) malloc(sizeof(*table) * nelem); + for (i=0,qp=table; iq_forw == (p)) + +struct qelem { + struct qelem *q_forw; + struct qelem *q_back; +}; + +#endif _QUEUE diff --git a/src/client/saveargv.c b/src/client/saveargv.c new file mode 100644 index 00000000..2d6fcc80 --- /dev/null +++ b/src/client/saveargv.c @@ -0,0 +1,53 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * saveargv.c: routine to copy and clear argv + * + * Known contributors to this file: + * + */ + +#include "misc.h" + +void +saveargv(ac, src, dst) + int ac; + s_char **src; + s_char **dst; +{ + extern s_char *strcpy(); + extern s_char *malloc(); + register s_char *ptr; + register int i; + + for (i = 0; i < ac; i++) { + dst[i] = strcpy(malloc(strlen(src[i])+1), src[i]); + ptr = src[i]; + while (*ptr) + *ptr++ = ' '; + } +} diff --git a/src/client/servcmd.c b/src/client/servcmd.c new file mode 100644 index 00000000..d2d43adf --- /dev/null +++ b/src/client/servcmd.c @@ -0,0 +1,373 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * servercmd.c: Change the state depending on the command from the server. + * + * Known contributors to this file: + * Dave Pare, 1989 + * Steve McClure, 1998 + */ + +#include "misc.h" +#include "proto.h" +#include "queue.h" +#include "ioqueue.h" + +#include +#include +#include +#if !defined(_WIN32) +#include +#endif + +extern s_char *gettag(); + +s_char num_teles[64]; +static s_char the_prompt[1024]; +static int mode; +static int nbtu; +static int nmin; +FILE *redir_fp; +FILE *pipe_fp; +int exec_fd; + +void prompt(); +void doredir(); +void dopipe(); +void doexecute(); +void output(); +void screen(); +void free(); +int sendeof(); +int termio(); +void _noecho(); + +extern s_char *SO; +extern s_char *SE; + +void +servercmd(ioq, auxfi) + struct ioqueue *ioq; + FILE *auxfi; +{ + s_char *ioq_gets(struct ioqueue *, s_char *, int); + s_char buf[1024]; + s_char *p; + int code; + + while (ioq_gets(ioq, buf, sizeof(buf))) { + p = buf; + while (*p && !isspace(*p)) + p++; + *p++ = 0; + if (isalpha(*buf)) + code = 10 + (*buf - 'a'); + else + code = *buf - '0'; + switch (code) { + case C_PROMPT: + if (sscanf(p, "%d %d", &nbtu, &nmin) != 2) { + fprintf(stderr, "prompt: bad server prompt %s\n", p); + } + mode = code; + sprintf(the_prompt, "[%d:%d] Command : ", nbtu, nmin); + prompt(auxfi); + break; + case C_REDIR: + doredir(p); + break; + case C_PIPE: + dopipe(p); + break; + case C_FLUSH: + mode = code; + sprintf(the_prompt, "%s", p); + prompt(auxfi); + break; + case C_EXECUTE: + doexecute(p, auxfi); + break; + case C_INFORM: + if (*p) { + p[strlen(p)-1] = '\0'; + sprintf(num_teles, "(%s) ", p + 1); + if (!redir_fp && + !pipe_fp && + !exec_fd) { + putchar('\07'); + prompt(0); + } + } + else + *num_teles = '\0'; + break; + default: + output(code, p, auxfi); + break; + } + } +} + +void +prompt(auxfi) + FILE *auxfi; +{ + if (mode == C_PROMPT) { + if (redir_fp) { + (void) fclose(redir_fp); + redir_fp = 0; + } else if (pipe_fp) { +#ifndef _WIN32 + (void) pclose(pipe_fp); +#endif + pipe_fp = 0; + } else if (exec_fd > 0) { + close(exec_fd); + close(0); + exec_fd = -1; + open("/dev/tty", O_RDONLY, 0); + } + } + if (mode == C_PROMPT) + printf("\n"); + printf("%s%s", num_teles, the_prompt); + (void) fflush(stdout); + if (auxfi) { + fprintf(auxfi, "\n%s%s", num_teles, the_prompt); + (void)fflush(auxfi); + } +} + +/* + * opens redir_fp if successful + */ +void +doredir(p) + s_char *p; +{ + s_char *how; + s_char *name; + s_char *tag; + int mode; + int fd; + + if (redir_fp) { + (void) fclose(redir_fp); + redir_fp = 0; + } + how = p++; + if (*p && ((*p == '>') || (*p == '!'))) + p++; + tag = gettag(p); + while (*p && isspace(*p)) + p++; + name = p; + while (*p && !isspace(*p)) + p++; + *p = 0; + if (tag == NULL) { + fprintf(stderr, "WARNING! Server redirected output to file %s\n",name); + return; + } + mode = O_WRONLY | O_CREAT; + if (how[1] == '>') + mode |= O_APPEND; + else if (how[1] == '!') + mode |= O_TRUNC; + else + mode |= O_EXCL; + if (*name == 0) { + fprintf(stderr, "Null file name after redirect\n"); + free(tag); + return; + } + if ((fd = open(name, mode, 0600)) < 0) { + fprintf(stderr, "Redirect open failed\n"); + perror(name); + } else { + redir_fp = fdopen(fd, "w"); + } + free(tag); +} + +/* + * opens "pipe_fp" if successful + */ +void +dopipe(p) + s_char *p; +{ + extern FILE *popen(); + s_char *tag; + + if (*p == '|') + p++; + tag = gettag(p); + while (*p && isspace(*p)) + p++; + if (tag == NULL) { + fprintf(stderr, "WARNING! Server attempted to run: %s\n",p); + return; + } + if (*p == 0) { + fprintf(stderr, "Null program name after redirect\n"); + free(tag); + return; + } +#ifndef _WIN32 + if ((pipe_fp = popen(p, "w")) == 0) { +#else + if (1) { +#endif + fprintf(stderr, "Pipe open failed\n"); + perror(p); + } + free(tag); +} + +void +doexecute(p, auxfi) + s_char *p; + FILE *auxfi; +{ + extern int sock; + int fd; + s_char *tag; + + tag = gettag(p); + while (*p && isspace(*p)) + p++; + if (tag == NULL) { + fprintf(stderr, "WARNING! Server attempted unauthorized read of file %s\n",p); + return; + } + if (p == 0) { + fprintf(stderr, "Null file to execute\n"); + free(tag); + return; + } +#if !defined(_WIN32) + if ((fd = open(p, O_RDONLY, 0)) < 0) { +#else + if ((fd = open(p, O_RDONLY|O_BINARY, 0)) < 0) { +#endif + fprintf(stderr, "Can't open execute file\n"); + perror(p); + free(tag); + return; + } + /* copies 4k at a time to the socket */ + while (termio(fd, sock, auxfi)) /*do copy*/; + /* Some platforms don't send the eof (cntl-D) at the end of + copying a file. If emp_client hangs at the end of an + execute, include the following line and notify wolfpack + of the platform you are using. + sendeof(sock); + */ + close(fd); + free(tag); +} + +void +output(code, buf, auxfi) + int code; + s_char *buf; + FILE *auxfi; +{ + switch (code) { + case C_NOECHO: + _noecho(0); + break; + case C_FLUSH: + (void) fflush(stdout); + if (auxfi) + (void) fflush(auxfi); + break; + case C_ABORT: + printf("Aborted\n"); + if (auxfi) + fprintf(auxfi, "Aborted\n"); + break; + case C_CMDERR: + case C_BADCMD: + printf("Error; "); + if (auxfi) + fprintf(auxfi, "Error; "); + break; + case C_EXIT: + printf("Exit: "); + if (auxfi) + fprintf(auxfi, "Exit: "); + break; + case C_FLASH: + printf("\n"); + break; + default: + break; + } + if (auxfi) { + fprintf(auxfi, "%s", buf); + if (code == C_FLUSH) + (void) fflush(auxfi); + else + (void) putc('\n', auxfi); + } + + if (redir_fp) + fprintf(redir_fp, "%s\n", buf); + else if (pipe_fp) + fprintf(pipe_fp, "%s\n", buf); + else { + if (SO && SE) + screen(buf); + else + fputs(buf, stdout); + if (code == C_FLUSH) + (void) fflush(stdout); + else + (void) putc('\n', stdout); + } +} + +void +screen(buf) + register s_char *buf; +{ + register s_char *sop; + register s_char c; + + while ((c = *buf++)) { + if (c & 0x80) { + for (sop = SO; putc(*sop, stdout); sop++) + ; + (void) putc(c & 0x7f, stdout); + for (sop = SE; putc(*sop, stdout); sop++) + ; + } else + (void) putc(c, stdout); + } +} diff --git a/src/client/serverio.c b/src/client/serverio.c new file mode 100644 index 00000000..919950e2 --- /dev/null +++ b/src/client/serverio.c @@ -0,0 +1,92 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * serverio.c: Handle input from server + * + * Known contributors to this file: + * Steve McClure, 1998 + */ + +#include "misc.h" +#include "queue.h" +#include "ioqueue.h" + +#include + +#if !defined(_WIN32) +#include +#endif + +#ifdef _WIN32 +#include +#include +#endif + +void free(); +void ioq_write(); + +int +serverio(s, ioq) + int s; + struct ioqueue *ioq; +{ +#ifndef _WIN32 + extern s_char *realloc(); +#else + extern void *realloc(); +#endif + s_char *buf; + int n; + + if ((buf = malloc(ioq->bsize)) == 0) { + fprintf(stderr, "malloc server i/o failed\n"); + return 0; + } +#ifdef _WIN32 + n = recv(s, buf, ioq->bsize, 0); +#else + n = read(s, buf, ioq->bsize); +#endif + if (n < 0) { +#ifdef _WIN32 + errno = WSAGetLastError(); +#endif + perror("server i/o read"); + free(buf); + return 0; + } + if (n == 0) { + fprintf(stderr, "Server EOF\n"); + (void) close(s); + return 0; + } + if (n != ioq->bsize) + buf = (s_char *)realloc(buf, n); + ioq_write(ioq, buf, n); + return 1; +} + diff --git a/src/client/tags.c b/src/client/tags.c new file mode 100644 index 00000000..f6fb8abe --- /dev/null +++ b/src/client/tags.c @@ -0,0 +1,89 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * tags.c: save redir, execute and pipe info to protect against tampering + * by the deity. + * + * Known contributors to this file: + * John Yockey, 1998 + */ + +#include "misc.h" +#include "tags.h" + +#include + +#ifdef Rel4 +#include +#endif /* Rel4 */ + +#if !defined(_WIN32) +#include +#endif + +struct tagstruct *taglist; +s_char buf[4096]; +u_short tagnum; +s_char exec[8]; + +void free(); + +void +io_init() +{ + taglist = NULL; + buf[0] = 0; + tagnum = 0; + sprintf(exec,"execute"); +} + +s_char * +gettag(p) + s_char *p; +{ + struct tagstruct *tag1,*tag2; + + if (taglist == NULL) return NULL; + tag1 = taglist; + if (!strncmp(tag1->item,p,strlen(tag1->item))) { + p = tag1->item; + taglist = taglist->next; + free(tag1); + return p; + } + while (tag1->next != NULL) { + tag2 = tag1->next; + if (!strncmp(tag2->item,p,strlen(tag2->item))) { + p = tag2->item; + tag1->next = tag2->next; + free(tag2); + return p; + } + tag1 = tag1->next; + } + return NULL; +} diff --git a/src/client/tags.h b/src/client/tags.h new file mode 100644 index 00000000..0d79835b --- /dev/null +++ b/src/client/tags.h @@ -0,0 +1,42 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * tags.h: Tag structure definition + * + * Known contributors to this file: + * John Yockey, 1998 + */ + +#ifndef _TAGS_H_ +#define _TAGS_H_ + +struct tagstruct { + s_char *item; + struct tagstruct *next; +}; + +#endif diff --git a/src/client/termio.c b/src/client/termio.c new file mode 100644 index 00000000..2296f18b --- /dev/null +++ b/src/client/termio.c @@ -0,0 +1,310 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * termio.c: Various io functions + * + * Known contributors to this file: + * Steve McClure, 1998 + */ + +#include +#include +#if defined(aix) || defined(hpux) || defined(sgi) +#include +#elif defined(linux) +#include +#include +#else +#ifndef _WIN32 +#include +#include +#else +#include +#endif /* _WIN32 */ +#endif +#include "misc.h" +#include "tags.h" + +extern struct tagstruct *taglist; +extern s_char buf[4096]; +extern s_char exec[]; + +#ifdef _WIN32 +extern HANDLE hStdIn; +#endif + +int sendeof(); + +int +termio(fd, sock, auxfi) + int fd; + int sock; + FILE *auxfi; +{ + s_char out[4096]; + int i,n; + s_char *ptr; + s_char *p,*q,*r,*s,*t; + int nbytes; + int numarg,prespace,exec_com,inarg,quoted,tagging; + struct tagstruct *tag; +#ifdef _WIN32 + char c; + INPUT_RECORD InpBuffer[2]; + int err; +#endif + + i = strlen(buf); + p = buf + i; +#ifndef _WIN32 + n = read(fd, p, sizeof(buf) - i); +#else +/* The keyboard is sometimes generating both keydown and keyup + * events for the same key. Thus, we only want to grab keydown + * events. */ + if (fd == -1) { + err = PeekConsoleInput(hStdIn, InpBuffer, 1, &n); + if (InpBuffer[0].EventType != KEY_EVENT) { + ReadConsoleInput(hStdIn, InpBuffer, 1, &n); + return 1; + } + if (!InpBuffer[0].Event.KeyEvent.bKeyDown) { + ReadConsoleInput(hStdIn, InpBuffer, 1, &n); + return 1; + } + c = InpBuffer[0].Event.KeyEvent.uChar.AsciiChar; + + if (c == 13) + c = 10; + n = 1; + p[0] = c; + p[1] = '\0'; + if (c != 10) + ReadConsole(hStdIn, &p[0], sizeof(buf) - i , &n, NULL); + else + putchar(c); +/* Strip off the CRLF to just LF */ + if (n > 1) { + if (p[n-2] == 13 && p[n-1] == 10) { + p[n-2] = 10; + p[n-1] = 0; + n--; + } + } + FlushConsoleInputBuffer(hStdIn); + } else { + n = read(fd, p, sizeof(buf) - i); + } +#endif + if (n == 0) { + sendeof(sock); + return 0; + } + if (n < 0) { + perror("read standard input"); + return 0; + } + n += i; + ptr = buf; + p = buf; + q = out; + r = out; + numarg = 0; + tagging = 0; + inarg = 0; + prespace = 1; + quoted = 0; + while (p < buf + n && q < out + 4000) { + if (*p == '\n') { + if (tagging) { + tag = (struct tagstruct *) malloc(sizeof(struct tagstruct)); + tag->item = (s_char *) malloc((1+p-s) * sizeof(s_char)); + tag->next = taglist; + taglist = tag; + t = tag->item; + while (s < p) *t++ = *s++; + *t = 0; + } + *q++ = *p++; + numarg = 0; + tagging = 0; + inarg = 0; + prespace = 1; + quoted = 0; + ptr = p; + r = q; + } else if (tagging) { + *q++ = *p++; + } else if (!quoted && isspace(*p)) { + *q++ = *p++; + prespace = 1; + if (numarg == 1 && exec_com && s > exec + 2) { + tagging = 1; + s = p; + } + } else if (prespace && *p == '|') { + tagging = 1; + *q++ = *p++; + s = p; + } else if (prespace && *p == '>') { + tagging = 1; + *q++ = *p++; + if (*p != '\n' && (*p == '!' || *p == '>')) *q++ = *p++; + s = p; + } else { + prespace = 0; + if (*p == '"') { + quoted = !quoted; + } else { + if (!inarg && *p != '?') { + s = exec; + exec_com = 1; + numarg++; + } + inarg = 1; + if (*s && *s++ != *p) exec_com = 0; + } + *q++ = *p++; + } + } + p = buf; + while (ptr < buf + n) *p++ = *ptr++; + *p = 0; + ptr = out; + n = r - out; + if (auxfi) { + fwrite(out, n, 1, auxfi); + } + while (n > 0) { +#ifndef _WIN32 + nbytes = write(sock, ptr, n); +#else + nbytes = send(sock, ptr, n, 0); +#endif + if (nbytes <= 0) { +#ifdef _WIN32 + errno = WSAGetLastError(); +#endif + perror("write server socket"); + return 0; + } + ptr += nbytes; + n -= nbytes; + } + return 1; +} + +int +sendeof(sock) + int sock; +{ +#ifndef _WIN32 + if (write(sock, "ctld\n", 5) < 5) { +#else + if (send(sock, "ctld\n", 5, 0) < 5) { +#endif + fprintf(stderr, "sendeof: EOF send failed\n"); + close(sock); + return 0; + } + return 1; +} + +int echomode = 1; + +#if defined(hpux) || defined(aix) || defined (sgi) || defined(linux) +void +_noecho(fd) + int fd; +{ + struct termio io; + + echomode = 0; + (void) ioctl(fd, TCGETA, &io); + io.c_line |= ECHO; + (void) ioctl(fd, TCSETA, &io); +} + +void +_echo(fd) + int fd; +{ + struct termio io; + + if (echomode) + return; + (void) ioctl(fd, TCGETA, &io); + io.c_line &= ~ECHO; + (void) ioctl(fd, TCSETA, &io); + echomode++; +} + +#else +#ifndef _WIN32 + +void +_noecho(fd) + int fd; +{ + struct sgttyb sgbuf; + + echomode = 0; + (void) ioctl(fd, TIOCGETP, &sgbuf); + sgbuf.sg_flags &= ~ECHO; + (void) ioctl(fd, TIOCSETP, &sgbuf); +} + +void +_echo(fd) + int fd; +{ + struct sgttyb sgbuf; + + if (echomode) + return; + (void) ioctl(fd, TIOCGETP, &sgbuf); + sgbuf.sg_flags |= ECHO; + (void) ioctl(0, TIOCSETP, &sgbuf); + echomode++; +} +#else +void +_noecho(fd) +int fd; +{ + echomode = 0; +} + +void +_echo(fd) +int fd; +{ + echomode++; +} + +#endif /* _WIN32 */ +#endif diff --git a/src/client/termlib.c b/src/client/termlib.c new file mode 100644 index 00000000..822b4c8e --- /dev/null +++ b/src/client/termlib.c @@ -0,0 +1,96 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * termlib.c: Various termlib stuff + * + * Known contributors to this file: + * Dave Pare, 1986 + * Steve McClure, 1998 + */ + +#include +#include +#include "misc.h" + +#if !defined(_WIN32) +#include +#endif + +s_char *SO = 0; +s_char *SE = 0; + +int tgetent(); + +void +parsedelay(r) + s_char *r; +{ + s_char *s, *t; + + s = r; + while (isdigit(*s) || (*s == '*') || (*s == '.')) { + s++; + } + for (t = r; *s != 0; (s++, t++)) { + *t = *s; + } + *t = 0; +} + +void +getsose() +{ +#ifndef _WIN32 + extern s_char *getenv(); + extern s_char *tgetstr(); +#endif + static s_char tbuf[1024]; + static s_char cbuf[20]; + s_char *cp; + s_char *term; + +#ifndef _WIN32 + memset((s_char *)&cbuf[0], 0, 20); + term = getenv("TERM"); + if (term == 0) { + fprintf(stderr, "warning: no TERM environment variable\n"); + return; + } + tgetent(tbuf, term); + cp = cbuf; + SO = tgetstr("so", &cp); + SE = tgetstr("se", &cp); + if (SO == 0) { + SO = tgetstr("us", &cp); + SE = tgetstr("ue", &cp); + } + if (SO != 0) { + parsedelay(SO); + parsedelay(SE); + } +#endif +} diff --git a/src/doconfig/Makefile b/src/doconfig/Makefile new file mode 100644 index 00000000..d08ca625 --- /dev/null +++ b/src/doconfig/Makefile @@ -0,0 +1,73 @@ +# +# Empire - A multi-player, client/server Internet based war game. +# Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, +# Ken Stevens, Steve McClure +# +# 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 2 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, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# --- +# +# See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the +# related information and legal notices. It is expected that any future +# projects/authors will amend these files as needed. +# +# Makefile - Wolfpack, 1996 +# build the configuration program, then run it. +# Note that this is a stand-alone - it doesn't need anything +# else to build and run, other than build.conf for definitions. + + +include ../../build.conf + +DPV = -DPV="\"$(MYNAME)\"" +DHN = -DHN="\"$(HOSTNAME)\"" +DPN = -DPN=$(PORTNUM) +DEM = -DEM="\"$(EMAIL)\"" +DEP = -DEP="\"$(EMPDIR)\"" +DMC = -DMC=$(MAXNOC) +DWX = -DWX=$(WORLDX) +DWY = -DWY=$(WORLDY) +DBL = -DBL=$(BLITZ) +DET = -DET=$(ETUS) +DEF = -DEF="\"$(ETUFREQ)\"" +DIP = -DIP="\"$(IPADDR)\"" +DUN = -DUN="\"$(USERNAME)\"" + +DALL = $(DPV) $(DHN) $(DPN) $(DEM) $(DEP) $(DMC) $(DWX) $(DWY) $(DBL) $(DET) $(DEF) $(DIP) $(DUN) + +all: doconfig + +doconfig: ../../build.conf doconfig.c + @echo 'globalcflags = $(GLOBALCFLAGS)' + @echo 'globallflags = $(GLOBALLFLAGS)' + $(CC) $(GLOBALCFLAGS) $(DALL) doconfig.c -o doconfig $(GLOBALLFLAGS) + ./doconfig + +nt: ntdoconfig + +ntdoconfig: ..\..\build.conf doconfig.c + @echo 'globalcflags = $(GLOBALCFLAGS)' + @echo 'globallflags = $(GLOBALLFLAGS)' + $(CC) $(GLOBALCFLAGS) $(DALL) doconfig.c -o doconfig $(GLOBALLFLAGS) + doconfig.exe + +clean: + -(rm -f doconfig) + -(del doconfig.exe) + -(del *.obj) + -(del *.pdb) + +include ../make.rules +include Makedepend diff --git a/src/doconfig/doconfig.c b/src/doconfig/doconfig.c new file mode 100644 index 00000000..1e327f96 --- /dev/null +++ b/src/doconfig/doconfig.c @@ -0,0 +1,276 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * doconfig.c: Generates the gamesdef.h file used to build the game, and + * the various make include files needed to build correctly. + * + * Known contributors to this file: + * Steve McClure, 1996-2000 + */ + +#include +#include +#include +#include +#if !defined(_WIN32) +#include +#endif +#include + +void wrmakesrc(char *pathname); +void wripglob(char *filename); +void wrauth(char *filename); +void wrgamesdef(char *filename); + +char *_c_copyright_header = "/*\n * Empire - A multi-player, client/server Internet based war game.\n * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak,\n * Ken Stevens, Steve McClure\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\n *\n * ---\n *\n * See the \"LEGAL\", \"LICENSE\", \"CREDITS\" and \"README\" files for all the\n * related information and legal notices. It is expected that any future\n * projects/authors will amend these files as needed.\n *\n * ---\n *\n * gamesdef.h: This is an auto-generated file.\n * \n * Known contributors to this file:\n * Automatically generated by doconfig.c\n */\n\n"; + +char *_ipglob_copyright_header = "/*\n * Empire - A multi-player, client/server Internet based war game.\n * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak,\n * Ken Stevens, Steve McClure\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\n *\n * ---\n *\n * See the \"LEGAL\", \"LICENSE\", \"CREDITS\" and \"README\" files for all the\n * related information and legal notices. It is expected that any future\n * projects/authors will amend these files as needed.\n *\n * ---\n *\n * ipglob.c: This is an auto-generated file.\n * \n * Known contributors to this file:\n * Automatically generated by doconfig.c\n */\n\n"; + +#if defined(_WIN32) +char * +rindex(char *path, char c) +{ + int i; + char *cp; + + i = strlen(path); + cp = &path[i - 1]; + + while (i) { + if (*cp == c) + return cp; + i--; + cp--; + } + return (char *)0; +} + +char * +index(char *path, char c) +{ + int i; + char *cp; + + cp = &path[0]; + + i = 0; + while (path[i]) { + if (*cp == c) + return cp; + i++; + cp++; + } + return (char *)0; +} + +#endif + +int +main() +{ + char buf[256]; + char *cp; + char *pathname; + + if ((pathname = getcwd(NULL, 255)) == NULL) { + printf("Can't get current path!\n"); + exit(-1); + } + +#if !defined(_WIN32) + cp = (char *)rindex(pathname, '/'); + *cp = '\0'; + cp = (char *)rindex(pathname, '/'); + *cp = '\0'; +#else + cp = (char *)rindex(pathname, '\\'); + *cp = '\0'; + cp = (char *)rindex(pathname, '\\'); + *cp = '\0'; +#endif + printf("Configuring...\n"); + wrmakesrc(pathname); + sprintf(buf, "%s/include/gamesdef.h", pathname); + wrgamesdef(buf); + sprintf(buf, "%s/src/client/ipglob.c", pathname); + wripglob(buf); + + if (access(EP, 0)) { + printf("making directory %s\n", EP); + if (mkdir(EP, 493)) { + printf("mkdir failed on %s, exiting.\n", EP); + exit(-1); + } + } + sprintf(buf, "%s/data", EP); + if (access(buf, 0)) { + printf("making directory %s\n", buf); + if (mkdir(buf, 493)) { + printf("mkdir failed on %s, exiting.\n", buf); + exit(-1); + } + } + sprintf(buf, "%s/data/auth", EP); + wrauth(buf); + exit(0); +} + +void +wrmakesrc(char *pathname) +{ + FILE *fp; + char buf[256]; + + sprintf(buf, "%s/src/make.src", pathname); + if ((fp = fopen(buf, "w")) == NULL) { + printf("Cannot open %s for writing, exiting.\n", buf); + exit(-1); + } + fprintf(fp, "# make.src - Wolfpack, 1996-2000\n"); + fprintf(fp, "# Source tree absolute pathname - auto generated.\n\n"); + fprintf(fp, "SRCDIR = %s\n", pathname); + fclose(fp); +} + +void +wripglob(char *filename) +{ + FILE *fp; + + printf("Writing %s\n", filename); + if ((fp = fopen(filename, "w")) == NULL) { + printf("Cannot open %s for writing, exiting.\n", filename); + exit(-1); + } + fprintf(fp, _ipglob_copyright_header); + fprintf(fp, "#include \n"); + fprintf(fp, "#include \n"); + fprintf(fp, "#include \"misc.h\"\n"); + fprintf(fp, "#include \"fnlist.h\"\n"); + fprintf(fp, "#include \"proto.h\"\n\n"); + fprintf(fp, "s_char empirehost[] = \"%s\";\n", HN); + fprintf(fp, "s_char empireport[] = \"%d\";\n", PN); + fclose(fp); +} + +void +wrauth(char *filename) +{ + FILE *fp; + + printf("Writing %s\n", filename); + if ((fp = fopen(filename, "w")) == NULL) { + printf("Cannot open %s for writing, exiting.\n", filename); + exit(-1); + } + + fprintf(fp, "# Wolfpack, 1996-2000\n#\n"); + fprintf(fp, "# Empire Authorization File - Users listed will be allowed to log in as deities.\n#\n"); + fprintf(fp, "# Format is:\n"); + fprintf(fp, "# hostname that authorized user uses on a line\n"); + fprintf(fp, "# username that authorized user uses on a line\n#\n"); + fprintf(fp, "# REMEMBER TO USE PAIRS OF LINES!\n#\n"); + fprintf(fp, "# Example:\n#\n"); + fprintf(fp, "nowhere.land.edu\nnowhereman\n"); + fprintf(fp, "%s\n%s\n", HN, UN); + fprintf(fp, "%s\n%s\n", IP, UN); + fprintf(fp, "127.0.0.1\n%s\n", UN); + fclose(fp); +} + +void +wrgamesdef(char *filename) +{ + FILE *fp; + char path[512]; + char *cp; + unsigned int i; + int s_p_etu; + char buf[40]; + char c = 'b'; + + cp = &path[0]; + for (i = 0; i < strlen(EP); i++) { + *cp++ = EP[i]; + if (EP[i] == '\\') + *cp++ = '\\'; + } + *cp = 0; + + strcpy(buf, EF); + if (strlen(buf) > 0) + c = buf[strlen(buf) - 1]; + if (index("dhm", c) && strlen(buf) > 0) { + s_p_etu = atoi(buf); + if (c == 'd') + s_p_etu = (((double)s_p_etu * 60.0 * 60.0 * 24.0) / (double)ET); + else if (c == 'h') + s_p_etu = (((double)s_p_etu * 60.0 * 60.0) / (double)ET); + else if (c == 'm') + s_p_etu = (((double)s_p_etu * 60.0) / (double)ET); + } else { + printf("ETU frequency is bad - using 10 minutes.\n"); + s_p_etu = 600 / ET; + } + + printf("Writing %s\n", filename); + if ((fp = fopen(filename, "w")) == NULL) { + printf("Cannot open %s for writing, exiting.\n", filename); + exit(-1); + } + fprintf(fp, _c_copyright_header); + fprintf(fp, "/*\n * Wolfpack, 1996-2000\n *\n"); + fprintf(fp, " * gamesdef.h - generated automatically by doconfig. Feel\n"); + fprintf(fp, " * free to change these, but if you rebuild with overwrite on\n"); + fprintf(fp, " * this file will be overwritten again.\n"); + fprintf(fp, " */\n\n"); + fprintf(fp, "#ifndef _GAMESDEF_H_\n"); + fprintf(fp, "#define _GAMESDEF_H_\n\n"); + fprintf(fp, "#if !defined(_WIN32)\n"); + fprintf(fp, "#ifdef __STDC__\n"); + fprintf(fp, "#define EMPPATH(xyz) \"%s/\" #xyz /* ANSI C */\n", EP); + fprintf(fp, "#else\n"); + fprintf(fp, "#define EMPPATH(xyz) \"%s/xyz\" /* traditional */\n", EP); + fprintf(fp, "#endif /* __STDC__ */\n"); + fprintf(fp, "#else\n"); + fprintf(fp, "#define EMPPATH(xyz) \"%s\\\\\" #xyz /* ANSI C */\n", path); + fprintf(fp, "#endif /* _WIN32 */\n\n"); + fprintf(fp, "#define PRVNAM \"%s\"\n", PV); + fprintf(fp, "#define PRVLOG \"%s\"\n", EM); + fprintf(fp, "#define GET_SOURCE \"using:\\n ftp://ftp.wolfpackempire.com/pub/empire/server or \\n http://www.wolfpackempire.com/\"\n"); + fprintf(fp, "#define EMP_HOST \"%s\"\n", IP); + fprintf(fp, "#define EMP_PORT \"%d\"\n\n", PN); + fprintf(fp, "#define MAXNOC %d\n\n", MC); + fprintf(fp, "#define DEF_WORLD_X %d\n", WX); + fprintf(fp, "#define DEF_WORLD_Y %d\n\n", WY); + fprintf(fp, "#define DEF_S_P_ETU %d\n", s_p_etu); + fprintf(fp, "#define ETUS %d\n\n", ET); + if (BL) + fprintf(fp, "#define BLITZ 1\n\n"); + fprintf(fp, "#endif /* _GAMESDEF_H_ */\n"); + fclose(fp); +} diff --git a/src/lib/as/COPYRIGHT b/src/lib/as/COPYRIGHT new file mode 100644 index 00000000..bf3e1ab9 --- /dev/null +++ b/src/lib/as/COPYRIGHT @@ -0,0 +1,41 @@ +(Note that this copyright notice was changed with permission from Phil +Lapsley to a copyright that complies with the GNU GPL. The new +copyright is supplied here, along with the old copyright notice +below.) + +----- + + A* Search - A search library used in Empire to determine paths between + objects. + Copyright (C) 1990-1998 Phil Lapsley + + 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 2 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, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +----- + +Old Copyright notice follows: + +"Copyright 1990 Phil Lapsley. All rights reserved. + +Redistribution and use in source and binary forms for noncommercial +purposes in support of BSD Empire are permitted provided that this +notice is preserved and that due credit is given to the copyright +holder. This software is provided ``as is'' without express or implied +warranty. Entities interested in other distribution of this software +should contact the copyright holder. + +(Phil is located at phil@east.berkeley.edu)" + +----- diff --git a/src/lib/as/Makefile b/src/lib/as/Makefile new file mode 100644 index 00000000..ff73f225 --- /dev/null +++ b/src/lib/as/Makefile @@ -0,0 +1,62 @@ +# +# Empire - A multi-player, client/server Internet based war game. +# Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, +# Ken Stevens, Steve McClure +# +# 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 2 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, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# --- +# +# See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the +# related information and legal notices. It is expected that any future +# projects/authors will amend these files as needed. +# +# Makefile - Wolfpack, 1996 + +# Note that these could have been listed 1 per line, but I chose to just +# stick them all together this way to shorten the file. + +include ../../../build.conf +include ../../make.src +include ../../make.defs + +LIB = $(SRCDIR)/lib/libas.a +NTLIB = $(SRCDIR)\lib\libas.lib + +OBJS = as_cache.o as_costcomp.o as_delete.o as_extend.o as_hash.o as_init.o \ + as_merge.o as_search.o as_stats.o as_winnow.o + +NTOBJS = as_cache.obj as_costcomp.obj as_delete.obj as_extend.obj as_hash.obj \ + as_init.obj as_merge.obj as_search.obj as_stats.obj as_winnow.obj + +all: $(LIB) + +nt: $(NTLIB) + +$(NTLIB): $(NTOBJS) + -del /q $@ + lib /OUT:$@ /DEBUGTYPE:CV $(NTOBJS) + +$(LIB): $(OBJS) + rm -f $(LIB) + ar cq $(LIB) $(OBJS) + $(RANLIB) $(LIB) + +clean: + -(rm -f $(OBJS)) + -(del /q $(NTOBJS)) + +include ../../make.rules +include Makedepend diff --git a/src/lib/as/README b/src/lib/as/README new file mode 100644 index 00000000..00069f4b --- /dev/null +++ b/src/lib/as/README @@ -0,0 +1,300 @@ +Tue Nov 13 11:50:24 PST 1990 Phil Lapsley phil@Berkeley.EDU + +This library implements a reasonably general version of the A* algorithm. +Basically, A* is like an ordered search, but with a heuristic that allows +it to make a better choices as to which path to take. The subdirectory +"test" has example code for using A* to search a weighted cartesian matrix. +The file "XXX//bestpath.c" has code to interface Empire to the A* +algorithms. + +This library is copyrighted; see the file COPYRIGHT for details. + +COMPILATION + +Do a "make" in this directory to make the library. Cd into "test" and +do a "make" there to make a test program, called (ta da) "test". + +LIBRARY USAGE + +Pretty much all the data that the user needs to communicate to the library +is stored in an "as_data" structure, which is created by a call to "as_init": + + struct as_data *adp; + + adp = as_init( ... ); + +The arguments to as_init specify a number of key things the algorithm will +use, and these are discussed below. + +Once you have an "as_data" structure, you can fill in its "from" and "to" +members, which specify the coordinates of the points between which you want +to go. The basic coordinate data structure is the "as_coord", which is +just an "x" integer and a "y" integer. So: + + adp->from.x = ...; + adp->from.y = ...; + adp->to.x = ...; + adp->to.y = ...; + +and then call as_search: + + as_search(adp); + +If the return value of as_search is 0, the algorithm found a path from +"from" to "to". The path is stored in the "path" member of the "as_data" +structure, and is just a linked list of coordinates ("as_coord" structs) +from "from" to "to". + +If the return value of as_search is -1, the algorithm couldn't find a +path from "from" to "to". If the return is -2, a system error occurred +(most probably malloc failed). + +After a call to as_search, lots of malloced data 'n' stuff will be +floating around, all pointed to by items in the "as_data" data structure. +If you call "as_search" again (presumably with new "from" and "to" +coordinates), the system will free these data structures and reallocate +new ones. If you no longer want the data structures at all (i.e., you +never intend to call "as_search" again), you can call: + + as_delete(adp); + +and this will free up all data associated with the as_data structure pointed +to by adp. + +ARGUMENTS TO AS_INIT + +"as_init" takes eight arguments, in the following order: + + maxneighbors The maximum number of neighboring sectors a + coordinate can have. On a cartesian grid, + this would be 8. On a hex map, it would be 6. + + hashsize The size of the hash table used to determine + if we've visited a particular coordinate. + + hashfunc A pointer to a function that takes an + "as_coord" as an argument and returns an + integer that will be used as a hash value. + If this is a NULL pointer, the as library + will assign its own hash function that just + adds the x and y coordinates together. + + neighborfunc A pointer to a function that takes a coordinate + (call it "c"), a pointer to an array of + coordinates of length "maxneighbors", and + a user data pointer (see below). This + function should figure out the coordinates + of all the neighbors of "c" and put them in + the array cp[0] ... cp[maxneighbors-1]. + It should then return the number of neighbors + found. + + lbcostfunc A pointer to a function that takes two + coordinates, call them "from" and "to", + and a user data pointer (see below). It + returns a double precision *LOWER BOUND* + on the cost to get from "from" to "to". + "from" and "to" may be separated by an + arbitrary distance. More on this below. + + realcostfunc A pointer to a function that takes two + coordinates, call them "from" and "to", + and a user data pointer (see below). It + returns a double precision value of + the *actual cost* to move from "from" to + "to". Note that "from" will never be more + than one sector away from "to". + + seccostfunc A pointer to a function that takes two + coordinates, call them "from" and "to", + and a user data pointer (see below). It + returns a double precision value that will + be used to break ties when two nodes have + the same lower bound to the target. An + example will be discussed below. + + userdata A (char *) that can be a pointer to + any kind of data you want. This will + be passed as the third argument to the + neighborfunc, lbcostfunc, realcostfunc, + and seccostfunc. + +Look in test/cart.c to see examples of these functions for cartesian +coordinates. + +NOTES ON THE LOWER BOUND FUNCTION + +"lbcostfunc" is *CRUCIAL* to the algorithm's performance. The entire +idea behind the A* algorithm is that, when considering whether to move +to a new coordinate, you know two things: + + (1) how much it's cost you to get to that coordinate so far, + + (2) a LOWER BOUND on how much it will cost to get to the + destination from that coordinate. + +If these two conditions are met, the algorithm will return the optimal +path to the destination. The closer the lower bound is to the actual +cost to get from one point to another, the quicker the algorithm will +find this path. HOWEVER, if the lower bound is ever violated, i.e., +if the so-called lower bound function returns a value that is greater +than the actual cost to get to the destination, then the algorithm will +not necessarily find the optimal path. + +Example: + +Assume that we're on a cartesian matrix, and the cost to move from one point +to another is just the distance between the two points, and that no +other costs are involved. In this case, the lower bound function could +be the same as the actual cost function, i.e., + + real cost = lower bound cost = sqrt(dx^2 + dy^2); + +In this case, the algorithm will find the destination as quickly as possible. + +Another example: + +Again assume we're on a cartesian matrix, and the cost to move from +one point to another is two things: (1) the distance between them, (2) some +arbitrary cost function we get off of a map. E.g., + + X + + 0 1 2 3 + 0 0 0 0 0 + 1 0 0 0 0 + Y 2 0 0 2 0 + 3 0 0 0 0 + +The real cost to move from (x,y) 0,0 to 1,0 is 1. That is, it's the distance +(1) plus the value of the map at (1,0), which is 0. The real cost to move +from (1,2) to (2,2) is 3: the distance (1) plus the map value at (2,2), which +is 2, totaling 3. + +In this case, the lower bound function could still be the distance between +the two points, since this WILL NEVER BE MORE than the actual cost, and +hence is a lower bound. I.e., + + real cost = sqrt(dx^2 + dy^2) + map costs + + lower bound cost = sqrt(dx^2 + dy^2) + + lower bound cost <= real cost for all coordinates + +This is what the the example in the "test" directory uses. + +A third example: + +You could make the lower bound function always return 0. This would be +a valid lower bound of the cost to move between any two points. In this +case, the A* algorithm will behave like a breadth-first search, and isn't +very much fun. + +SECONDARY COST FUNCTION + +The algorithm tries new coordinates in order of lowest lower-bound. +There can be cases where the lower-bound function for two (or more) +coordinates is the same, i.e., there is a tie. The algorithm uses +the secondary cost function (which does NOT have to be a lower bound) +to choose which coordinate to pick. A typical heuristic might be +to use Euclidian distance for this secondary cost function, on the +assumption that it's always better to move closer the destination. +The Empire code does just this. + +If you don't need a secondary cost function, just specify a NULL pointer +to the seccost argument to as_init, and the routines will use 0.0 for you. + +EMPIRE INTERFACE + +The interface code in "XXX/bestpath.c" is a rather complicated example +of A* interface code. What it does is based on some features of Empire +that are explained here. + +First, movement cost in Empire is based on a quantity called "mobility +cost", which is a property of every sector. As we trace a path from +source to destination, we add up mobility cost as we go. Once we're +there, we have a total mobility cost. This is what we'd like to +minimize. + +Second, Empire has highways, which are zero cost movement paths. This +hurts the A* algorithm, because it means that the lower bound cost +function is very weak. For example, think what happens if we move from +one side of the country to another: if the two sectors are attached via +a highway, the cost will be very small -- in fact, it will be the cost +to move out of the source sector, and the cost to move into the +destination sector. If, on the other hand, the two sectors aren't +connected by a highway, the cost could be quite large. Thus, the lower +bound is just the cost to move out of a sector plus the cost to move +into a sector. This is a pretty weak lower bound, and means that we +have to explore a lot of sectors. + +Third, the mobility costs tend to tie a lot, as explained in the +section above on secondary cost functions. Thus, we use the Empire +"mapdist" function as a secondary sort function to break ties. For +example, consider the case where a sector borders two highway sectors, +one on each side. The lower bound function will say that the two have +equal lower bound costs, since they're both highways and cost nothing +to move on. The secondary sort function is then used to break the tie -- +it says, "Take the one that moves you closer to the destination". + +Fourth, all of the information we need about a sector (its mobility +cost, who owns it, etc.) is stored in the sector file on disk. This +means that the getsect() function to get it off disk will do a read(), +which is VERY expensive. Because of the weak lower bound, A* ends up +checking lots of sectors, including sectors that it's seen before. +To avoid doing thousands of system calls per second, the bestpath.c file +has sector caching routines that store in memory copies of every +sector we read. (The function bp_getsect handles this). This means +we never read a sector from disk more than once, although at the expense +of using lots of memory. + +THEORY OF OPERATION + +The basic idea is as follows: + + 1. Add the start node to the head of a master queue. + 2. Is the head of the queue where we want to be? If so, stop. + 3. Make a list of all the neighbors coordinates around the + coordinate of the head. + + 4. For each neighbor coordinate, + + Compute the lower bound cost to the destination from here. + + If this coordinate is already on the either the + master queue or the "tried" queue: + + 4a. If it was on either the "master" queue or the + "tried" queue and the one on the queue has a + smaller lower-bound than the neighbor, ignore + this neighbor and go on to the next neighbor. + + 4b. If it was on the "master" queue and the new + neighbor has a smaller lower bound, + Move the one on the queue to a different + queue called "subsumed". + + 4c. If it was on the "tried" queue and the new + neighbor has a smaller lower bound, + Move the one on the "tried" queue to the + master queue, and update its lower bound + value to be as the new neighbor, and + update its backpointer appropriately. + + We now have a list of all neighbor coordinates that are either + not on the queue already, or are cheaper than the ones on the + queue. + + 5. Move the node at the head of the queue (the one whose neighbors + we now have in a list) onto a different queue called "tried". + + 6. Sort this list of neighbors, and merge it into the master queue, + keeping the master queue ordered by lower bound cost to destination. + + 7. Goto 2. + +My algorithm does all of this, plus a little more (the above doesn't really +mention backpointers except in passing), EXCEPT: I don't do step 4c. +I'm not convinced that this can ever occur if the lower bound rule isn't +broken, and I have yet to see it occur. However, if as_winnow returns -1, +this error has occurred. diff --git a/src/lib/as/as.h b/src/lib/as/as.h new file mode 100644 index 00000000..88362195 --- /dev/null +++ b/src/lib/as/as.h @@ -0,0 +1,180 @@ +/* + * A* Search - A search library used in Empire to determine paths between + * objects. + * Copyright (C) 1990-1998 Phil Lapsley + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +/* + * A* definitions. + * + * @(#)as.h 1.9 11/13/90 + */ +/* + * 11/09/98 - Steve McClure + * Added path list caching structures + */ + +#include /* for FILE */ +#include "misc.h" /* for s_char */ + +/* + * Coordinate. + */ +struct as_coord { + int x, y; +}; + +/* + * Path, made up of a linked list of coordinates. + */ +struct as_path { + struct as_coord c; + struct as_path *next; +}; + +/* + * Basic node, used internally by A* algorithm. + */ +struct as_node { + struct as_coord c; /* our coordinate */ + double knowncost; /* cost so far */ + double lbcost; /* lower bound on cost to dest */ + double inclbcost; /* incremental lower bound cost */ + double seccost; /* used to break ties */ + int step; + int flags; + struct as_node *back; +}; +#define AS_TRIED 1 /* we've tried this node before */ + +/* + * Linked list of nodes, used internally by A* algorithm. + */ +struct as_queue { + struct as_node *np; + struct as_queue *next; + struct as_queue *prev; +}; + +/* + * Hash table entry, used to determine if we've seen a particular + * coordinate before. + */ +struct as_hash { + struct as_coord c; + struct as_queue *qp; + struct as_hash *next; +}; + +/* + * User's handle on A*, returned by as_init(). Some of the data here is + * used by A* internals. + */ +struct as_data { + int maxneighbors; /* max # of neighbors a cell can have */ + int hashsize; /* size of internal hash table */ + + int (*hash)(struct as_coord); /* hash function (coord -> int) */ + int (*neighbor)(struct as_coord, struct as_coord *, s_char *); /* function to find neighbors */ + double (*lbcost)(struct as_coord, struct as_coord, s_char *); /* function to give lower bound cost */ + double (*realcost)(struct as_coord, struct as_coord, s_char *); /* function to give real cost */ + double (*seccost)(struct as_coord, struct as_coord, s_char *); /* function to secondary cost */ + char *userdata; /* user's data, passed to callbacks */ + struct as_coord from; /* from coordinate */ + struct as_coord to; /* to coordinate */ + struct as_path *path; /* solution */ + + /* below are "private" to as_ routines */ + struct as_queue *head; + struct as_queue *tried; + struct as_hash **hashtab; + struct as_queue *subsumed; + struct as_coord *neighbor_coords; + struct as_node **neighbor_nodes; +}; + +/* + * Added these for caching of paths as we stumble across them + */ + +struct as_topath { + coord x; + struct as_path *path; /* Path from holder of this list to here */ + struct as_topath *next; +}; + +struct as_frompath { + coord x; + struct as_topath **tolist; /* List of nodes we have a path to */ + struct as_frompath *next; +}; + +/* + * Some cheezy allocation macros. + */ +#define AS_NEW_ARRAY(p, type, n, err) \ + (p) = (type *)calloc((n), sizeof (*(p))); \ + if ((p) == NULL) \ + return err; \ + +#define AS_NEW(p, type, err) \ + AS_NEW_ARRAY((p), type, 1, err); + +#define AS_NEW_MALLOC(p, type, err) \ + (p) = (type *)malloc(sizeof(type)); \ + if ((p) == NULL) \ + return err; \ + +/* Functions that the user can call. */ + +extern struct as_data * +as_init(int maxneighbors, int hashsize, + int (*hashfunc) (struct as_coord), + int (*neighborfunc) (struct as_coord, struct as_coord *, s_char *), + double (*lbcostfunc) (struct as_coord, struct as_coord, s_char *), + double (*realcostfunc) (struct as_coord, struct as_coord, s_char *), + double (*seccostfunc) (struct as_coord, struct as_coord, s_char *), + s_char *userdata); +extern int as_search(struct as_data *adp); +extern void as_delete(struct as_data *adp); +extern void as_reset(struct as_data *adp); +extern void as_stats(struct as_data *adp, FILE *fp); +extern struct as_path *as_find_cachepath(coord fx, + coord fy, + coord tx, + coord ty); + +/* Functions that are "private" to algorithm */ + +extern void as_add_cachepath(struct as_data *adp); +extern void as_clear_cachepath(); +extern void as_enable_cachepath(); +extern void as_disable_cachepath(); + +extern void as_makepath(struct as_data *adp); +extern void as_free_path(struct as_path *pp); + +extern int as_costcomp(struct as_node **n1, struct as_node **n2); +extern struct as_queue *as_extend(struct as_data *adp); +extern struct as_queue *as_merge(struct as_data *adp, + struct as_queue *head, + struct as_node **neighbors); +extern struct as_queue *as_iscinq(struct as_data *adp, struct as_coord c); +extern void as_setcinq(struct as_data *adp, + struct as_coord c, struct as_queue *qp); +extern void as_free_hashtab(struct as_data *adp); +extern int as_winnow(struct as_data *adp, + struct as_coord *coords, int ncoords); diff --git a/src/lib/as/as_cache.c b/src/lib/as/as_cache.c new file mode 100644 index 00000000..737300f9 --- /dev/null +++ b/src/lib/as/as_cache.c @@ -0,0 +1,196 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * as_cache.c: Routines used to create/delete caches of A* paths. + * + * Known contributors to this file: + * Steve McClure, 1998 + */ + +#include "as.h" +#include "optlist.h" + +/* The way this works is interesting. :) */ +/* We keep a pointer to a list of pointers. The index into this list + * is the y coordinate of the from sector. This member points to a list + * of from sectors on that y coordinate. So, we march that list checking + * the x value to find the from x,y we want. */ +/* Once we find the from x,y, that node has the same type of pointer to + * a list of pointers. The index into this list is the y coordinate of + * the to sector. This member points to a list of to sectors on that y + * coordinate. So, we march that list checking the x value to find the + * to x,y we want. */ +/* These lists are dynamically created since the world is dynamically sized. */ +/* See, I told you it was interesting. :) */ + +static struct as_frompath **fromhead = (struct as_frompath **)0; + +/* Note that we only want to cache during updates. Other times, it + * probably doesn't make much sense, but can be done. */ + +static int as_cachepath_on = 0; /* Default to off */ + +void +as_enable_cachepath() +{ + as_cachepath_on = 1; +} + +void +as_disable_cachepath() +{ + as_cachepath_on = 0; +} + +/* Note we want these to be as fast as possible */ + +void +as_add_cachepath(struct as_data *adp) +{ + struct as_frompath *from; + struct as_topath *to = (struct as_topath *)0; + struct as_node *np; + + /* Don't do anything if we aren't cacheing these */ + if (as_cachepath_on == 0) + return; + + /* Note we will only allocate this once. Afterwards, we just keep + * zeroing it since it's rather small and we don't need to re-allocate + * each time. */ + if (fromhead == (struct as_frompath **)0) { + fromhead = calloc(1, sizeof(struct as_frompath *) * WORLD_Y); + if (fromhead == (struct as_frompath **)0) + return; + } + + np = adp->head->np; + for (from = fromhead[adp->from.y]; from; from = from->next) + if (from->x == adp->from.x) + break; + if (from) { + for (to = from->tolist[np->c.y]; to; to = to->next) { + if (to->x == np->c.x) { + /* It is already here! Don't bother adding it again */ + return; + } + } + } else { + /* We must make a new one of these */ + from = (struct as_frompath *)malloc(sizeof(struct as_frompath)); + if (from == NULL) + return; + /* And set some stuff */ + from->x = adp->from.x; + /* Here we malloc a whole bunch of tolist pointers. */ + from->tolist = (struct as_topath **)calloc(1, + sizeof(struct as_topath *) * + WORLD_Y); + /* Now, add from to the global list */ + from->next = fromhead[adp->from.y]; + fromhead[adp->from.y] = from; + } + if (!to) { + /* We must make a new one */ + to = (struct as_topath *)malloc(sizeof(struct as_topath)); + /* We can't, sorry */ + if (to == NULL) + return; + /* Now set some stuff */ + to->x = np->c.x; + /* Now add it to the list we are in */ + to->next = from->tolist[np->c.y]; + from->tolist[np->c.y] = to; + } + /* Now, make the path */ + as_makepath(adp); + /* Now, take the path */ + to->path = adp->path; + /* And clear the path in the adp */ + adp->path = NULL; +} + +void +as_clear_cachepath() +{ + struct as_frompath *from, *from2; + struct as_topath *to, *to2; + int i, j; + + /* Cache not used yet :) */ + if (fromhead == (struct as_frompath **)0) + return; + + for (j = 0; j < WORLD_Y; j++) { + for (from = fromhead[j]; from; from = from2) { + for (i = 0; i < WORLD_Y; i++) { + for (to = from->tolist[i]; to; to = to2) { + to2 = to->next; + /* Free this path */ + as_free_path(to->path); + /* Free this node */ + free((s_char *)to); + } + } + /* Now, free the list of lists */ + free((s_char *)from->tolist); + /* Save the next pointer */ + from2 = from->next; + /* now, free this from node */ + free((s_char *)from); + } + } + /* Note we don't free the fromhead here, we just zero it. That way, + we can use it next time without mallocing int */ + bzero((s_char *)fromhead, (sizeof(struct as_frompath *) * WORLD_Y)); +} + +struct as_path * +as_find_cachepath(coord fx, coord fy, coord tx, coord ty) +{ + struct as_frompath *from; + struct as_topath *to; + + /* Is the cache on? if not, return NULL */ + if (as_cachepath_on == 0) + return (NULL); + + /* Do we have any cached? */ + if (fromhead == (struct as_frompath **)0) + return (NULL); + + /* Yes! */ + for (from = fromhead[fy]; from; from = from->next) { + if (from->x == fx) { + for (to = from->tolist[ty]; to; to = to->next) { + if (to->x == tx) + return (to->path); + } + } + } + return (NULL); +} diff --git a/src/lib/as/as_costcomp.c b/src/lib/as/as_costcomp.c new file mode 100644 index 00000000..7e50db9d --- /dev/null +++ b/src/lib/as/as_costcomp.c @@ -0,0 +1,49 @@ +/* + * A* Search - A search library used in Empire to determine paths between + * objects. + * Copyright (C) 1990-1998 Phil Lapsley + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include "as.h" + +#if !defined(lint) && !defined(SABER) +static char sccsid[] = "@(#)as_costcomp.c 1.4 11/13/90"; +#endif /* not lint*/ + +/* + * Compare the lower bound costs of two nodes. If the two nodes have + * equal lower bound costs, sort on the secondary field. + * Used as comparision function for qsort. + */ +int +as_costcomp(struct as_node **n1, struct as_node **n2) +{ + double diff; + + diff = (*n1)->lbcost - (*n2)->lbcost; + if (diff < -0.0001) + return (-1); + if (diff > 0.0001) + return (1); + + /* equal, check secondary cost */ + diff = (*n1)->seccost - (*n2)->seccost; + if (diff < -0.0001) + return (-1); + if (diff > 0.0001) + return (1); + return (0); +} diff --git a/src/lib/as/as_delete.c b/src/lib/as/as_delete.c new file mode 100644 index 00000000..24b7a193 --- /dev/null +++ b/src/lib/as/as_delete.c @@ -0,0 +1,88 @@ +/* + * A* Search - A search library used in Empire to determine paths between + * objects. + * Copyright (C) 1990-1998 Phil Lapsley + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include +#include +#include "as.h" + +#if !defined(lint) && !defined(SABER) +static char sccsid[] = "@(#)as_delete.c 1.5 11/13/90"; +#endif /* not lint */ + +static void as_free_queue(struct as_queue *queue); + +/* + * Free any dynamically allocated data stored in the as_data structure. + */ +void +as_reset(struct as_data *adp) +{ + + as_free_queue(adp->head); + adp->head = NULL; + as_free_queue(adp->tried); + adp->tried = NULL; + as_free_queue(adp->subsumed); + adp->subsumed = NULL; + as_free_hashtab(adp); + as_free_path(adp->path); + adp->path = NULL; +} + +/* + * Free a queue (either the main, subsumed, or tried). + */ +static void +as_free_queue(struct as_queue *queue) +{ + struct as_queue *qp, *qp2; + + for (qp = queue; qp; qp = qp2) { + free((s_char *)qp->np); + qp2 = qp->next; + free((s_char *)qp); + } +} + +/* + * Free a path. + */ +void +as_free_path(struct as_path *pp) +{ + struct as_path *pp2; + + for (; pp; pp = pp2) { + pp2 = pp->next; + free((s_char *)pp); + } +} + +/* + * Delete the as_data structure (which includes freeing its data). + */ +void +as_delete(struct as_data *adp) +{ + as_reset(adp); + free((s_char *)adp->neighbor_coords); + free((s_char *)adp->neighbor_nodes); + free((s_char *)adp->hashtab); + free((s_char *)adp); +} diff --git a/src/lib/as/as_extend.c b/src/lib/as/as_extend.c new file mode 100644 index 00000000..8e097ef6 --- /dev/null +++ b/src/lib/as/as_extend.c @@ -0,0 +1,74 @@ +/* + * A* Search - A search library used in Empire to determine paths between + * objects. + * Copyright (C) 1990-1998 Phil Lapsley + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include +#include +#include "as.h" + +#if !defined(lint) && !defined(SABER) +static char sccsid[] = "@(#)as_extend.c 1.2 11/13/90"; +#endif /* not lint */ + +/* + * Extend the queue by neighbors. This entails getting the + * coordinates of all the neighbors, figuring out their lower bound + * costs, throwing away ones that are more expensive than ones we + * already have, sorting, tand then merging into the queue. + */ +struct as_queue * +as_extend(struct as_data *adp) +{ + struct as_queue *qp; + int i; + struct as_queue *head; + + head = adp->head; + + /* Find the neighboring coordinates. */ + i = (*adp->neighbor)(head->np->c, adp->neighbor_coords, adp->userdata); + if (i == 0) + return (NULL); + /* + * Get rid of neighbors that are more costly than ones we already have, + * and sort the rest into an array of as_nodes. + */ + i = as_winnow(adp, adp->neighbor_coords, i); + if (i < 0) + return (NULL); + if (i > 1) + qsort(adp->neighbor_nodes, i, + sizeof (*adp->neighbor_nodes), + (qsort_func_t) as_costcomp); + + /* remove old coord from head of queue and add to list of tried */ + qp = head; + head = head->next; + if (head) + head->prev = NULL; + if (adp->tried) { + adp->tried->prev = qp; + qp->next = adp->tried; + adp->tried = qp; + } else + adp->tried = qp; + adp->tried->np->flags |= AS_TRIED; + + head = as_merge(adp, head, adp->neighbor_nodes); + return (head); +} diff --git a/src/lib/as/as_hash.c b/src/lib/as/as_hash.c new file mode 100644 index 00000000..8e4b9713 --- /dev/null +++ b/src/lib/as/as_hash.c @@ -0,0 +1,85 @@ +/* + * A* Search - A search library used in Empire to determine paths between + * objects. + * Copyright (C) 1990-1998 Phil Lapsley + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include +#include +#include "as.h" + +#if !defined(lint) && !defined(SABER) +static char sccsid[] = "@(#)as_hash.c 1.2 11/13/90"; +#endif /* not lint */ + +/* + * Return a pointer to the as_queue structure associated with + * this coordinate if the coordinate is in the queue. + */ +struct as_queue * +as_iscinq(struct as_data *adp, struct as_coord c) +{ + int hashval; + struct as_hash *hp; + + hashval = (*adp->hash)(c) % adp->hashsize; + + for (hp = adp->hashtab[hashval]; hp; hp = hp->next) + if (hp->c.x == c.x && hp->c.y == c.y) + return (hp->qp); + + return (NULL); +} + +/* + * Set the queue structure associated with this coordinate. + */ +void +as_setcinq(struct as_data *adp, struct as_coord c, struct as_queue *qp) +{ + int hashval; + struct as_hash *hp; + struct as_hash *new; + + new = (struct as_hash *)malloc(sizeof(struct as_hash)); + new->c = c; + new->qp = qp; + + hashval = (*adp->hash)(c) % adp->hashsize; + hp = adp->hashtab[hashval]; + + new->next = (hp) ? hp : NULL; + adp->hashtab[hashval] = new; +} + +/* + * Walk down the hash table array, freeing the chains and zeroing + * the chain pointers. + */ +void +as_free_hashtab(struct as_data *adp) +{ + int i; + struct as_hash *hp, *hp2; + + for (i = 0; i < adp->hashsize; i++) { + for (hp = adp->hashtab[i]; hp; hp = hp2) { + hp2 = hp->next; + free((char *)hp); + } + adp->hashtab[i] = NULL; + } +} diff --git a/src/lib/as/as_init.c b/src/lib/as/as_init.c new file mode 100644 index 00000000..926b3b15 --- /dev/null +++ b/src/lib/as/as_init.c @@ -0,0 +1,62 @@ +/* + * A* Search - A search library used in Empire to determine paths between + * objects. + * Copyright (C) 1990-1998 Phil Lapsley + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include +#include +#include "as.h" + +#if !defined(lint) && !defined(SABER) +static char sccsid[] = "@(#)as_init.c 1.4 11/13/90"; +#endif /* not lint */ + +/* + * Return an as_data structure with the necessary fields filled in + * and space malloced. Return NULL if malloc fails. + */ +struct as_data * +as_init(int maxneighbors, + int hashsize, + int (*hashfunc) (struct as_coord), + int (*neighborfunc) (struct as_coord, struct as_coord *, s_char *), + double (*lbcostfunc) (struct as_coord, struct as_coord, s_char *), + double (*realcostfunc) (struct as_coord, struct as_coord, s_char *), + double (*seccostfunc) (struct as_coord, struct as_coord, s_char *), + s_char *userdata) +{ + struct as_data *adp; + + AS_NEW(adp, struct as_data, NULL); + AS_NEW_ARRAY(adp->neighbor_coords, struct as_coord, + maxneighbors, NULL); + AS_NEW_ARRAY(adp->neighbor_nodes, struct as_node *, + maxneighbors + 1, NULL); + AS_NEW_ARRAY(adp->hashtab, struct as_hash *, + hashsize, NULL); + + adp->maxneighbors = maxneighbors; + adp->hashsize = hashsize; + adp->hash = hashfunc; + adp->neighbor = neighborfunc; + adp->lbcost = lbcostfunc; + adp->realcost = realcostfunc; + adp->seccost = seccostfunc; + adp->userdata = userdata; + + return (adp); +} diff --git a/src/lib/as/as_merge.c b/src/lib/as/as_merge.c new file mode 100644 index 00000000..531b474c --- /dev/null +++ b/src/lib/as/as_merge.c @@ -0,0 +1,84 @@ +/* + * A* Search - A search library used in Empire to determine paths between + * objects. + * Copyright (C) 1990-1998 Phil Lapsley + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include +#include +#include "as.h" + +#if !defined(lint) && !defined(SABER) +static char sccsid[] = "@(#)as_merge.c 1.2 11/13/90"; +#endif /* not lint */ + +/* + * Merge neighbors into queue, keeping it sorted. "neighbors" is sorted, + * both by lower bound cost and then by secondary cost. + */ +struct as_queue * +as_merge(struct as_data *adp, struct as_queue *head, struct as_node **neighbors) +{ + struct as_queue *qp; + struct as_queue *pp; /* previous pointer */ + struct as_queue *ip; /* insert pointer */ + struct as_node *np; + int i; + + qp = head; + pp = NULL; + for (i = 0; neighbors[i]; i++) { + np = neighbors[i]; + /* scan until qp points to a node we should go in front of */ + while (qp && (qp->np->lbcost < np->lbcost)) { + pp = qp; + qp = qp->next; + } + /* check for equal lower bounds, and use secondary cost if = */ + if (qp && qp->np->lbcost == np->lbcost) { + while (qp && (qp->np->lbcost == np->lbcost) && + (qp->np->seccost < np->seccost)) { + pp = qp; + qp = qp->next; + } + } + AS_NEW_MALLOC(ip, struct as_queue, NULL); + /* if there was such a node, insert us in front of it */ + if (qp) { + ip->prev = qp->prev; + if (ip->prev) + ip->prev->next = ip; + ip->next = qp; + qp->prev = ip; + if (qp == head) + head = ip; + } else { /* otherwise add us to end of queue */ + ip->next = NULL; + ip->prev = pp; + if (ip->prev) + ip->prev->next = ip; + else { + head = ip; + } + pp = ip; + } + ip->np = np; + as_setcinq(adp, np->c, ip); + np->step++; + } + + return (head); +} diff --git a/src/lib/as/as_search.c b/src/lib/as/as_search.c new file mode 100644 index 00000000..c81ed78a --- /dev/null +++ b/src/lib/as/as_search.c @@ -0,0 +1,149 @@ +/* + * A* Search - A search library used in Empire to determine paths between + * objects. + * Copyright (C) 1990-1998 Phil Lapsley + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +/* + * 11/09/98 - Steve McClure + * Added path list caching structures + */ +#include +#include +#include "as.h" + +#if !defined(lint) && !defined(SABER) +static char sccsid[] = "@(#)as_search.c 1.2 11/13/90"; +#endif /* not lint */ + +/* + * Basic A* search function. "adp" should have been initialized by + * as_init (any previously allocated data will be freed by as_reset here), + * and adp->from and adp->to should be set accordingly. On success, + * returns 0, with adp->path set to a linked list of coordinates to target. + * If we can't find target, return -1; if malloc fails, return -2. + */ +int +as_search(struct as_data *adp) +{ + int iter = 0; + struct as_queue *head; + struct as_node *np; +#ifdef DEBUG + int i; + struct as_queue *qp; + struct as_path *pp; +#endif /* DEBUG */ + struct as_queue *as_extend(struct as_data *adp); + + as_reset(adp); + + /* + * Jump start the queue by making first element the zero-cost + * node where we start. + */ + AS_NEW_MALLOC(head, struct as_queue, -2); + adp->head = head; + head->next = head->prev = NULL; + AS_NEW(np, struct as_node, -2); + np->c = adp->from; + head->np = np; + as_setcinq(adp, head->np->c, adp->head); + + for (;;) { + iter++; +#ifdef DEBUG + fprintf(stderr, "Iteration %d, head at %d, %d\n", iter, + head->np->c.x, head->np->c.y); +#endif /* DEBUG */ + + /* see if we're done, one way or another */ + if (head == NULL) + break; + + /* Add it to the cache */ + as_add_cachepath(adp); + + if (head->np->c.x == adp->to.x && head->np->c.y == adp->to.y) + break; + + /* extend queue by neighbors */ +#ifdef DEBUG + fprintf(stderr, "\tExtending queue\n"); +#endif /* DEBUG */ + adp->head = head = as_extend(adp); + +#ifdef DEBUG + fprintf(stderr, "queue:\n"); + i = 0; + for (qp = head; qp; qp = qp->next) { + fprintf(stderr, "\t%d, %d so far %f lb %f sec %f\n", + qp->np->c.x, qp->np->c.y, + qp->np->knowncost, + qp->np->lbcost, + qp->np->seccost); + i++; + } + fprintf(stderr, "\tqueue len %d\n", i); +#endif /* DEBUG */ + + } + + if (head == NULL) { +#ifdef DEBUG + fprintf(stderr, "Failed\n"); +#endif /* DEBUG */ + return (-1); + } + + as_makepath(adp); + +#ifdef DEBUG + fprintf(stderr, "Succeeded, iter %d, cost %f!\n", iter, head->np->knowncost); + fprintf(stderr, "Path:\n"); + for (pp = adp->path; pp; pp = pp->next) { + fprintf(stderr, "\t%d, %d\n", pp->c.x, pp->c.y); + } + fprintf(stderr, "Tried queue:\n"); + for (qp = adp->tried; qp; qp = qp->next) { + fprintf(stderr, "\t%d, %d\n", qp->np->c.x, qp->np->c.y); + } + fprintf(stderr, "Subsumed queue:\n"); + for (qp = adp->subsumed; qp; qp = qp->next) { + fprintf(stderr, "\t%d, %d\n", qp->np->c.x, qp->np->c.y); + } +#endif /* DEBUG */ + + return (0); +} + +/* + * Work backwards through the list of nodes (starting at head) + * to produce a path. + */ +void +as_makepath(struct as_data *adp) +{ + struct as_path *pp; + struct as_node *np; + + for (np = adp->head->np; np; np = np->back) { + pp = (struct as_path *)malloc(sizeof(struct as_path)); + pp->c = np->c; + pp->next = adp->path; + adp->path = pp; + } +} diff --git a/src/lib/as/as_stats.c b/src/lib/as/as_stats.c new file mode 100644 index 00000000..6c93fd12 --- /dev/null +++ b/src/lib/as/as_stats.c @@ -0,0 +1,73 @@ +/* + * A* Search - A search library used in Empire to determine paths between + * objects. + * Copyright (C) 1990-1998 Phil Lapsley + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include +#include "as.h" + +#if !defined(lint) && !defined(SABER) +static char sccsid[] = "@(#)as_stats.c 1.2 11/13/90"; +#endif /* not lint */ + +/* + * Print statistics on algorithm performance to the file pointer "fp". + */ +void +as_stats(struct as_data *adp, FILE *fp) +{ + int i; + int j; + int total_q; + int total_h; + struct as_queue *qp; + struct as_hash *hp; + + fprintf(fp, "Statistics:\n"); + + fprintf(fp, "queue lengths:\n"); + total_q = 0; + total_h = 0; + for (i = 0, qp = adp->head; qp; qp = qp->next) + i++; + fprintf(fp, "\tmain:\t%d\n", i); + total_q += i; + for (i = 0, qp = adp->tried; qp; qp = qp->next) + i++; + fprintf(fp, "\ttried:\t%d\n", i); + total_q += i; + for (i = 0, qp = adp->subsumed; qp; qp = qp->next) + i++; + fprintf(fp, "\tsubsumed:\t%d\n", i); + total_q += i; + fprintf(fp, "hash table statistics (size %d):\n", adp->hashsize); + for (i = 0; i < adp->hashsize; i++) { + for (j = 0, hp = adp->hashtab[i]; hp; hp = hp->next) + j++; + fprintf(fp, "\t%d\t%d\n", i, j); + total_h += j; + } + fprintf(fp, "\ttotal\t%d\n", total_h); + fprintf(fp, "approximate memory usage (bytes):\n"); + fprintf(fp, "\tqueues\t%d\n", (int)(total_q * sizeof (struct as_queue))); + fprintf(fp, "\tnodes\t%d\n", (int)(total_q * sizeof (struct as_node))); + fprintf(fp, "\thash ents\t%d\n", (int)(total_h * sizeof (struct as_hash))); + fprintf(fp, "\ttotal\t%d\n", + (int)(total_q * sizeof (struct as_queue) + + total_q * sizeof (struct as_node) + + total_h * sizeof (struct as_hash))); +} diff --git a/src/lib/as/as_winnow.c b/src/lib/as/as_winnow.c new file mode 100644 index 00000000..03b01c64 --- /dev/null +++ b/src/lib/as/as_winnow.c @@ -0,0 +1,177 @@ +/* + * A* Search - A search library used in Empire to determine paths between + * objects. + * Copyright (C) 1990-1998 Phil Lapsley + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include +#include +#include "as.h" + +#if !defined(lint) && !defined(SABER) +static char sccsid[] = "@(#)as_winnow.c 1.8 11/13/90"; +#endif /* not lint */ + +static struct as_node * +as_newnode(struct as_node *backp, struct as_coord c, + double inclbcost, double lbcost, double knowncost, double seccost); + +/* + * Take a list of neighbor coordinates and winnow them down into + * an interesting list of neighbor nodes. This means: + * + * For each neighbor, + * Compute a lower bound on the total cost to target. + * If this neighbor is already in our queue, + * See if the new neighbor is cheaper. + * If so, add it to queue and move the + * old node to the subsumed list. + * If not, ignore this neighbor. + * If this neighbor isn't in the queue, add it. + * + */ +int +as_winnow(struct as_data *adp, struct as_coord *coords, int ncoords) +{ + int i = 0; + int fix_pointer; + double knowncost; + double incknowncost; + double lbcost; + double inclbcost; + double seccost; + struct as_coord *cp; + struct as_coord *end; + struct as_queue *qp; + struct as_node *np; + + for (cp = coords, end = coords + ncoords; cp < end; cp++) { + fix_pointer = 0; + incknowncost = (*adp->realcost)(adp->head->np->c, *cp, + adp->userdata); + knowncost = adp->head->np->knowncost + incknowncost; + /* + * If this neighbor is already in the queue, we can + * save some time. + */ + qp = as_iscinq(adp, *cp); + inclbcost = qp ? qp->np->inclbcost : + (*adp->lbcost)(*cp, adp->to, adp->userdata); + if (inclbcost < 0.0) /* skip bad cases */ + continue; + lbcost = knowncost + inclbcost; +#ifdef DEBUG +fprintf(stderr, "\tneighbor %d, %d, lbcost %f ", cp->x, cp->y, lbcost); +#endif /* DEBUG */ + /* + * If this neighbor is already in the queue, check to + * see which has the lower cost. If the one already in + * the queue is cheaper, skip this neighbor as bad. If + * the neighbor does, delete the one in the queue. + */ + if (qp) { + if (qp->np->lbcost <= lbcost) { +#ifdef DEBUG +fprintf(stderr, "old, loses to %f\n", qp->np->lbcost); +#endif /* DEBUG */ + continue; + } else { +#ifdef DEBUG +fprintf(stderr, "old, wins over %f\n", qp->np->lbcost); +#endif /* DEBUG */ + if (qp->np->flags & AS_TRIED) { + /* should "never happen" */ + return (0); + } + /* + * The neighbor is better than a previously visited coordinate; + * remove the old coordinate from the queue and add it to + * the subsumed nodes queue. To get here at + * all we can't be the head, thus qp->prev is defined. + */ + /* Delete from main queue */ + qp->prev->next = qp->next; + if (qp->next) + qp->next->prev = qp->prev; + + /* Add to subsumed queue */ + if (adp->subsumed) { + adp->subsumed->prev = qp; + qp->next = adp->subsumed; + } else { + qp->next = NULL; + } + adp->subsumed = qp; + adp->subsumed->prev = NULL; + fix_pointer = 1; + /* + * At this point, the as_iscinq code may contain bogus pointer + * refs. They'll be fixed when as_merge merges the new + * neighbors into the main queue. + */ + } + } +#ifdef DEBUG +else { +fprintf(stderr, "new\n"); +} +#endif /* DEBUG */ + + if (qp) + seccost = qp->np->seccost; + else + seccost = (adp->seccost) ? + (*adp->seccost)(*cp, adp->to, adp->userdata) : + 0.0; + np = as_newnode(adp->head->np, *cp, inclbcost, lbcost, + knowncost, seccost); + if (np == NULL) + return (0); + if (fix_pointer) { +#ifdef DEBUG +fprintf(stderr, "Fixing pointer for %d, %d\n", adp->subsumed->np->c.x, +adp->subsumed->np->c.y); +#endif + adp->subsumed->np->back = np; + } + adp->neighbor_nodes[i++] = np; + + } + adp->neighbor_nodes[i] = NULL; + + return (i); +} + + +static struct as_node * +as_newnode(struct as_node *backp, struct as_coord c, + double inclbcost, double lbcost, double knowncost, double seccost) +{ + struct as_node *np; + + /* Got an interesting coordinate; make a node for it. */ + AS_NEW_MALLOC(np, struct as_node, NULL); + np->flags = 0; + np->c = c; + np->inclbcost = inclbcost; + np->lbcost = lbcost; + np->knowncost = knowncost; + np->seccost = seccost; + np->step = backp->step; + np->back = backp; + + return (np); +} diff --git a/src/lib/commands/Makefile b/src/lib/commands/Makefile new file mode 100644 index 00000000..5586b894 --- /dev/null +++ b/src/lib/commands/Makefile @@ -0,0 +1,98 @@ +# +# Empire - A multi-player, client/server Internet based war game. +# Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, +# Ken Stevens, Steve McClure +# +# 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 2 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, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# --- +# +# See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the +# related information and legal notices. It is expected that any future +# projects/authors will amend these files as needed. +# +# Makefile - Wolfpack, 1996 + +# Note that these could have been listed 1 per line, but I chose to just +# stick them all together this way to shorten the file. + +include ../../../build.conf +include ../../make.src +include ../../make.defs + +LIB = $(SRCDIR)/lib/libcommands.a +NTLIB = $(SRCDIR)\lib\libcommands.lib + +OBJS = acce.o add.o anti.o arm.o army.o assa.o atta.o bdes.o best.o boar.o \ + bomb.o brea.o budg.o buil.o buy.o capi.o carg.o cede.o cens.o chan.o \ + coas.o coll.o comm.o cons.o conv.o coun.o cuto.o decl.o deli.o demo.o \ + desi.o disa.o diss.o dist.o drop.o dump.o echo.o edit.o enab.o enli.o \ + expl.o fina.o flash.o flee.o fly.o foll.o forc.o fort.o fuel.o give.o \ + grin.o hard.o head.o hidd.o improve.o info.o land.o laun.o lboard.o \ + ldump.o ledg.o leve.o load.o look.o lost.o lstat.o lten.o map.o \ + marc.o mark.o mfir.o mine.o miss.o mobq.o mobu.o mora.o move.o mult.o \ + name.o nati.o navi.o ndump.o new.o newe.o news.o nuke.o offe.o offs.o \ + orde.o orig.o para.o path.o payo.o pboa.o pdump.o plan.o play.o \ + powe.o prod.o pstat.o rada.o rang.o rea.o real.o reco.o reje.o rela.o \ + repa.o repo.o rese.o reso.o retr.o rout.o sabo.o sail.o sate.o scra.o \ + scut.o sdump.o sect.o sell.o set.o setres.o setsect.o shar.o shark.o \ + shi.o shoo.o show.o shut.o sinf.o skyw.o sona.o spy.o sstat.o star.o \ + stop.o stre.o strv.o supp.o surv.o swap.o tele.o tend.o terr.o thre.o \ + togg.o torp.o trad.o tran.o trea.o turn.o upda.o upgr.o vers.o wai.o \ + wing.o wipe.o work.o zdon.o + +NTOBJS = acce.obj add.obj anti.obj arm.obj army.obj assa.obj atta.obj \ + bdes.obj best.obj boar.obj bomb.obj brea.obj budg.obj buil.obj \ + buy.obj capi.obj carg.obj cede.obj cens.obj chan.obj coas.obj \ + coll.obj comm.obj cons.obj conv.obj coun.obj cuto.obj decl.obj \ + deli.obj demo.obj desi.obj disa.obj diss.obj dist.obj drop.obj \ + dump.obj echo.obj edit.obj enab.obj enli.obj expl.obj fina.obj \ + flash.obj flee.obj fly.obj foll.obj forc.obj fort.obj fuel.obj \ + give.obj grin.obj hard.obj head.obj hidd.obj improve.obj info.obj \ + land.obj laun.obj lboard.obj ldump.obj ledg.obj leve.obj load.obj \ + look.obj lost.obj lstat.obj lten.obj map.obj marc.obj mark.obj \ + mfir.obj mine.obj miss.obj mobq.obj mobu.obj mora.obj move.obj \ + mult.obj name.obj nati.obj navi.obj ndump.obj new.obj newe.obj \ + news.obj nuke.obj offe.obj offs.obj orde.obj orig.obj para.obj \ + path.obj payo.obj pboa.obj pdump.obj plan.obj play.obj powe.obj \ + prod.obj pstat.obj rada.obj rang.obj rea.obj real.obj reco.obj \ + reje.obj rela.obj repa.obj repo.obj rese.obj reso.obj retr.obj \ + rout.obj sabo.obj sail.obj sate.obj scra.obj scut.obj sdump.obj \ + sect.obj sell.obj set.obj setres.obj setsect.obj shar.obj shark.obj \ + shi.obj shoo.obj show.obj shut.obj sinf.obj skyw.obj sona.obj spy.obj \ + sstat.obj star.obj stop.obj stre.obj strv.obj supp.obj surv.obj \ + swap.obj tele.obj tend.obj terr.obj thre.obj togg.obj torp.obj \ + trad.obj tran.obj trea.obj turn.obj upda.obj upgr.obj vers.obj \ + wai.obj wing.obj wipe.obj work.obj zdon.obj + +all: $(LIB) + +nt: $(NTLIB) + +$(NTLIB): $(NTOBJS) + -del /q $@ + lib /OUT:$@ /DEBUGTYPE:CV $(NTOBJS) + +$(LIB): $(OBJS) + rm -f $(LIB) + ar cq $(LIB) $(OBJS) + $(RANLIB) $(LIB) + +clean: + -(rm -f $(OBJS)) + -(del /q $(NTOBJS)) + +include ../../make.rules +include Makedepend diff --git a/src/lib/commands/acce.c b/src/lib/commands/acce.c new file mode 100644 index 00000000..3c68874b --- /dev/null +++ b/src/lib/commands/acce.c @@ -0,0 +1,92 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * acce.c: Report rejection status of telegrams/treaties/annos/loans + * + * Known contributors to this file: + * + */ + +#include "misc.h" +#include "player.h" +#include "var.h" +#include "nat.h" +#include "sect.h" +#include "file.h" +#include "xy.h" +#include "commands.h" +#include "optlist.h" + +/* + * report rejection status of telegrams and treaties. + * Optional argument reports staus from the + * viewpoint of another country + */ +int +acce(void) +{ + struct natstr *natp; + struct natstr *np; + natid cn; + natid as; + int n; + + if (player->argp[1] == 0) + as = player->cnum; + else { + if ((n = natarg(player->argp[1], "Which country? ")) < 0) { + pr("Bad country number\n"); + return RET_SYN; + } + as = (natid) n; + } + if ((natp = getnatp(as)) == 0) { + pr("Bad country number %d\n", player->cnum); + return RET_SYN; + } + pr("\t%s Acceptance Status Report\t", cname(as)); + prdate(); + pr("\n Acceptance status %5s theirs\n", + player->cnum == as ? "yours" : " his"); + pr(" tel trty anno loan tel trty anno loan\n"); + for (cn=1; cn < MAXNOC; cn++) { + if ((np = getnatp(cn)) == 0) + break; + if (cn == as) + continue; + if ((np->nat_stat & STAT_NORM) == 0 && + (np->nat_stat & STAT_SANCT) == 0) + continue; + if (opt_HIDDEN) { + if (!player->god && !getcontact(getnatp(player->cnum), cn)) + continue; + } + pr("%3d) %-14.14s ", cn, cname(cn)); + pr("%-9s %s\n", rejectname(natp, cn), rejectname(np, as)); + } + return RET_OK; +} diff --git a/src/lib/commands/add.c b/src/lib/commands/add.c new file mode 100644 index 00000000..1d87bd1e --- /dev/null +++ b/src/lib/commands/add.c @@ -0,0 +1,231 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * add.c: Add a new country to the game + * + * Known contributors to this file: + * Steve McClure, 2000 + * + */ + +#include +#include "misc.h" +#include "player.h" +#include "var.h" +#include "sect.h" +#include "nat.h" +#include "xy.h" +#include "nsc.h" +#include "file.h" +#include "tel.h" +#include "land.h" +#include "commands.h" + +extern float start_education, start_happiness; +extern float start_technology, start_research; + +int +add(void) +{ + struct natstr *natp; + struct sctstr sect; + struct nstr_sect nstr; + register int i; + s_char cntryname[21]; + s_char pname[21]; + natid coun; + natid freecn; + s_char prompt[128]; + s_char buf[1024]; + s_char *p; + s_char loopflag; + int stat; + struct nstr_item ni; + struct lndstr land; + + for (freecn=0; NULL != (natp = getnatp(freecn)); freecn++) { + if ((natp->nat_stat & STAT_INUSE) == 0) + break; + } + if (freecn < MAXNOC) + sprintf(prompt, "New country number? (%d is unused) ", freecn); + else + strcpy(prompt, "New country number? (they all seem to be used) "); + while ((p = getstarg(player->argp[1], prompt, buf)) && *p) { + coun = atoi(p); + if (coun < MAXNOC) + break; + pr("Max # countries is %d\n", MAXNOC); + player->argp[1] = 0; + } + if (p == 0 || *p == 0) + return RET_FAIL; + if (coun == 0) { + pr("Not allowed to add country #0\n"); + return RET_FAIL; + } + natp = getnatp(coun); + while ((p = getstarg(player->argp[2], "Country Name? ", buf)) && *p) { + if (strlen(p) < 20) { + (void) strcpy(cntryname, p); + break; + } + pr("Too long.\n"); + player->argp[2] = 0; + } + if (p == 0 || *p == 0) + return RET_OK; + while ((p = getstarg(player->argp[3], "Representative? ", buf)) && *p) { + if (strlen(p) < 20) { + (void) strcpy(pname, p); + break; + } + pr("Too long.\n"); + player->argp[3] = 0; + } + if (p == 0 || *p == 0) + return RET_OK; + loopflag = 1; + stat = natp->nat_stat; + strcpy(prompt, "Status? (visitor, new, active, god, delete) "); + while (loopflag && (p = getstarg(player->argp[4], prompt, buf))) { + loopflag = 0; + switch (*p) { + case 'v': + stat = STAT_INUSE; + break; + case 'n': + stat = STAT_NEW|STAT_INUSE; + break; + case 'a': + stat = STAT_NORM|STAT_INUSE; + break; + case 'g': + stat = STAT_GOD|STAT_NORM|STAT_INUSE; + break; + case 'd': + stat = 0; + break; + default: + pr("Illegal selection\n"); + loopflag = 1; + break; + } + player->argp[4] = 0; + } + if (p == 0) + return RET_OK; + p = getstarg(player->argp[5], + "Check, wipe, or ignore existing sectors (c|w|i) ", buf); + if (p == 0) + return RET_OK; + snxtitem_all(&ni,EF_LAND); + while(nxtitem(&ni, (s_char *)&land)) { + if (land.lnd_own == coun){ + makelost(EF_LAND, land.lnd_own, land.lnd_uid, land.lnd_x, land.lnd_y); + land.lnd_own = 0; + pr("Land unit %d wiped\n",land.lnd_uid); + putland(land.lnd_uid,&land); + } + } + natp->nat_stat = stat; + strcpy(natp->nat_cnam, cntryname); + strcpy(natp->nat_pnam, pname); + if (*p != 'w' && *p != 'c') { + pr("Any existing sectors ignored\n"); + } else { + pr("Checking sectors...\n"); + snxtsct_all(&nstr); + while (nxtsct(&nstr, §)) { + if (sect.sct_own != coun) + continue; + pr("%s ", xyas(nstr.x, nstr.y, player->cnum)); + if (*p == 'w') { + sect.sct_mobil = 0; + sect.sct_effic = 0; + sect.sct_road = 0; + sect.sct_rail = 0; + sect.sct_defense = 0; + sect.sct_own = 0; + sect.sct_oldown = 0; + if (sect.sct_type != SCT_MOUNT && + sect.sct_type != SCT_PLAINS) { + sect.sct_type = SCT_RURAL; + sect.sct_newtype = SCT_RURAL; + } + /* No dist path */ + sect.sct_dist_x = sect.sct_x; + sect.sct_dist_y = sect.sct_y; + sect.sct_nv = 0; + putsect(§); + pr("wiped\n"); + } else { + pr("\n"); + } + } + } + + if ((natp->nat_stat & (STAT_INUSE|STAT_NORM|STAT_GOD)) == STAT_INUSE) { + *natp->nat_hostaddr = '\0'; + *natp->nat_hostname = '\0'; + *natp->nat_userid = '\0'; + natp->nat_btu = 0; + natp->nat_connected = 0; + natp->nat_reserve = 0; + natp->nat_tgms = 0; + natp->nat_ystart = 0; + natp->nat_xstart = 0; + natp->nat_ycap = 0; + natp->nat_xcap = 0; + natp->nat_yorg = 0; + natp->nat_xorg = 0; + natp->nat_dayno = 0; + natp->nat_minused = 0; + bzero((s_char *)natp->nat_b, sizeof (natp->nat_b)); + (void) time(&natp->nat_last_login); + (void) time(&natp->nat_last_logout); + natp->nat_money = 0; + natp->nat_level[NAT_TLEV] = start_technology; + natp->nat_level[NAT_RLEV] = start_research; + natp->nat_level[NAT_ELEV] = start_education; + natp->nat_level[NAT_HLEV] = start_happiness; + for (i=0; inat_rejects[i] = 0; + natp->nat_newstim = 0; + natp->nat_annotim = 0; + (void) creat(mailbox(buf, coun), 0660); + } else + pr("No special initializations done...\n"); + + for (i=0; inat_priorities[i] = -1; + natp->nat_flags = NF_FLASH | NF_BEEP | NF_COASTWATCH | NF_SONAR | NF_TECHLISTS; + for (i=0; inat_relate[i] = NEUTRAL; + putnat(natp); + return 0; +} diff --git a/src/lib/commands/anti.c b/src/lib/commands/anti.c new file mode 100644 index 00000000..1d01d552 --- /dev/null +++ b/src/lib/commands/anti.c @@ -0,0 +1,172 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * anti.c: Take action against che + * + * Known contributors to this file: + * Pat Loney, 1992 + * Steve McClure, 1997 + */ + + +#include +#include +#include "misc.h" +#include "player.h" +#include "var.h" +#include "xy.h" +#include "sect.h" +#include "nat.h" +#include "news.h" +#include "nsc.h" +#include "item.h" +#include "file.h" +#include "commands.h" +#include "optlist.h" + +extern int etu_per_update; +extern int sect_mob_neg_factor; +/* + * format: anti + */ +int +anti(void) +{ + struct sctstr sect; + int nsect; + struct nstr_sect nstr; + int cond[I_MAX+1]; + int mil, che, target; + int avail_mil; + int amil, ache; + int milkilled, chekilled; + double odds, damil, dache; + int mob; + int n_cheleft; + extern double hap_fact(); + + if (!snxtsct(&nstr, player->argp[1])) + return RET_SYN; + prdate(); + nsect = 0; + while (nxtsct(&nstr, §)) { + if (!player->owner) + continue; + if (nsect++ == 0) { + pr(" sect subversion activity report\n"); + pr(" ---- --------------------------\n"); + } + getvec(VT_COND, cond, (char *)§, EF_SECTOR); + mil = getvar(V_MILIT, (char *)§, EF_SECTOR); + che = get_che_value(cond[C_CHE]); + target = get_che_cnum(cond[C_CHE]); + avail_mil = sect.sct_mobil/2; + if (mil <= avail_mil) + avail_mil = mil; + prxy("%4d,%-4d ", sect.sct_x, sect.sct_y, player->cnum); + if (avail_mil <= 0) { + pr("No available mil or mob in sector.\n"); + continue; + } + pr("Sector mobility/troop strength will allow %d troops to engage.\n", + avail_mil); + + if (target == player->cnum) { + amil = mil; + ache = che; + milkilled = 0; + chekilled = 0; + mob = sect.sct_mobil; + while (amil != 0 && ache != 0 && mob > 1) { + damil = amil; + dache = ache; + odds = (dache * 2.0 / (damil + dache)); + odds /= hap_fact(getnatp(sect.sct_own),getnatp(sect.sct_oldown)); + mob = mob - 2; + if (chance(odds)) { + amil = amil - 1; + milkilled = milkilled + 1; + } else { + ache = ache - 1; + chekilled = chekilled + 1; + } + } + if (mil - milkilled > 0) { + sect.sct_mobil = sect.sct_mobil - chekilled - milkilled; + putvar(V_MILIT, mil - milkilled, (char *)§, + EF_SECTOR); + if ( ache == 0 ) + cond[C_CHE] = 0; + set_che_value(cond[C_CHE], ache); + putvar(V_CHE, cond[C_CHE], (char *)§, EF_SECTOR); + putsect(§); + pr(" Body count: Military %d - Guerillas %d.\n", + milkilled, chekilled); + if (ache == 0) { + pr(" Partisans cleared out of this sector for now.\n"); + } else { + pr(" Partisans still active in this sector.\n"); + } + } else { + if (opt_MOB_ACCESS) { + sect.sct_mobil = + -(etu_per_update/sect_mob_neg_factor); + } else { + sect.sct_mobil = 0; + } + sect.sct_loyal = sect.sct_loyal * 0.5; + n_cheleft = (random() % 4); + /* 75% chance some che will get left */ + if (n_cheleft) { + /* Ok, now leave anywhere from 16% to 25% of the che */ + n_cheleft = (ache / (n_cheleft + 3)); + ache -= n_cheleft; + set_che_value(cond[C_CHE], n_cheleft); + } else + cond[C_CHE] = 0; + putvar(V_MILIT, ache, (char *)§, EF_SECTOR); + putvar(V_CHE, cond[C_CHE], (char *)§, EF_SECTOR); + if (sect.sct_own == sect.sct_oldown) + sect.sct_oldown = 0; + makelost(EF_SECTOR, sect.sct_own, 0, sect.sct_x, sect.sct_y); + makenotlost(EF_SECTOR, sect.sct_oldown, 0, sect.sct_x, sect.sct_y); + sect.sct_own = sect.sct_oldown; + sect.sct_off = 1; /* Turn the sector off */ + putsect(§); + pr(" Partisans take over the sector. You blew it.\n"); + wu(0, sect.sct_oldown, + "Sector %s regained from Partisan activity.\n", + xyas(nstr.x,nstr.y,sect.sct_oldown)); + } + } else { + pr(" Body count: Military 0 - Guerillas 0.\n"); + pr(" Partisans cleared out of this sector for now.\n"); + } + } + pr("%d sector%s\n", nsect, splur(nsect)); + return RET_OK; +} diff --git a/src/lib/commands/arm.c b/src/lib/commands/arm.c new file mode 100644 index 00000000..30e6b666 --- /dev/null +++ b/src/lib/commands/arm.c @@ -0,0 +1,164 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * arm.c: Arm planes (missiles) with nuclear devices + * + * Known contributors to this file: + * Dave Pare, 1986 + * Ken Stevens, 1995 + * Steve McClure, 2000 + */ + +#ifdef Rel4 +#include +#endif /* Rel4 */ +#include "misc.h" +#include "player.h" +#include "var.h" +#include "sect.h" +#include "nuke.h" +#include "plane.h" +#include "xy.h" +#include "nsc.h" +#include "file.h" +#include "nat.h" +#include "commands.h" +#include "optlist.h" + +int +arm(void) +{ + struct nchrstr *ncp; + struct plchrstr *plc; + struct plnstr pl; + struct plnstr start; /* Used for sanity checking */ + struct nukstr nuke; + s_char *p; + int i; + int pno; + int nuketype; + int nukenum; + int len; + struct nstr_item ni; + s_char buf[1024]; + int disarm = **player->argp=='d'; + s_char *prompt = disarm?"Disarm plane: ":"Arm plane: "; + + if (!(p = getstarg(player->argp[1], prompt, buf)) || !*p) + return RET_SYN; + pno = atoi(p); + if (pno < 0 || !getplane(pno, &pl) || pl.pln_own != player->cnum) + return RET_FAIL; + memcpy(&start, &pl, sizeof(struct plnstr)); + plc = &plchr[(int)pl.pln_type]; + if ((plc->pl_flags & (P_O | P_M)) == (P_O | P_M)) { + pr("A %s cannot carry nuclear devices!\n",plc->pl_name); + return RET_FAIL; + } + if (opt_MARKET) { + if (ontradingblock(EF_PLANE, (int *)&pl)) { + pr("You cannot arm/disarm an item on the trading block!\n"); + return RET_FAIL; + } + } + if (pl.pln_nuketype == -1) { + if (disarm) { + pr("%s is not carrying any nuclear devices\n", + prplane(&pl)); + return RET_FAIL; + } + if ((p = getstarg(player->argp[2], "Device type: ", buf)) == 0) + return RET_SYN; + if (!check_plane_ok(&start)) + return RET_FAIL; + len = strlen(p); + for (i=0, ncp = nchr; in_name, p, len) == 0) + break; + } + if (i >= N_MAXNUKE) { + pr("No such nuke type!\n"); + return RET_SYN; + } + nuketype = i; + nukenum = -1; + snxtitem_all(&ni, EF_NUKE); + while (nxtitem(&ni, (s_char *)&nuke)) { + if (nuke.nuk_own != player->cnum) + continue; + if (nuke.nuk_x != pl.pln_x || nuke.nuk_y != pl.pln_y) + continue; + nukenum = ni.cur; + break; + } + if (nukenum < 0) { + pr("You don't own any nukes in that sector.\n"); + return RET_FAIL; + } + if (nuke.nuk_types[nuketype] == 0) { + pr("No nukes of that type in that sector.\n"); + return RET_FAIL; + } + if (pl.pln_load < ncp->n_weight) { + pr("A %s cannot carry %s devices!\n", plc->pl_name,ncp->n_name); + return RET_FAIL; + } + p = getstarg(player->argp[3], "Airburst [n]? ", buf); + + if (!check_plane_ok(&start)) + return RET_FAIL; + + if (p && (*p == 'y' || *p == 'Y')) + pl.pln_flags |= PLN_AIRBURST; + else + pl.pln_flags &= ~PLN_AIRBURST; + + pl.pln_nuketype = nuketype; + nuk_delete(&nuke, nuketype, 1); + } else if (!disarm) { + pr("%s already carrying a warhead.\n", prplane(&pl)); + } + if (disarm) { + pr("%s warhead removed from %s and added to %s\n", + nchr[(int)pl.pln_nuketype].n_name, + prplane(&pl), + xyas(pl.pln_x, pl.pln_y, player->cnum)); + nuk_add(pl.pln_x, pl.pln_y, pl.pln_nuketype, 1); + pl.pln_nuketype = -1; + pl.pln_flags &= ~PLN_AIRBURST; + } else { + pr("%s armed with a %s warhead.\n", prplane(&pl), + nchr[(int)pl.pln_nuketype].n_name); + pr("Warhead on %s is programmed to %s\n", + prplane(&pl), + pl.pln_flags & PLN_AIRBURST? + "airburst":"groundburst"); + } + + putplane(pl.pln_uid, &pl); + return RET_OK; +} diff --git a/src/lib/commands/army.c b/src/lib/commands/army.c new file mode 100644 index 00000000..e5e087cf --- /dev/null +++ b/src/lib/commands/army.c @@ -0,0 +1,88 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * army.c: Add units to an army + * + * Known contributors to this file: + * + */ + +#include +#include "misc.h" +#include "player.h" +#include "var.h" +#include "land.h" +#include "xy.h" +#include "nsc.h" +#include "file.h" +#include "nat.h" +#include "commands.h" + +int +army(void) +{ + struct lndstr land; + register int count; + s_char *cp; + s_char c; + struct nstr_item nstr; + struct nstr_item ni; + struct lndstr land2; + int r; + s_char buf[1024]; + + cp = getstarg(player->argp[1], "army? ", buf); + if (cp == 0) + return RET_SYN; + c = *cp; + if (!isalpha(c) && c != '~') { + pr("Specify army, (1 alpha char or '~')\n"); + return RET_SYN; + } + if (c == '~') + c = ' '; + if (!snxtitem(&nstr, EF_LAND, player->argp[2])) + return RET_SYN; + count = 0; + while (nxtitem(&nstr, (s_char *)&land)) { + if (!player->owner) + continue; + land.lnd_army = c; + snxtitem(&ni, EF_LAND, cp); + while ((r=nxtitem(&ni, (s_char *)&land2)) && + (land2.lnd_army != c)) + ; + if (r){ + bcopy(land2.lnd_rpath, land.lnd_rpath,10); + land.lnd_rflags = land2.lnd_rflags; + } + putland(land.lnd_uid, &land); + count++; + } + pr("%d unit%s added to army `%c'\n", count, splur(count), c); + return RET_OK; +} diff --git a/src/lib/commands/assa.c b/src/lib/commands/assa.c new file mode 100644 index 00000000..3351569d --- /dev/null +++ b/src/lib/commands/assa.c @@ -0,0 +1,231 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * assa.c: Hit the beaches! + * + * Known contributors to this file: + * Ken Stevens, 1995 + * Steve McClure, 1997 + */ + +#include +#include "misc.h" +#include "player.h" +#include "file.h" +#include "var.h" +#include "sect.h" +#include "path.h" +#include "news.h" +#include "treaty.h" +#include "nat.h" +#include "xy.h" +#include "land.h" +#include "nsc.h" +#include "mission.h" +#include "ship.h" +#include "combat.h" +#include "commands.h" + +int +assa(void) { + struct combat off[1]; /* assaulting ship */ + struct combat def[1]; /* defending sector */ + int fort_sup, ship_sup, land_sup, plane_sup; + struct emp_qelem olist; /* assaulting units */ + struct emp_qelem dlist; /* defending units */ + int ototal; /* total assaulting strength */ + int a_engineer = 0; /* assaulter engineers are present */ + int a_spy = 0; /* the best assaulter scout */ + double osupport = 1.0; /* assault support */ + double dsupport = 1.0; /* defense support */ + s_char *p; + s_char buf[1024]; + int n; + int ourtotal; + struct emp_qelem *qp, *next; + struct llist *llp; + int rel; + + att_combat_init(off, EF_SHIP); + att_combat_init(def, EF_SECTOR); + /* + * Collect input from the assaulter + */ + + /* What are we assaulting? */ + + if (!(p = getstarg(player->argp[1], "Sector : ", buf))) + return RET_SYN; + if (!sarg_xy(p, &def->x, &def->y)) + return RET_SYN; + if (att_abort(A_ASSAULT, 0, def)) + return RET_FAIL; + + /* + * Ask the assaulter what he wants to assault with + */ + + if ((off->shp_uid = onearg(player->argp[2], "Assault from ship #")) < 0) { + pr("You may only assault from one ship!\n"); + return RET_FAIL; + } + if (att_abort(A_ASSAULT, off, def)) { + pr("Assault aborted\n"); + return RET_OK; + } + + /* Show what we're assaulting, and check treaties */ + + if (att_show(def)) + return RET_FAIL; + + /* Ask about offensive support */ + + att_ask_support(3, &fort_sup, &ship_sup, &land_sup, &plane_sup); + if (att_abort(A_ASSAULT, off, def)) { + att_empty_attack(A_ASSAULT, 0, def); + return RET_OK; + } + + /* Ask the player what he wants to assault with */ + + att_ask_offense(A_ASSAULT, off, def, &olist, &a_spy, &a_engineer); + if (att_abort(A_ASSAULT, off, def)) { + pr("Assault aborted\n"); + att_empty_attack(A_ASSAULT, 0, def); + return att_free_lists(&olist, 0); + } + + /* If we're assaulting our own sector, end here */ + if (def->own == player->cnum) { + if (off->troops) + pr("You reinforce %s with %d troops\n", + xyas(def->x, def->y, player->cnum), off->troops); + if (off->troops || !QEMPTY(&olist)) + att_move_in_off(A_ASSAULT, off, &olist, def); + return RET_OK; + } + + /* + * Estimate the defense strength and give the player a chance to abort + */ + + ototal = att_estimate_defense(A_ASSAULT, off, &olist, def, a_spy); + if (att_abort(A_ASSAULT, off, def)) { + pr("Assault aborted\n"); + att_empty_attack(A_ASSAULT, 0, def); + return att_free_lists(&olist, 0); + } + + /* + * We have now got all the answers from the assaulter. From this point + * forward, we can assume that this battle is the _only_ thing + * happening in the game. + */ + + /* First, we check to see if the only thing we have are spies + * assaulting. If so, we try to sneak them on land. If they + * make it, the defenders don't see a thing. If they fail, well, + * the spies die, and the defenders see them. */ + + ourtotal = 0; + for (n = 0; n <= off->last; n++) { + if (off[n].type == EF_BAD) + continue; + ourtotal += off[n].troops * att_combat_eff(off + n); + } + for (qp = olist.q_forw; qp != &olist; qp = next ) { + next = qp->q_forw; + llp = (struct llist *)qp; + if (lchr[(int)llp->land.lnd_type].l_flags & L_SPY) + continue; + ourtotal++; + } + + /* If no attacking forces (i.e. we got here with only spies) + * then try to sneak on-land. */ + + if (!ourtotal) { + pr("Trying to sneak on shore...\n"); + + for (qp = olist.q_forw; qp != &olist; qp = next ) { + next = qp->q_forw; + llp = (struct llist *)qp; + rel = getrel(getnatp(def->own), player->cnum); + if (chance(0.10) || rel == ALLIED || !def->own) { + pr("%s made it on shore safely.\n", prland(&llp->land)); + llp->land.lnd_x = def->x; + llp->land.lnd_y = def->y; + llp->land.lnd_ship = -1; + putland(llp->land.lnd_uid, &llp->land); + } else { + pr("%s was spotted", prland(&llp->land)); + if (rel == HOSTILE || rel == AT_WAR || rel == SITZKRIEG || + rel == MOBILIZATION) { + wu(0, def->own, "%s spy shot and killed in %s.\n", + cname(player->cnum), xyas(def->x, def->y, def->own)); + pr(" and was killed in the attempt.\n"); + llp->land.lnd_effic = 0; + putland(llp->land.lnd_uid, &llp->land); + lnd_delete(llp, ""); + } else { + wu(0, def->own, "%s spy spotted in %s.\n", + cname(player->cnum), xyas(def->x, def->y, def->own)); + pr(" but made it ok.\n"); + llp->land.lnd_x = def->x; + llp->land.lnd_y = def->y; + llp->land.lnd_ship = -1; + putland(llp->land.lnd_uid, &llp->land); + } + } + } + return RET_OK; + } + + /* Get the real defense */ + + att_get_defense(&olist, def, &dlist, a_spy, ototal); + + /* Get assaulter and defender support */ + + att_get_support(A_ASSAULT, fort_sup, ship_sup, land_sup, plane_sup, + &olist, off, &dlist, def, &osupport, &dsupport, + a_engineer); + if (att_abort(A_ASSAULT, off, def)) { + pr("Assault aborted\n"); + att_empty_attack(A_ASSAULT, 0, def); + return att_free_lists(&olist, &dlist); + } + + /* + * Death, carnage, and destruction. + */ + + att_fight(A_ASSAULT,off,&olist,osupport,def,&dlist,dsupport); + + return RET_OK; +} diff --git a/src/lib/commands/atta.c b/src/lib/commands/atta.c new file mode 100644 index 00000000..83fdfcfe --- /dev/null +++ b/src/lib/commands/atta.c @@ -0,0 +1,163 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * atta.c: Attack another sector + * + * Known contributors to this file: + * Dave Pare + * Ken Stevens, 1995 + * Steve McClure, 1996 + */ + +#include +#include "misc.h" +#include "player.h" +#include "file.h" +#include "var.h" +#include "sect.h" +#include "path.h" +#include "news.h" +#include "treaty.h" +#include "nat.h" +#include "xy.h" +#include "land.h" +#include "nsc.h" +#include "mission.h" +#include "ship.h" +#include "combat.h" +#include "commands.h" + +int +atta(void) { + struct combat off[6]; /* attacking sectors */ + struct combat def[1]; /* defending sector */ + coord newx, newy; + struct sctstr sect; + int fort_sup, ship_sup, land_sup, plane_sup; + struct emp_qelem olist; /* attacking units */ + struct emp_qelem dlist; /* defending units */ + int ototal; /* total attacking strength */ + int a_engineer = 0; /* attacker engineers are present */ + int a_spy = 0; /* the best attacker scout */ + double osupport = 1.0; /* attack support */ + double dsupport = 1.0; /* defense support */ + int last, n; + s_char *p; + s_char buf[1024]; + int rel; + + att_combat_init(def, EF_SECTOR); + /* + * Collect input from the attacker + */ + + /* What are we attacking? */ + + if (!(p = getstarg(player->argp[1], "Sector : ", buf))) + return RET_SYN; + if (!sarg_xy(p, &def->x, &def->y)) + return RET_SYN; + if (att_abort(A_ATTACK, 0, def)) + return RET_FAIL; + + /* Show what we're attacking, and check treaties */ + + if (att_show(def)) + return RET_FAIL; + + /* Ask about offensive support */ + + att_ask_support(2, &fort_sup, &ship_sup, &land_sup, &plane_sup); + if (att_abort(A_ATTACK, 0, def)) { + att_empty_attack(A_ATTACK, 0, def); + return RET_OK; + } + + /* initialize the off[] array */ + + for (n = 0, last = -1; n < 6; ++n) { /* Directions */ + newx = def->x + diroff[n+1][0]; + newy = def->y + diroff[n+1][1]; + getsect(newx,newy,§); /* incase cross world boundary */ + rel = getrel(getnatp(sect.sct_own), player->cnum); + if (!player->owner && rel != ALLIED) + continue; + att_combat_init(&off[++last], EF_SECTOR); + off[last].x = sect.sct_x; + off[last].y = sect.sct_y; + } + off->last = last; + + /* Ask the player what he wants to attack with */ + + att_ask_offense(A_ATTACK, off, def, &olist, &a_spy, &a_engineer); + if (att_abort(A_ATTACK, off, def)) { + pr("Attack aborted\n"); + att_empty_attack(A_ATTACK, 0, def); + return att_free_lists(&olist, 0); + } + + /* + * Estimate the defense strength and give the player a chance to abort + */ + + ototal = att_estimate_defense(A_ATTACK, off, &olist, def, a_spy); + if (att_abort(A_ATTACK, off, def)) { + pr("Attack aborted\n"); + att_empty_attack(A_ATTACK, 0, def); + return att_free_lists(&olist, 0); + } + + /* + * We have now got all the answers from the attacker. From this point + * forward, we can assume that this battle is the _only_ thing + * happening in the game. + */ + + /* Get the real defense */ + + att_get_defense(&olist, def, &dlist, a_spy, ototal); + + /* Get attacker and defender support */ + + att_get_support(A_ATTACK, fort_sup, ship_sup, land_sup, plane_sup, + &olist, off, &dlist, def, &osupport, &dsupport, + a_engineer); + if (att_abort(A_ATTACK, off, def)) { + pr("Attack aborted\n"); + att_empty_attack(A_ATTACK, 0, def); + return att_free_lists(&olist, &dlist); + } + + /* + * Death, carnage, and destruction. + */ + + att_fight(A_ATTACK,off,&olist,osupport,def,&dlist,dsupport); + + return RET_OK; +} diff --git a/src/lib/commands/bdes.c b/src/lib/commands/bdes.c new file mode 100644 index 00000000..4a2ae0e4 --- /dev/null +++ b/src/lib/commands/bdes.c @@ -0,0 +1,78 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * bdes.c: Change bmap designations + * + * Known contributors to this file: + * + */ + +#include "misc.h" +#include "player.h" +#include "var.h" +#include "sect.h" +#include "item.h" +#include "xy.h" +#include "path.h" +#include "nsc.h" +#include "deity.h" +#include "file.h" +#include "nat.h" +#include "commands.h" + +int +bdes(void) +{ + s_char *p, d; + struct nstr_sect nstr; + struct sctstr sect; + s_char prompt[128]; + s_char buf[1024]; + int changed = 0; + + if (!snxtsct(&nstr, player->argp[1])) + return RET_SYN; + while (!player->aborted && nxtsct(&nstr, §)) { + if ((nstr.ncond > 0) && (sect.sct_own != player->cnum)) + continue; + d = player->map[sctoff(nstr.x, nstr.y)]; + sprintf(prompt, "%s '%c' desig? ", + xyas(nstr.x, nstr.y, player->cnum), d); + if ((p = getstarg(player->argp[2], prompt, buf)) == 0) + continue; + if (!isprint(*p)){ + pr("Bad character. Must be printable!\n"); + continue; + } + changed |= map_set(player->cnum, nstr.x, nstr.y, *p, 2); + } + if (changed) + writebmap(player->cnum); + return RET_OK; +} + + diff --git a/src/lib/commands/best.c b/src/lib/commands/best.c new file mode 100644 index 00000000..9c02e211 --- /dev/null +++ b/src/lib/commands/best.c @@ -0,0 +1,88 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * best.c: Show the best path between two sectors + * + * Known contributors to this file: + * + */ + +#include "misc.h" +#include "player.h" +#include "var.h" +#include "sect.h" +#include "item.h" +#include "xy.h" +#include "path.h" +#include "nsc.h" +#include "deity.h" +#include "file.h" +#include "nat.h" +#include "commands.h" + +int +best(void) +{ + double cost; + s_char *BestDistPath(), *BestLandPath(), *s; + struct sctstr s1, s2; + struct nstr_sect nstr, nstr2; + int dist=0; + s_char buf[1024]; + + dist = player->argp[0][4] == 'd'; + + if (!snxtsct(&nstr, player->argp[1])) + return RET_SYN; + + if (!snxtsct(&nstr2, player->argp[2])) + return RET_SYN; + + while (!player->aborted && nxtsct(&nstr, &s1)){ + if (s1.sct_own != player->cnum) + continue; + snxtsct(&nstr2, player->argp[2]); + while (!player->aborted && nxtsct(&nstr2, &s2)){ + if (s2.sct_own != player->cnum) + continue; + if (dist) + s = BestDistPath(buf, &s1,&s2,&cost, MOB_ROAD); + else + s = BestLandPath(buf, &s1,&s2,&cost, MOB_ROAD); + if (s != (s_char *)0) + pr("Best %spath from %s to %s is %s (cost %1.3f)\n", + (dist ? "dist" : ""), + xyas(s1.sct_x,s1.sct_y,player->cnum), + xyas(s2.sct_x,s2.sct_y,player->cnum), s, cost); + else + pr("No owned path from %s to %s exists!\n", + xyas(s1.sct_x,s1.sct_y,player->cnum), + xyas(s2.sct_x,s2.sct_y,player->cnum)); + } + } + return 0; +} diff --git a/src/lib/commands/boar.c b/src/lib/commands/boar.c new file mode 100644 index 00000000..4352cc02 --- /dev/null +++ b/src/lib/commands/boar.c @@ -0,0 +1,187 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * boar.c: Board an enemy ship + * + * Known contributors to this file: + * Ken Stevens, 1995 + */ + +#include +#include "misc.h" +#include "player.h" +#include "file.h" +#include "var.h" +#include "sect.h" +#include "path.h" +#include "news.h" +#include "treaty.h" +#include "nat.h" +#include "xy.h" +#include "land.h" +#include "nsc.h" +#include "mission.h" +#include "ship.h" +#include "combat.h" +#include "retreat.h" +#include "commands.h" + +int +boar(void) +{ + struct combat off[1]; /* boarding ship or sector */ + struct combat def[1]; /* defending ship */ + struct emp_qelem olist; /* boarding units */ + struct emp_qelem dlist; /* defending units */ + int ototal; /* total boarding strength */ + int a_engineer = 0; /* boarder engineers are present */ + int a_spy = 0; /* the best boarder scout */ + struct shpstr ship; /* for retreating */ + struct sctstr sect; + struct lndstr land; + struct nstr_item ni; + int foundland; + s_char *p; + s_char buf[1024]; + + att_combat_init(def, EF_SHIP); + /* + * Collect input from the boarder + */ + + /* What are we boarding? */ + + if (!(p = getstarg(player->argp[1], "Victim ship #? ", buf)) || + (def->shp_uid = atoi(p)) < 0) + return RET_SYN; + + /* + * Ask the boarder what he wants to board with + */ + + if (!(p = getstarg(player->argp[2], "Boarding party from? ", buf))) + return RET_SYN; + if (issector(p)) { + att_combat_init(off, EF_SECTOR); + if (!sarg_xy(p, &off->x, &off->y)) + return RET_SYN; + getsect(off->x, off->y, §); + if (sect.sct_own != player->cnum) { + pr("You don't own %s!\n", + xyas(off->x, off->y, player->cnum)); + return RET_SYN; + } + if (sect.sct_mobil <= 0) { + /* Look for land units with mobility */ + snxtitem_xy(&ni, EF_LAND, off->x, off->y); + foundland = 0; + while (nxtitem(&ni, (s_char *)&land)) { + if (land.lnd_own != player->cnum) + continue; + if (land.lnd_ship >= 0) + continue; + if (land.lnd_mobil <= 0) + continue; + /* Only land units with assault can board */ + if (!(lchr[(int)land.lnd_type].l_flags & L_ASSAULT)) + continue; + foundland = 1; + } + if (!foundland) { + pr("You don't have any mobility (sector or land units) in %s!\n", + xyas(off->x, off->y, player->cnum)); + return RET_SYN; + } + } + } else { + att_combat_init(off, EF_SHIP); + if ((off->shp_uid = atoi(p)) < 0) + return RET_SYN; + } + if (att_abort(A_BOARD, off, def)) { + pr("Board aborted\n"); + return RET_OK; + } + + /* Fire at the attacking ship */ + + att_approach(off, def); + if (att_abort(A_BOARD, off, def)) { + pr("Board aborted\n"); + att_empty_attack(A_BOARD, 0, def); + return RET_OK; + } + + /* Show what we're boarding, and check treaties */ + + if (att_show(def)) + return RET_FAIL; + + /* Ask the player what he wants to board with */ + + att_ask_offense(A_BOARD, off, def, &olist, &a_spy, &a_engineer); + if (att_abort(A_BOARD, off, def)) { + pr("Board aborted\n"); + att_empty_attack(A_BOARD, 0, def); + return att_free_lists(&olist, 0); + } + + /* + * Estimate the defense strength and give the player a chance to abort + */ + + ototal = att_estimate_defense(A_BOARD, off, &olist, def, a_spy); + if (att_abort(A_BOARD, off, def)) { + pr("Board aborted\n"); + att_empty_attack(A_BOARD, 0, def); + return att_free_lists(&olist, 0); + } + + /* + * We have now got all the answers from the boarder. From this point + * forward, we can assume that this battle is the _only_ thing + * happening in the game. + */ + + /* Get the real defense */ + + att_get_defense(&olist, def, &dlist, a_spy, ototal); + + /* + * Death, carnage, and destruction. + */ + + if (!(att_fight(A_BOARD,off,&olist,1.0,def,&dlist,1.0))) { + getship(def->shp_uid, &ship); + if (ship.shp_rflags & RET_BOARDED) { + retreat_ship(&ship, 'u'); + putship(def->shp_uid, &ship); + } + } + + return RET_OK; +} diff --git a/src/lib/commands/bomb.c b/src/lib/commands/bomb.c new file mode 100644 index 00000000..1e62f4c9 --- /dev/null +++ b/src/lib/commands/bomb.c @@ -0,0 +1,976 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * bomb.c: Fly bombing missions + * + * Known contributors to this file: + * Dave Pare, 1986 + * Ken Stevens, 1995 + * Steve McClure, 1998-2000 + */ + +#include +#include "misc.h" +#include "player.h" +#include "var.h" +#include "sect.h" +#include "ship.h" +#include "land.h" +#include "item.h" +#include "plane.h" +#include "nuke.h" +#include "retreat.h" +#include "xy.h" +#include "nsc.h" +#include "news.h" +#include "file.h" +#include "nat.h" +#include "path.h" +#include "optlist.h" +#include "damage.h" +#include "commands.h" + +static void pin_bomb(struct emp_qelem *list, struct sctstr *target); +static void strat_bomb(struct emp_qelem *list, struct sctstr *target); +static void comm_bomb(struct emp_qelem *list, struct sctstr *target); +static void eff_bomb(struct emp_qelem *list, struct sctstr *target); + +static void plane_bomb(struct emp_qelem *list, struct sctstr *target); +static void land_bomb(struct emp_qelem *list, struct sctstr *target); +static void ship_bomb(struct emp_qelem *list, struct sctstr *target); +int pinflak_planedamage(struct plnstr *pp, struct plchrstr *pcp, natid from, int flak); + +static int bombcomm[] = { + I_CIVIL, + I_MILIT, + I_SHELL, + I_GUN, + I_PETROL, + I_IRON, + I_DUST, + I_BAR, + I_FOOD, + I_OIL, + I_LCM, + I_HCM, + I_UW, + I_RAD +}; +static int nbomb = sizeof(bombcomm) / sizeof(int); + +int +bomb(void) +{ + s_char *p; + int mission_flags; + int tech; + coord tx, ty; + coord ax, ay; + int ap_to_target; + struct ichrstr *ip; + s_char flightpath[MAX_PATH_LEN]; + struct nstr_item ni_bomb; + struct nstr_item ni_esc; + coord x, y; + struct sctstr target; + struct emp_qelem bomb_list; + struct emp_qelem esc_list; + int wantflags; + struct sctstr ap_sect; + s_char mission; + int rel; + struct natstr *natp; + s_char buf[1024]; + + wantflags = 0; + if (!snxtitem(&ni_bomb, EF_PLANE, player->argp[1])) + return RET_SYN; + if (!snxtitem(&ni_esc, EF_PLANE, getstarg(player->argp[2], "escort(s)? ", buf))) + pr("No escorts...\n"); + if ((p = getstarg(player->argp[3], "pinpoint, or strategic? ", buf)) == 0) + return RET_SYN; + mission = *p; + if (index("ps", mission) == 0) + return RET_SYN; + if ((p = getstarg(player->argp[4], "assembly point? ", buf)) == 0 || *p == 0) + return RET_SYN; + if (!sarg_xy(p, &x, &y) || !getsect(x, y, &ap_sect)) + return RET_SYN; + if (ap_sect.sct_own && ap_sect.sct_own != player->cnum && + getrel(getnatp(ap_sect.sct_own), player->cnum) != ALLIED) { + pr("Assembly point not owned by you or an ally!\n"); + return RET_SYN; + } + ax = x; + ay = y; + if (getpath(flightpath, player->argp[5], ax, ay, 0, 0, + 0, P_FLYING) == 0 || *flightpath == 0) + return RET_SYN; + tx = ax; + ty = ay; + (void) pathtoxy(flightpath, &tx, &ty, fcost); + pr("target sector is %s\n", xyas(tx, ty, player->cnum)); + getsect(tx, ty, &target); + if (target.sct_type == SCT_SANCT) { + pr("You can't bomb that sector!\n"); + return RET_SYN; + } + ip = 0; + ap_to_target = strlen(flightpath); + if (*(flightpath+strlen(flightpath)-1) == 'h') + ap_to_target--; + pr("range to target is %d\n", ap_to_target); + /* + * select planes within range + */ + mission_flags = 0; + pln_sel(&ni_bomb, &bomb_list, &ap_sect, ap_to_target, + 2, wantflags, P_M|P_O); + pln_sel(&ni_esc, &esc_list, &ap_sect, ap_to_target, + 2, wantflags|P_F|P_ESC, P_M|P_O); + /* + * now arm and equip the bombers, transports, whatever. + * tech is stored in high 16 bits of mission_flags. + * yuck. + */ + tech = 0; + mission_flags |= P_X; /* stealth (shhh) */ + mission_flags |= P_H; /* gets turned off if not all choppers */ + mission_flags = pln_arm(&bomb_list, 2*ap_to_target, mission, ip, 0, mission_flags, &tech); + if (QEMPTY(&bomb_list)) { + pr("No planes could be equipped for the mission.\n"); + return RET_FAIL; + } + mission_flags = pln_arm(&esc_list, 2*ap_to_target, mission, ip,P_F|P_ESC,mission_flags,&tech); + ac_encounter(&bomb_list,&esc_list,ax,ay,flightpath,mission_flags,0,0,0); + if (QEMPTY(&bomb_list)) { + pr("No planes got through fighter defenses\n"); + } else { + switch (mission) { + case 'p': + pin_bomb(&bomb_list, &target); + break; + case 's': + if (opt_SLOW_WAR) { + natp = getnatp(player->cnum); + if (target.sct_own){ + rel = getrel(natp,target.sct_own); + if ((rel != AT_WAR) && (player->cnum != target.sct_own) + && (target.sct_own) && + (target.sct_oldown != player->cnum)){ + pr("You're not at war with them!\n"); + pln_put(&bomb_list); + pln_put(&esc_list); + return RET_FAIL; + } + } + } + nreport(player->cnum, N_SCT_BOMB, target.sct_own, 1); + strat_bomb(&bomb_list, &target); + break; + default: + pr("Bad mission %c\n", mission); + break; + } + } + pln_put(&bomb_list); + pln_put(&esc_list); + return RET_OK; +} + +static void +pin_bomb(struct emp_qelem *list, struct sctstr *target) +{ + extern s_char *effadv(); + struct dchrstr *dcp; + int nplanes; + int nships; + int type; + int bad; + s_char *p; + int vec[I_MAX+1]; + struct plist *plp; + struct emp_qelem *qp; + int bestacc; + int nsubs; + int nunits; + struct natstr *natp; + int rel; + s_char buf[1024]; + int i; + + bad = 0; + type = target->sct_type; + dcp = &dchr[type]; + pr("Target sector is a %s constructed %s\n", + effadv((int)target->sct_effic), dcp->d_name); + nsubs = 0; + plp = (struct plist *) list->q_forw; + if (plp->pcp->pl_flags & P_A){ + bestacc=0; + for (qp = list->q_forw; qp != list; qp = qp->q_forw) + plp = (struct plist *) qp; + if (plp->plane.pln_acc < bestacc) + bestacc = plp->plane.pln_acc; + nships = num_shipsatxy(target->sct_x, target->sct_y, 0, 0); + nsubs = nships - + shipsatxy(target->sct_x, target->sct_y, 0, M_SUB); + if (nsubs > 0) + pr("Some subs are present in the sector.\n"); + } else { + nships = shipsatxy(target->sct_x, target->sct_y, 0, M_SUB); + } + nplanes = planesatxy(target->sct_x, target->sct_y, 0, 0, list); + nunits = unitsatxy(target->sct_x, target->sct_y, 0, 0); + getvec(VT_ITEM, vec, (s_char *)target, EF_SECTOR); +retry: + p = getstring("Bomb what? (ship, plane, land unit, efficiency, commodities) ", buf); + if (p == 0 || *p == 0) { + if (player->aborted) + return; + bad++; + if (bad > 2) + return; + goto retry; + } + switch (*p) { + case 'l': + if (opt_SLOW_WAR) { + natp = getnatp(player->cnum); + if (target->sct_own){ + rel = getrel(natp,target->sct_own); + if ((rel != AT_WAR) && (player->cnum != target->sct_own) + && (target->sct_own) && + (target->sct_oldown != player->cnum)){ + pr("You're not at war with them!\n"); + goto retry; + } + } + } + if (nunits == 0) { + pr("no units there\n"); + goto retry; + } + land_bomb(list, target); + break; + case 'p': + if (opt_SLOW_WAR) { + natp = getnatp(player->cnum); + if (target->sct_own){ + rel = getrel(natp,target->sct_own); + if ((rel != AT_WAR) && (player->cnum != target->sct_own) + && (target->sct_own) && + (target->sct_oldown != player->cnum)){ + pr("You're not at war with them!\n"); + goto retry; + } + } + } + if (nplanes == 0) { + pr("no planes there\n"); + goto retry; + } + plane_bomb(list, target); + break; + case 's': + if (nships == 0) { + if (((struct plist *)list->q_forw)->pcp->pl_flags & P_A){ + if (nsubs == 0){ + pr("no ships there\n"); + goto retry; + } + }else{ + pr("no ships there\n"); + goto retry; + } + } + ship_bomb(list, target); + break; + case 'c': + if (opt_SLOW_WAR) { + natp = getnatp(player->cnum); + if (target->sct_own){ + rel = getrel(natp,target->sct_own); + if ((rel != AT_WAR) && (player->cnum != target->sct_own) + && (target->sct_own) && + (target->sct_oldown != player->cnum)){ + pr("You're not at war with them!\n"); + goto retry; + } + } + } + + for (i = 0; i < nbomb; i++) { + if (!vec[bombcomm[i]]) + continue; + break; + } + if (i >= nbomb) { + pr("No bombable commodities in %s\n", + xyas(target->sct_x, target->sct_y, player->cnum)); + goto retry; + } + comm_bomb(list, target); + break; + case 'e': + if (opt_SLOW_WAR) { + natp = getnatp(player->cnum); + if (target->sct_own){ + rel = getrel(natp,target->sct_own); + if ((rel != AT_WAR) && (player->cnum != target->sct_own) + && (target->sct_own) && + (target->sct_oldown != player->cnum)){ + pr("You're not at war with them!\n"); + goto retry; + } + } + } + eff_bomb(list, target); + break; + case 'q': + pr("Aborting mission.\n"); + return; + default: + pr("Bad target type.\n"); + goto retry; + } +} + +static void +eff_bomb(struct emp_qelem *list, struct sctstr *target) +{ + register struct plist *plp; + struct emp_qelem *qp; + struct sctstr sect; + int oldeff, dam = 0; + int nukedam; + + for (qp = list->q_forw; qp != list; qp = qp->q_forw) { + plp = (struct plist *) qp; + if ((plp->pcp->pl_flags & P_C) && (!(plp->pcp->pl_flags & P_T))) + continue; + if (plp->bombs || plp->plane.pln_nuketype != -1) + dam += pln_damage(&plp->plane, target->sct_x, target->sct_y, 'p', &nukedam, 1); + } + if (dam <= 0) /* dam == 0 if only nukes were delivered */ + return; + getsect(target->sct_x, target->sct_y, §); + target = § + oldeff = target->sct_effic; + target->sct_effic = effdamage(target->sct_effic, dam); + target->sct_road = effdamage(target->sct_road, dam); + target->sct_rail = effdamage(target->sct_rail, dam); + target->sct_defense = effdamage(target->sct_defense, dam); + if (!opt_DEFENSE_INFRA) + target->sct_defense = target->sct_effic; + pr("did %d%% damage to efficiency in %s\n", + oldeff - target->sct_effic, + xyas(target->sct_x, target->sct_y, player->cnum)); + if (target->sct_own) + wu(0, target->sct_own, + "%s bombing raid did %d%% damage in %s\n", + cname(player->cnum), oldeff - target->sct_effic, + xyas(target->sct_x, target->sct_y, target->sct_own)); + if (target->sct_effic < 20) { + if (target->sct_type == SCT_BSPAN) + knockdown(target, list); + else if (target->sct_type == SCT_BTOWER) { + knockdown(target, list); + bridgefall(target, list); + } + } + putsect(§); + collateral_damage(target->sct_x, target->sct_y, dam, list); +} + +static void +comm_bomb(struct emp_qelem *list, struct sctstr *target) +{ + register struct plist *plp; + float b; + int i; + int amt, before; + struct ichrstr *ip; + int vec[I_MAX+1]; + struct emp_qelem *qp; + struct sctstr sect; + int dam = 0; + int nukedam; + + getvec(VT_ITEM, vec, (s_char *)target, EF_SECTOR); + for (i=0; ii_name); + } + for(;;) { + ip = whatitem((s_char *) 0, "commodity to bomb? "); + if (player->aborted) + return; + if (!ip) + continue; + + for (i=0; ii_name); + for (i=0; iq_forw; qp != list; qp = qp->q_forw) { + plp = (struct plist *) qp; + if ((plp->pcp->pl_flags & P_C) && (!(plp->pcp->pl_flags & P_T))) + continue; + if (plp->bombs || plp->plane.pln_nuketype != -1) + dam += pln_damage(&plp->plane, target->sct_x, target->sct_y, 'p', &nukedam, 1); + } + if (dam <= 0) /* dam == 0 if only nukes were delivered */ + return; + getsect(target->sct_x, target->sct_y, §); + target = § + before = amt = getvar(ip->i_vtype, (s_char *)target, EF_SECTOR); + putvar(ip->i_vtype, commdamage(amt, dam, ip->i_vtype), (s_char *)target, EF_SECTOR); + amt = getvar(ip->i_vtype, (s_char *)target, EF_SECTOR); + if (before>0.0) + b = 100.0*(1.0 - ((float)amt/(float)before)); + else + b = 0.0; + pr("did %.2f%% damage to %s in %s\n", + b, ip->i_name, + xyas(target->sct_x, target->sct_y, player->cnum)); + nreport(player->cnum, N_SCT_BOMB, target->sct_own, 1); + if(target->sct_own != 0) + wu(0, target->sct_own, + "%s precision bombing raid did %.2f%% damage to %s in %s\n", + cname(player->cnum), b, ip->i_name, + xyas(target->sct_x, target->sct_y, target->sct_own)); + putsect(§); + collateral_damage(target->sct_x, target->sct_y, dam, list); +} + +static void +ship_bomb(struct emp_qelem *list, struct sctstr *target) +{ + struct plist *plp; + int onsea; + struct mchrstr *mcp; + int dam; + s_char *q; + int n; + struct emp_qelem *qp; + int shipno; + int ignore; + struct shpstr ship; + int nships=0; + struct shiplook head, *s, *s2; + s_char buf[1024]; + s_char prompt[128]; + s_char msg[128]; + int hitchance; + int nukedam; + int flak; + int gun; + int shell; + + bzero((s_char *)&head,sizeof(struct shiplook)); + head.uid = -1; + onsea = (target->sct_type == SCT_WATER) ? 1 : 0; + for (qp = list->q_forw; qp != list && !player->aborted; qp = qp->q_forw) { + if (head.uid != -1){ + s=head.next; + while (s != (struct shiplook *)0){ + s2=s; + s=s->next; + free(s2); + } + } + bzero((s_char *)&head,sizeof(struct shiplook)); + head.uid = -1; + plp = (struct plist *) qp; + if ((plp->pcp->pl_flags & P_C) && (!(plp->pcp->pl_flags & P_T))) + continue; + if (plp->pcp->pl_flags & P_A) + nships=asw_shipsatxy(target->sct_x, target->sct_y,0,0, + &plp->plane,&head); + else + nships=shipsatxy(target->sct_x,target->sct_y,0,M_SUB); + if (nships == 0){ + pr("%s could not find any ships!\n", + prplane(&plp->plane)); + continue; + } + (void) sprintf(prompt, "%s, %d bombs. Target ('~' to skip)? ", + prplane(&plp->plane), + plp->bombs); + ignore=0; + shipno = -1; + while (shipno < 0 && !player->aborted && !ignore) { + if ((q = getstring(prompt, buf)) == 0 || *q == 0) + continue; + if (*q == '~'){ + ignore=1; + continue; + } + if (*q == '?') { + if (plp->pcp->pl_flags & P_A) + print_found(&head); + else + shipsatxy(target->sct_x, target->sct_y, + 0, M_SUB); + continue; + } + if (*q == 'd') + goto next; + if (!isdigit(*q)) + continue; + n = atoi(q); + if (n < 0) + continue; + if (getship(n, &ship) && ship.shp_x == target->sct_x && + ship.shp_y == target->sct_y) + shipno = n; + } + if (shipno < 0) + continue; + + shell = gun = 0; + gun = min(getvar(V_GUN, (s_char *)&ship, EF_SHIP), ship.shp_glim); + if (gun > 0) { + shell = getvar(V_SHELL, (s_char *)&ship, EF_SHIP); + if (shell <= 0) + shell = supply_commod(ship.shp_own, ship.shp_x, + ship.shp_y, I_SHELL, 1); + } + mcp = &mchr[(int)ship.shp_type]; + if (gun > 0 && shell > 0 && !(mcp->m_flags & M_SUB)) { + flak = (int)(techfact(ship.shp_tech, (double)gun) * 2.0); + putvar(V_SHELL, shell, (s_char *)&ship, EF_SHIP); + putship(ship.shp_uid, &ship); + sprintf(msg, "Flak! Firing %d guns from ship %s\n", + flak, prship(&ship)); + PR(ship.shp_own, msg); + if (pinflak_planedamage(&plp->plane, plp->pcp, ship.shp_own, flak)) + continue; + } + + dam = 0; + if (plp->plane.pln_nuketype != -1) + hitchance = 100; + else { + hitchance = pln_hitchance(&plp->plane, shp_hardtarget(&ship), EF_SHIP); + pr("%d%% hitchance...", hitchance); + } + if (roll(100) <= hitchance) { + /* pinbombing is more accurate than normal bombing */ + dam = 2 * pln_damage(&plp->plane, target->sct_x, target->sct_y, 'p', &nukedam, 1); + } else { + pr("splash\n"); + /* Bombs that miss have to land somewhere! */ + dam = pln_damage(&plp->plane, target->sct_x, target->sct_y, 'p', &nukedam, 0); + collateral_damage(target->sct_x, target->sct_y, dam, list); + dam = 0; + } + if (dam <= 0) /* dam == 0 if only nukes were delivered */ + continue; + if (mcp->m_flags & M_SUB) + nreport(player->cnum, N_SUB_BOMB, ship.shp_own, 1); + else + nreport(player->cnum, N_SHP_BOMB, ship.shp_own, 1); + if (ship.shp_own) { + wu(0, ship.shp_own, "%s bombs did %d damage to %s at %s\n", + cname(player->cnum), dam, + prship(&ship), + xyas(target->sct_x, target->sct_y, ship.shp_own)); + } + pr("\n"); + check_retreat_and_do_shipdamage(&ship, dam); + if (ship.shp_rflags & RET_BOMBED) + if (((ship.shp_rflags & RET_INJURED) == 0) || !dam) + retreat_ship(&ship,'b'); + putship(ship.shp_uid, &ship); + getship(n, &ship); + if (!ship.shp_own) { + pr("%s at %s sunk!\n", + prship(&ship), + xyas(target->sct_x, target->sct_y, player->cnum)); + } + collateral_damage(target->sct_x, target->sct_y, dam/2, list); +next: + ; + } + s=head.next; + while (s != (struct shiplook *)0){ + s2=s; + s=s->next; + free(s2); + } +} + +static void +plane_bomb(struct emp_qelem *list, struct sctstr *target) +{ + int dam; + s_char *q; + int n; + natid own; + struct plnstr plane; + struct emp_qelem *qp; + int planeno; + int ignore; + struct plist *plp; + s_char prompt[128]; + s_char buf[1024]; + int hitchance; + int nukedam; + int nplanes; + + for (qp = list->q_forw; qp != list; qp = qp->q_forw) { + plp = (struct plist *) qp; + if ((plp->pcp->pl_flags & P_C) && (!(plp->pcp->pl_flags & P_T))) + continue; + nplanes = planesatxy(target->sct_x, target->sct_y, 0, 0, list); + if (nplanes == 0) { + pr("%s could not find any planes!\n", + prplane(&plp->plane)); + continue; + } + (void) sprintf(prompt, "%s, %d bombs. Target ('~' to skip)? ", + prplane(&plp->plane), + plp->bombs); + planeno = -1; + ignore=0; + while (planeno < 0 && !player->aborted && !ignore) { + if ((q = getstring(prompt, buf)) == 0 || *q == 0) + continue; + if (*q == '~'){ + ignore=1; + continue; + } + if (*q == '?') { + planesatxy(target->sct_x, target->sct_y, 0, 0, list); + continue; + } + if (*q == 'd') + goto next; + n = atoi(q); + if (n < 0) + continue; + if (getplane(n, &plane) && + plane.pln_x == target->sct_x && + plane.pln_y == target->sct_y && + ((plane.pln_flags & PLN_LAUNCHED) == 0) && + (!ac_isflying(&plane, list))) + planeno = n; + else + pr("Plane #%d not spotted\n", n); + } + if (planeno < 0) + continue; + dam = 0; + if (plp->plane.pln_nuketype != -1) + hitchance = 100; + else { + hitchance = pln_hitchance(&plp->plane, 0, EF_PLANE); + pr("%d%% hitchance...", hitchance); + } + if (roll(100) <= hitchance) { + /* pinbombing is more accurate than normal bombing */ + dam = 2 * pln_damage(&plp->plane,target->sct_x,target->sct_y, 'p', &nukedam, 1); + } else { + pr("thud\n"); + /* Bombs that miss have to land somewhere! */ + dam = pln_damage(&plp->plane,target->sct_x,target->sct_y, 'p', &nukedam, 0); + collateral_damage(target->sct_x, target->sct_y, dam, list); + dam = 0; + } + if (dam <= 0) /* dam == 0 if only nukes were delivered */ + continue; + if (dam > 100) + dam = 100; + own = plane.pln_own; + if (dam > plane.pln_effic) { + plane.pln_effic = 0; + makelost(EF_PLANE, plane.pln_own, plane.pln_uid, plane.pln_x, plane.pln_y); + plane.pln_own = 0; + } else + plane.pln_effic -= dam; + plane.pln_mobil = (dam * plane.pln_mobil / 100.0); + if (own == player->cnum) { + pr("%s reports %d%% damage\n", + prplane(&plane), + dam); + } else { + if(own != 0) + wu(0, own, + "%s pinpoint bombing raid did %d%% damage to %s\n", + cname(player->cnum), dam, prplane(&plane)); + } + nreport(player->cnum, N_DOWN_PLANE, own, 1); + if(own != 0) + wu(0, own, "%s bombs did %d%% damage to %s at %s\n", + cname(player->cnum), dam, prplane(&plane), + xyas(target->sct_x, target->sct_y, own)); + putplane(plane.pln_uid, &plane); + collateral_damage(plane.pln_x, plane.pln_y, dam, list); + next: + ; + } +} + +static void +land_bomb(struct emp_qelem *list, struct sctstr *target) +{ + int dam; + s_char *q; + int n; + natid own; + s_char prompt[128]; + s_char buf[1024]; + s_char msg[128]; + struct lndstr land; + struct lchrstr *lcp; + struct emp_qelem *qp; + int unitno; + int ignore, flak, hitchance; + struct plist *plp; + int nukedam; + int nunits; + + for (qp = list->q_forw; qp != list; qp = qp->q_forw) { + plp = (struct plist *) qp; + if ((plp->pcp->pl_flags & P_C) && (!(plp->pcp->pl_flags & P_T))) + continue; + nunits = unitsatxy(target->sct_x, target->sct_y, 0, 0); + if (nunits == 0) { + pr("%s could not find any units!\n", + prplane(&plp->plane)); + continue; + } + (void) sprintf(prompt, "%s, %d bombs. Target ('~' to skip)? ", + prplane(&plp->plane), + plp->bombs); + unitno = -1; + ignore = 0; + while (unitno < 0 && !player->aborted && !ignore) { + if ((q = getstring(prompt, buf)) == 0 || *q == 0) + continue; + if (*q == '~') { + ignore=1; + continue; + } + if (*q == '?') { + unitsatxy(target->sct_x, target->sct_y, 0, 0); + continue; + } + if (*q == 'd') + goto next; + n = atoi(q); + if (n < 0) + continue; + if (getland(n, &land) && + land.lnd_x == target->sct_x && + land.lnd_y == target->sct_y) + unitno = n; + else + pr("Unit #%d not spotted\n", n); + } + if (unitno < 0) + continue; + + lcp = &lchr[(int)land.lnd_type]; + + flak = (int)(techfact(land.lnd_tech, (double)land.lnd_aaf) * 3.0); + if (flak) { + sprintf(msg, "Flak! Firing flak guns from unit %s (aa rating %d)\n", + prland(&land), land.lnd_aaf); + PR(land.lnd_own, msg); + if (pinflak_planedamage(&plp->plane, plp->pcp, land.lnd_own, flak)) + continue; + } + + dam = 0; + if (plp->plane.pln_nuketype != -1) + hitchance = 100; + else { + hitchance = pln_hitchance(&plp->plane, lnd_hardtarget(&land), EF_LAND); + pr("%d%% hitchance...", hitchance); + } + if (roll(100) <= hitchance) { + dam = 2 * pln_damage(&plp->plane,target->sct_x,target->sct_y, 'p', &nukedam, 1); + } else { + pr("thud\n"); + /* Bombs that miss have to land somewhere! */ + dam = pln_damage(&plp->plane,target->sct_x,target->sct_y, 'p', &nukedam, 0); + collateral_damage(target->sct_x, target->sct_y, dam, list); + dam = 0; + } + if (dam <= 0) /* dam == 0 if only nukes were delivered */ + continue; + if (dam > 100) + dam = 100; + own = land.lnd_own; + if (own != 0) + mpr(own, + "%s pinpoint bombing raid did %d damage to %s\n", + cname(player->cnum), dam, prland(&land)); + check_retreat_and_do_landdamage(&land, dam); + + if (land.lnd_rflags & RET_BOMBED) + if (((land.lnd_rflags & RET_INJURED) == 0) || !dam) + retreat_land(&land,'b'); + nreport(player->cnum, N_UNIT_BOMB, own, 1); + putland(land.lnd_uid, &land); + collateral_damage(land.lnd_x, land.lnd_y, dam, list); +next: + ; + } +} + +static void +strat_bomb(struct emp_qelem *list, struct sctstr *target) +{ + register struct plist *plp; + int dam = 0; + struct emp_qelem *qp; + struct sctstr sect; + int nukedam; + + for (qp = list->q_forw; qp != list; qp = qp->q_forw) { + plp = (struct plist *) qp; + if ((plp->pcp->pl_flags & P_C) && (!(plp->pcp->pl_flags & P_T))) + continue; + if (plp->bombs || plp->plane.pln_nuketype != -1) + dam += pln_damage(&plp->plane, target->sct_x, target->sct_y, 's', &nukedam, 1); + } + if (dam <= 0) /* dam == 0 if only nukes were delivered */ + return; + getsect(target->sct_x, target->sct_y, §); + target = § + if (target->sct_own) + wu(0, target->sct_own, "%s bombing raid did %d damage in %s\n", + cname(player->cnum), PERCENT_DAMAGE(dam), + xyas(target->sct_x, target->sct_y, target->sct_own)); + + sectdamage(target, dam, list); + + pr("did %d damage in %s\n", PERCENT_DAMAGE(dam), + xyas(target->sct_x, target->sct_y, player->cnum)); + putsect(§); +} + +#define FLAK_MAX 15 +float lflaktable[16] = { 0.20, 0.20, 0.25, 0.30, 0.35, 0.40, 0.45, 0.50, + 0.50, 0.55, 0.60, 0.65, 0.70, 0.75, 0.80, 0.85, }; +int +pinflak_planedamage(struct plnstr *pp, struct plchrstr *pcp, natid from, int flak) +{ + extern double flakscale; + int disp; + s_char dmess[255]; + int eff; + s_char mesg[128]; + struct shpstr ship; + struct lndstr land; + natid plane_owner; + int dam; + float mult; + + flak -= (pp->pln_def+1); + if (pcp->pl_flags & P_X) + flak -= 2; + if (pcp->pl_flags & P_H) + flak -= 1; + if (flak > 8) + mult = lflaktable[FLAK_MAX] * 1.33; + else if (flak < -7) + mult = lflaktable[0] * 0.66; + else { + flak += 7; + mult = lflaktable[flak]; + } + mult *= flakscale; + dam = (int) ((roll(8) + 2) * mult); + if (dam > 100) + dam = 100; + + disp = 0; + plane_owner = pp->pln_own; + eff = pp->pln_effic; + if (dam <= 0) + return 0; + bzero(dmess,255); + eff -= dam; + if (eff < 0) + eff = 0; + if (eff < PLANE_MINEFF) { + sprintf(dmess," -- shot down"); + disp = 1; + } else if (chance((100-eff)/100.0)){ + sprintf(dmess," -- aborted with %d%%%% damage", 100-eff); + disp = 2; + } + sprintf(mesg, " Flak! %s %s takes %d%s.\n", + cname(pp->pln_own), prplane(pp), + dam, dmess); + PR(plane_owner, mesg); + + pp->pln_effic = eff; + if (disp == 1) { + if (from != 0) + nreport(from, N_DOWN_PLANE, pp->pln_own, 1); + if (pp->pln_ship >= 0) { + getship(pp->pln_ship,&ship); + take_plane_off_ship(pp,&ship); + } + if (pp->pln_land >= 0) { + getland(pp->pln_land,&land); + take_plane_off_land(pp,&land); + } + makelost(EF_PLANE, pp->pln_own, pp->pln_uid, pp->pln_x, pp->pln_y); + pp->pln_own = 0; + putplane(pp->pln_uid, pp); + } else + putplane(pp->pln_uid, pp); + + if (disp > 0) + return 1; + return 0; +} diff --git a/src/lib/commands/brea.c b/src/lib/commands/brea.c new file mode 100644 index 00000000..fa03cdbb --- /dev/null +++ b/src/lib/commands/brea.c @@ -0,0 +1,56 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * brea.c: Break out of sanctuary + * + * Known contributors to this file: + * Jeff Wallace, 1989 + */ + +#include "misc.h" +#include "player.h" +#include "file.h" +#include "nat.h" +#include "commands.h" + +int +brea(void) +{ + struct natstr *natp; + + natp = getnatp(player->cnum); + if ((natp->nat_stat & STAT_SANCT) == 0) { + pr("You aren't in sanctuary!\n"); + return RET_SYN; + } + bsanct(); + natp->nat_stat &= ~STAT_SANCT; + natp->nat_stat |= STAT_NORM; + putnat(natp); + player->nstat |= NORM; + return RET_OK; +} diff --git a/src/lib/commands/budg.c b/src/lib/commands/budg.c new file mode 100644 index 00000000..1f53961f --- /dev/null +++ b/src/lib/commands/budg.c @@ -0,0 +1,477 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * budg.c: Calculate production levels, prioritize + * + * Known contributors to this file: + * Thomas Ruschak, 1992 + * Ville Virrankoski, 1995 + * Steve McClure, 1997-2000 + */ + +#ifdef Rel4 +#include +#endif /* Rel4 */ +#include "misc.h" +#include "player.h" +#include "var.h" +#include "xy.h" +#include "nsc.h" +#include "sect.h" +#include "product.h" +#include "nat.h" +#include "item.h" +#include "file.h" +#include "deity.h" +#include "ship.h" +#include "land.h" +#include "plane.h" +#include "optlist.h" +#include "budg.h" +#include "commands.h" + +#ifndef MIN +#define MIN(x,y) ((x) > (y) ? (y) : (x)) +#endif + +extern int etu_per_update; +extern double bankint; +extern double money_civ; +extern double money_uw; +extern double money_mil; +extern double obrate, uwbrate; +extern int etu_per_update; +extern double money_res; + +s_char *dotsprintf(s_char *buf, s_char *format, int data); +int goodsect(char c); +void prexpense(long int cash, int *expensesp, s_char priority, int amount); +static void calc_all(long int (*p_sect)[2], int *taxes, int *Ncivs, int *Nuws, int *bars, int *Nbars, int *mil, int *ships, int *sbuild, int *nsbuild, int *smaint, int *units, int *lbuild, int *nlbuild, int *lmaint, int *planes, int *pbuild, int *npbuild, int *pmaint); + +int +budg(void) +{ + s_char stype=0, *pq; + int priority, x; + long p_sect[SCT_MAXDEF+1][2]; + int taxes=0, bars=0, mil=0; + int Ncivs=0, Nuws=0, Nbars=0; + int n, etu; + int income = 0, expenses = 0; + int sbuild=0,smaint=0,pbuild=0,pmaint=0, ships=0,planes=0; + int nsbuild=0,npbuild=0, which=0; + int lbuild=0,lmaint=0,units=0,nlbuild=0; + struct natstr *np; + s_char buf[1024]; + s_char in[80]; + + bzero((s_char *)p_sect,sizeof(p_sect)); + etu = etu_per_update; + + np=getnatp(player->cnum); + if (player->argp[1] != (s_char *)0){ + if (goodsect(player->argp[1][0])) + stype=player->argp[1][0]; + else switch(player->argp[1][0]){ + case 'P': + case 'S': + case 'L': + case 'A': + case 'M': + case 'N': + case 'C': stype = player->argp[1][0]; break; + default: return RET_SYN; + } + } + if ((stype != 0) && (stype != 'C')) { + pq = getstarg(player->argp[2], "Priority? ", buf); + } else { + pq = (s_char *)0; + } + if (pq != (s_char *)0) { + if (isdigit(*pq)){ + priority=(atoi(pq) < 0 ? -1*atoi(pq) : atoi(pq)); + if (priority >= SCT_MAXDEF+8){ + pr("Priorities must be less than %d!\n", + SCT_MAXDEF+8); + return RET_FAIL; + } + for(x=0;xnat_priorities[x] == priority)){ + pr("Priorities must be unique!\n"); + return RET_FAIL; + } + } else if (*pq == '~') + priority = -1; + else + return RET_SYN; + } + if ((stype) && !player->god){ + if (!isupper(stype)){ + which=0; + while ((whichnat_priorities[x] = -1; + } + } else { + np->nat_priorities[which] = priority; + } + + } + putnat(np); + + player->simulation = 1; + calc_all(p_sect,&taxes,&Ncivs,&Nuws,&bars,&Nbars,&mil,&ships,&sbuild,&nsbuild, + &smaint,&units,&lbuild,&nlbuild,&lmaint,&planes,&pbuild, + &npbuild,&pmaint); + + income = taxes + bars; + pr("Sector Type\t\tAbbr\tProduction\tPriority\t Cost\n"); + for(x=0;xnat_priorities[x] == -1) + continue; + if (!pchr[dchr[x].d_prd].p_cost && + np->nat_priorities[x] == -1 && + x != SCT_ENLIST) { + continue; + } + + pr("%-17s\t%c\t",dchr[x].d_name,dchr[x].d_mnem); + if (x == SCT_ENLIST) + pr("%d mil \t",p_sect[x][0]); + else if (pchr[dchr[x].d_prd].p_cost != 0) + pr("%d %-7s\t",p_sect[x][0], + pchr[dchr[x].d_prd].p_sname); + else pr("\t\t"); + + if (np->nat_priorities[x] != -1){ + pr("%d",np->nat_priorities[x]); + } + pr("\t"); + pr("\t"); + if (np->nat_priorities[x] != 0){ + if ((np->nat_money+income-expenses) > 0){ + pr("%8d",p_sect[x][1]); + expenses += p_sect[x][1]; + } + else + pr("[%7d]",p_sect[x][1]); + }else{ + if ((np->nat_money+income-expenses) > 0) + pr("(%7d)",p_sect[x][1]); + else + pr("[(%7d)]",p_sect[x][1]); + } + + pr("\n"); + } + + if (lbuild) { + sprintf(buf,"%d unit%s",nlbuild,splur(nlbuild)); + pr("Unit building\t\tL\t%-16s", buf); + if (np->nat_priorities[PRI_LBUILD] != -1) + pr("%d",np->nat_priorities[PRI_LBUILD]); + prexpense(np->nat_money+income, &expenses, np->nat_priorities[PRI_LBUILD], -1*lbuild); + } + + if (lmaint) { + sprintf(buf,"%d unit%s",units,splur(units)); + pr("Unit maintenance\tA\t%-16s",buf); + if (np->nat_priorities[PRI_LMAINT] != -1) + pr("%d",np->nat_priorities[PRI_LMAINT]); + prexpense(np->nat_money+income, &expenses, np->nat_priorities[PRI_LMAINT], -1*lmaint); + } + + if (sbuild) { + sprintf(buf,"%d ship%s",nsbuild,splur(nsbuild)); + pr("Ship building\t\tS\t%-16s", buf); + if (np->nat_priorities[PRI_SBUILD] != -1) + pr("%d",np->nat_priorities[PRI_SBUILD]); + prexpense(np->nat_money+income, &expenses, np->nat_priorities[PRI_SBUILD], -1*sbuild); + } + + if (smaint) { + sprintf(buf,"%d ship%s",ships,splur(ships)); + pr("Ship maintenance\tM\t%-16s",buf); + if (np->nat_priorities[PRI_SMAINT] != -1) + pr("%d",np->nat_priorities[PRI_SMAINT]); + prexpense(np->nat_money+income, &expenses, np->nat_priorities[PRI_SMAINT], -1*smaint); + } + + if (pbuild) { + sprintf(buf,"%d plane%s",npbuild,splur(npbuild)); + pr("Plane building\t\tP\t%-16s",buf); + if (np->nat_priorities[PRI_PBUILD] != -1) + pr("%d",np->nat_priorities[PRI_PBUILD]); + prexpense(np->nat_money+income, &expenses, np->nat_priorities[PRI_PBUILD], -1*pbuild); + } + + if (pmaint) { + sprintf(buf,"%d plane%s",planes,splur(planes)); + pr("Plane maintenance\tN\t%-16s",buf); + if (np->nat_priorities[PRI_PMAINT] != -1) + pr("%d",np->nat_priorities[PRI_PMAINT]); + prexpense(np->nat_money+income, &expenses, np->nat_priorities[PRI_PMAINT], -1*pmaint); + } + if (p_sect[SCT_EFFIC][1]) { + pr("Sector building\t\t\t\t%8d sct(s)\t\t%8d\n",p_sect[SCT_EFFIC][0], p_sect[SCT_EFFIC][1]); + expenses += p_sect[SCT_EFFIC][1]; + } + if (mil) { + + n = (mil - np->nat_reserve * money_res * etu)/(etu*money_mil); + sprintf(in, "%d mil, %d res", n, (int)np->nat_reserve); + pr("Military payroll\t\t%-32s%8d\n", + in, -mil); + expenses -= mil; + } + if (p_sect[SCT_CAPIT][0]) { + n = p_sect[SCT_CAPIT][0]; + sprintf(in, "%d %s", + n, + n==1?opt_BIG_CITY?"city":"capital":opt_BIG_CITY?"cities":"capitals"); + pr("%s maintenance\t\t%-32s%8d\n", + opt_BIG_CITY?"City":"Capital", + in, + p_sect[SCT_CAPIT][1]); + expenses += p_sect[SCT_CAPIT][1]; + } + pr("Total expenses%s\n", dotsprintf(buf,"%58d", expenses)); + if (taxes) { + sprintf(in, "%d civ%s, %d uw%s", + Ncivs,splur(Ncivs), + Nuws,splur(Nuws)); + pr("Income from taxes\t\t%-32s%+8d\n", + in, + taxes); + } + if (bars) { + sprintf(in, "%d bar%s", Nbars, splur(Nbars)); + pr("Income from bars\t\t%-32s%+8d\n", + in, + bars); + } + pr("Total income%s\n", dotsprintf(buf,"%+60d", income)); + pr("Balance forward\t\t\t\t\t\t %10d\n", np->nat_money); + pr("Estimated delta\t\t\t\t\t\t %+10d\n",income-expenses); + pr("Estimated new treasury%s\n",dotsprintf(buf,"%50d",np->nat_money+income-expenses)); + if (((np->nat_money+income-expenses) < 0) && !player->god){ + pr("After processsing sectors, you will be broke!\n"); + pr("Sectors will not produce, distribute, or deliver!\n\n"); + } + + player->simulation = 0; + return RET_OK; +} + +static void +calc_all(long int (*p_sect)[2], int *taxes, int *Ncivs, int *Nuws, int *bars, int *Nbars, int *mil, int *ships, int *sbuild, int *nsbuild, int *smaint, int *units, int *lbuild, int *nlbuild, int *lmaint, int *planes, int *pbuild, int *npbuild, int *pmaint) +{ + register int y,z; + struct natstr *np; + int sm=0,sb=0,pm=0,pb=0,lm=0,lb=0; + int *bp; + long pop = 0; + int n, civ_tax, uw_tax, mil_pay; + struct sctstr *sp; + int etu=etu_per_update; + int vec[I_MAX+1]; + long tmp_money; + extern long sea_money[MAXNOC]; + extern long lnd_money[MAXNOC]; + extern long air_money[MAXNOC]; + extern long tpops[MAXNOC]; + extern int mil_dbl_pay; + + lnd_money[player->cnum] = sea_money[player->cnum] = 0; + air_money[player->cnum] = 0; + mil_dbl_pay = 0; + *taxes = 0; + *Ncivs = 0; + np = getnatp(player->cnum); + bp = (int *)calloc(WORLD_X * WORLD_Y * 8, sizeof(int)); + for (n=0; NULL != (sp = getsectid(n)) ;n++){ + fill_update_array(bp, sp); + if (sp->sct_own == player->cnum) { + sp->sct_updated = 0; + tax(sp, np, etu, &pop, &civ_tax, &uw_tax, &mil_pay); + getvec(VT_ITEM, vec, (s_char *)sp, EF_SECTOR); + *Ncivs += vec[I_CIVIL]; + *Nuws += vec[I_UW]; + *taxes += civ_tax + uw_tax; + *mil += mil_pay; + if (sp->sct_type == SCT_BANK) { + *bars += bank_income(sp, etu); + *Nbars += vec[I_BAR]; + } + } + } + tpops[player->cnum] = pop; + *mil += (int) (np->nat_reserve * money_res * etu); + + *mil += (int) upd_slmilcosts(np->nat_cnum, etu); + + for(y=1;ynat_priorities[z] == y) + switch(z){ + case PRI_SMAINT: + tmp_money = lnd_money[player->cnum]; + *ships=prod_ship(etu, player->cnum,bp,0); + *smaint = lnd_money[player->cnum] - tmp_money; + sm=1; + break; + case PRI_SBUILD: + tmp_money = sea_money[player->cnum]; + *nsbuild=prod_ship(etu, player->cnum,bp,1); + *sbuild = sea_money[player->cnum] - tmp_money; + sb=1; + break; + case PRI_LMAINT: + tmp_money = lnd_money[player->cnum]; + *units=prod_land(etu, player->cnum,bp,0); + *lmaint = lnd_money[player->cnum] - tmp_money; + lm=1; + break; + case PRI_LBUILD: + tmp_money = lnd_money[player->cnum]; + *nlbuild=prod_land(etu, player->cnum,bp,1); + *lbuild = lnd_money[player->cnum] - tmp_money; + lb=1; + break; + case PRI_PMAINT: + tmp_money = air_money[player->cnum]; + *planes=prod_plane(etu, player->cnum,bp,0); + *pmaint = air_money[player->cnum] - tmp_money; + pm=1; + break; + case PRI_PBUILD: + tmp_money = air_money[player->cnum]; + *npbuild=prod_plane(etu, player->cnum,bp,1); + *pbuild = air_money[player->cnum] - tmp_money; + pb=1; + break; + default: + produce_sect(player->cnum,etu,bp,p_sect,z); + break; + } + } + /* 0 is maintain, 1 is build */ + if (!sm) { + tmp_money = sea_money[player->cnum]; + *ships=prod_ship(etu,player->cnum,bp,0); + *smaint = sea_money[player->cnum] - tmp_money; + } + if (!sb) { + tmp_money = sea_money[player->cnum]; + *nsbuild=prod_ship(etu,player->cnum,bp,1); + *sbuild = sea_money[player->cnum] - tmp_money; + } + if (!lm) { + tmp_money = lnd_money[player->cnum]; + *units=prod_land(etu,player->cnum,bp,0); + *lmaint = lnd_money[player->cnum] - tmp_money; + } + if (!lb) { + tmp_money = lnd_money[player->cnum]; + *nlbuild=prod_land(etu,player->cnum,bp,1); + *lbuild = lnd_money[player->cnum] - tmp_money; + } + if (!pm) { + tmp_money = air_money[player->cnum]; + *planes=prod_plane(etu,player->cnum,bp,0); + *pmaint = air_money[player->cnum] - tmp_money; + } + if (!pb) { + tmp_money = air_money[player->cnum]; + *npbuild=prod_plane(etu,player->cnum,bp,1); + *pbuild = air_money[player->cnum] - tmp_money; + } + + /* produce all sects that haven't produced yet */ + produce_sect(player->cnum,etu,bp,p_sect,-1); + + lnd_money[player->cnum] = sea_money[player->cnum] = 0; + air_money[player->cnum] = 0; + free(bp); +} + +int +goodsect(char c) +{ + register int x; + + for(x=4;x *expensesp) { + if (priority) { + pr("\t\t%8d\n",amount); + *expensesp += amount; + } else + pr("\t\t(%7d)\n",amount); + } else { + if (priority) { + pr("\t\t[%7d]\n", amount); + *expensesp += amount; + } else + pr("\t\t[(%6d)]\n", amount); + } +} + diff --git a/src/lib/commands/buil.c b/src/lib/commands/buil.c new file mode 100644 index 00000000..257593ed --- /dev/null +++ b/src/lib/commands/buil.c @@ -0,0 +1,1120 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * buil.c: Build ships, nukes, bridges, planes, land units, bridge towers + * + * Known contributors to this file: + * Steve McClure, 1998-2000 + */ + +#ifdef Rel4 +#include +#endif /* Rel4 */ +#include "misc.h" +#include "player.h" +#include "var.h" +#include "sect.h" +#include "nat.h" +#include "retreat.h" +#include "ship.h" +#include "land.h" +#include "nuke.h" +#include "plane.h" +#include "xy.h" +#include "nsc.h" +#include "treaty.h" +#include "deity.h" +#include "file.h" +#include "path.h" +#include "optlist.h" +#include "commands.h" + +static int build_nuke(register struct sctstr *sp, register struct nchrstr *np, register int *vec); +static int build_ship(register struct sctstr *sp, register struct mchrstr *mp, register int *vec, int tlev); +static int build_land(register struct sctstr *sp, register struct lchrstr *lp, register int *vec, int tlev); +static int build_bridge(register struct sctstr *sp, register int *vec); +static int build_tower(register struct sctstr *sp, register int *vec); +static int build_plane(register struct sctstr *sp, register struct plchrstr *pp, register int *vec, int tlev); + +static int cash; /* static ok */ + +double sqrt(double); +double logx(); + +extern int morale_base; +extern int sect_mob_neg_factor; +extern int etu_per_update; + +/* + * build [NUMBER] + */ +int +buil(void) +{ + extern double buil_bt; + extern double buil_tower_bt; + struct sctstr sect; + struct nstr_sect nstr; + struct natstr *natp; + int rqtech; + int tlev; + int rlev; + int n; + int type; + int what; + struct lchrstr *lp; + struct mchrstr *mp; + struct plchrstr *pp; + struct nchrstr *np; + s_char *p; + int vec[I_MAX+1]; + int gotsect = 0; + int built; + int hold, found, number=1, x; + extern float drnuke_const; + int asked = 0; + s_char buf[1024]; + + natp = getnatp(player->cnum); + if ((p = getstarg(player->argp[1], "Build (ship, nuke, bridge, plane, land unit, tower)? ", buf)) == 0) + return RET_SYN; + what = *p; + + for(x= 0 ; x < number; x++) { + if (!snxtsct(&nstr, player->argp[2])) { + pr("Bad sector specification.\n"); + return RET_SYN; + } +ask_again: + tlev = (int) natp->nat_level[NAT_TLEV]; + rlev = (int) natp->nat_level[NAT_RLEV]; + + switch (what) { + case 'p': + p = getstarg(player->argp[3], "Plane type? ", buf); + if (p == 0 || *p == 0) + return RET_SYN; + n = strlen(p); + while (n && iscntrl(p[n-1])) + n--; + if ( !n ) + return RET_SYN; + for (found=0,type=0,pp=plchr; type <= pln_maxno; type++,pp++) { + if (pp->pl_tech > tlev) + continue; + if(pp->pl_name && strncmp(p, pp->pl_name, n) == 0) { + found++; + hold = type; + break; + } + } + if (found != 1) { + pr("Illegal plane type: \"%s\"\n", p); + if (confirm("List plane types? ")) + show_plane_build (tlev); + player->argp[3] = 0; + goto ask_again; + } + type = hold; + pp = &(plchr[type]); + rqtech = pp->pl_tech; + break; + case 's': + p = getstarg(player->argp[3], "Ship type? ", buf); + if (p == 0 || *p == 0) + return RET_SYN; + n = strlen(p); + while (n && iscntrl(p[n-1])) + n--; + if ( !n ) + return RET_SYN; + for (found=0,mp=mchr,type=0; type <= shp_maxno; type++, mp++) { + if (mp->m_tech > tlev) + continue; + /* Can't build trade ships unless it's turned on */ + if ((mp->m_flags & M_TRADE) && !opt_TRADESHIPS) + continue; + if(mp->m_name && strncmp(p, mp->m_name, n) == 0) { + found++; + hold = type; + break; + } + } + if (found != 1) { + pr("Illegal ship type: \"%s\"\n", p); + if (confirm("List ship types? ")) + show_ship_build (tlev); + player->argp[3] = 0; + goto ask_again; + } + type = hold; + mp = &(mchr[type]); + rqtech = mp->m_tech; + break; + case 'l': + p = getstarg(player->argp[3], "Land unit type? ", buf); + if (p == 0 || *p == 0) + return RET_SYN; + n = strlen(p); + while (n && iscntrl(p[n-1])) + n--; + if ( !n ) + return RET_SYN; + for (found=0,lp=lchr,type=0; type <= lnd_maxno; type++, lp++) { + if (lp->l_tech > tlev) + continue; + if ((lp->l_flags & L_SPY) && !opt_LANDSPIES) + continue; + if(lp->l_name && strncmp(p, lp->l_name, n) == 0) { + found++; + hold = type; + break; + } + } + if (found != 1) { + pr("Illegal land unit type: \"%s\"\n", p); + if (confirm("List unit types? ")) + show_land_build (tlev); + player->argp[3] = 0; + goto ask_again; + } + type = hold; + lp = &(lchr[type]); + rqtech = lp->l_tech; + break; + case 'b': + if (natp->nat_level[NAT_TLEV]+0.005 < buil_bt) { + pr("Building a span requires a tech of %.0f\n", + buil_bt); + return 2; + } + break; + case 't': + if (!opt_BRIDGETOWERS) { + pr("Bridge tower building is disabled.\n"); + return RET_FAIL; + } + if (natp->nat_level[NAT_TLEV]+0.005 < buil_tower_bt) { + pr("Building a tower requires a tech of %.0f\n", + buil_tower_bt); + return 2; + } + break; + case 'n': + if (opt_NONUKES) { + pr("There are no nukes in this game.\n"); + return RET_FAIL; + } + p = getstarg(player->argp[3], "Nuke type? ", buf); + if (p == 0 || *p == 0) + return RET_SYN; + n = strlen(p); + while (n && iscntrl(p[n-1])) + n--; + if ( !n ) + return RET_SYN; + for (found=0,np=nchr,type=0; type < nuk_maxno; type++, np++) { + if ((np->n_tech > tlev) || + (opt_DRNUKE && ((np->n_tech*drnuke_const) > rlev))) + continue; + if (opt_NEUTRON == 0 && (np->n_flags & N_NEUT)) + continue; + + if(np->n_name && strncmp(p, np->n_name, n) == 0) { + found++; + hold = type; + break; + } + } + if (found != 1) { + int tt = tlev; + pr("Possible nuke types are:\n"); + if (opt_DRNUKE) + tt = (tlev < (rlev/drnuke_const) ? (int)tlev : + (int)(rlev/drnuke_const)); + + show_nuke_build(tt); + player->argp[3] = 0; + goto ask_again; + } + type = hold; + np = &(nchr[type]); + rqtech = np->n_tech; + break; + default: + pr("You can't build that!\n"); + return RET_FAIL; + } + if (what != 'b' && what != 't') { + if (player->argp[4]) { + if (atoi(player->argp[4]) > 20 && !asked) { + s_char bstr[80]; + asked = 1; + (void) sprintf(bstr,"Are you sure that you want to build %s of them? ", player->argp[4]); + p = getstarg(player->argp[6], bstr, buf); + if (p == 0 || *p != 'y') + return RET_SYN; + } + number=atoi(player->argp[4]); + } + } + if (what != 'b' && what != 'n' && what != 't') { + if (player->argp[5]) { + tlev = atoi(player->argp[5]); + if (tlev > natp->nat_level[NAT_TLEV] && !player->god) { + pr("Your tech level is only %d.\n", + (int)natp->nat_level[NAT_TLEV]); + return RET_FAIL; + } + if (rqtech > tlev) { + pr("Required tech is %d.\n",rqtech); + return RET_FAIL; + } + pr("building with tech level %d.\n", tlev); + } else + tlev = (int)natp->nat_level[NAT_TLEV]; + } + cash = natp->nat_money; + while (nxtsct(&nstr, §)) { + gotsect++; + if (!player->owner) + continue; + getvec(VT_ITEM, vec, (s_char *)§, EF_SECTOR); + switch (what) { + case 'l': + built = build_land(§, lp, vec, tlev); + break; + case 's': + built = build_ship(§, mp, vec, tlev); + break; + case 'b': + built = build_bridge(§, vec); + break; + case 't': + built = build_tower(§, vec); + break; + case 'n': + built = build_nuke(§, np, vec); + break; + case 'p': + built = build_plane(§, pp, vec, tlev); + break; + default: + pr("internal error in build (%d)\n", what); + return RET_FAIL; + } + if (built) { + putvec(VT_ITEM, vec, (s_char *)§, EF_SECTOR); + putsect(§); + } + } + } + if (!gotsect) { + pr("Bad sector specification.\n"); + } + return RET_OK; +} + +static int +build_ship(register struct sctstr *sp, register struct mchrstr *mp, register int *vec, int tlev) +{ + struct shpstr ship; + struct nstr_item nstr; + int cost, i; + int w_p_eff,x; + float eff=((float)SHIP_MINEFF/100.0); + int points, lcm, hcm; + int freeship = 0; + int techdiff; + + hcm = roundavg(((double)mp->m_hcm * (double)eff)); + lcm = roundavg(((double)mp->m_lcm * (double)eff)); + + if (sp->sct_type != SCT_HARBR) { + pr("Ships must be built in harbours.\n"); + return 0; + } + if (sp->sct_effic < 60 && !player->god) { + pr("Sector %s is not 60%% efficient.\n", + xyas(sp->sct_x, sp->sct_y, player->cnum)); + return 0; + } + if (vec[I_LCM] < lcm || vec[I_HCM] < hcm) { + pr("Not enough materials in %s\n", + xyas(sp->sct_x, sp->sct_y, player->cnum)); + return 0; + } + w_p_eff = (20 + mp->m_lcm + (mp->m_hcm * 2)); + points = sp->sct_avail * 100 / w_p_eff; + if (points < SHIP_MINEFF) { + pr("Not enough available work in %s to build a %s\n", + xyas(sp->sct_x, sp->sct_y, player->cnum), mp->m_name); + pr(" (%d available work required)\n", + 1 + (w_p_eff * SHIP_MINEFF)/100); + return 0; + } + cost = mp->m_cost * eff; + if (cash < cost) { + pr("Not enough money left to build a %s\n", mp->m_name); + return 0; + } + if (!trechk(player->cnum, 0, NEWSHP)) + return 0; + if (!check_sect_ok(sp)) + return 0; + sp->sct_avail = (sp->sct_avail * 100 - w_p_eff * SHIP_MINEFF) / 100; + player->dolcost += cost; + cash -= cost; + snxtitem_all(&nstr, EF_SHIP); + while (nxtitem(&nstr, (s_char *)&ship)) { + if (ship.shp_own == 0) { + freeship++; + break; + } + } + if (freeship == 0) { + ef_extend(EF_SHIP, 50); + } + bzero(&ship, sizeof(struct shpstr)); + ship.shp_x = sp->sct_x; + ship.shp_y = sp->sct_y; + ship.shp_destx[0] = sp->sct_x; + ship.shp_desty[0] = sp->sct_y; + ship.shp_destx[1] = sp->sct_x; + ship.shp_desty[1] = sp->sct_y; + ship.shp_autonav = 0; + /* new code for autonav, Chad Zabel 1-15-94 */ + for (i=0;icnum; + ship.shp_type = mp - mchr; + ship.shp_effic = SHIP_MINEFF; + if (opt_MOB_ACCESS) { + time(&ship.shp_access); + ship.shp_mobil = -(etu_per_update / sect_mob_neg_factor); + } else { + ship.shp_mobil = 0; + } + ship.shp_uid = nstr.cur; + ship.shp_nplane = 0; + ship.shp_nland = 0; + ship.shp_nxlight = 0; + ship.shp_nchoppers = 0; + ship.shp_fleet = ' '; + ship.shp_nv = 0; + ship.shp_sell = 0; + ship.shp_tech = tlev; + + techdiff = (int)(tlev - mp->m_tech); + ship.shp_armor = (short)SHP_DEF(mp->m_armor, techdiff); + ship.shp_speed = (short)SHP_SPD(mp->m_speed, techdiff); + ship.shp_visib = (short)SHP_VIS(mp->m_visib, techdiff); + ship.shp_frnge = (short)SHP_RNG(mp->m_frnge, techdiff); + ship.shp_glim = (short)SHP_FIR(mp->m_glim, techdiff); + + ship.shp_mobquota = 0; + *ship.shp_path = 0; + ship.shp_follow = nstr.cur; + ship.shp_name[0] = 0; + ship.shp_orig_own = player->cnum; + ship.shp_orig_x = sp->sct_x; + ship.shp_orig_y = sp->sct_y; + ship.shp_fuel = mchr[(int)ship.shp_type].m_fuelc; + ship.shp_rflags = 0; + for(x=0;x<10;x++) + ship.shp_rpath[x]=0; + + vec[I_LCM] -= lcm; + vec[I_HCM] -= hcm; + + if (getvar(V_PSTAGE, (s_char *)sp, EF_SECTOR) == PLG_INFECT) + putvar(V_PSTAGE, PLG_EXPOSED, (s_char *)&ship, EF_SHIP); + makenotlost(EF_SHIP, ship.shp_own, ship.shp_uid, ship.shp_x, ship.shp_y); + putship(ship.shp_uid, &ship); + pr("%s", prship(&ship)); + pr(" built in sector %s\n", xyas(sp->sct_x, sp->sct_y, player->cnum)); + return 1; +} + +static int +build_land(register struct sctstr *sp, register struct lchrstr *lp, register int *vec, int tlev) +{ + struct lndstr land; + struct nstr_item nstr; + int cost; + int w_p_eff; + int points; + struct natstr *natp; + float eff=((float)LAND_MINEFF/100.0); + double techfact(int, double); + int mil, lcm, hcm, gun, shell; + int freeland = 0; + + /* + mil = roundavg(((double)lp->l_mil * (double)eff)); + shell = roundavg(((double)lp->l_shell * (double)eff)); + gun = roundavg(((double)lp->l_gun * (double)eff)); + */ + mil = shell = gun = 0; + hcm = roundavg(((double)lp->l_hcm * (double)eff)); + lcm = roundavg(((double)lp->l_lcm * (double)eff)); + + natp = getnatp(player->cnum); + + if (sp->sct_type != SCT_HEADQ) { + pr("Land Units must be built in headquarters.\n"); + return 0; + } + if (sp->sct_effic < 60 && !player->god) { + pr("Sector %s is not 60%% efficient.\n", + xyas(sp->sct_x, sp->sct_y, player->cnum)); + return 0; + } + if (vec[I_LCM] < lcm || vec[I_HCM] < hcm) { + pr("Not enough materials in %s\n", + xyas(sp->sct_x, sp->sct_y, player->cnum)); + return 0; + } +#if 0 + if (vec[I_GUN] < gun || vec[I_GUN] == 0){ + pr("Not enough guns in %s\n", + xyas(sp->sct_x, sp->sct_y, player->cnum)); + return 0; + } + if (vec[I_SHELL] < shell){ + pr("Not enough shells in %s\n", + xyas(sp->sct_x, sp->sct_y, player->cnum)); + return 0; + } + if (vec[I_MILIT] < mil){ + pr("Not enough military in %s\n", + xyas(sp->sct_x, sp->sct_y, player->cnum)); + return 0; + } +#endif + if (!trechk(player->cnum, 0, NEWLND)) + return 0; + if (!check_sect_ok(sp)) + return 0; + w_p_eff = (20 + lp->l_lcm + (lp->l_hcm * 2)); + points = sp->sct_avail * 100 / w_p_eff; + if (points < LAND_MINEFF) { + pr("Not enough available work in %s to build a %s\n", + xyas(sp->sct_x, sp->sct_y, player->cnum), lp->l_name); + pr(" (%d available work required)\n", + 1 + (w_p_eff * LAND_MINEFF)/100); + return 0; + } + cost = ((float)lp->l_cost * eff); + /* cost = (int)LND_COST(cost, tlev - lp->l_tech);*/ + if (cash < cost) { + pr("Not enough money left to build a %s\n", lp->l_name); + return 0; + } + sp->sct_avail = (sp->sct_avail * 100 - w_p_eff * LAND_MINEFF) / 100; + player->dolcost += cost; + cash -= cost; + snxtitem_all(&nstr, EF_LAND); + while (nxtitem(&nstr, (s_char *)&land)) { + if (land.lnd_own == 0) { + freeland++; + break; + } + } + if (freeland == 0) { + ef_extend(EF_LAND, 50); + } + bzero(&land, sizeof(struct lndstr)); + land.lnd_x = sp->sct_x; + land.lnd_y = sp->sct_y; + land.lnd_own = player->cnum; + land.lnd_mission = 0; + land.lnd_type = lp - lchr; + land.lnd_effic = LAND_MINEFF; + if (opt_MOB_ACCESS) { + time(&land.lnd_access); + land.lnd_mobil = -(etu_per_update / sect_mob_neg_factor); + } else { + land.lnd_mobil = 0; + } + land.lnd_sell = 0; + land.lnd_tech = tlev; + land.lnd_uid = nstr.cur; + land.lnd_army = ' '; + land.lnd_flags = 0; + land.lnd_ship = -1; + land.lnd_land = -1; + land.lnd_nland = 0; + land.lnd_harden = 0; + land.lnd_retreat = morale_base; + land.lnd_fuel = lp->l_fuelc; + land.lnd_nxlight = 0; + land.lnd_rflags = 0; + bzero(land.lnd_rpath,10); + land.lnd_rad_max = 0; + land.lnd_nv = 0; + land.lnd_att = (float)LND_ATTDEF(lp->l_att, tlev - lp->l_tech); + land.lnd_def = (float)LND_ATTDEF(lp->l_def, tlev - lp->l_tech); + land.lnd_vul = (int)LND_VUL(lp->l_vul, tlev - lp->l_tech); + land.lnd_spd = (int)LND_SPD(lp->l_spd, tlev - lp->l_tech); + land.lnd_vis = (int)LND_VIS(lp->l_vis, tlev - lp->l_tech); + land.lnd_spy = (int)LND_SPY(lp->l_spy, tlev - lp->l_tech); + land.lnd_rad = (int)LND_RAD(lp->l_rad, tlev - lp->l_tech); + land.lnd_frg = (int)LND_FRG(lp->l_frg, tlev - lp->l_tech); + land.lnd_acc = (int)LND_ACC(lp->l_acc, tlev - lp->l_tech); + land.lnd_dam = (int)LND_DAM(lp->l_dam, tlev - lp->l_tech); + land.lnd_ammo = (int)LND_AMM(lp->l_ammo, lp->l_dam, tlev - lp->l_tech); + land.lnd_aaf = (int)LND_AAF(lp->l_aaf, tlev - lp->l_tech); + land.lnd_fuelc = (int)LND_FC(lp->l_fuelc, tlev - lp->l_tech); + land.lnd_fuelu = (int)LND_FU(lp->l_fuelu, tlev - lp->l_tech); + land.lnd_maxlight = (int)LND_XPL(lp->l_nxlight, tlev - lp->l_tech); + land.lnd_maxland = (int)LND_MXL(lp->l_mxland, tlev - lp->l_tech); + + vec[I_LCM] -= lcm; + vec[I_HCM] -= hcm; + vec[I_MILIT] -= mil; + vec[I_GUN] -= gun; + vec[I_SHELL] -= shell; + +/* Disabled autoloading of food onto units + max_amt = vl_find(V_FOOD, lp->l_vtype, lp->l_vamt, (int) lp->l_nv); + food_needed = (etu_per_update * eatrate) * + (vec[I_CIVIL] + vec[I_MILIT] + vec[I_UW])+1; + if ((vec[I_FOOD]-max_amt) < food_needed) + max_amt = (vec[I_FOOD]-food_needed); + + if (max_amt < 0) + max_amt = 0; + + vec[I_FOOD] -= max_amt; + + bzero(lvec, sizeof(lvec)); + getvec(VT_ITEM, lvec, (s_char *)&land, EF_LAND); + lvec[I_FOOD] += max_amt; + putvec(VT_ITEM, lvec, (s_char *)&land, EF_LAND); +*/ + + if (getvar(V_PSTAGE, (s_char *)sp, EF_SECTOR) == PLG_INFECT) + putvar(V_PSTAGE, PLG_EXPOSED, (s_char *)&land, EF_LAND); + putland(nstr.cur, &land); + makenotlost(EF_LAND, land.lnd_own, land.lnd_uid, land.lnd_x, land.lnd_y); + pr("%s", prland(&land)); + pr(" built in sector %s\n", xyas(sp->sct_x, sp->sct_y, player->cnum)); + return 1; +} + +static +int +build_bridge(register struct sctstr *sp, register int *vec) +{ + extern int buil_bh; + extern double buil_bc; + struct sctstr sect; + int val; + int newx, newy; + int w_p_eff; + int points; + int nx,ny,i,good=0; + s_char *p; + s_char buf[1024]; + + if (opt_EASY_BRIDGES == 0) { /* must have a bridge head or tower */ + if (sp->sct_type != SCT_BTOWER) { + if (sp->sct_type != SCT_BHEAD) + return 0; + if (sp->sct_newtype != SCT_BHEAD) + return 0; + } + } +#if 0 + else { + + for (i = 1; i <= 6; i++) { + struct sctstr s2; + nx = sp->sct_x + diroff[i][0]; + ny = sp->sct_y + diroff[i][1]; + getsect(nx, ny, §); + for (j = 1; j <= 6; j++) { + nx2 = sect.sct_x + diroff[j][0]; + ny2 = sect.sct_y + diroff[j][1]; + getsect(nx2, ny2, &s2); + if ((s2.sct_type != SCT_WATER) && + (s2.sct_type != SCT_BSPAN)) + good=1; + } + + } + + if (!good){ + pr("Bridges must be built adjacent to land or bridge towers.\n"); + pr("No eligible sectors adjacent to this sector.\n"); + return 0; + } + } /* end EASY_BRIDGES */ +#endif + + if (sp->sct_effic < 60 && !player->god) { + pr("Sector %s is not 60%% efficient.\n", + xyas(sp->sct_x, sp->sct_y, player->cnum)); + return 0; + } + + if (!opt_NO_HCMS) { + if (vec[I_HCM] < buil_bh) { + pr("%s only has %d unit%s of hcm,\n", + xyas(sp->sct_x, sp->sct_y, player->cnum), + vec[I_HCM], vec[I_HCM] > 1 ? "s" : ""); + pr("(a bridge span requires %d)\n", buil_bh); + return 0; + } + } else if (!opt_NO_LCMS) { + if (vec[I_LCM] < buil_bh) { + pr("%s only has %d unit%s of lcm,\n", + xyas(sp->sct_x, sp->sct_y, player->cnum), + vec[I_LCM], vec[I_LCM] > 1 ? "s" : ""); + pr("(a bridge span requires %d)\n", buil_bh); + return 0; + } + } + if (cash < buil_bc) { + pr("A span costs $%.2f to build; ", buil_bc); + pr("you only have %d.\n", cash); + return 0; + } + w_p_eff = buil_bh * 2; + points = sp->sct_avail * 100 / w_p_eff; + if (points < 20) { + pr("Not enough available work in %s to build a bridge\n", + xyas(sp->sct_x, sp->sct_y, player->cnum)); + pr(" (%d available work required)\n", + 1 + (w_p_eff * 20)/100); + return 0; + } + if (!player->argp[3]) { + pr("Bridge head at %s\n", xyas(sp->sct_x, sp->sct_y, player->cnum)); + nav_map(sp->sct_x, sp->sct_y, 1); + } + if (!(p = getstarg(player->argp[3], "build span in what direction? ", buf)) || !*p) { + return 0; + } + /* Sanity check time */ + if (!check_sect_ok(sp)) + return 0; + + if ((val = chkdir(*p, DIR_FIRST, DIR_LAST)) < 0) { + pr("'%c' is not a valid direction...\n", *p); + direrr(0, 0, 0); + return 0; + } + newx = sp->sct_x + diroff[val][0]; + newy = sp->sct_y + diroff[val][1]; + if (getsect(newx, newy, §) == 0 || sect.sct_type != SCT_WATER) { + pr("%s is not a water sector\n", + xyas(newx, newy, player->cnum)); + return 0; + } + if (opt_EASY_BRIDGES) { + good=0; + + for (i = 1; i <= 6; i++) { + struct sctstr s2; + nx = sect.sct_x + diroff[i][0]; + ny = sect.sct_y + diroff[i][1]; + getsect(nx, ny, &s2); + if ((s2.sct_type != SCT_WATER) && + (s2.sct_type != SCT_BSPAN)) + good=1; + } + if (!good){ + pr("Bridges must be built adjacent to land or bridge towers.\n"); + pr("That sector is not adjacent to land or a bridge tower.\n"); + return 0; + } + } /* end EASY_BRIDGES */ + sp->sct_avail = (sp->sct_avail * 100 - w_p_eff * 20) / 100; + player->dolcost += buil_bc; + cash -= buil_bc; + sect.sct_type = SCT_BSPAN; + sect.sct_newtype = SCT_BSPAN; + sect.sct_effic = 20; + sect.sct_road = 0; + sect.sct_rail = 0; + sect.sct_defense = 0; + if (!opt_DEFENSE_INFRA) + sect.sct_defense = sect.sct_effic; + if (opt_MOB_ACCESS) { + time(§.sct_access); + sect.sct_mobil = -(etu_per_update / sect_mob_neg_factor); + } else { + sect.sct_mobil = 0; + } + putvar(V_MINE,0,(s_char *)§,EF_SECTOR); + putsect(§); + pr("Bridge span built over %s\n", + xyas(sect.sct_x, sect.sct_y, player->cnum)); + if (!opt_NO_HCMS) + vec[I_HCM] -= buil_bh; + else if (!opt_NO_LCMS) + vec[I_LCM] -= buil_bh; + return 1; +} + +static +int +build_nuke(register struct sctstr *sp, register struct nchrstr *np, register int *vec) +{ + int w_p_eff; + int points; + + if (sp->sct_type != SCT_NUKE && !player->god) { + pr("Nuclear weapons must be built in nuclear plants.\n"); + return 0; + } + if (sp->sct_effic < 60 && !player->god) { + pr("Sector %s is not 60%% efficient.\n", + xyas(sp->sct_x, sp->sct_y, player->cnum)); + return 0; + } + if (vec[I_HCM] < np->n_hcm || vec[I_LCM] < np->n_lcm || + vec[I_OIL] < np->n_oil || vec[I_RAD] < np->n_rad) { + pr("Not enough materials for a %s bomb in %s\n", + np->n_name, xyas(sp->sct_x, sp->sct_y, player->cnum)); + pr("(%d hcm, %d lcm, %d oil, & %d rads).\n", + np->n_hcm, np->n_lcm, np->n_oil, np->n_rad); + return 0; + } + if (cash < np->n_cost) { + pr("You need $%d, you only have %d.\n", np->n_cost, cash); + return 0; + } + w_p_eff = np->n_rad + np->n_oil + np->n_lcm + np->n_hcm * 2; + points = sp->sct_avail * 100 / w_p_eff; + /* + * XXX when nukes turn into units (or whatever), then + * make them start at 20%. Since they don't have efficiency + * now, we choose 20% as a "big" number. + */ + if (points < 20) { + pr("Not enough available work in %s to build a %s;\n", + xyas(sp->sct_x, sp->sct_y, player->cnum), np->n_name); + pr(" (%d available work required)\n", + 1 + w_p_eff*20/100); + return 0; + } + if (!trechk(player->cnum, 0, NEWNUK)) + return 0; + if (!check_sect_ok(sp)) + return 0; + sp->sct_avail = (sp->sct_avail * 100 - w_p_eff * 20) / 100; + player->dolcost += np->n_cost; + cash -= np->n_cost; + nuk_add(sp->sct_x, sp->sct_y, np - nchr, 1); + vec[I_HCM] -= np->n_hcm; + vec[I_LCM] -= np->n_lcm; + vec[I_OIL] -= np->n_oil; + vec[I_RAD] -= np->n_rad; + pr("%s warhead created in %s\n", np->n_name, + xyas(sp->sct_x, sp->sct_y, player->cnum)); + return 1; +} + +static +int +build_plane(register struct sctstr *sp, register struct plchrstr *pp, register int *vec, int tlev) +{ + struct plnstr plane; + int cost; + struct nstr_item nstr; + float eff=((float)PLANE_MINEFF/100.0); + int points; + int w_p_eff; + int hcm, lcm, mil; + int freeplane = 0; + + mil = roundavg(((double)pp->pl_crew * (double)eff)); + /* Always use at least 1 mil to build a plane */ + if (mil == 0 && pp->pl_crew > 0) + mil = 1; + hcm = roundavg(((double)pp->pl_hcm * (double)eff)); + lcm = roundavg(((double)pp->pl_lcm * (double)eff)); + if (sp->sct_type != SCT_AIRPT && !player->god) { + pr("Planes must be built in airports.\n"); + return 0; + } + if (sp->sct_effic < 60 && !player->god) { + pr("Sector %s is not 60%% efficient.\n", + xyas(sp->sct_x, sp->sct_y, player->cnum)); + return 0; + } + if (vec[I_LCM] < lcm || vec[I_HCM] < hcm) { + pr("Not enough materials in %s\n", + xyas(sp->sct_x, sp->sct_y, player->cnum)); + return 0; + } + w_p_eff = (20 + pp->pl_lcm + (pp->pl_hcm * 2)); + points = sp->sct_avail * 100 / w_p_eff; + if (points < PLANE_MINEFF) { + pr("Not enough available work in %s to build a %s\n", + xyas(sp->sct_x, sp->sct_y, player->cnum), pp->pl_name); + pr(" (%d available work required)\n", + 1 + PLANE_MINEFF * w_p_eff/100); + return 0; + } + cost = pp->pl_cost * eff; + if (cash < cost) { + pr("Not enough money left to build a %s\n", pp->pl_name); + return 0; + } + if (vec[I_MILIT] < mil || (vec[I_MILIT] == 0 && pp->pl_crew > 0)) { + pr("Not enough military for crew in %s\n", + xyas(sp->sct_x, sp->sct_y, player->cnum)); + return 0; + } + if (!trechk(player->cnum, 0, NEWPLN)) + return 0; + if (!check_sect_ok(sp)) + return 0; + sp->sct_avail = (sp->sct_avail * 100 - w_p_eff * PLANE_MINEFF) / 100; + player->dolcost += cost; + cash -= cost; + snxtitem_all(&nstr, EF_PLANE); + freeplane = 0; + while (nxtitem(&nstr, (s_char *)&plane)) { + if (plane.pln_own == 0) { + freeplane++; + break; + } + } + if (freeplane == 0) { + ef_extend(EF_PLANE, 50); + } + bzero(&plane, sizeof(struct plnstr)); + plane.pln_x = sp->sct_x; + plane.pln_y = sp->sct_y; + plane.pln_own = sp->sct_own; + plane.pln_type = pp - plchr; + plane.pln_effic = PLANE_MINEFF; + if (opt_MOB_ACCESS) { + time(&plane.pln_access); + plane.pln_mobil = -(etu_per_update / sect_mob_neg_factor); + } else { + plane.pln_mobil = 0; + } + plane.pln_mission = 0; + plane.pln_opx = 0; + plane.pln_opy = 0; + plane.pln_radius = 0; + + /* Note that this next block of variables can be changed so that individual + * planes may have their own stats (like based on tech maybe? :) ) Thus, + * the code now checks the pln_acc, pln_load and pln_fuel instead of using + * the static definitions of them. */ +/* + n = (int) (pp->pl_range * (0.75 + techfact(tlev - pp->pl_tech, 2.0))); + if (n > 127) + n = 127; + plane.pln_range = n; + plane.pln_range_max = n; + n = (int) (pp->pl_att * (0.75 + techfact(tlev - pp->pl_tech, 2.0))); + if (n > 127) + n = 127; + plane.pln_att = n; + n = (int) (pp->pl_def * (0.75 + techfact(tlev - pp->pl_tech, 2.0))); + if (n > 127) + n = 127; + if (n < pp->pl_def) + n = pp->pl_def; + plane.pln_def = n; + plane.pln_acc = pp->pl_acc; + plane.pln_load = pp->pl_load; + plane.pln_fuel = pp->pl_fuel; +*/ + plane.pln_att = PLN_ATTDEF(pp->pl_att, (int)(tlev - pp->pl_tech)); + plane.pln_def = PLN_ATTDEF(pp->pl_def, (int)(tlev - pp->pl_tech)); + plane.pln_acc = PLN_ACC(pp->pl_acc, (int)(tlev - pp->pl_tech)); + plane.pln_range = PLN_RAN(pp->pl_range, (int)(tlev - pp->pl_tech)); + plane.pln_range_max = plane.pln_range; + plane.pln_load = PLN_LOAD(pp->pl_load, (int)(tlev - pp->pl_tech)); + plane.pln_fuel = pp->pl_fuel; + + plane.pln_wing = ' '; + plane.pln_tech = tlev; + plane.pln_ship = -1; + plane.pln_land = -1; + plane.pln_uid = nstr.cur; + plane.pln_nuketype = -1; + plane.pln_harden = 0; + plane.pln_sell = 0; + plane.pln_flags = 0; + makenotlost(EF_PLANE, plane.pln_own, plane.pln_uid, plane.pln_x, plane.pln_y); + putplane(plane.pln_uid, &plane); + pr("%s built in sector %s\n", prplane(&plane), + xyas(sp->sct_x, sp->sct_y, player->cnum)); + vec[I_LCM] -= lcm; + vec[I_HCM] -= hcm; + vec[I_MILIT] -= mil; + return 1; +} + +static +int +build_tower(register struct sctstr *sp, register int *vec) +{ + extern int buil_tower_bh; + extern double buil_tower_bc; + struct sctstr sect; + int val; + int newx, newy; + int w_p_eff; + int points; + s_char *p; + s_char buf[1024]; + int good; + int i; + int nx; + int ny; + + if (sp->sct_type != SCT_BSPAN) { + pr("Bridge towers can only be built from bridge spans.\n"); + return 0; + } + + if (sp->sct_effic < 60 && !player->god) { + pr("Sector %s is not 60%% efficient.\n", + xyas(sp->sct_x, sp->sct_y, player->cnum)); + return 0; + } + + if (!opt_NO_HCMS) { + if (vec[I_HCM] < buil_tower_bh) { + pr("%s only has %d unit%s of hcm,\n", + xyas(sp->sct_x, sp->sct_y, player->cnum), + vec[I_HCM], vec[I_HCM] > 1 ? "s" : ""); + pr("(a bridge tower requires %d)\n", buil_tower_bh); + return 0; + } + } else if (!opt_NO_LCMS) { + if (vec[I_LCM] < buil_tower_bh) { + pr("%s only has %d unit%s of lcm,\n", + xyas(sp->sct_x, sp->sct_y, player->cnum), + vec[I_LCM], vec[I_LCM] > 1 ? "s" : ""); + pr("(a bridge tower requires %d)\n", buil_tower_bh); + return 0; + } + } + if (cash < buil_tower_bc) { + pr("A bridge tower costs $%.2f to build; ", buil_tower_bc); + pr("you only have %d.\n", cash); + return 0; + } + w_p_eff = buil_tower_bh * 2; + points = sp->sct_avail * 100 / w_p_eff; + if (points < 20) { + pr("Not enough available work in %s to build a bridge tower\n", + xyas(sp->sct_x, sp->sct_y, player->cnum)); + pr(" (%d available work required)\n", + 1 + (w_p_eff * 20)/100); + return 0; + } + if (!player->argp[3]) { + pr("Building from %s\n", xyas(sp->sct_x, sp->sct_y, player->cnum)); + nav_map(sp->sct_x, sp->sct_y, 1); + } + if (!(p = getstarg(player->argp[3], "build tower in what direction? ", buf)) || !*p) { + return 0; + } + /* Sanity check time */ + if (!check_sect_ok(sp)) + return 0; + + if ((val = chkdir(*p, DIR_FIRST, DIR_LAST)) < 0) { + pr("'%c' is not a valid direction...\n", *p); + direrr(0, 0, 0); + return 0; + } + newx = sp->sct_x + diroff[val][0]; + newy = sp->sct_y + diroff[val][1]; + if (getsect(newx, newy, §) == 0 || sect.sct_type != SCT_WATER) { + pr("%s is not a water sector\n", + xyas(newx, newy, player->cnum)); + return 0; + } + + /* Now, check. You aren't allowed to build bridge towers + next to land. */ + good = 0; + for (i = 1; i <= 6; i++) { + struct sctstr s2; + nx = sect.sct_x + diroff[i][0]; + ny = sect.sct_y + diroff[i][1]; + getsect(nx, ny, &s2); + if ((s2.sct_type != SCT_WATER) && + (s2.sct_type != SCT_BTOWER) && + (s2.sct_type != SCT_BSPAN)) { + good = 1; + break; + } + } + if (good){ + pr("Bridge towers cannot be built adjacent to land.\n"); + pr("That sector is adjacent to land.\n"); + return 0; + } + + sp->sct_avail = (sp->sct_avail * 100 - w_p_eff * 20) / 100; + player->dolcost += buil_tower_bc; + cash -= buil_tower_bc; + sect.sct_type = SCT_BTOWER; + sect.sct_newtype = SCT_BTOWER; + sect.sct_effic = 20; + sect.sct_road = 0; + sect.sct_rail = 0; + sect.sct_defense = 0; + if (opt_MOB_ACCESS) { + time(§.sct_access); + sect.sct_mobil = -(etu_per_update / sect_mob_neg_factor); + } else { + sect.sct_mobil = 0; + } + if (!opt_DEFENSE_INFRA) + sect.sct_defense = sect.sct_effic; + putvar(V_MINE,0,(s_char *)§,EF_SECTOR); + putsect(§); + pr("Bridge tower built in %s\n", + xyas(sect.sct_x, sect.sct_y, player->cnum)); + if (!opt_NO_HCMS) + vec[I_HCM] -= buil_tower_bh; + else if (!opt_NO_LCMS) + vec[I_LCM] -= buil_tower_bh; + return 1; +} + diff --git a/src/lib/commands/buy.c b/src/lib/commands/buy.c new file mode 100644 index 00000000..c891dec7 --- /dev/null +++ b/src/lib/commands/buy.c @@ -0,0 +1,374 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * buy.c: Buy commodities from other nations + * + * Known contributors to this file: + * Dave Pare, 1986 + * Pat Loney, 1992 + * Steve McClure, 1996-2000 + */ + +#include "misc.h" +#include "xy.h" +#include "file.h" +#include "var.h" +#include "sect.h" +#include "nat.h" +#include "news.h" +#include "nsc.h" +#include "item.h" +#include "deity.h" +#include "land.h" +#include "commodity.h" +#include "plane.h" +#include "nuke.h" +#include "ship.h" +#include "trade.h" +#include "player.h" +#include "loan.h" +#include "commands.h" +#include "optlist.h" + +extern int MARK_DELAY; + +/* + * format: buy + * + */ +int +buy(void) +{ + struct sctstr sect; + struct natstr *natp; + struct comstr comm; + struct comstr ncomm; + struct comstr comt; + struct trdstr tmpt; + struct ichrstr *ip; + int qty; + int o, n, q; + coord x, y; + char *p; + float bid; + time_t now; + double tally; + double canspend; + extern double buytax; + extern double tradetax; + s_char buf[1024]; + + if (!opt_MARKET) { + pr("The market is disabled.\n"); + return RET_FAIL; + } + natp = getnatp(player->cnum); + display_mark(player->argp[1]); + pr("\n"); + p = getstarg(player->argp[2], "Which lot are you bidding on: ", buf); + if (p == 0) + return RET_SYN; + if (*p == 0) + return RET_SYN; + o = atoi(p); + if (o < 0) + return RET_SYN; + if(!getcomm(o, &comm) || comm.com_owner == 0){ + pr("Invalid lot number.\n"); + return RET_OK; + } + if (player->argp[1] && *(player->argp[1]) && + comm.com_type != player->argp[1][0]) { + pr("That lot is not of the type you specified.\n"); + return RET_OK; + } + if (comm.com_owner == player->cnum){ + pr("You can't bid on your own lot.\n"); + return RET_OK; + } + pr("WARNING! This market issues credit. If you make more\n"); + pr(" bids than your treasury can cover at the time of sale,\n"); + pr(" you can potentially go into financial ruin, and see no\n"); + pr(" gains. You have been warned.\n\n"); + if ((p = getstarg(player->argp[3], "How much per unit: ",buf)) == 0) + return RET_SYN; + bid = atof(p); + if (bid <= 0) + return RET_FAIL; + if (natp->nat_money < (bid * comm.com_amount * buytax)) { + pr("This purchase would cost %.2f, %.2f more than you have.\n", + bid * comm.com_amount * buytax, + bid * comm.com_amount * buytax - natp->nat_money); + return RET_FAIL; + } +/* check to see if all of the bids that this player has out plus this new bid + would make him go broke. Ken, I ought to skin you alive for making me code + this part up.*/ + tally = 0.0; + for (q = 0; gettrade(q, &tmpt); q++) { + if (tmpt.trd_maxbidder == player->cnum && + tmpt.trd_unitid >= 0 && + tmpt.trd_owner != player->cnum) { + tally += tmpt.trd_maxprice * tradetax; + } + } + for (q = 0; getcomm(q, &comt); q++) { + if (comt.com_maxbidder == player->cnum && + comt.com_owner != 0 && + comt.com_owner != player->cnum) { + tally += (comt.com_maxprice * comt.com_amount) * buytax; + } + } + canspend = natp->nat_money - tally; + getcomm(o, &comm); + if ((bid * comm.com_amount * buytax) > canspend) { + pr("You have overextended yourself in the market\n"); + pr("You can not bid on the current items at that price.\n"); + return RET_OK; + } + if (!(p = getstarg(player->argp[4], "destination sector : ", buf))) + return RET_SYN; + if (!sarg_xy(p, &x, &y)) + return RET_SYN; + if (!getsect(x, y, §)) { + pr("Could not access sector"); + return RET_FAIL; + } + if ((sect.sct_type != SCT_WAREH && sect.sct_type != SCT_HARBR) || + sect.sct_own != player->cnum) { + pr("The destination sector is not one of your warehouses.\n"); + return RET_FAIL; + } + if (sect.sct_effic < 60) { + pr("That sector is under construction.\n"); + return RET_FAIL; + } + ip = whichitem(comm.com_type); + n = getvar(ip->i_vtype, (char *)§, EF_SECTOR); + qty = comm.com_amount; + if (qty + n > 9990) { + pr("That sector cannot hold %d more %s. It currently holds %d.\n", + qty, ip->i_name, n); + return RET_FAIL; + } + /* First we check for room, then we yank back. Probably not necessary. */ + if (putvar(ip->i_vtype, n + qty, (char *)§, EF_SECTOR) <= 0) { + pr("No room to store %s in %s\n", + ip->i_name, xyas(sect.sct_x, sect.sct_y, player->cnum)); + return RET_FAIL; + } + if (putvar(ip->i_vtype, n, (char *)§, EF_SECTOR) <= 0) { + pr("Something weird just happened, tell the deity.\n"); + logerror("buy.c: putvar failed.\n"); + return RET_FAIL; + } + if ((bid * comm.com_amount) > natp->nat_money) { + pr("You don't have that much to spend!\n"); + return RET_FAIL; + } + getcomm(o, &ncomm); + if (!ncomm.com_owner) { + pr("That lot has been taken off the market.\n"); + return RET_FAIL; + } + if (bid > 0.04 + comm.com_maxprice){ + comm.com_maxprice = bid; + /* Add five minutes to the time if less than 5 minutes */ + time(&now); + if (((MARK_DELAY - (now - comm.com_markettime)) < 300) && + comm.com_maxbidder != player->cnum) { + comm.com_markettime += 300; + /* Special case - what if so much time has gone by? Well, + Just reset the markettime so that only 5 minutes are left */ + if ((MARK_DELAY - (now - comm.com_markettime)) < 0) + comm.com_markettime = (now - (MARK_DELAY - 300)); + } + comm.com_maxbidder = player->cnum; + comm.com_x = x; + comm.com_y = y; + putcomm(o, &comm); + pr("Your bid is being considered.\n"); + } else { + pr("Your bid wasn't high enough (you need to bid at least $0.05 higher\n"); + pr("than the last bid.\n"); + return RET_OK; + } + + check_market(); + + return RET_OK; +} + +int +check_market(void) +{ + extern double buytax; + struct comstr comm; + struct sctstr *sect; + struct ichrstr *ip; + struct natstr *natp; + int m; + int n; + time_t now; + double tmoney; + double tleft; + double subleft; + double monleft; + double gain; + double price; + struct lonstr loan; + long outstanding; /* Outstanding debt */ + long couval; /* Value of country's goods */ + int foundloan; + int j; + +/* logerror("Checking the market.\n");*/ + for (n = 0; getcomm(n, &comm); n++) { + if (comm.com_maxbidder == comm.com_owner || + comm.com_owner == 0) + continue; + (void)time(&now); + tleft = MARK_DELAY / 3600.0 - (now - comm.com_markettime) / 3600.0; + if (tleft < 0) + tleft = 0; + if (tleft > 0.0) + continue; + ip = whichitem(comm.com_type); + sect = getsectp(comm.com_x, comm.com_y); + m = getvar(ip->i_vtype, (char *)sect, EF_SECTOR); + + monleft = 0; + + price = comm.com_maxprice * comm.com_amount * buytax; + gain = comm.com_maxprice * comm.com_amount; + + natp = getnatp(comm.com_maxbidder); + tmoney = natp->nat_money; + if (tmoney <= 0) + monleft = price; + if (tmoney < price && tmoney > 0) { + monleft = price - (tmoney - 1); + tmoney = 1; + price = price - monleft; + } else if (tmoney > 0) { + monleft = 0; + tmoney = tmoney - price; + } + + /* Subtract the amount of money that needs to come out in a loan. */ + subleft = monleft; + + if (opt_LOANS) { + /* Try to make a loan for the rest from the owner. */ + if (monleft > 0 && tmoney > 0) { + if ((float)((float)price / (float)(price + monleft)) < 0.1) { + wu(0, comm.com_maxbidder, "You need at least 10 percent down to purchase something on credit.\n"); + } else { + couval = get_couval(comm.com_maxbidder); + outstanding = get_outstand(comm.com_maxbidder); + couval = couval - outstanding; + if (couval > monleft) { + /* Make the loan */ + foundloan = 0; + for (j = 0; getloan(j, &loan); j++) { + if (loan.l_status != LS_FREE) + continue; + foundloan = 1; + break; + } + if (!foundloan) + ef_extend(EF_LOAN, 1); + loan.l_status = LS_SIGNED; + loan.l_loner = comm.com_owner; + loan.l_lonee = comm.com_maxbidder; + loan.l_irate = 25; + loan.l_ldur = 4; + loan.l_amtpaid = 0; + loan.l_amtdue = monleft; + time(&loan.l_lastpay); + loan.l_duedate = (loan.l_ldur * SECS_PER_DAY) + loan.l_lastpay; + loan.l_uid = j; + if (!putloan(j, &loan)) + logerror("Error writing to the loan file.\n"); + else + monleft = 0; + nreport(comm.com_maxbidder,N_FIN_TROUBLE, comm.com_owner, 1); + wu(0, comm.com_maxbidder, "You just took loan #%d for $%.2f to cover the cost of your purchase.\n", j, loan.l_amtdue); + wu(0, comm.com_owner, "You just extended loan #%d to %s to help with the purchase cose.\n", j, cname(comm.com_maxbidder)); + } else { + nreport(comm.com_maxbidder,N_CREDIT_JUNK, comm.com_owner, 1); + wu(0, comm.com_maxbidder, "You don't have enough credit to get a loan.\n"); + wu(0, comm.com_owner, "You just turned down a loan to %s.\n", cname(comm.com_maxbidder)); + } + } + } + } + + if (monleft > 0) { + nreport(comm.com_maxbidder, N_WELCH_DEAL, comm.com_owner, 1); + wu(0, comm.com_maxbidder, + "You didn't have enough cash/credit to cover the cost.\n"); + wu(0, comm.com_owner, + "Sale #%d fell through. Goods remain on the market.\n", n); + comm.com_maxbidder = comm.com_owner; + } else if (sect->sct_type != SCT_WAREH && sect->sct_type != SCT_HARBR) { + wu(0, comm.com_maxbidder, + "Sector not a warehouse now, sale #%d fell though.\n", n); + wu(0, comm.com_owner, + "Sale #%d fell through. Goods remain on the market.\n", n); + comm.com_maxbidder = comm.com_owner; + } else if (putvar(ip->i_vtype, m + comm.com_amount, + (char *)sect, EF_SECTOR) <= 0) { + wu(0, comm.com_maxbidder, + "Warehouse full, sale #%d fell though.\n", n); + wu(0, comm.com_owner, + "Sale #%d fell through. Goods remain on the market.\n", n); + comm.com_maxbidder = comm.com_owner; + } else { + putsect(sect); + nreport(comm.com_owner, N_MAKE_SALE, comm.com_maxbidder, 1); + wu(0, comm.com_owner, "%s bought %d %c's from you for $%.2f\n", + cname(comm.com_maxbidder), comm.com_amount, + comm.com_type, gain); + wu(0, comm.com_maxbidder, "You just bought %d %c's from %s for $%.2f\n", + comm.com_amount, comm.com_type, cname(comm.com_owner), + gain * buytax); + natp=getnatp(comm.com_owner); + /* Make sure we subtract the amount that came out in a loan */ + natp->nat_money += (gain - subleft); + natp=getnatp(comm.com_maxbidder); + natp->nat_money = tmoney; + comm.com_owner = 0; + } + comm.com_owner = 0; + putcomm(n, &comm); + } +/* logerror("Done checking the market.\n");*/ + return RET_OK; +} + + diff --git a/src/lib/commands/capi.c b/src/lib/commands/capi.c new file mode 100644 index 00000000..d351526d --- /dev/null +++ b/src/lib/commands/capi.c @@ -0,0 +1,79 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * capi.c: Move your capital + * + * Known contributors to this file: + * Dave Pare, 1986 + * Steve McClure, 2000 + */ + + +#include "misc.h" +#include "player.h" +#include "var.h" +#include "sect.h" +#include "nat.h" +#include "xy.h" +#include "nsc.h" +#include "item.h" +#include "file.h" +#include "commands.h" + +int +capi(void) +{ + struct sctstr sect; + struct natstr *np; + struct nstr_sect nstr; + int found; + + if (!snxtsct(&nstr, player->argp[1])) + return RET_SYN; + np = getnatp(player->cnum); + found = 0; + while (!found && nxtsct(&nstr, §)) { + if (player->owner && (sect.sct_type == SCT_CAPIT || + sect.sct_type == SCT_MOUNT)) + found++; + } + if (!found) + return RET_FAIL; + if (sect.sct_x == np->nat_xcap && sect.sct_y == np->nat_ycap) { + pr("%s is already your capital.\n", + xyas(sect.sct_x, sect.sct_y, player->cnum)); + return RET_FAIL; + } + player->nstat |= CAP; + np->nat_xcap = sect.sct_x; + np->nat_ycap = sect.sct_y; + /* They have set a capital, so it wasn't sacked last. */ + np->nat_flags &= ~NF_SACKED; + putnat(np); + pr("Capital now at %s.\n", xyas(sect.sct_x, sect.sct_y, player->cnum)); + return 0; +} diff --git a/src/lib/commands/carg.c b/src/lib/commands/carg.c new file mode 100644 index 00000000..582839fa --- /dev/null +++ b/src/lib/commands/carg.c @@ -0,0 +1,153 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * carg.c: List cargo contents of a ship + * + * Known contributors to this file: + * + */ + +#include "misc.h" +#include "player.h" +#include "var.h" +#include "xy.h" +#include "sect.h" +#include "ship.h" +#include "land.h" +#include "nsc.h" +#include "nat.h" +#include "file.h" +#include "deity.h" +#include "commands.h" +#include "optlist.h" + +int +carg(void) +{ + int nships; + struct nstr_item ni; + struct shpstr ship; + int vec[I_MAX+1]; + + if (!snxtitem(&ni, EF_SHIP, player->argp[1])) + return RET_SYN; + nships = 0; + while (nxtitem(&ni, (s_char *)&ship)) { + if (ship.shp_own == 0) + continue; + if ((player->cnum != ship.shp_own) && !player->god) + continue; + if (ship.shp_type < 0 || ship.shp_type > shp_maxno) { + pr("bad ship type %d (#%d)\n", ship.shp_type, + ni.cur); + continue; + } + if (nships++ == 0) + pr("shp# ship type x,y flt eff sh gun pet irn dst bar oil lcm hcm rad\n"); + pr("%4d ", ni.cur); + pr("%-16.16s ", mchr[(int)ship.shp_type].m_name); + prxy("%4d,%-4d ", ship.shp_x, ship.shp_y, player->cnum); + pr(" %1c", ship.shp_fleet); + pr("%4d%%", ship.shp_effic); + getvec(VT_ITEM, vec, (s_char *)&ship, EF_SHIP); + pr("%4d", vec[I_SHELL]); + pr("%4d", vec[I_GUN]); + pr("%4d", vec[I_PETROL]); + pr("%4d", vec[I_IRON]); + pr("%4d", vec[I_DUST]); + pr("%4d", vec[I_BAR]); + pr("%4d", vec[I_OIL]); + pr("%4d", vec[I_LCM]); + pr("%4d", vec[I_HCM]); + pr("%4d\n", vec[I_RAD]); + if (opt_SHIPNAMES) { + if (ship.shp_name[0] != 0) { + pr(" %s\n",ship.shp_name); + } + } + } + if (nships == 0) { + if (player->argp[1]) + pr("%s: No ship(s)\n", player->argp[1]); + else + pr("%s: No ship(s)\n", ""); + return RET_FAIL; + }else + pr("%d ship%s\n", nships, splur(nships)); + return RET_OK; +} + +int +lcarg(void) +{ + int nunits; + struct nstr_item ni; + struct lndstr land; + int vec[I_MAX+1]; + + if (!snxtitem(&ni, EF_LAND, player->argp[1])) + return RET_SYN; + nunits = 0; + while (nxtitem(&ni, (s_char *)&land)) { + if (!land.lnd_own) + continue; + if ((player->cnum != land.lnd_own) && !player->god) + continue; + if (land.lnd_type < 0 || land.lnd_type > lnd_maxno) { + pr("bad unit type %d (#%d)\n", land.lnd_type, + ni.cur); + continue; + } + if (nunits++ == 0) + pr("lnd# unit type x,y a eff sh gun pet irn dst bar oil lcm hcm rad\n"); + pr("%4d ", ni.cur); + pr("%-16.16s ", lchr[(int)land.lnd_type].l_name); + prxy("%4d,%-4d ", land.lnd_x, land.lnd_y, player->cnum); + pr(" %1c", land.lnd_army); + pr("%4d%%", land.lnd_effic); + getvec(VT_ITEM, vec, (s_char *)&land, EF_LAND); + pr("%4d", vec[I_SHELL]); + pr("%4d", vec[I_GUN]); + pr("%4d", vec[I_PETROL]); + pr("%4d", vec[I_IRON]); + pr("%4d", vec[I_DUST]); + pr("%4d", vec[I_BAR]); + pr("%4d", vec[I_OIL]); + pr("%4d", vec[I_LCM]); + pr("%4d", vec[I_HCM]); + pr("%4d\n", vec[I_RAD]); + } + if (nunits == 0) { + if (player->argp[1]) + pr("%s: No unit(s)\n", player->argp[1]); + else + pr("No unit(s)\n"); + return RET_FAIL; + }else + pr("%d unit%s\n", nunits, splur(nunits)); + return RET_OK; +} diff --git a/src/lib/commands/cede.c b/src/lib/commands/cede.c new file mode 100644 index 00000000..3439c8e5 --- /dev/null +++ b/src/lib/commands/cede.c @@ -0,0 +1,393 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * cede.c: Give a sector to a neighbor + * + * Known contributors to this file: + * Dave Pare + * Thomas Ruschak + */ + +#include "misc.h" +#include "player.h" +#include "var.h" +#include "xy.h" +#include "sect.h" +#include "nsc.h" +#include "nat.h" +#include "deity.h" +#include "path.h" +#include "file.h" +#include "plane.h" +#include "land.h" +#include "ship.h" +#include "nuke.h" +#include "item.h" +#include "commands.h" + +static void cede_hdr(void); + +int +cede(void) +{ + natid to; + int n; + int is_sector=0,is_ship=0; + s_char *p; + struct nstr_sect ns; + struct nstr_item ni; + struct natstr *natp; + s_char buf[1024]; + + if ((p = getstarg(player->argp[1], "Cede what? ", buf)) == 0) + return RET_SYN; + if (snxtsct(&ns, p)) + is_sector = 1; + if (snxtitem(&ni, EF_SHIP, p)) + is_ship = 1; + if (!is_sector && !is_ship) + return RET_SYN; + if ((n = natarg(player->argp[2], "to which country? ")) < 0) + return RET_SYN; + if (is_sector && is_ship){ + int type; + + if ((p = getstarg(player->argp[3], "Cede sectors or ships (se, sh)? ", buf)) == 0) + return RET_FAIL; + if (strlen(p) > 4) + p[2] = 0; + type = ef_byname(p); + + if (type == EF_SECTOR) + is_ship = 0; + else if (type == EF_SHIP) + is_sector = 0; + else{ + pr("Please type 'se' or 'sh'!\n"); + return RET_FAIL; + } + } + + + if (n == player->cnum){ + pr("Giving something to yourself?\n"); + return RET_FAIL; + } + natp = getnatp(n); + if (natp->nat_stat & STAT_GOD){ + pr("You can only give to normal countries...\n"); + return RET_FAIL; + } + if (getrel(natp, player->cnum) < FRIENDLY) { + pr("You can only cede to a country that is friendly towards you...\n"); + return RET_FAIL; + } + to = n; + + if (is_sector) + return cede_sect(&ns,to); + else + return cede_ship(&ni,to); +} + +int +cede_sect(struct nstr_sect *ns, natid to) +{ + struct sctstr sect, osect; + int nsect; + int n, bad; + s_char dirstr[20]; + int off_x, off_y; + struct nstr_item ni; + struct shpstr ship; + + prdate(); + for (n = 1; n <= 6; n++) + dirstr[n] = dirch[n]; + dirstr[0] = '.'; + dirstr[7] = '$'; + dirstr[8] = '\0'; + nsect = 0; + while (nxtsct(ns, §)) { + if (!player->owner) + continue; + if (sect.sct_mobil == 0){ + pr("%s has no mobility and cannot be ceded\n", + xyas(sect.sct_x,sect.sct_y,player->cnum)); + continue; + } + + bad = 1; + for (n = 1; n <= 6; n++) { /* Directions */ + off_x = sect.sct_x + diroff[n][0]; + off_y = sect.sct_y + diroff[n][1]; + + if (!getsect(off_x, off_y, &osect)) + continue; + if ((osect.sct_own == to) && (osect.sct_mobil)) + bad=0; + if ((osect.sct_own == to) && + has_units_with_mob(osect.sct_x, osect.sct_y,to)) + bad=0; + } + snxtitem_all(&ni,EF_SHIP); + while (nxtitem(&ni, (s_char *)&ship)){ + if ((ship.shp_own == to) && + ((ship.shp_x == sect.sct_x) && + (ship.shp_y == sect.sct_y))) + bad = 0; + } + if (bad){ + pr("%s has no sector with mobility adjacent to or ship in %s!\n", + cname(to), xyas(sect.sct_x,sect.sct_y,player->cnum)); + continue; + } + + if (nsect++ == 0) + cede_hdr(); + + grab_sect(§,to); + putsect(§); + pr(" %s %d%% ceded\n",xyas(sect.sct_x,sect.sct_y,player->cnum), + (int)sect.sct_effic); + wu(0,(natid)to,"%s ceded to you by %s\n", + xyas(sect.sct_x,sect.sct_y,to), cname(player->cnum)); + } + pr("%d sector%s\n", nsect, splur(nsect)); + return RET_OK; +} + +static void +cede_hdr(void) +{ + if (player->god) + pr("own "); + pr(" sect eff\n"); +} + + + +void +grab_sect(register struct sctstr *sp, natid to) +{ + struct plnstr *pp; + struct lndstr *lp; + struct nukstr *np; + int oldche; + struct nstr_item ni; + struct plnstr p; + struct lndstr l; + struct nukstr nuk; + int vec[I_MAX+1]; + + /* Wipe all the distribution info */ + bzero((s_char *)vec, sizeof(vec)); + putvec(VT_DIST, vec, (s_char *)sp, EF_SECTOR); + putvec(VT_DEL, vec, (s_char *)sp, EF_SECTOR); + sp->sct_dist_x = sp->sct_x; + sp->sct_dist_y = sp->sct_y; + + pp = &p; + snxtitem_xy(&ni, EF_PLANE, sp->sct_x, sp->sct_y); + while (nxtitem(&ni, (caddr_t)pp)) { + if (pp->pln_own == 0) + continue; + if (pp->pln_ship >= 0) + continue; + if (pp->pln_own != player->cnum) + continue; + if (pp->pln_flags & PLN_LAUNCHED) + continue; + + wu(0,to,"\t%s ceded to you by %s\n", + prplane(pp), + cname(player->cnum)); + makelost(EF_PLANE, pp->pln_own, pp->pln_uid, pp->pln_x, pp->pln_y); + pp->pln_own = to; + makenotlost(EF_PLANE, pp->pln_own, pp->pln_uid, pp->pln_x, pp->pln_y); + pp->pln_mobil = 0; + pp->pln_mission = 0; + putplane(pp->pln_uid, pp); + } + + np = &nuk; + snxtitem_xy(&ni, EF_NUKE, sp->sct_x, sp->sct_y); + while (nxtitem(&ni, (caddr_t)np)) { + if (np->nuk_own == 0) + continue; + + wu(0,to,"\tnuclear stockpile #%d ceded to you by %s\n", + np->nuk_uid, cname(player->cnum)); + makelost(EF_NUKE, np->nuk_own, np->nuk_uid, np->nuk_x, np->nuk_y); + np->nuk_own = to; + makenotlost(EF_NUKE, np->nuk_own, np->nuk_uid, np->nuk_x, np->nuk_y); + putnuke(ni.cur, np); + } + + lp = &l; + snxtitem_xy(&ni, EF_LAND, sp->sct_x, sp->sct_y); + while (nxtitem(&ni, (caddr_t)lp)) { + if (lp->lnd_own == 0) + continue; + if (lp->lnd_ship == 0) + continue; + if (lp->lnd_own != player->cnum) + continue; + + wu(0,to,"\t%s ceded to you by %s\n", prland(lp), + cname(player->cnum)); + makelost(EF_LAND, lp->lnd_own, lp->lnd_uid, lp->lnd_x, lp->lnd_y); + makenotlost(EF_LAND, to, lp->lnd_uid, lp->lnd_x, lp->lnd_y); + lp->lnd_own = to; + lp->lnd_mobil = 0; + lp->lnd_mission = 0; + putland(ni.cur, lp); + } + + sp->sct_avail = 0; + + if (sp->sct_oldown == to) { + oldche = get_che_value(getvar(V_CHE, (s_char *)sp, EF_SECTOR)); + set_che_value(oldche, 0); + set_che_cnum(oldche, 0); + (void) putvar(V_CHE, oldche, (s_char *)sp, EF_SECTOR); + sp->sct_loyal = 0; + } + + if (sp->sct_oldown == to) + sp->sct_loyal = 0; + else /* people don't like being given away */ + sp->sct_loyal = 50; + + sp->sct_dist_x = sp->sct_x; + sp->sct_dist_y = sp->sct_y; + makelost(EF_SECTOR, sp->sct_own, 0, sp->sct_x, sp->sct_y); + makenotlost(EF_SECTOR, to, 0, sp->sct_x, sp->sct_y); + if (sp->sct_oldown == sp->sct_own) + sp->sct_oldown = to; + sp->sct_own = to; + sp->sct_mobil = 0; +} + +int +cede_ship(struct nstr_item *ni, natid to) +{ + struct shpstr ship; + struct shpstr tship; + struct sctstr sect; + struct nstr_item tni; + int nships=0; + int bad=0; + + while (nxtitem(ni, (s_char *)&ship)) { + + if (!player->owner || ship.shp_own == 0) + continue; + + bad = 1; + snxtitem_xy(&tni,EF_SHIP,ship.shp_x,ship.shp_y); + while (nxtitem(&tni, (s_char *)&tship) && bad) + if (tship.shp_own == to) + bad = 0; + + getsect(ship.shp_x,ship.shp_y,§); + if (bad && (sect.sct_own != to)){ + pr("%s isn't in a %s sector, and is not with a %s ship!\n", prship(&ship), + cname(to), cname(to)); + continue; + } + grab_ship(&ship,to); + putship(ship.shp_uid,&ship); + nships++; + wu(0,to,"%s ceded to you by %s\n", + prship(&ship), + cname(player->cnum)); + pr("%s ceded to %s\n", + prship(&ship), + cname(to)); + } + pr(" %d ship%s\n", nships, splur(nships)); + + return RET_OK; +} + +void +grab_ship(register struct shpstr *sp, natid to) +{ + register struct plnstr *pp; + register struct lndstr *lp; + struct nstr_item ni; + struct plnstr p; + struct lndstr l; + + pp = &p; + snxtitem_xy(&ni, EF_PLANE, sp->shp_x, sp->shp_y); + while (nxtitem(&ni, (caddr_t)pp)) { + if (pp->pln_own == 0) + continue; + if (pp->pln_flags & PLN_LAUNCHED) + continue; + if (pp->pln_ship != sp->shp_uid) + continue; + if (pp->pln_own != player->cnum) + continue; + + wu(0,to,"\t%s ceded to you by %s\n", + prplane(pp), + cname(player->cnum)); + makelost(EF_PLANE, pp->pln_own, pp->pln_uid, pp->pln_x, pp->pln_y); + pp->pln_own = to; + makenotlost(EF_PLANE, pp->pln_own, pp->pln_uid, pp->pln_x, pp->pln_y); + pp->pln_mobil = 0; + pp->pln_mission = 0; + putplane(pp->pln_uid, pp); + } + + lp = &l; + snxtitem_xy(&ni, EF_LAND, sp->shp_x, sp->shp_y); + while (nxtitem(&ni, (caddr_t)lp)) { + if (lp->lnd_own == 0) + continue; + if (lp->lnd_ship != sp->shp_uid) + continue; + if (lp->lnd_own != player->cnum) + continue; + + wu(0,to,"\t%s ceded to you by %s\n", + prland(lp), cname(player->cnum)); + makelost(EF_LAND, lp->lnd_own, lp->lnd_uid, lp->lnd_x, lp->lnd_y); + makenotlost(EF_LAND, to, lp->lnd_uid, lp->lnd_x, lp->lnd_y); + lp->lnd_own = to; + lp->lnd_mobil = 0; + lp->lnd_mission = 0; + putland(ni.cur, lp); + } + + makelost(EF_SHIP, sp->shp_own, sp->shp_uid, sp->shp_x, sp->shp_y); + sp->shp_own = to; + makenotlost(EF_SHIP, sp->shp_own, sp->shp_uid, sp->shp_x, sp->shp_y); +} diff --git a/src/lib/commands/cens.c b/src/lib/commands/cens.c new file mode 100644 index 00000000..f808e52d --- /dev/null +++ b/src/lib/commands/cens.c @@ -0,0 +1,179 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * cens.c: Do a census report + * + * Known contributors to this file: + * Steve McClure, 2000 + * + */ + +#include "misc.h" +#include "player.h" +#include "var.h" +#include "xy.h" +#include "sect.h" +#include "nsc.h" +#include "nat.h" +#include "deity.h" +#include "path.h" +#include "file.h" +#include "commands.h" +#include "optlist.h" + +static void cens_hdr(void); + +int +cens(void) +{ + struct sctstr sect; + int nsect; + int n; + struct nstr_sect nstr; + s_char dirstr[20]; + int vec[I_MAX+1]; + + if (!snxtsct(&nstr, player->argp[1])) + return RET_SYN; + prdate(); + for (n = 1; n <= 6; n++) + dirstr[n] = dirch[n]; + dirstr[0] = '.'; + dirstr[7] = '$'; + dirstr[8] = '\0'; + nsect = 0; + while (nxtsct(&nstr, §)) { + if (!player->owner) + continue; + if (nsect++ == 0) + cens_hdr(); + if (player->god) + pr("%3d ", sect.sct_own); + prxy("%4d,%-4d", nstr.x, nstr.y, player->cnum); + pr(" %c", dchr[sect.sct_type].d_mnem); + if (sect.sct_newtype != sect.sct_type) + pr("%c", dchr[sect.sct_newtype].d_mnem); + else + pr(" "); + pr("%4d%%", sect.sct_effic); + if (sect.sct_off) + pr(" no "); + else + pr(" "); + pr("%4d", sect.sct_mobil); + + getvec(VT_DEL, vec, (s_char *)§, EF_SECTOR); + pr(" %c", dirstr[vec[I_UW] & 0x7]); + pr("%c", dirstr[vec[I_FOOD] & 0x7]); + + getvec(VT_DIST, vec, (s_char *)§, EF_SECTOR); + n = vec[I_UW] % 1000; + pr(" %c", n == 0 ? '.' : '0'+ (n/100)); + n = vec[I_FOOD] % 1000; + pr("%c ", n == 0 ? '.' : '0'+ (n/100)); + pr("%c", sect.sct_own != sect.sct_oldown ? '*' : ' '); + + getvec(VT_ITEM, vec, (s_char *)§, EF_SECTOR); + pr("%5d", vec[I_CIVIL]); + pr("%5d", vec[I_MILIT]); + pr("%5d", vec[I_UW]); + pr("%5d", vec[I_FOOD]); + pr("%4d%%", sect.sct_work); + pr("%5d", sect.sct_avail); + if (!player->god) { + if (sect.sct_terr) + pr("%4d", sect.sct_terr); + else + pr(" "); + } + if (opt_FALLOUT) { + getvec(VT_COND, vec, (void *)§, EF_SECTOR); + pr("%5d",vec[C_FALLOUT]); + } + set_coastal(§); + if (sect.sct_coastal) + pr("%4d", sect.sct_coastal); + pr("\n"); + } + if (nsect == 0) { + if (player->argp[1]) + pr("%s: No sector(s)\n", player->argp[1]); + else + pr("%s: No sector(s)\n", ""); + return RET_FAIL; + }else + pr("%d sector%s\n", nsect, splur(nsect)); + return 0; +} + +static void +cens_hdr(void) +{ + if (player->god) + pr(" "); + pr("CENSUS del dst\n"); + if (player->god) + pr("own "); + pr(" sect eff "); + pr("prd "); + pr("mob uf uf * civ mil uw food work avail "); + if (!player->god) + pr("ter "); + if (opt_FALLOUT) + pr("fall "); + pr("coa"); + pr("\n"); +} + +void +set_coastal(struct sctstr *sp) +{ + int n; + struct sctstr sect; + u_char start_flags = sp->sct_coastal; + + /* It's already been set, it didn't change (you can't fill + in water, even with bridge spans they are still coastal.) */ + if (sp->sct_coastal) + return; + for (n = 1; n <= 6; ++n) { /* Directions */ + getsect(sp->sct_x + diroff[n][0], + sp->sct_y + diroff[n][1], + §); + if (sect.sct_type == SCT_WATER || + sect.sct_type == SCT_BTOWER || + sect.sct_type == SCT_BSPAN) { + sp->sct_coastal = 1; + if (start_flags != sp->sct_coastal) + putsect(sp); + return; + } + } + sp->sct_coastal = 0; + if (start_flags != sp->sct_coastal) + putsect(sp); +} diff --git a/src/lib/commands/chan.c b/src/lib/commands/chan.c new file mode 100644 index 00000000..a1b452b5 --- /dev/null +++ b/src/lib/commands/chan.c @@ -0,0 +1,135 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * chan.c: Change country/representative name + * + * Known contributors to this file: + * Steve McClure, 2000 + * + */ + +#include +#include "misc.h" +#include "player.h" +#include "nat.h" +#include "deity.h" +#include "file.h" +#include "news.h" +#include "optlist.h" +#include "commands.h" + +int +chan(void) +{ + s_char *temp; + struct natstr *natp; + register s_char *p; + natid cn; + int charge; + int nonb; + int btucost; + s_char buf[1024]; + struct natstr *us; + + if ((p = getstarg(player->argp[1], "country name or representative? ", buf)) == 0) + return RET_SYN; + us = getnatp(player->cnum); + if (us->nat_stat == VIS) { + pr("Visitor countries can't change their country name or representative.\n"); + return RET_FAIL; + } + switch (*p) { + case 'n': + case 'c': + charge = 0; + btucost = 0; + if (!player->god && (us->nat_stat & STAT_NORM)) { + if (us->nat_btu < 254) { + pr("You need 254 btus to change your country name!\n"); + return RET_FAIL; + } + if (opt_BLITZ == 0) { + pr("This command costs 254 BTU's and 10%% of your money.\n"); + if (!confirm("Are you sure you want to do this? ")) + return RET_FAIL; + btucost = 254; + /* charge = 2000; */ + /*if (us->nat_money < charge*10)*/ + /* charge = us->nat_money / 10;*/ + if (us->nat_money <= 0) + charge = 0; + else + charge = us->nat_money / 10; + } + } + if ((p = getstarg(player->argp[2], "New country name -- ", buf)) == 0) + return RET_SYN; + p[sizeof(us->nat_cnam)-1] = 0; + for (cn = 0; NULL != (natp = getnatp(cn)); cn++) { + if (same(p, natp->nat_cnam)) { + pr("Country #%d is already called `%s'!\n", + cn, p); + return RET_FAIL; + } + } + nonb = 0; + for (temp = p; *temp != '\0'; temp++) { + if (iscntrl(*temp)) { + pr("No control characters allowed in country names!\n"); + return RET_FAIL; + } else if (*temp != ' ') + nonb = 1; + } + if (!nonb) { + pr("Must have a non-blank name!\n"); + return RET_FAIL; + } + if (opt_BLITZ == 0) { + player->dolcost += charge; + player->btused += btucost; + } + strcpy(us->nat_cnam, p); + putnat(us); + nreport(player->cnum, N_NAME_CHNG, 0, 1); + break; + case 'p': + case 'r': + pr("(note: these are stored in plain text.)\n"); + if ((p = getstarg(player->argp[2], + "New representative name -- ", buf)) == 0) + return RET_SYN; + p[8] = 0; + strcpy(us->nat_pnam, p); + putnat(us); + break; + default: + pr("Only \"country\" or \"representative\" can change.\n"); + return RET_SYN; + } + return RET_OK; +} + diff --git a/src/lib/commands/coas.c b/src/lib/commands/coas.c new file mode 100644 index 00000000..fab689ae --- /dev/null +++ b/src/lib/commands/coas.c @@ -0,0 +1,179 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * coas.c: Look at all the ships in the world + * + * Known contributors to this file: + * Keith Muller, 1983 + * Dave Pare, 1986 (rewrite) + */ + +#include "misc.h" +#include "player.h" +#include "var.h" +#include "sect.h" +#include "ship.h" +#include "nat.h" +#include "xy.h" +#include "nsc.h" +#include "file.h" +#include "commands.h" +#include "optlist.h" + +#define TSIZE 200 + +struct coast { + struct coast *c_next; + int c_spotted; + int c_number; + struct shpstr c_shp; +}; + +static int showship(struct coast **cpp, int x, int y); + +/* + * format: coastwatch [] + */ +int +coas(void) +{ + struct sctstr sect; + struct nstr_sect nstr; + struct coast *cp; + struct coast *list[TSIZE]; + int i, k, j, n; + int vrange, see; + int x, y; + int mink, minj, maxk, maxj; + int nship = 0; + float tech; + struct nstr_item ni; + + if (snxtsct(&nstr, player->argp[1]) == 0) + return RET_SYN; + for (i = 0; i < TSIZE; i++) + list[i] = 0; + cp = (struct coast *)malloc(sizeof(*cp)); + snxtitem_all(&ni, EF_SHIP); + while (nxtitem(&ni, (s_char *) &cp->c_shp)) { + if (cp->c_shp.shp_own == 0 || cp->c_shp.shp_own == player->cnum) + continue; + /* + * don't bother putting subs in the table... + * unless they're in a sector you own (harbor or such) + */ + getsect(cp->c_shp.shp_x, cp->c_shp.shp_y, §); + if ((mchr[(int)cp->c_shp.shp_type].m_flags & M_SUB) && + (sect.sct_own != player->cnum)) + continue; + n = scthash(cp->c_shp.shp_x, cp->c_shp.shp_y, TSIZE); + cp->c_spotted = 0; + cp->c_number = i; + cp->c_next = list[n]; + list[n] = cp; + cp = (struct coast *)malloc(sizeof(*cp)); + nship++; + } + /* get that last one! */ + free((s_char *)cp); + pr("- = [ Coastwatch report for %s ] = -\n", cname(player->cnum)); + pr(" Country Ship Location\n"); + tech = tfact(player->cnum, 1.0); + while (nxtsct(&nstr, §) && nship) { + if (sect.sct_own != player->cnum) + continue; + see = sect.sct_type == SCT_RADAR ? 14 : 4; + vrange = (int) (sect.sct_effic / 100.0 * see * tech); + if (vrange < 1) + vrange = 1; + maxk = vrange; + maxj = vrange * 2; + vrange *= vrange; + mink = -maxk; + minj = -maxj; + for (j = minj; j <= maxj && nship; j++) { + x = xnorm(sect.sct_x + j); + for (k = mink; k <= maxk && nship; k++) { + if ((j + k) & 01) + continue; + /* quick range check to save time... */ + if (vrange < (j * j + 3 * k * k) / 4) + continue; + y = ynorm(sect.sct_y + k); + n = scthash(x, y, TSIZE); + if (list[n] == 0) + continue; + nship -= showship(&list[n], x, y); + } + } + } + /* free up the coast structs calloc'ed above */ + for (i = 0; i < TSIZE; i++) { + while (NULL != (cp = list[i])) { + list[i] = cp->c_next; + free((s_char *)cp); + } + } + return RET_OK; +} + +static int +showship(struct coast **cpp, int x, int y) +{ + register struct coast *cp; + register struct coast *todelete = 0; + register struct coast **prev; + int nship = 0; + + prev = 0; + cp = *cpp; + prev = cpp; + do { + /* we delete it, we free it. */ + if (todelete) { + free((s_char *)todelete); + todelete = 0; + } + if (cp->c_shp.shp_x != x || cp->c_shp.shp_y != y) { + prev = &(*prev)->c_next; + continue; + } + pr(" %12.12s (#%3d) %s @ %s\n", + cname(cp->c_shp.shp_own), cp->c_shp.shp_own, + prship(&cp->c_shp), xyas(x, y, player->cnum)); + if (opt_HIDDEN) { + setcont(player->cnum, cp->c_shp.shp_own, FOUND_COAST); + } + *prev = cp->c_next; + todelete = cp; + nship++; + } while (NULL != (cp = cp->c_next)); + /* check that last one! */ + if (todelete) + free((s_char *)todelete); + return (nship); +} diff --git a/src/lib/commands/coll.c b/src/lib/commands/coll.c new file mode 100644 index 00000000..496e23a6 --- /dev/null +++ b/src/lib/commands/coll.c @@ -0,0 +1,181 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * coll.c: Collet on a loan + * + * Known contributors to this file: + * Pat Loney, 1992 + * Steve McClure, 1996-2000 + */ + +#include +#include "misc.h" +#include "player.h" +#include "var.h" +#include "file.h" +#include "sect.h" +#include "item.h" +#include "loan.h" +#include "news.h" +#include "nat.h" +#include "xy.h" +#include "commands.h" +#include "optlist.h" + +int +coll(void) +{ + register int arg; + register int i; + register int val; + time_t now; + s_char *p; + struct lonstr loan; + struct sctstr sect; + coord x, y; + long due; + long last; + long rdur; + long xdur; + double rate; + double owed; + double pay; + s_char buf[1024]; + int vec[I_MAX+1]; + + if (!opt_LOANS) { + pr("Loans are not enabled.\n"); + return RET_FAIL; + } + if ((arg = onearg(player->argp[1], "Collect on loan #")) < 0) + return RET_SYN; + /* Check if it's a valid loan. That means, is it a valid loan, + owed to this player, with a valid duration and it's been signed. */ + if (!getloan(arg,&loan) || (loan.l_loner != player->cnum) || + (loan.l_ldur == 0) || (loan.l_status != LS_SIGNED)) { + pr("You aren't owed anything on that loan...\n"); + return RET_FAIL; + } + /* If we got here, we check to see if it's been defaulted on. We + already know it's owed to this player. */ + (void) time(&now); + due = loan.l_duedate; + if (now <= due) { + pr("There has been no default on loan %d\n", arg); + return RET_FAIL; + } + last = loan.l_lastpay; + if (last < due && due < now) { + rdur = due - last; + xdur = now - due; + } else if (due < last) { + rdur = 0; + xdur = now - last; + } + rate = loan.l_irate / (loan.l_ldur * 8.64e6); + +/* changed following to avoid overflow 3/27/89 bailey@math-cs.kent.edu + owed = ((rdur * rate) + (xdur * rate * 2.0) + 1.0) * loan.l_amtdue; + Begin overflow fix */ + owed = ((rdur * rate) + (xdur * rate * 2.0) + 1.0); + if (((1 << 30) / owed) < loan.l_amtdue) + owed = (1 << 30); + else + owed *= loan.l_amtdue; +/* End overflow fix */ + pr("You are owed $%.2f on that loan.\n", owed); + if (!(p = getstarg(player->argp[2], "What sector do you wish to confiscate? ", buf))) + return RET_SYN; + if (!check_loan_ok(&loan)) + return RET_FAIL; + if (!sarg_xy(p, &x, &y) || !getsect(x, y, §)) + return RET_SYN; + if (!neigh(x, y, player->cnum)) { + pr("You are not adjacent to %s\n", xyas(x, y, player->cnum)); + return RET_FAIL; + } + if (sect.sct_own != loan.l_lonee) { + pr("%s is not owned by %s.\n", + xyas(x, y, player->cnum), cname(loan.l_lonee)); + return RET_FAIL; + } + pay = dchr[sect.sct_type].d_value * ((float)sect.sct_effic + 100.0); + for (i = 0; ichr[i].i_name; i++) { + if (ichr[i].i_value == 0 || ichr[i].i_vtype == 0) + continue; + val = getvar(ichr[i].i_vtype, (s_char *)§, EF_SECTOR); + pay += val * ichr[i].i_value; + } + pr("That sector (and its contents) is valued at $%.2f\n", pay); + if (pay > owed * 1.2) { + pr("That is more than is owed!\n"); + return RET_FAIL; + } + if (sect.sct_type == SCT_CAPIT || sect.sct_type == SCT_MOUNT) + caploss(§, sect.sct_own, "that was %s's capital!\n"); + putvar(V_MILIT, 1, (s_char *)§, EF_SECTOR); + +/* Consider modifying takeover to take a "no che" argument and + putting using it here again. */ +/* (void) takeover(§, player->cnum);*/ + makelost(EF_SECTOR, sect.sct_own, 0, sect.sct_x, sect.sct_y); + makenotlost(EF_SECTOR, player->cnum, 0, sect.sct_x, sect.sct_y); + sect.sct_own = player->cnum; + + bzero((s_char *)vec, sizeof(vec)); + putvec(VT_DIST, vec, (s_char *)§, EF_SECTOR); + putvec(VT_DEL, vec, (s_char *)§, EF_SECTOR); + sect.sct_off = 1; + sect.sct_dist_x = sect.sct_x; + sect.sct_dist_y = sect.sct_y; + + putsect(§); + nreport(player->cnum, N_SEIZE_SECT, loan.l_lonee, 1); + if (pay >= owed) { + loan.l_ldur = 0; + nreport(loan.l_lonee, N_REPAY_LOAN, player->cnum, 1); + wu(0, loan.l_lonee, + "%s seized %s to satisfy loan #%d\n", + cname(player->cnum), + xyas(sect.sct_x, sect.sct_y, loan.l_lonee), + arg); + pr("That loan is now considered repaid.\n"); + } else { + (void) time(&loan.l_lastpay); + owed -= pay; + loan.l_amtdue = (long) owed; + pay += loan.l_amtpaid; + loan.l_amtpaid = pay; + wu(0, loan.l_lonee, + "%s seized %s in partial payment of loan %d.\n", + cname(player->cnum), + xyas(sect.sct_x, sect.sct_y, loan.l_lonee), arg); + pr("You are still owed $%.2f on loan %d.\n", owed, arg); + } + putloan(arg, &loan); + return RET_OK; +} diff --git a/src/lib/commands/comm.c b/src/lib/commands/comm.c new file mode 100644 index 00000000..87c223cd --- /dev/null +++ b/src/lib/commands/comm.c @@ -0,0 +1,141 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * comm.c: Do a commodity report + * + * Known contributors to this file: + * + */ + +#include "misc.h" +#include "player.h" +#include "var.h" +#include "sect.h" +#include "xy.h" +#include "nsc.h" +#include "path.h" +#include "nat.h" +#include "deity.h" +#include "file.h" +#include "commands.h" + +static void prthresh(s_char *format, int val); + +int +comm(void) +{ + struct sctstr sect; + s_char dirstr[12]; + int nsect; + int n; + struct nstr_sect nstr; + int del[I_MAX+1]; + int dist[I_MAX+1]; + int item[I_MAX+1]; + + if (!snxtsct(&nstr, player->argp[1])) + return RET_SYN; + prdate(); + (void) strcpy(dirstr, ". $"); + n = 1; + for (n = 1; n <= 6; n++) + dirstr[n] = dirch[n]; + nsect = 0; + while (nxtsct(&nstr, §)) { + if (!player->owner) + continue; + if (nsect++ == 0) { + if (player->god) + pr(" "); + pr("COMMODITIES deliver-- distribute\n"); + if (player->god) + pr(" "); + pr(" sect sgpidbolhr sgpidbolhr sh gun pet iron dust bar oil lcm hcm rad\n"); + } + if (player->god) + pr("%3d", sect.sct_own); + getvec(VT_DEL, del, (s_char *)§, EF_SECTOR); + getvec(VT_DIST, dist, (s_char *)§, EF_SECTOR); + getvec(VT_ITEM, item, (s_char *)§, EF_SECTOR); + prxy("%4d,%-4d", nstr.x, nstr.y, player->cnum); + pr(" %c", dchr[sect.sct_type].d_mnem); + pr(" %c", dirstr[del[I_SHELL] & 0x7]); + pr("%c", dirstr[del[I_GUN] & 0x7]); + pr("%c", dirstr[del[I_PETROL] & 0x7]); + pr("%c", dirstr[del[I_IRON] & 0x7]); + pr("%c", dirstr[del[I_DUST] & 0x7]); + pr("%c", dirstr[del[I_BAR] & 0x7]); + pr("%c", dirstr[del[I_OIL] & 0x7]); + pr("%c", dirstr[del[I_LCM] & 0x7]); + pr("%c", dirstr[del[I_HCM] & 0x7]); + pr("%c", dirstr[del[I_RAD] & 0x7]); + prthresh(" %c", dist[I_SHELL]); + prthresh("%c", dist[I_GUN]); + prthresh("%c", dist[I_PETROL]); + prthresh("%c", dist[I_IRON]); + prthresh("%c", dist[I_DUST]); + prthresh("%c", dist[I_BAR]); + prthresh("%c", dist[I_OIL]); + prthresh("%c", dist[I_LCM]); + prthresh("%c", dist[I_HCM]); + prthresh("%c", dist[I_RAD]); + pr("%4d", item[I_SHELL]); + pr("%4d", item[I_GUN]); + pr("%5d", item[I_PETROL]); + pr("%5d", item[I_IRON]); + pr("%5d", item[I_DUST]); + pr("%4d", item[I_BAR]); + pr("%5d", item[I_OIL]); + pr("%5d", item[I_LCM]); + pr("%5d", item[I_HCM]); + pr("%4d", item[I_RAD]); + pr("\n"); + } + if (nsect == 0) { + if (player->argp[1]) + pr("%s: No sector(s)\n", player->argp[1]); + else + pr("%s: No sector(s)\n", ""); + return RET_FAIL; + }else + pr("%d sector%s\n", nsect, splur(nsect)); + return 0; +} + +static void +prthresh(s_char *format, int val) +{ + if (val >= 1000) + val = 'a'; + else if (val > 0) + val = val / 100 + '0'; + else + val = '.'; + pr(format, val); +} + + diff --git a/src/lib/commands/cons.c b/src/lib/commands/cons.c new file mode 100644 index 00000000..37bb99db --- /dev/null +++ b/src/lib/commands/cons.c @@ -0,0 +1,414 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * cons.c: Consider a loan or treaty + * + * Known contributors to this file: + * + */ + +#include "misc.h" +#include "player.h" +#include "loan.h" +#include "nat.h" +#include "treaty.h" +#include "news.h" +#include "xy.h" +#include "nsc.h" +#include "file.h" +#include "commands.h" +#include "optlist.h" + +/* + * Things common to a loan or treaty. + */ +struct ltcomstr { + int type; /* EF_LOAN or EF_TREATY */ + int num; /* number */ + s_char *name; /* "loan" or "treaty" */ + s_char *Name; /* "Loan" or "Treaty" */ + natid proposer; /* country offering */ + natid proposee; /* country offered to */ + natid mailee; /* who gets mail about it */ + s_char op; /* 'a', 'd', or 'p' */ + union { + struct lonstr l; /* the loan */ + struct trtstr t; /* the treaty */ + } u; +}; + +static int cons_choose(struct ltcomstr *ltcp); +static int treaty_accept(struct ltcomstr *ltcp); +static int treaty_decline(struct ltcomstr *ltcp); +static int loan_accept(struct ltcomstr *ltcp); +static int loan_decline(struct ltcomstr *ltcp); +static int postpone(struct ltcomstr *ltcp); +static void accpt(struct ltcomstr *ltcp); +static void decline(struct ltcomstr *ltcp); +static void late(struct ltcomstr *ltcp); +static void prev_signed(struct ltcomstr *ltcp); + +int +cons(void) +{ + int rv; + struct ltcomstr ltc; + + rv = cons_choose(<c); + if (rv != RET_OK) + return rv; + + switch (ltc.op) { + case 'a': + rv = (ltc.type == EF_TREATY) ? treaty_accept(<c) + : loan_accept(<c); + break; + case 'd': + rv = (ltc.type == EF_TREATY) ? treaty_decline(<c) + : loan_decline(<c); + break; + case 'p': + rv = postpone(<c); + break; + default: + pr("Bad operation %c from cons_choose; get help!\n", + ltc.op); + break; + }; + + return rv; +} + +/* + * Choose whether we want to accept, decline, or postpone a + * loan or treaty. Put all the goodies in ltcp, and return + * RET_OK if all goes well, and anything else on error. + */ +static int +cons_choose(struct ltcomstr *ltcp) +{ + s_char *p; + extern int disloan(); + extern int distrea(); + int (*dis)(); + struct lonstr *lp; + struct trtstr *tp; + s_char prompt[128]; + s_char buf[1024]; + + bzero((s_char *)ltcp, sizeof (*ltcp)); + if (getstarg(player->argp[1], "loan or treaty? ", buf) == 0) + return RET_SYN; + ltcp->type = ef_byname(buf); + switch (ltcp->type) { + case EF_TREATY: + if (!opt_TREATIES) { + pr("Treaties are not enabled.\n"); + return RET_FAIL; + } + ltcp->name = "treaty"; + ltcp->Name = "Treaty"; + dis = distrea; + break; + case EF_LOAN: + if (!opt_LOANS) { + pr("Loans are not enabled.\n"); + return RET_FAIL; + } + ltcp->name = "loan"; + ltcp->Name = "Loan"; + dis = disloan; + break; + default: + pr("You must specify \"loan\" or \"treaty\".\n"); + return RET_SYN; + } + sprintf(prompt, "%s number? ", ltcp->Name); + if ((ltcp->num = onearg(player->argp[2], prompt)) < 0) + return RET_SYN; + if (!ef_read(ltcp->type, ltcp->num, (caddr_t)<cp->u) || + !(*dis)(ltcp->num, <cp->u)) { + pr("%s #%d is not being offered to you!\n", + ltcp->Name, ltcp->num); + return RET_SYN; + } + switch (ltcp->type) { + case EF_LOAN: + lp = <cp->u.l; + if (lp->l_status == LS_SIGNED) { + pr("That loan has already been accepted!\n"); + return RET_FAIL; + } + ltcp->proposer = lp->l_loner; + ltcp->proposee = lp->l_lonee; + break; + case EF_TREATY: + tp = <cp->u.t; + if (tp->trt_status == TS_SIGNED) { + pr("That treaty has already been accepted!\n"); + return RET_FAIL; + } + ltcp->proposer = tp->trt_cna; + ltcp->proposee = tp->trt_cnb; + break; + } + ltcp->mailee = (ltcp->proposer == player->cnum) + ? ltcp->proposee : ltcp->proposer; + while ((p = getstarg(player->argp[3], "Accept, decline or postpone? ", buf)) && *p) +{ + if (*p == 'a' || *p == 'd' || *p == 'p') + break; + player->argp[3] = 0; + } + if (p == 0 || *p == 0) + return RET_SYN; + ltcp->op = *p; + return RET_OK; +} + +/* + * Accept a loan. If the offering country has too little money, + * leave him $100 left and offer the rest. Return RET_OK on + * success, anything else on error. + */ +static int +loan_accept(struct ltcomstr *ltcp) +{ + struct lonstr *lp; + struct natstr *lender; + struct nstr_item nstr; + struct lonstr loan; + + lp = <cp->u.l; + if (ltcp->proposee != player->cnum) { + pr("%s %d is still pending.\n", ltcp->Name, ltcp->num); + return RET_OK; + } + if (!getloan(ltcp->num, (caddr_t)lp)) { + pr("loan_accept: can't read loan; get help!\n"); + return RET_SYS; + } + if (lp->l_status == LS_FREE) { /* other guy retratcted already */ + late(ltcp); + return RET_OK; + } + if (lp->l_status == LS_SIGNED) { /* already signed somehow */ + prev_signed(ltcp); + return RET_OK; + } + /* check to see if a loan already exists */ + snxtitem_all(&nstr, EF_LOAN); + while (nxtitem(&nstr, (s_char *) &loan)) { + if (loan.l_status == LS_SIGNED && loan.l_lonee == lp->l_loner + && (loan.l_loner == lp->l_lonee)) { + pr("He already owes you money - make him repay his loan!\n"); + return RET_OK; + } + } + lender = getnatp(ltcp->proposer); + if (lender->nat_money < lp->l_amtdue) { /* other guy is poor */ + lp->l_amtdue = lender->nat_money - 100; + pr("%s no longer has the funds.\n", cname(ltcp->proposer)); + if (lp->l_amtdue <= 0) + return RET_FAIL; + pr("You may borrow $%d at the same terms.\n", + lp->l_amtdue); + } + lender->nat_money -= lp->l_amtdue; + putnat(lender); + player->dolcost -= lp->l_amtdue; + lp->l_amtpaid = 0; + (void) time(&lp->l_lastpay); + lp->l_duedate = lp->l_ldur * 86400 + lp->l_lastpay; + lp->l_status = LS_SIGNED; + if (!putloan(ltcp->num, (s_char *)lp)) { + pr("Problem writing lp->to disk; get help!\n"); + return RET_FAIL; + } + accpt(ltcp); + pr("You are now $%d richer (sort of).\n", lp->l_amtdue); + return RET_OK; +} + +/* + * Declne a loan. Return RET_OK on success, anything else on error. + */ +static int +loan_decline(struct ltcomstr *ltcp) +{ + struct lonstr *lp; + + lp = <cp->u.l; + if (!getloan(ltcp->num, lp)) { + pr("Decline: can't read loan; get help!\n"); + return RET_SYS; + } + /* loan got accepted somehow between now and last time we checked */ + if (lp->l_status == LS_SIGNED) { + late(ltcp); + return RET_OK; + } + lp->l_status = LS_FREE; + if (!putloan(ltcp->num, lp)) { + pr("loan_decline: can't write loan; get help!\n"); + return RET_SYS; + } + decline(ltcp); + return RET_OK; +} + +/* + * Accept a treaty. Return RET_OK on success, anything else on error. + */ +static int +treaty_accept(struct ltcomstr *ltcp) +{ + struct trtstr *tp; + + tp = <cp->u.t; + if (ltcp->proposee != player->cnum) { + pr("%s %d is still pending.\n", ltcp->Name, ltcp->num); + return RET_OK; + } + if (!gettre(ltcp->num, tp)) { + pr("Accept: can't read treaty; get help!\n"); + return RET_SYS; + } + if (tp->trt_status == TS_FREE) { /* treaty offer withdrawn */ + late(ltcp); + return RET_OK; + } + if (tp->trt_status == TS_SIGNED) { /* somehow got accepted */ + prev_signed(ltcp); + return RET_OK; + } + tp->trt_status = TS_SIGNED; + if (!puttre(ltcp->num, tp)) { + pr("Problem saving treaty; get help!\n"); + return RET_SYS; + } + accpt(ltcp); + pr("Treaty in effect until %s", ctime(&tp->trt_exp)); + return RET_OK; +} + +/* + * Decline a treaty. Return RET_OK on success, anything else on error. + */ +static int +treaty_decline(struct ltcomstr *ltcp) +{ + struct trtstr *tp; + + tp = <cp->u.t; + if (!gettre(ltcp->num, tp)) { + pr("Decline: can't read treaty; get help!\n"); + return RET_SYS; + } + /* treaty got signed somehow between now and last time we read it */ + if (tp->trt_status == TS_SIGNED) { + late(ltcp); + return RET_OK; + } + tp->trt_status = TS_FREE; + if (!puttre(ltcp->num, tp)) { + pr("Problem saving treaty; get help!\n"); + return RET_SYS; + } + decline(ltcp); + return RET_OK; +} + +/* + * Postpone a treaty; always succeeds. + */ +static int +postpone(struct ltcomstr *ltcp) +{ + pr("%s %d is still pending.\n", ltcp->Name, ltcp->num); + if (ltcp->proposee == player->cnum) + wu(0, ltcp->proposer, "%s %d considered by %s\n", + ltcp->name, ltcp->num, cname(player->cnum)); + return RET_OK; +} + +/* + * Somebody tried to accept a loan/treaty that was retracted, + * or to decline a loan/treaty they already signed. + */ +static void +late(struct ltcomstr *ltcp) +{ + pr("Too late; that %s %s!\n", ltcp->name, + (ltcp->op == 'a') ? "is no longer being offered" + : "has already been accepted"); +} + +/* + * Loan or treaty was previously signed. + */ +static void +prev_signed(struct ltcomstr *ltcp) +{ + pr("%s #%d is already in effect.\n", ltcp->Name, ltcp->num); +} + +/* + * Post-processing after successful declination of loan or treaty. + * Notify the folks involved. + */ +static void +decline(struct ltcomstr *ltcp) +{ + if (ltcp->proposee == player->cnum) { + wu(0, ltcp->proposer, "%s %d refused by %s\n", + ltcp->Name, ltcp->num, cname(player->cnum)); + pr("%s %d refused.\n", ltcp->Name, ltcp->num); + } else { + wu(0, ltcp->proposee, + "%s offer %d retracted by %s\n", + ltcp->Name, ltcp->num, cname(player->cnum)); + pr("%s offer %d retracted.\n", + ltcp->Name, ltcp->num); + } +} + +/* + * Post-processing after successful acceptance of loan or treaty. + * Notify the press, and the folks involved. + * (Weird spelling is to avoid accept(2)). + */ +static void +accpt(struct ltcomstr *ltcp) +{ + if (ltcp->type == EF_LOAN) + nreport(ltcp->proposer, N_MAKE_LOAN, player->cnum, 1); + else + nreport(player->cnum, N_SIGN_TRE, ltcp->mailee, 1); + wu(0, ltcp->mailee, "%s #%d accepted by %s\n", + ltcp->Name, ltcp->num, cname(player->cnum)); +} diff --git a/src/lib/commands/conv.c b/src/lib/commands/conv.c new file mode 100644 index 00000000..f4ccdedf --- /dev/null +++ b/src/lib/commands/conv.c @@ -0,0 +1,187 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * conv.c: Convert conquered populace into uw's + * + * Known contributors to this file: + * Dave Pare, 1986 + */ + +/* + * format: convert + */ + +#include "misc.h" +#include "player.h" +#include "var.h" +#include "sect.h" +#include "nat.h" +#include "xy.h" +#include "nsc.h" +#include "file.h" +#include "land.h" +#include "commands.h" + +long do_conv(struct nstr_sect nstr, int uwtoconvert, int for_real); + +int +conv(void) +{ + struct natstr *natp; + long cash; + long cost; + struct nstr_sect nstr; + int uwtoconvert; + + natp = getnatp(player->cnum); + cash = natp->nat_money; + if (!snxtsct(&nstr, player->argp[1])) + return RET_SYN; + uwtoconvert = onearg(player->argp[2], "Number to convert: "); + if (uwtoconvert < 0) + return RET_SYN; + cost = do_conv(nstr, uwtoconvert, 0); + if (chkmoney(cost, cash, player->argp[3])) + return RET_SYN; + return (int)do_conv(nstr, uwtoconvert, 1); +} + +long +do_conv(struct nstr_sect nstr, int uwtoconvert, int for_real) +{ + struct sctstr sect; + int newuw, totaluw, uw; + int civ, mil, adj_mob, mob; + double security_extra=1.0; + struct lndstr land; + struct nstr_item ni; + long cost = 0; + + totaluw = 0; + while (nxtsct(&nstr, §)) { + if (!player->owner) + continue; + if (sect.sct_oldown == player->cnum) + continue; + civ = getvar(V_CIVIL, (s_char *)§, EF_SECTOR); + if (civ == 0) + continue; + mil = getvar(V_MILIT, (s_char *)§, EF_SECTOR); + + /* + * Military units count according to the number of + * mil in them. (i.e. attack/defense modified don't + * count. + */ + snxtitem_xy(&ni, EF_LAND, sect.sct_x, sect.sct_y); + while (nxtitem(&ni, (s_char *)&land)){ + mil += lnd_getmil(&land); +/* mil += (lnd_getmil(&land) * + ((double)land.lnd_effic/100.0));*/ + + /* Anti-terrorist units count double */ + if (lchr[(int)land.lnd_type].l_flags & L_SECURITY){ + + /* + * They also increase the efficiency of + * the conversion process by 10% each. + * (but they use 10 mobility doing it) + */ + security_extra += .1; + land.lnd_mobil -= 10; + if (for_real) + putland(land.lnd_uid,&land); + mil += lnd_getmil(&land); +/* mil += (lchr[land.lnd_type].l_mil * + ((double)land.lnd_effic/100.0));*/ + } + } + /* + * Must have military control to convert captured civs. + */ + if (mil * 10 < civ) + continue; + newuw = civ; + if (newuw > uwtoconvert) + newuw = uwtoconvert; + uw = getvar(V_UW, (s_char *)§, EF_SECTOR); + if (uw > 999) + continue; + if (newuw > 999 - uw) + newuw = 999 - uw; + if (newuw == 0) + continue; + /* + * So entire civilian populations don't disappear immediately + * into re-education camps, charge a healthy mobility cost for + * conversions. + */ + mob = sect.sct_mobil * 5; + + /* security troops make conversion more effective */ + adj_mob = ldround(((double)mob*security_extra),1); + + if (adj_mob < newuw) + newuw = adj_mob; + if (newuw <= 0) + continue; + if (!for_real) { + cost += newuw * 1.5; + continue; + } + player->btused += (newuw - 1) / 100 + 1; + player->dolcost += newuw * 1.5; + if (newuw < mob) + mob = newuw; + if (putvar(V_UW, newuw + uw, (s_char *)§, EF_SECTOR) == 0) { + pr("No room for new uw in %s\n", + xyas(sect.sct_x, sect.sct_y, player->cnum)); + continue; + } + civ -= newuw; + putvar(V_CIVIL, civ, (s_char *)§, EF_SECTOR); + mob = roundavg(mob * 0.2); + if (mob > sect.sct_mobil) + mob = sect.sct_mobil; + sect.sct_mobil -= (u_char)mob; + pr("%3d conquered civilians converted in %s (%d)\n", + newuw, xyas(sect.sct_x, sect.sct_y, player->cnum), + uw + newuw); + if (civ == 0) { + sect.sct_oldown = sect.sct_own; + pr("%s is now completely yours.\n", + xyas(sect.sct_x, sect.sct_y, player->cnum)); + } + putsect(§); + totaluw += newuw; + } + if (!for_real) + return cost; + pr("Total civilians converted: %d\n", totaluw); + pr("Paperwork at conversion places ... %d\n", player->btused); + return RET_OK; +} diff --git a/src/lib/commands/coun.c b/src/lib/commands/coun.c new file mode 100644 index 00000000..2e278043 --- /dev/null +++ b/src/lib/commands/coun.c @@ -0,0 +1,116 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * coun.c: Do a country roster + * + * Known contributors to this file: + * + */ + +#include "misc.h" +#include "player.h" +#include "var.h" +#include "sect.h" +#include "nat.h" +#include "xy.h" +#include "nsc.h" +#include "file.h" +#include "deity.h" +#include +#include +#include "commands.h" + +static void coun_header(void); +static void coun_list(natid cn, struct natstr *natp); + +int +coun(void) +{ + struct nstr_item ni; + struct natstr nat; + int first; + + pr("The 'country' command is temporarily out of order.\n"); + pr("Please use the 'players' command instead.\n"); + if (!snxtitem(&ni, EF_NATION, player->argp[1])) + return RET_SYN; + first = 1; + while (nxtitem(&ni, (s_char *)&nat)) { + if ((nat.nat_stat & STAT_INUSE) == 0) + continue; + if (((nat.nat_stat & GOD) != GOD) && !player->god) + continue; + if (first) { + coun_header(); + first = 0; + } + coun_list((natid)ni.cur, &nat); + } + return RET_OK; +} + +static void +coun_header(void) +{ + prdate(); + pr(" # last access time\tstatus\t\t country name\n"); +} + +static void +coun_list(natid cn, struct natstr *natp) +{ + s_char *status; + struct sctstr sect; + + if (natp->nat_connected) + pr("%3d %-16.16s [%d]",cn," Now logged on", + natp->nat_btu); + else + pr("%3d %-16.16s [%d]", cn, ctime(&natp->nat_last_login), + natp->nat_btu); + + if (natp->nat_stat & STAT_GOD) + status = "DEITY"; + else if (natp->nat_stat & STAT_NEW) + status = "New"; + else if (natp->nat_stat & STAT_SANCT) + status = "Sanctuary"; + else if (natp->nat_stat & STAT_NORM) { + getsect(natp->nat_xcap, natp->nat_ycap, §); + if (sect.sct_own != cn || + (sect.sct_type != SCT_CAPIT && + sect.sct_type != SCT_MOUNT)) + status = "In flux"; + else if (natp->nat_money < 0) + status = "Broke"; + else + status = "Active"; + } else { + status = "Visitor"; + } + pr("\t%-9.9s\t %s\n", status, natp->nat_cnam); +} diff --git a/src/lib/commands/cuto.c b/src/lib/commands/cuto.c new file mode 100644 index 00000000..6afbc74d --- /dev/null +++ b/src/lib/commands/cuto.c @@ -0,0 +1,117 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * cuto.c: Do a delivery cutoff level report + * + * Known contributors to this file: + * David Muir Sharnoff, 1987 + */ + +#include "misc.h" +#include "player.h" +#include "var.h" +#include "sect.h" +#include "xy.h" +#include "nsc.h" +#include "nat.h" +#include "path.h" +#include "deity.h" +#include "file.h" +#include "commands.h" + +int +cuto(void) +{ + struct sctstr sect; + int nsect; + int n; + struct nstr_sect nstr; + s_char dirstr[12]; + int del[I_MAX+1]; + + if (!snxtsct(&nstr, player->argp[1])) + return RET_SYN; + prdate(); + (void) strcpy(dirstr, ". $"); + n = 1; + for (n = 1; n <= 6; n++) + dirstr[n] = dirch[n]; + nsect = 0; + while (nxtsct(&nstr, §)) { + if (!player->owner) + continue; + if (nsect++ == 0) { + pr("DELIVERY CUTOFF LEVELS\n"); + if (player->god) + pr("own"); +pr(" sect cmufsgpidbolhr civ mil uw food sh gun pet irn dst bar oil lcm hcm rad\n"); + } + if (player->god) + pr("%3d", sect.sct_own); + getvec(VT_DEL, del, (s_char *)§, EF_SECTOR); + pr("%7s", xyas(nstr.x, nstr.y, player->cnum)); + pr(" %c ", dchr[sect.sct_type].d_mnem); + pr("%c", dirstr[del[I_CIVIL] & 0x7]); + pr("%c", dirstr[del[I_MILIT] & 0x7]); + pr("%c", dirstr[del[I_UW] & 0x7]); + pr("%c", dirstr[del[I_FOOD] & 0x7]); + pr("%c", dirstr[del[I_SHELL] & 0x7]); + pr("%c", dirstr[del[I_GUN] & 0x7]); + pr("%c", dirstr[del[I_PETROL] & 0x7]); + pr("%c", dirstr[del[I_IRON] & 0x7]); + pr("%c", dirstr[del[I_DUST] & 0x7]); + pr("%c", dirstr[del[I_BAR] & 0x7]); + pr("%c", dirstr[del[I_OIL] & 0x7]); + pr("%c", dirstr[del[I_LCM] & 0x7]); + pr("%c", dirstr[del[I_HCM] & 0x7]); + pr("%c", dirstr[del[I_RAD] & 0x7]); + pr("%4d", del[I_CIVIL] & ~0x7); + pr("%4d", del[I_MILIT] & ~0x7); + pr("%4d", del[I_UW] & ~0x7); + pr("%4d", del[I_FOOD] & ~0x7); + pr("%4d", del[I_SHELL] & ~0x7); + pr("%4d", del[I_GUN] & ~0x7); + pr("%4d", del[I_PETROL] & ~0x7); + pr("%4d", del[I_IRON] & ~0x7); + pr("%4d", del[I_DUST] & ~0x7); + pr("%4d", del[I_BAR] & ~0x7); + pr("%4d", del[I_OIL] & ~0x7); + pr("%4d", del[I_LCM] & ~0x7); + pr("%4d", del[I_HCM] & ~0x7); + pr("%4d", del[I_RAD] & ~0x7); + pr("\n"); + } + if (nsect == 0) { + if (player->argp[1]) + pr("%s: No sector(s)\n", player->argp[1]); + else + pr("%s: No sector(s)\n", ""); + return RET_FAIL; + }else + pr("%d sector%s\n", nsect, splur(nsect)); + return RET_OK; +} diff --git a/src/lib/commands/decl.c b/src/lib/commands/decl.c new file mode 100644 index 00000000..80340552 --- /dev/null +++ b/src/lib/commands/decl.c @@ -0,0 +1,114 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * decl.c: Declare war, neutrality, alliance, hostile or friendly + * + * Known contributors to this file: + * + */ + +#include "misc.h" +#include "player.h" +#include "nat.h" +#include "news.h" +#include "file.h" +#include "deity.h" +#include "xy.h" +#include "nsc.h" +#include "commands.h" +#include "optlist.h" + +int +decl(void) +{ + struct natstr nat, *natp; + int rel; + int who; + struct nstr_item ni; + s_char *p; + s_char buf[1024]; + + if (!(p = getstarg(player->argp[1], "alliance, friendly, neutrality, hostility, or war? ", buf))) + return RET_SYN; + switch (*p) { + case 'a': + rel = ALLIED; + break; + case 'f': + rel = FRIENDLY; + break; + case 'n': + rel = NEUTRAL; + break; + case 'h': + rel = HOSTILE; + break; + case 'm': + if (!opt_SLOW_WAR) return RET_SYN; + if (!player->god) return RET_SYN; + rel = MOBILIZATION; + break; + case 's': + if (!opt_SLOW_WAR) return RET_SYN; + if (!player->god) return RET_SYN; + rel = SITZKRIEG; + break; + case 'w': + rel = AT_WAR; + break; + default: + pr("That's no declaration!\n"); + return RET_SYN; + } + + if (!snxtitem(&ni, EF_NATION, player->argp[2])) + return RET_SYN; + who = player->cnum; + if (player->god){ + who = natarg(player->argp[3], "for which country? "); + if (who < 0) return RET_SYN; + } + if (who == 255) return RET_SYN; + + natp = getnatp(who); + while (nxtitem(&ni, (s_char *) &nat)) { + if (!(nat.nat_stat & STAT_INUSE)) + continue; + if (player->cnum == (natid)ni.cur) + continue; + if (opt_HIDDEN) { + if (!player->god && !getcontact(natp, ni.cur)) { + pr("You haven't contacted country #%d yet\n", ni.cur); + continue; + } + } + if (getrel(natp, (natid)ni.cur) == rel) + continue; + setrel(who, (natid)ni.cur, rel); + } + return RET_OK; +} diff --git a/src/lib/commands/deli.c b/src/lib/commands/deli.c new file mode 100644 index 00000000..0cb55b98 --- /dev/null +++ b/src/lib/commands/deli.c @@ -0,0 +1,124 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * deli.c: Set deliveries from a sector + * + * Known contributors to this file: + * + */ + +#include "misc.h" +#include "player.h" +#include "xy.h" +#include "var.h" +#include "sect.h" +#include "item.h" +#include "file.h" +#include "path.h" +#include "nsc.h" +#include "nat.h" +#include "commands.h" + +int +deli(void) +{ + struct sctstr sect; + register int dir, del; + register struct ichrstr *ich; + register int thresh = -1; + int i_del; + int sx, sy; + int status; + struct nstr_sect nstr; + s_char buf[1024]; + s_char prompt[128]; + s_char *p; + + if ((ich = whatitem(player->argp[1], "deliver what? ")) == 0) + return RET_SYN; + /* + if (ich->i_vtype == V_CIVIL || ich->i_vtype == V_MILIT) { + pr("You cannot deliver people!\n"); + return RET_FAIL; + } + */ + if (!snxtsct(&nstr, player->argp[2])) + return RET_SYN; + i_del = V_DEL(ich-ichr); + + while (nxtsct(&nstr, §) > 0) { + if (!player->owner) + continue; + sprintf(prompt, "%s %s 'query' or %s threshold? ", + xyas(nstr.x, nstr.y, player->cnum), + dchr[sect.sct_type].d_name, + ich->i_name); + if (!(p = getstarg(player->argp[3], prompt, buf)) || !*p) + return RET_SYN; + del = getvar(i_del, (s_char *)§, EF_SECTOR); + if (((*p >= '0') && (*p <= '9')) || *p == '+') { + thresh = atoi(p) & ~0x7; + if (*p == '+' || !(p = getstarg(player->argp[4], "Direction? ", buf)) || !*p) + dir = del & 0x7; + else if ((dir = chkdir(*p, DIR_STOP, DIR_LAST)) < 0) + return RET_SYN; + } else if (*p != 'q') + return RET_SYN; + + if (!check_sect_ok(§)) + continue; + + if (thresh >= 0) { + del = thresh + dir; + status = putvar(i_del, del,(s_char *)§,EF_SECTOR); + if (status < 0) { + pr("No room for delivery path in %s\n", + xyas(sect.sct_x, sect.sct_y, player->cnum)); + continue; + } else if (!status) { + /* Either nothing to set, or bogus amount. */ + continue; + } else + putsect(§); + } + if (!del) + continue; + dir = del & 0x7; + sx = diroff[dir][0] + sect.sct_x; + sy = diroff[dir][1] + sect.sct_y; + pr("Deliver %s from %s @ %s to %s", + ich->i_name, + dchr[sect.sct_type].d_name, + xyas(sect.sct_x, sect.sct_y, player->cnum), + xyas(sx, sy, player->cnum)); + if (!(del & ~0x7)) + pr("\n"); + else + pr(" (cutoff %d)\n", del & ~0x7); + } + return RET_OK; +} diff --git a/src/lib/commands/demo.c b/src/lib/commands/demo.c new file mode 100644 index 00000000..515cdffe --- /dev/null +++ b/src/lib/commands/demo.c @@ -0,0 +1,137 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * demo.c: De-mobilize "n" military in a given sector + * + * Known contributors to this file: + * Dave Pare, 1986 + */ + +#include "misc.h" +#include "player.h" +#include "xy.h" +#include "deity.h" +#include "var.h" +#include "sect.h" +#include "nat.h" +#include "nsc.h" +#include "file.h" +#include "commands.h" + +/* + * format: demo number + * + */ + +long do_demo(struct natstr *natp, struct nstr_sect nstr, int number, s_char *p, int for_real); + +int +demo(void) +{ + struct natstr *natp; + long cash; + long cost; + int number; + s_char *p; + s_char buf[1024]; + struct nstr_sect nstr; + + natp = getnatp(player->cnum); + cash = natp->nat_money; + if (!snxtsct(&nstr, player->argp[1])) + return RET_SYN; + if ((p = getstarg(player->argp[2], "Number to de-mobilize : ", buf)) == 0) + return RET_SYN; + number = atoi(p); + if (!(p = getstarg(player->argp[3], "New civilians on active reserve? (y/n) ", buf))) + return RET_SYN; + if (*p != 'y' && *p != 'n') + return RET_SYN; + cost = do_demo(natp, nstr, number, p, 0); + if (chkmoney(cost, cash, player->argp[4])) + return RET_SYN; + return (int)do_demo(natp, nstr, number, p, 1); +} + +long do_demo(struct natstr *natp, struct nstr_sect nstr, int number, s_char *p, int for_real) +{ + struct sctstr sect; + int mil_demob; + int mil; + int civ; + int deltamil; + int reserves; + long cost = 0; + + mil_demob = 0; + reserves = 0; + while (nxtsct(&nstr, §)) { + if (!player->owner || sect.sct_effic < 60) + continue; + if ((mil = getvar(V_MILIT, (s_char *)§, EF_SECTOR)) == 0) + continue; + if (sect.sct_own != sect.sct_oldown) + continue; + civ = getvar(V_CIVIL, (s_char *)§, EF_SECTOR); + if (number < 0){ + if ((deltamil = mil + number) <= 0) + continue; + } + else if ((deltamil = min(mil, number)) <= 0) + continue; + civ += deltamil; + mil -= deltamil; + mil_demob += deltamil; + if (!for_real) { + cost += deltamil * 5; + continue; + } + player->dolcost += deltamil * 5; + pr("%d demobilized in %s (%d mil left)\n", + deltamil, xyas(sect.sct_x, sect.sct_y, player->cnum), mil); + if (*p == 'y') + reserves += deltamil; + putvar(V_MILIT, mil, (s_char *)§, EF_SECTOR); + putvar(V_CIVIL, civ, (s_char *)§, EF_SECTOR); + putsect(§); + } + if (!for_real) + return cost; + if (!mil_demob) { + pr("No eligible sectors/military for demobilization\n"); + return (long)RET_FAIL; + } + pr("Total new civilians : %d\n", mil_demob); + if (*p == 'y') + pr("Military reserve stands at %d (up %d)\n", + natp->nat_reserve + reserves, reserves); + if (reserves > 0) { + natp->nat_reserve += reserves; + putnat(natp); + } + return RET_OK; +} diff --git a/src/lib/commands/desi.c b/src/lib/commands/desi.c new file mode 100644 index 00000000..1e03db67 --- /dev/null +++ b/src/lib/commands/desi.c @@ -0,0 +1,239 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * desi.c: Redesignate sectors + * + * Known contributors to this file: + * Steve McClure, 1998-2000 + */ + +#include "misc.h" +#include "player.h" +#include "var.h" +#include "sect.h" +#include "item.h" +#include "xy.h" +#include "path.h" +#include "nsc.h" +#include "deity.h" +#include "file.h" +#include "nat.h" +#include "optlist.h" +#include "commands.h" + +long do_desi(struct natstr *natp, s_char *sects, s_char *deschar, long int cash, int for_real); + +int +desi(void) +{ + long cash; + long cost; + struct natstr *natp; + + natp = getnatp(player->cnum); + cash = natp->nat_money; + if (player->argp[2]) { + cost = do_desi(natp, player->argp[1], player->argp[2], cash, 0); + if (cost < 0) + return (int)(-cost); + if (chkmoney(cost, cash, player->argp[3])) + return RET_SYN; + } + return (int)do_desi(natp, player->argp[1], player->argp[2], cash, 1); +} + +long +do_desi(struct natstr *natp, s_char *sects, s_char *deschar, long int cash, int for_real) +{ + extern int opt_NO_LCMS; + extern int opt_NO_HCMS; + register int n; + s_char *p; + int breaksanct; + int cap_x; + int cap_y; + int des; + struct nstr_sect nstr; + struct sctstr sect; + struct sctstr check; + s_char prompt[128]; + s_char buf[1024]; + long cost = 0; + int changed = 0; + int warned = 0; + + breaksanct = 0; + if (!snxtsct(&nstr, sects)) { + if (for_real) + return (long)RET_SYN; + else + return (long)-RET_SYN; + } + cap_x = natp->nat_xcap; + cap_y = natp->nat_ycap; + while (!player->aborted && nxtsct(&nstr, §)) { + if (!player->owner) + continue; + if (!player->god) { + if (sect.sct_type == SCT_MOUNT || + sect.sct_type == SCT_BTOWER || + sect.sct_type == SCT_BSPAN || + sect.sct_type == SCT_WASTE || + sect.sct_type == SCT_PLAINS || + (opt_NO_LCMS && sect.sct_type == SCT_LIGHT) || + (opt_NO_HCMS && sect.sct_type == SCT_HEAVY) || + (opt_NO_OIL && sect.sct_type == SCT_OIL) || + (opt_NO_OIL && sect.sct_type == SCT_REFINE)) + continue; + } + sprintf(prompt, "%s %d%% %s desig? ", + xyas(sect.sct_x, sect.sct_y, player->cnum), + sect.sct_effic, dchr[sect.sct_type].d_name); + if ((p = getstarg(deschar, prompt, buf)) == 0) + continue; + + if (!check_sect_ok(§)) + continue; + + des = typematch(p, EF_SECTOR); + if (des < 0 || (((des == SCT_BSPAN) || (des == SCT_BTOWER)) && + !player->god)) { + pr("See \"info Sector-types\"\n"); + if (for_real) + return (long)RET_FAIL; + else + return (long)-RET_FAIL; + } + if (!player->god) { + if (des == SCT_WATER || des == SCT_MOUNT || + des == SCT_SANCT || des == SCT_PLAINS || + (opt_NO_LCMS && des == SCT_LIGHT) || + (opt_NO_HCMS && des == SCT_HEAVY) || + (opt_NO_OIL && des == SCT_OIL) || + (opt_NO_OIL && des == SCT_REFINE)) { + pr("Only %s can make a %s!\n", cname(0), + dchr[des].d_name); + continue; + } + if (des == SCT_WASTE) { + pr("Only a nuclear device (or %s) can make a %s!\n", + cname(0), dchr[des].d_name); + continue; + } + } + if (sect.sct_type == des && sect.sct_newtype == des) + continue; + if (sect.sct_type == SCT_SANCT) + breaksanct++; + if (sect.sct_x == cap_x && sect.sct_y == cap_y && + des != SCT_CAPIT && des != SCT_SANCT && + des != SCT_MOUNT && for_real) + pr("You have redesignated your capital!\n"); + if (des == SCT_HARBR) { + for (n = 1; n <= 6; n++) { + getsect(nstr.x + diroff[n][0], + nstr.y + diroff[n][1], &check); + if (check.sct_type == SCT_WATER) + break; + if (check.sct_type == SCT_BSPAN) + break; + if (check.sct_type == SCT_BTOWER) + break; + } + if (n > 6) { + if (for_real) + pr("%s does not border on water.\n", + xyas(nstr.x, nstr.y, player->cnum)); + if (player->god) { + if (for_real) + pr("But if it's what you want ...\n"); + } else + continue; + } + } + if (des == SCT_BHEAD) { + for (n = 1; n <= 6; n++) { + getsect(nstr.x + diroff[n][0], + nstr.y + diroff[n][1], &check); + if (check.sct_type == SCT_WATER) + break; + if (check.sct_type == SCT_BSPAN) + break; + if (check.sct_type == SCT_BTOWER) + break; + } + if (n > 6) { + if (for_real) + pr("%s does not border on water.\n", + xyas(nstr.x, nstr.y,player->cnum)); + if (player->god) { + if (for_real) + pr("But if it's what you want...\n"); + } else + continue; + } + } + if (sect.sct_type == SCT_SANCT && !player->god) + continue; + n = sect.sct_type; + if ((sect.sct_newtype != des) && (sect.sct_type != des) && dchr[des].d_cost) { + if (for_real) { + if (check_cost(!deschar, dchr[des].d_cost, cash, &warned, player->argp[3])) + break; + } else { + cost += dchr[des].d_cost; + continue; + } + } + if (sect.sct_effic < 5 || player->god) { + sect.sct_type = des; + sect.sct_effic = 0; + /* No longer tear down infrasturcture + sect.sct_road = 0; + sect.sct_defense = 0; + */ + changed += map_set(player->cnum, sect.sct_x, sect.sct_y, + dchr[des].d_mnem, 0); + } + sect.sct_newtype = des; + putsect(§); + if (opt_EASY_BRIDGES == 0) { /* may cause a bridge fall */ + if (n != SCT_BHEAD) + continue; + bridgefall(§, 0); + } + } + if (for_real) { + if (changed) + writemap(player->cnum); + if (breaksanct) + bsanct(); + return (long)RET_OK; + } else { + return cost; + } +} diff --git a/src/lib/commands/disa.c b/src/lib/commands/disa.c new file mode 100644 index 00000000..a711a7ca --- /dev/null +++ b/src/lib/commands/disa.c @@ -0,0 +1,49 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * disa.c: Disable updates (deity) + * + * Known contributors to this file: + * + */ + +#include +#include "misc.h" +#include "commands.h" + +int +disa(void) +{ + extern s_char *disablefil; + int fd; + + if ((fd = open(disablefil, O_RDWR|O_CREAT|O_TRUNC, 0660)) < 0) + return RET_FAIL; + close(fd); + pr("Updates are disabled\n"); + return RET_OK; +} diff --git a/src/lib/commands/diss.c b/src/lib/commands/diss.c new file mode 100644 index 00000000..4736d156 --- /dev/null +++ b/src/lib/commands/diss.c @@ -0,0 +1,265 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * diss.c: Dissolve + * + * Known contributors to this file: + * + */ + +#include "misc.h" +#include "player.h" +#include "var.h" +#include "sect.h" +#include "ship.h" +#include "plane.h" +#include "land.h" +#include "nat.h" +#include "loan.h" +#include "treaty.h" +#include "news.h" +#include "file.h" +#include "xy.h" +#include "nsc.h" +#include "tel.h" +#include "nuke.h" +#include "trade.h" +#include "commands.h" + +int +diss(void) +{ + int quit(void); + struct sctstr sect; + struct lndstr land; + struct shpstr ship; + struct plnstr plane; + struct trtstr treaty; + struct trdstr trade; + struct lonstr loan; + struct nstr_item ni; + struct nstr_sect ns; + int sctnum; + int damage; + int annoyed; + int n; + s_char *p; + natid cn; + float dummy; + int val; + s_char buf[1024]; + struct natstr *np; + + if (player->cnum == 0) { + /* Dissolve the Deity??? */ + /* Probably someone broke in. */ + /* Send a tele to deity, and abort the session. */ + wu(0, 0, "Diety dissolve attempted! Session was aborted.\n"); + quit(); + } + if (player->argp[1]) + *player->argp[1] = 0; + p = getstarg(player->argp[1], "Are you SURE you want to do this? (n) ", buf); + if (p == 0 || *p != 'y') + return RET_SYN; + pr("\nIf you want some problem fixed and hope to force the issue\n"); + pr("by dissolving, DON'T DO IT. Even if an earlier version of\n"); + pr("this game is brought up, YOU WILL BE GONE.\n"); + pr("Forcing the issue makes it less likely that it will be\n"); + pr("resolved the way you wish it.\n\n"); + pr("Be part of the solution, not part of the problem.\n\n"); + pr("If this is a test game, dissolving will not help the test.\n\n"); + pr("If you are down to 0 sectors, and a 25% fishing vessel with\n"); + pr("1 mil on it, well, I can see your point. Go ahead.\n\n"); + pr("But at least pay back your loans, if you can.\n\n"); + + if (player->argp[1]) + *player->argp[1] = 0; + p = getstarg(player->argp[1], "Once again, are you SURE you want to do this? (n) ", buf); + if (p == 0 || *p != 'y') + return RET_SYN; + + np = getnatp(player->cnum); + np->nat_stat = VIS; + snxtsct_all(&ns); + sctnum = 0; + while (nxtsct(&ns, §)) { + if (!player->owner) + continue; + annoyed = 75 - (random() % (sect.sct_loyal+40)); + if (annoyed <= 0 || sect.sct_oldown != sect.sct_own) { + pr("Populace celebrates in %s\n", + xyas(sect.sct_x, sect.sct_y, player->cnum)); + if (sect.sct_oldown != sect.sct_own) { + makelost(EF_SECTOR, sect.sct_own, 0, sect.sct_x, sect.sct_y); + makenotlost(EF_SECTOR, sect.sct_oldown, 0, sect.sct_x, sect.sct_y); + sect.sct_own = sect.sct_oldown; + if(sect.sct_own != 0) + wu(0, sect.sct_own, + "%s reverts back to you!\n", + xyas(sect.sct_x, sect.sct_y, + sect.sct_own)); + } + } else if (annoyed < 25) { + pr("Populace unmoved in %s\n", + xyas(sect.sct_x, sect.sct_y, player->cnum)); + makelost(EF_SECTOR, sect.sct_own, 0, sect.sct_x, sect.sct_y); + sect.sct_own = 0; + sect.sct_oldown = 0; + } else { + pr("Rioting breaks out in %s\n", + xyas(sect.sct_x, sect.sct_y, player->cnum)); + sectdamage(§, annoyed, 0); + sctnum++; + makelost(EF_SECTOR, sect.sct_own, 0, sect.sct_x, sect.sct_y); + sect.sct_own = 0; + sect.sct_oldown = 0; + } + putsect(§); + } + snxtitem_all(&ni, EF_LAND); + while (nxtitem(&ni, (s_char *)&land)) { + if (!player->owner) + continue; + + pr("%s disbands!\n", prland(&land)); + land.lnd_effic = 0; + putland(land.lnd_uid, &land); + } + snxtitem_all(&ni, EF_SHIP); + while (nxtitem(&ni, (s_char *)&ship)) { + if (!player->owner) + continue; + pr("%s ", prship(&ship)); + switch (random() % 3) { + case 0: + pr("scuttled!\n"); + ship.shp_effic = 0; + break; + case 1: + pr("abandoned!\n"); + putvar(V_MILIT, 0, (s_char *)&ship, EF_SHIP); + putvar(V_CIVIL, 0, (s_char *)&ship, EF_SHIP); + putvar(V_UW, 0, (s_char *)&ship, EF_SHIP); + break; + case 2: + default: + damage = (random() % 80) + 10; + pr("crew has rioted! (%d damage)\n", damage); + shipdamage(&ship, damage); + sctnum++; + break; + } + putship(ship.shp_uid, &ship); + } + snxtitem_all(&ni, EF_PLANE); + while (nxtitem(&ni, (s_char *)&plane)) { + if (!player->owner) + continue; + pr("%s ", prplane(&plane)); + switch (random() % 2) { + case 0: + pr("blown up!\n"); + plane.pln_effic = 0; + break; + case 1: + default: + damage = (random() % 80) + 10; + pr("crew has rioted! (%d damage)\n", damage); + planedamage(&plane, damage); + sctnum++; + break; + } + putplane(plane.pln_uid, &plane); + } + snxtitem_all(&ni, EF_TREATY); + while (nxtitem(&ni, (s_char *)&treaty)) { + if (treaty.trt_status == TS_FREE) + continue; + if (treaty.trt_cna != player->cnum && + treaty.trt_cnb != player->cnum) + continue; + cn = treaty.trt_cna == player->cnum ? treaty.trt_cnb : treaty.trt_cna; + pr("No more treaty with %s\n", cname(cn)); + wu(0, cn, "Treaty #%d with %s voided\n", + ni.cur, cname(player->cnum)); + treaty.trt_status = TS_FREE; + puttre(ni.cur, &treaty); + } + snxtitem_all(&ni, EF_LOAN); + while (nxtitem(&ni, (s_char *)&loan)) { + if (loan.l_status == LS_FREE) + continue; + if (loan.l_loner != player->cnum && loan.l_lonee != player->cnum) + continue; + if (loan.l_loner == player->cnum) { + pr("Loan #%d to %s will never be repaid\n", + ni.cur, cname(loan.l_lonee)); + wu(0, loan.l_lonee, + "Loan #%d from %s has been voided\n", + ni.cur, cname(player->cnum)); + } else { + pr("Loan #%d from %s will never be repaid\n", + ni.cur, cname(loan.l_lonee)); + wu(0, loan.l_loner, + "Loan #%d to %s has been voided\n", + ni.cur, cname(player->cnum)); + } + loan.l_status = LS_FREE; + putloan(ni.cur, &loan); + } + /* clean up commodity and trade for this nation. */ + commlock(); + commread(); + for (n=1; ncnum, n, &dummy); + commset(player->cnum, n, -val); + } + commwrite(); + communlock(); + snxtitem_all(&ni, EF_TRADE); + while (nxtitem(&ni, (s_char *)&trade)) { + if (trade.trd_unitid >= 0 && trade.trd_owner == player->cnum) { + trade.trd_unitid = -1; + (void) puttrade(ni.cur, &trade); + } + } + while (sctnum > 0) { + n = sctnum > 127 ? 127 : sctnum; + nreport(player->cnum, N_RIOT, 0, n); + sctnum -= n; + } + filetruncate(mailbox(buf, player->cnum)); + np->nat_stat = STAT_INUSE; + np->nat_btu = 0; + player->nstat = VIS; + wu(0, 0, "Country #%d (%s) has dissolved\n", + player->cnum, cname(player->cnum)); + nreport(player->cnum, N_DISS_GOV, 0, 1); + putnat(np); + return RET_OK; +} diff --git a/src/lib/commands/dist.c b/src/lib/commands/dist.c new file mode 100644 index 00000000..e751245c --- /dev/null +++ b/src/lib/commands/dist.c @@ -0,0 +1,136 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * dist.c: Name distribution sector for a given range of sectors + * + * Known contributors to this file: + * Dave Pare, 1986 + * Thomas Ruschak, 1993 (rewritten) + * Steve McClure, 1998 + */ + +#include "misc.h" +#include "player.h" +#include "var.h" +#include "xy.h" +#include "sect.h" +#include "nsc.h" +#include "nat.h" +#include "file.h" +#include "path.h" +#include "commands.h" + +/* + * distribute + */ +int +dist(void) +{ + struct sctstr sect, dsect, tsect; + struct nstr_sect nstr; + s_char *path, *p; + double move_cost=0.0; + coord dstx, dsty; + s_char buf[1024]; + + if (!snxtsct(&nstr, player->argp[1])) + return RET_SYN; + while (!player->aborted && nxtsct(&nstr, §)) { + if (!player->owner) + continue; + pr("%s at %s ", dchr[sect.sct_type].d_name, + xyas(nstr.x, nstr.y, player->cnum)); + if ((sect.sct_dist_x != sect.sct_x) || + (sect.sct_dist_y != sect.sct_y)) { + getsect(sect.sct_dist_x, sect.sct_dist_y, &tsect); + if (tsect.sct_own != player->cnum) + pr("distributes to %s, not owned by you.\n", + xyas(tsect.sct_x, tsect.sct_y, player->cnum)); + else + pr("distributes to %s. \n", + xyas(tsect.sct_x, tsect.sct_y, player->cnum)); + } else + pr("has no dist sector. \n"); + p = getstarg(player->argp[2], "Distribution sector? ", buf); + if (p && (*p == 0)) + continue; + + if (!check_sect_ok(§)) + continue; + + if (p && (*p != '.') && (*p != 'h') && + (!sarg_xy(p, &dstx, &dsty))) + return RET_SYN; + + if (p && ((*p == '.') || (*p == 'h'))){ + dstx = sect.sct_x; + dsty = sect.sct_y; + } + + if (!getsect(dstx,dsty,&dsect)){ + pr("Bad sector.\n"); + return RET_FAIL; + } + + if (dsect.sct_own != player->cnum) + pr("Warning: you don't own %s!\n", + xyas(dsect.sct_x,dsect.sct_y,player->cnum)); + + path = BestDistPath(buf, §,&dsect,&move_cost,MOB_ROAD); + + if (path == (s_char *)0){ + pr("No owned path from %s to %s.\n", + xyas(dsect.sct_x,dsect.sct_y,player->cnum), + xyas(sect.sct_x,sect.sct_y,player->cnum)); + continue; + } + + if ((dsect.sct_x == sect.sct_x) && + (dsect.sct_y == sect.sct_y)) { + pr("Distribution from and to %s %s terminated\n", + dchr[sect.sct_type].d_name, + xyas(sect.sct_x, sect.sct_y, player->cnum)); + } else { + pr("%s %s now distributes to %s (cost %1.3f)\n", + dchr[sect.sct_type].d_name, + xyas(sect.sct_x, sect.sct_y, player->cnum), + xyas(dsect.sct_x, dsect.sct_y, player->cnum), + move_cost); + } + pr("\n"); + /* Only change and write out if we are really changing where it + distributes to. Otherwise, it's a waste of time (since nothing + changed.) */ + if ((sect.sct_dist_x != dsect.sct_x) || + (sect.sct_dist_y != dsect.sct_y)) { + sect.sct_dist_x = dsect.sct_x; + sect.sct_dist_y = dsect.sct_y; + putsect(§); + } + } + return RET_OK; +} diff --git a/src/lib/commands/drop.c b/src/lib/commands/drop.c new file mode 100644 index 00000000..41236005 --- /dev/null +++ b/src/lib/commands/drop.c @@ -0,0 +1,152 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * drop.c: Air-drop commodities + * + * Known contributors to this file: + * Dave Pare, 1986 + */ + +#include "misc.h" +#include "player.h" +#include "var.h" +#include "sect.h" +#include "ship.h" +#include "item.h" +#include "plane.h" +#include "nuke.h" +#include "xy.h" +#include "nsc.h" +#include "news.h" +#include "file.h" +#include "nat.h" +#include "path.h" +#include "commands.h" + +int +drop(void) +{ + int rel; + s_char *p; + int mission_flags; + int tech; + coord tx, ty; + coord ax, ay; + int ap_to_target; + struct ichrstr *ip; + s_char flightpath[MAX_PATH_LEN]; + struct nstr_item ni_bomb; + struct nstr_item ni_esc; + coord x, y; + struct sctstr target; + struct emp_qelem bomb_list; + struct emp_qelem esc_list; + int wantflags; + struct sctstr ap_sect; + s_char buf[1024]; + + wantflags = 0; + if (!snxtitem(&ni_bomb, EF_PLANE, player->argp[1])) + return RET_SYN; + if (!snxtitem(&ni_esc, EF_PLANE, getstarg(player->argp[2], "escort(s)? ", buf))) + pr("No escorts...\n"); + if ((p = getstarg(player->argp[3], "assembly point? ", buf)) == 0 || *p == 0) + return RET_SYN; + if (!sarg_xy(p, &x, &y) || !getsect(x, y, &ap_sect)) + return RET_SYN; + if (ap_sect.sct_own && ap_sect.sct_own != player->cnum && + getrel(getnatp(ap_sect.sct_own), player->cnum) != ALLIED) { + pr("Assembly point not owned by you or an ally!\n"); + return RET_SYN; + } + ax = x; + ay = y; + if (getpath(flightpath, player->argp[4], ax, ay, 0, 0, + 0, P_FLYING) == 0 || *flightpath == 0) + return RET_SYN; + tx = ax; + ty = ay; + (void) pathtoxy(flightpath, &tx, &ty, fcost); + pr("target is %s\n", xyas(tx, ty, player->cnum)); + getsect(tx, ty, &target); + + rel = getrel(getnatp(target.sct_own), player->cnum); + if (rel != ALLIED && target.sct_own != player->cnum && target.sct_type != SCT_WATER) { + pr("You don't own %s!\n", xyas(tx,ty,player->cnum)); + return RET_FAIL; + } + + if ((ip = whatitem(player->argp[5], "Drop off what? ")) == 0) + return RET_SYN; + if (ip->i_vtype == V_CIVIL && target.sct_own != target.sct_oldown) { + pr("Can't drop civilians into occupied sectors.\n"); + return RET_FAIL; + } + ap_to_target = strlen(flightpath); + if (*(flightpath+strlen(flightpath)-1) == 'h') + ap_to_target--; + pr("range to target is %d\n", ap_to_target); + /* + * select planes within range + */ + mission_flags = 0; + pln_sel(&ni_bomb, &bomb_list, &ap_sect, ap_to_target, + 2, wantflags, P_M|P_O); + pln_sel(&ni_esc, &esc_list, &ap_sect, ap_to_target, + 2, P_ESC|P_F, P_M|P_O); + /* + * now arm and equip the bombers, transports, whatever. + * tech is stored in high 16 bits of mission_flags. + * yuck. + */ + tech=0; + mission_flags |= P_X; /* stealth (shhh) */ + mission_flags |= P_H; /* gets turned off if not all choppers */ + mission_flags |= P_MINE; + mission_flags = pln_arm(&bomb_list, 2*ap_to_target, 'd', ip, 0, mission_flags,&tech); + if (rel != ALLIED && target.sct_own != player->cnum && + target.sct_type == SCT_WATER && !(mission_flags & P_MINE)) { + pr("You don't own %s!\n", xyas(tx,ty,player->cnum)); + return RET_FAIL; + } + if (QEMPTY(&bomb_list)) { + pr("No planes could be equipped for the mission.\n"); + return RET_FAIL; + } + mission_flags = pln_arm(&esc_list, 2*ap_to_target, 'd', ip, P_ESC|P_F, mission_flags,&tech); + ac_encounter(&bomb_list,&esc_list,ax,ay,flightpath,mission_flags,0,0,0); + if (QEMPTY(&bomb_list)) { + pr("No planes got through fighter defenses\n"); + } else { + getsect(tx, ty, &target); + pln_dropoff(&bomb_list, ip, tx, ty, (s_char *)&target, + EF_SECTOR); + } + pln_put(&bomb_list); + pln_put(&esc_list); + return RET_OK; +} diff --git a/src/lib/commands/dump.c b/src/lib/commands/dump.c new file mode 100644 index 00000000..c1890cae --- /dev/null +++ b/src/lib/commands/dump.c @@ -0,0 +1,474 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * dump.c: Dump sector information + * + * Known contributors to this file: + * Jeff Wallace, 1989 + * Steve McClure, 1997 (added timestamping) + */ + +#include "misc.h" +#include "player.h" +#include "var.h" +#include "xy.h" +#include "sect.h" +#include "nsc.h" +#include "nat.h" +#include "deity.h" +#include "path.h" +#include "file.h" +#include "commands.h" +#include "optlist.h" + +int +dump(void) +{ + struct sctstr sect; + s_char dirstr[20]; + int nsect; + int n,i; + struct nstr_sect nstr; + int del[I_MAX+1]; + int dist[I_MAX+1]; + int item[I_MAX+1]; + int cond[I_MAX+1]; + int field[128]; + struct natstr *np; + time_t now; + + if (!snxtsct(&nstr, player->argp[1])) + return RET_SYN; + prdate(); + (void) strcpy(dirstr, ". $"); + n = 1; + for (n = 1; n <= 6; n++) + dirstr[n] = dirch[n]; + nsect = 0; + np = getnatp(player->cnum); + + if (!player->argp[2]) { + for (n = 1; n <= 80; n++) field[n-1] = n; + field[n-1] = 0; + } else { + n = 2; + i = 0; + while (player->argp[n]) { + if (!strcmp("des",player->argp[n])) { + field[i++] = 1; + } else if (!strcmp("sdes",player->argp[n])) { + field[i++] = 2; + } else if (!strcmp("eff",player->argp[n])) { + field[i++] = 3; + } else if (!strcmp("mob",player->argp[n])) { + field[i++] = 4; + } else if (!strcmp("*",player->argp[n])) { + field[i++] = 5; + } else if (!strcmp("off",player->argp[n])) { + field[i++] = 6; + } else if (!strcmp("min",player->argp[n])) { + field[i++] = 7; + } else if (!strcmp("gold",player->argp[n])) { + field[i++] = 8; + } else if (!strcmp("fert",player->argp[n])) { + field[i++] = 9; + } else if (!strcmp("ocontent",player->argp[n])) { + field[i++] = 10; + } else if (!strcmp("uran",player->argp[n])) { + field[i++] = 11; + } else if (!strcmp("work",player->argp[n])) { + field[i++] = 12; + } else if (!strcmp("avail",player->argp[n])) { + field[i++] = 13; + } else if (!strcmp("terr",player->argp[n])) { + field[i++] = 14; + } else if (!strcmp("civ",player->argp[n])) { + field[i++] = 15; + } else if (!strcmp("mil",player->argp[n])) { + field[i++] = 16; + } else if (!strcmp("uw",player->argp[n])) { + field[i++] = 17; + } else if (!strcmp("food",player->argp[n])) { + field[i++] = 18; + } else if (!strcmp("shell",player->argp[n])) { + field[i++] = 19; + } else if (!strcmp("gun",player->argp[n])) { + field[i++] = 20; + } else if (!strcmp("pet",player->argp[n])) { + field[i++] = 21; + } else if (!strcmp("iron",player->argp[n])) { + field[i++] = 22; + } else if (!strcmp("dust",player->argp[n])) { + field[i++] = 23; + } else if (!strcmp("bar",player->argp[n])) { + field[i++] = 24; + } else if (!strcmp("oil",player->argp[n])) { + field[i++] = 25; + } else if (!strcmp("lcm",player->argp[n])) { + field[i++] = 26; + } else if (!strcmp("hcm",player->argp[n])) { + field[i++] = 27; + } else if (!strcmp("rad",player->argp[n])) { + field[i++] = 28; + } else if (!strcmp("u_del",player->argp[n])) { + field[i++] = 29; + } else if (!strcmp("f_del",player->argp[n])) { + field[i++] = 30; + } else if (!strcmp("s_del",player->argp[n])) { + field[i++] = 31; + } else if (!strcmp("g_del",player->argp[n])) { + field[i++] = 32; + } else if (!strcmp("p_del",player->argp[n])) { + field[i++] = 33; + } else if (!strcmp("i_del",player->argp[n])) { + field[i++] = 34; + } else if (!strcmp("d_del",player->argp[n])) { + field[i++] = 35; + } else if (!strcmp("b_del",player->argp[n])) { + field[i++] = 36; + } else if (!strcmp("o_del",player->argp[n])) { + field[i++] = 37; + } else if (!strcmp("l_del",player->argp[n])) { + field[i++] = 38; + } else if (!strcmp("h_del",player->argp[n])) { + field[i++] = 39; + } else if (!strcmp("r_del",player->argp[n])) { + field[i++] = 40; + } else if (!strcmp("u_cut",player->argp[n])) { + field[i++] = 41; + } else if (!strcmp("f_cut",player->argp[n])) { + field[i++] = 42; + } else if (!strcmp("s_cut",player->argp[n])) { + field[i++] = 43; + } else if (!strcmp("g_cut",player->argp[n])) { + field[i++] = 44; + } else if (!strcmp("p_cut",player->argp[n])) { + field[i++] = 45; + } else if (!strcmp("i_cut",player->argp[n])) { + field[i++] = 46; + } else if (!strcmp("d_cut",player->argp[n])) { + field[i++] = 47; + } else if (!strcmp("b_cut",player->argp[n])) { + field[i++] = 48; + } else if (!strcmp("o_cut",player->argp[n])) { + field[i++] = 49; + } else if (!strcmp("l_cut",player->argp[n])) { + field[i++] = 50; + } else if (!strcmp("h_cut",player->argp[n])) { + field[i++] = 51; + } else if (!strcmp("r_cut",player->argp[n])) { + field[i++] = 52; + } else if (!strcmp("dist_x",player->argp[n])) { + field[i++] = 53; + } else if (!strcmp("dist_y",player->argp[n])) { + field[i++] = 54; + } else if (!strcmp("c_dist",player->argp[n])) { + field[i++] = 55; + } else if (!strcmp("m_dist",player->argp[n])) { + field[i++] = 56; + } else if (!strcmp("u_dist",player->argp[n])) { + field[i++] = 57; + } else if (!strcmp("f_dist",player->argp[n])) { + field[i++] = 58; + } else if (!strcmp("s_dist",player->argp[n])) { + field[i++] = 59; + } else if (!strcmp("g_dist",player->argp[n])) { + field[i++] = 60; + } else if (!strcmp("p_dist",player->argp[n])) { + field[i++] = 61; + } else if (!strcmp("i_dist",player->argp[n])) { + field[i++] = 62; + } else if (!strcmp("d_dist",player->argp[n])) { + field[i++] = 63; + } else if (!strcmp("b_dist",player->argp[n])) { + field[i++] = 64; + } else if (!strcmp("o_dist",player->argp[n])) { + field[i++] = 65; + } else if (!strcmp("l_dist",player->argp[n])) { + field[i++] = 66; + } else if (!strcmp("h_dist",player->argp[n])) { + field[i++] = 67; + } else if (!strcmp("r_dist",player->argp[n])) { + field[i++] = 68; + } else if (!strcmp("road",player->argp[n])) { + field[i++] = 69; + } else if (!strcmp("rail",player->argp[n])) { + field[i++] = 70; + } else if (!strcmp("defense",player->argp[n])) { + field[i++] = 71; + } else if (!strcmp("fallout",player->argp[n])) { + field[i++] = 72; + } else if (!strcmp("coast",player->argp[n])) { + field[i++] = 73; + } else if (!strcmp("c_del",player->argp[n])) { + field[i++] = 74; + } else if (!strcmp("m_del",player->argp[n])) { + field[i++] = 75; + } else if (!strcmp("c_cut",player->argp[n])) { + field[i++] = 76; + } else if (!strcmp("m_cut",player->argp[n])) { + field[i++] = 77; + } else if (!strcmp("terr1",player->argp[n])) { + field[i++] = 78; + } else if (!strcmp("terr2",player->argp[n])) { + field[i++] = 79; + } else if (!strcmp("terr3",player->argp[n])) { + field[i++] = 80; + } else { + pr("Unrecognized field %s\n",player->argp[n]); + } + if (n++ > 100) { + pr("Too many fields\n"); + return RET_FAIL; + } + } + field[i] = 0; + } + + if (player->god) + pr(" "); + time(&now); + pr("DUMP SECTOR %d\n", now); + if (player->god) + pr("own "); + pr("x y"); + n = 0; + while (field[n]) { + pr(" "); + switch (field[n]) { + case 1: pr("des"); break; + case 2: pr("sdes"); break; + case 3: pr("eff"); break; + case 4: pr("mob"); break; + case 5: pr("*"); break; + case 6: pr("off"); break; + case 7: pr("min"); break; + case 8: pr("gold"); break; + case 9: pr("fert"); break; + case 10: pr("ocontent"); break; + case 11: pr("uran"); break; + case 12: pr("work"); break; + case 13: pr("avail"); break; + case 14: pr("terr"); break; + case 15: pr("civ"); break; + case 16: pr("mil"); break; + case 17: pr("uw"); break; + case 18: pr("food"); break; + case 19: pr("shell"); break; + case 20: pr("gun"); break; + case 21: pr("pet"); break; + case 22: pr("iron"); break; + case 23: pr("dust"); break; + case 24: pr("bar"); break; + case 25: pr("oil"); break; + case 26: pr("lcm"); break; + case 27: pr("hcm"); break; + case 28: pr("rad"); break; + case 29: pr("u_del"); break; + case 30: pr("f_del"); break; + case 31: pr("s_del"); break; + case 32: pr("g_del"); break; + case 33: pr("p_del"); break; + case 34: pr("i_del"); break; + case 35: pr("d_del"); break; + case 36: pr("b_del"); break; + case 37: pr("o_del"); break; + case 38: pr("l_del"); break; + case 39: pr("h_del"); break; + case 40: pr("r_del"); break; + case 41: pr("u_cut"); break; + case 42: pr("f_cut"); break; + case 43: pr("s_cut"); break; + case 44: pr("g_cut"); break; + case 45: pr("p_cut"); break; + case 46: pr("i_cut"); break; + case 47: pr("d_cut"); break; + case 48: pr("b_cut"); break; + case 49: pr("o_cut"); break; + case 50: pr("l_cut"); break; + case 51: pr("h_cut"); break; + case 52: pr("r_cut"); break; + case 53: pr("dist_x"); break; + case 54: pr("dist_y"); break; + case 55: pr("c_dist"); break; + case 56: pr("m_dist"); break; + case 57: pr("u_dist"); break; + case 58: pr("f_dist"); break; + case 59: pr("s_dist"); break; + case 60: pr("g_dist"); break; + case 61: pr("p_dist"); break; + case 62: pr("i_dist"); break; + case 63: pr("d_dist"); break; + case 64: pr("b_dist"); break; + case 65: pr("o_dist"); break; + case 66: pr("l_dist"); break; + case 67: pr("h_dist"); break; + case 68: pr("r_dist"); break; + case 69: pr("road"); break; + case 70: pr("rail"); break; + case 71: pr("defense"); break; + case 72: pr("fallout"); break; + case 73: pr("coast"); break; + case 74: pr("c_del"); break; + case 75: pr("m_del"); break; + case 76: pr("c_cut"); break; + case 77: pr("m_cut"); break; + case 78: pr("terr1"); break; + case 79: pr("terr2"); break; + case 80: pr("terr3"); break; + } + n++; + } + pr("\n"); + + while (nxtsct(&nstr, §)) { + if (!player->owner) + continue; + nsect++; + +/* census */ + if (player->god) + pr("%d ", sect.sct_own); + getvec(VT_DEL, del, (s_char *)§, EF_SECTOR); + getvec(VT_DIST, dist, (s_char *)§, EF_SECTOR); + getvec(VT_ITEM, item, (s_char *)§, EF_SECTOR); + getvec(VT_COND, cond, (s_char *)§, EF_SECTOR); + pr("%d %d", xrel(np,nstr.x), yrel(np,nstr.y)); + + set_coastal(§); + n = 0; + while (field[n]) { + pr(" "); + switch (field[n++]) { + case 1: pr("%c", dchr[sect.sct_type].d_mnem); break; + case 2: if (sect.sct_newtype != sect.sct_type) + pr("%c", dchr[sect.sct_newtype].d_mnem); + else + pr("_"); + break; + case 3: pr("%d", sect.sct_effic); break; + case 4: pr("%d", sect.sct_mobil); break; + case 5: pr("%c", sect.sct_own != sect.sct_oldown ? '*' : '.'); + break; + case 6: pr("%d", sect.sct_off); break; + case 7: pr("%d", sect.sct_min); break; + case 8: pr("%d", sect.sct_gmin); break; + case 9: pr("%d", sect.sct_fertil); break; + case 10: pr("%d", sect.sct_oil); break; + case 11: pr("%d", sect.sct_uran); break; + case 12: pr("%d", sect.sct_work); break; + case 13: pr("%d", sect.sct_avail); break; + case 14: pr("%d", sect.sct_terr); break; + case 15: pr("%d", item[I_CIVIL]); break; + case 16: pr("%d", item[I_MILIT]); break; + case 17: pr("%d", item[I_UW]); break; + case 18: pr("%d", item[I_FOOD]); break; +/* commodity */ + case 19: pr("%d", item[I_SHELL]); break; + case 20: pr("%d", item[I_GUN]); break; + case 21: pr("%d", item[I_PETROL]); break; + case 22: pr("%d", item[I_IRON]); break; + case 23: pr("%d", item[I_DUST]); break; + case 24: pr("%d", item[I_BAR]); break; + case 25: pr("%d", item[I_OIL]); break; + case 26: pr("%d", item[I_LCM]); break; + case 27: pr("%d", item[I_HCM]); break; + case 28: pr("%d", item[I_RAD]); break; +/* cutoff */ + case 29: pr("%c", dirstr[del[I_UW] & 0x7]); break; + case 30: pr("%c", dirstr[del[I_FOOD] & 0x7]); break; + case 31: pr("%c", dirstr[del[I_SHELL] & 0x7]); break; + case 32: pr("%c", dirstr[del[I_GUN] & 0x7]); break; + case 33: pr("%c", dirstr[del[I_PETROL] & 0x7]); break; + case 34: pr("%c", dirstr[del[I_IRON] & 0x7]); break; + case 35: pr("%c", dirstr[del[I_DUST] & 0x7]); break; + case 36: pr("%c", dirstr[del[I_BAR] & 0x7]); break; + case 37: pr("%c", dirstr[del[I_OIL] & 0x7]); break; + case 38: pr("%c", dirstr[del[I_LCM] & 0x7]); break; + case 39: pr("%c", dirstr[del[I_HCM] & 0x7]); break; + case 40: pr("%c", dirstr[del[I_RAD] & 0x7]); break; + case 41: pr("%d", del[I_UW] & ~0x7); break; + case 42: pr("%d", del[I_FOOD] & ~0x7); break; + case 43: pr("%d", del[I_SHELL] & ~0x7); break; + case 44: pr("%d", del[I_GUN] & ~0x7); break; + case 45: pr("%d", del[I_PETROL] & ~0x7); break; + case 46: pr("%d", del[I_IRON] & ~0x7); break; + case 47: pr("%d", del[I_DUST] & ~0x7); break; + case 48: pr("%d", del[I_BAR] & ~0x7); break; + case 49: pr("%d", del[I_OIL] & ~0x7); break; + case 50: pr("%d", del[I_LCM] & ~0x7); break; + case 51: pr("%d", del[I_HCM] & ~0x7); break; + case 52: pr("%d", del[I_RAD] & ~0x7); break; +/* level */ + case 53: pr("%d", xrel(getnatp(player->cnum),sect.sct_dist_x)); break; + case 54: pr("%d", yrel(getnatp(player->cnum),sect.sct_dist_y)); break; + case 55: pr("%d", dist[I_CIVIL]); break; + case 56: pr("%d", dist[I_MILIT]); break; + case 57: pr("%d", dist[I_UW]); break; + case 58: pr("%d", dist[I_FOOD]); break; + case 59: pr("%d", dist[I_SHELL]); break; + case 60: pr("%d", dist[I_GUN]); break; + case 61: pr("%d", dist[I_PETROL]); break; + case 62: pr("%d", dist[I_IRON]); break; + case 63: pr("%d", dist[I_DUST]); break; + case 64: pr("%d", dist[I_BAR]); break; + case 65: pr("%d", dist[I_OIL]); break; + case 66: pr("%d", dist[I_LCM]); break; + case 67: pr("%d", dist[I_HCM]); break; + case 68: pr("%d", dist[I_RAD]); break; + case 69: pr("%d", sect.sct_road); break; + case 70: pr("%d", sect.sct_rail); break; + case 71: pr("%d", sect.sct_defense); break; + case 72: + if (opt_FALLOUT) + pr("%d", cond[C_FALLOUT]); + else + pr("0"); + break; + case 73: pr("%d", sect.sct_coastal); break; + case 74: pr("%c", dirstr[del[I_CIVIL] & 0x7]); break; + case 75: pr("%c", dirstr[del[I_MILIT] & 0x7]); break; + case 76: pr("%d", del[I_CIVIL] & ~0x7); break; + case 77: pr("%d", del[I_MILIT] & ~0x7); break; + case 78: pr("%d", sect.sct_terr1); break; + case 79: pr("%d", sect.sct_terr2); break; + case 80: pr("%d", sect.sct_terr3); break; + } + } + pr("\n"); + } + if (nsect == 0) { + if (player->argp[1]) + pr("%s: No sector(s)\n", player->argp[1]); + else + pr("%s: No sector(s)\n", ""); + return RET_FAIL; + }else + pr("%d sector%s\n", nsect, splur(nsect)); + return RET_OK; +} + diff --git a/src/lib/commands/echo.c b/src/lib/commands/echo.c new file mode 100644 index 00000000..b0d58efa --- /dev/null +++ b/src/lib/commands/echo.c @@ -0,0 +1,44 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * echo.c: Just echo something + * + * Known contributors to this file: + * Ken Stevens, 1995 + */ + +#include "misc.h" +#include "player.h" +#include "commands.h" + +int +echo(void) +{ + pr("%s\n", player->argp[1]?player->argp[1]:(s_char *)""); + + return RET_OK; +} diff --git a/src/lib/commands/edit.c b/src/lib/commands/edit.c new file mode 100644 index 00000000..fc7292d5 --- /dev/null +++ b/src/lib/commands/edit.c @@ -0,0 +1,1176 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * edit.c: Edit things (sectors, ships, planes, units, nukes, countries) + * + * Known contributors to this file: + * David Muir Sharnoff + * Chad Zabel, 1994 + * Steve McClure, 1998-2000 + */ + +#include +#include +#ifdef Rel4 +#include +#endif /* Rel4 */ +#include "misc.h" +#include "player.h" +#include "var.h" +#include "xy.h" +#include "sect.h" +#include "nat.h" +#include "news.h" +#include "nsc.h" +#include "item.h" +#include "file.h" +#include "plane.h" +#include "ship.h" +#include "land.h" +#include "optlist.h" +#include "commands.h" + +#define END -1 +static void prnat(natid n); +static void pr_plane(struct plnstr *plane); +static void pr_land(struct lndstr *land); +static void pr_ship(struct shpstr *ship); +static void prsect(struct sctstr *sect); +static void noise(struct sctstr *sptr, int public_amt, s_char *name, int old, int new); +static void benefit(natid who, int good); +int doland(s_char op, int arg, struct sctstr *sect); +int docountry(s_char op, int arg, s_char *p, float farg, natid nat, struct natstr *np); +int doship(s_char op, int arg, s_char *p, struct shpstr *ship); +int dounit(s_char op, int arg, s_char *p, struct lndstr *land); +int doplane(s_char op, int arg, s_char *p, struct plnstr *plane); + + +/* + * format: give c + */ +int +edit(void) +{ + struct sctstr sect; + struct plnstr plane; + struct shpstr ship; + struct lndstr land; + s_char *what; + s_char *ptr; + s_char *thing; + int num; + int arg; + int err; + coord x, y; + float farg; + natid nat; + struct natstr *np; + s_char buf[1024]; + s_char ewhat; /* saves information from the command line + for use later on. */ + + if ((what = getstarg(player->argp[1], + "Edit What (country, land, ship, plane, nuke, unit)? ", buf)) == 0) + return RET_SYN; + ewhat = what[0]; + switch (ewhat) { + case 'l': + if (!(ptr = getstarg(player->argp[2], "Sector : ", buf))) + return RET_FAIL; + if (!sarg_xy(ptr, &x, &y)) + return RET_FAIL; + if (!getsect(x, y, §)) + return RET_FAIL; + break; + case 'c': + if ((num = natarg(player->argp[2], "Country number? ")) < 0) + return RET_SYN; + nat = (natid) num; + np = getnatp(nat); + break; + case 'p': + if ((num = onearg(player->argp[2], "Plane number? ")) < 0) + return RET_SYN; + if (!getplane(num, &plane)) + return RET_SYN; + break; + case 's': + if ((num = onearg(player->argp[2], "Ship number? ")) < 0) + return RET_SYN; + if (!getship(num, &ship)) + return RET_SYN; + break; + case 'u': + if ((num = onearg(player->argp[2], "Unit number? ")) < 0) + return RET_SYN; + if (!getland(num, &land)) + return RET_SYN; + break; + case 'n': + pr("Not implemented yet.\n"); + break; + default: + pr("huh?\n"); + return RET_SYN; + } + if (player->argp[3] == 0) { + switch (ewhat) { + case 'l': + prsect(§); + break; + case 'c': + prnat(nat); + break; + case 'p': + pr_plane(&plane); + break; + case 's': + pr_ship(&ship); + break; + case 'u': + pr_land(&land); + break; + } + } else if (player->argp[4] != 0) + (void) strcat (player->argp[3], player->argp[4]); + ptr = &buf[0]; + *ptr = 0; + for (;;) { + if ((err = getin(&thing, &ptr, &arg, buf)) != RET_OK) { + if (err == END) { + switch (ewhat) { + case 'c': + prnat(nat); + break; + case 'l': + prsect(§); + break; + case 's': + pr_ship(&ship); + break; + case 'u': + pr_land(&land); + break; + case 'p': + pr_plane(&plane); + break; + } + break; + } else + return err; + } + switch (ewhat) { + case 'c': + farg = atof(ptr); + if ((err = docountry(thing[0], arg, ptr, farg, nat, np)) + != RET_OK) + return err; + break; + case 'l': + if ((err = doland(thing[0], arg, §)) != RET_OK) + return err; + if (!putsect(§)) + return RET_FAIL; + break; + case 's': + if ((err = doship(thing[0], arg, ptr, &ship)) != RET_OK) + return err; + if (!putship(ship.shp_uid, &ship)) + return RET_FAIL; + break; + case 'u': + farg = atof(ptr); + if ((err = dounit(thing[0], arg, ptr, &land)) + != RET_OK) + return err; + if (!putland(land.lnd_uid, &land)) + return RET_FAIL; + break; + case 'p': + if ((err = doplane(thing[0], arg, ptr, &plane)) + != RET_OK) + return err; + if (!putplane(plane.pln_uid, &plane)) + return RET_FAIL; + break; + } + if (err != RET_OK) + break; + else + ptr = 0; + } + return RET_OK; +} + +static void +benefit(natid who, int good) +{ + if (!opt_GODNEWS) + return; + + if (good) { + if (who) + nreport(player->cnum, N_AIDS, who, 1); + } else { + if (who) + nreport(player->cnum, N_HURTS, who, 1); + } +} + +static void +noise(struct sctstr *sptr, int public_amt, s_char *name, int old, int new) +{ + s_char p[100]; + + pr("%s of %s changed from %d to %d\n", + name, xyas(sptr->sct_x, sptr->sct_y, player->cnum), old, new); + if (public_amt) + (void) sprintf(p, "changed from %d to %d", old, new); + else + (void) sprintf(p, "%s", (oldsct_own) + wu(player->cnum, sptr->sct_own, + "%s in %s was %s by an act of %s\n", + name, xyas(sptr->sct_x, sptr->sct_y, sptr->sct_own), + p, cname(player->cnum)); + benefit(sptr->sct_own, (old < new)); +} + +static void +prsect(struct sctstr *sect) +{ + pr("X coord : %d\t",sect->sct_x); + pr("Y coord : %d\n",sect->sct_y); + pr("X dist coord: %d\t",sect->sct_dist_x); + pr("Y dist coord: %d\n",sect->sct_dist_y); + pr(" sect own oo eff mob min gld frt oil urn wrk lty che plg ptime fall avail\n"); + pr("things: o O e m i g f c u w l x p t F a\n"); + prxy("%4d,%-4d", sect->sct_x, sect->sct_y, player->cnum); + pr(" %c%c %3d %3d %3d %3d %3d %3d %3d %3d %3d %3d %3d %4d %3d %5d %4d %5d\n", + dchr[sect->sct_type].d_mnem, + (sect->sct_newtype == sect->sct_type) ? ' ' : + dchr[sect->sct_newtype].d_mnem, + sect->sct_own, sect->sct_oldown, + sect->sct_effic, sect->sct_mobil, + sect->sct_min, sect->sct_gmin, + sect->sct_fertil, sect->sct_oil, sect->sct_uran, + sect->sct_work, sect->sct_loyal, + getvar(V_CHE, (s_char *)sect, EF_SECTOR), + getvar(V_PSTAGE, (s_char *)sect, EF_SECTOR), + getvar(V_PTIME, (s_char *)sect, EF_SECTOR), + getvar(V_FALLOUT, (s_char *)sect, EF_SECTOR), + sect->sct_avail); + + pr(" Mines : %d\n", getvar(V_MINE, (s_char *)sect, EF_SECTOR)); + pr(" Road %% : %d\n", sect->sct_road); + pr(" Rail %% : %d\n", sect->sct_rail); + pr(" Defense %% : %d\n", sect->sct_defense); + pr(" Coastal : %d\n", sect->sct_coastal); +} + + +static void +prnat(natid n) +{ + struct natstr *np; + int i; + + if ((np = getnatp(n)) == 0) + return; + pr("Country #: %2d\n", n); + pr("Name : %-20s\t", np->nat_cnam); + pr("Connected: %d\n", np->nat_connected); + pr("Representative : %-20s\n", np->nat_pnam); + pr("BTUs : %3d\t\t\t", np->nat_btu); + pr("Reserves : %5d\n", np->nat_reserve); + pr("Capital : %s\t\t", xyas(np->nat_xcap, np->nat_ycap, player->cnum)); + pr("Origin : %3s\n", xyas(np->nat_xorg, np->nat_yorg, player->cnum)); + pr("Status : 0x%x\t\t\t", np->nat_stat); + pr("Min Used : %3d\n", np->nat_minused); + pr("Technology : %.2f\t\t", np->nat_level[NAT_TLEV]); + pr("Research : %.2f\n", np->nat_level[NAT_RLEV]); + pr("Education : %.2f\t\t", np->nat_level[NAT_ELEV]); + pr("Happiness : %.2f\n", np->nat_level[NAT_HLEV]); + pr("Money : $%6d\n", np->nat_money); + pr("Telegrams : %6d\n", np->nat_tgms); + if (opt_DEMANDUPDATE) + pr("Updates missed : %d\n", np->nat_missed); + if (opt_HIDDEN) { + pr("Countries contacted: "); + for (i=0; i: %d\t\t", (int)plane->pln_uid); + pr("Owner : %d\t\t", (int)plane->pln_own); + pr("Location : %s\n", xyas(plane->pln_x, plane->pln_y, player->cnum)); + pr("Efficiency : %d\t", (int)plane->pln_effic); + pr("Mobility : %d\n", (int)plane->pln_mobil); + pr("Tech : %d\t\t", plane->pln_tech); + pr("Wing : %c\n", plane->pln_wing); + pr("Attack : %d\t\t", plane->pln_att); + pr("Defense : %d\n", plane->pln_def); + pr("Range : %d\t\t", plane->pln_range); + pr("Flags : %d\n", plane->pln_flags); + pr("Ship : %d\t\t", plane->pln_ship); + pr("Land Unit : %d\t", plane->pln_land); + pr("Nuke Type : %d\n", plane->pln_nuketype); +} + +static void +pr_land(struct lndstr *land) +{ + int vec[I_MAX+1]; + struct lchrstr *lcp; + + lcp = &lchr[(int)land->lnd_type]; + pr("UID : %d\n", (int)land->lnd_uid); + pr("Owner : %d\n", (int)land->lnd_own); + pr("Location : %s\n", xyas(land->lnd_x, land->lnd_y, player->cnum)); + pr("Efficiency : %d\t", (int)land->lnd_effic); + pr("Mobility : %d\n", (int)land->lnd_mobil); + pr("Tech : %d\t\t", land->lnd_tech); + pr("Army : %c\n", land->lnd_army); + pr("Attack: %f\t", lcp->l_att); + pr("Defense: %f\n", lcp->l_def); + pr("Fortification : %d\t", land->lnd_harden); + pr("Fuel : %d\n", land->lnd_fuel); + count_land_planes(land); + pr("Xlight planes : %d\n", land->lnd_nxlight); + pr("Land unit : %d\n", land->lnd_land); + pr("Ship : %d\t\t", land->lnd_ship); + pr("Radius

: %d\n", land->lnd_rad_max); + pr("Retreat percentage : %d\n", (int)land->lnd_retreat); + pr("Retreat path : '%s'\t\tRetreat Flags : %d\n",land->lnd_rpath,(int)land->lnd_rflags); + getvec(VT_ITEM, vec, (s_char *)land, EF_LAND); + pr("civ mil uw food shl gun pet irn dst oil lcm hcm rad\n"); + pr(" c m u f s g p i d o l h r\n"); + pr("%3d", vec[I_CIVIL]); + pr("%4d", vec[I_MILIT]); + pr("%4d", vec[I_UW]); + pr("%5d", vec[I_FOOD]); + pr("%4d", vec[I_SHELL]); + pr("%4d", vec[I_GUN]); + pr("%5d", vec[I_PETROL]); + pr("%5d", vec[I_IRON]); + pr("%5d", vec[I_DUST]); + pr("%5d", vec[I_OIL]); + pr("%5d", vec[I_LCM]); + pr("%5d", vec[I_HCM]); + pr("%4d", vec[I_RAD]); + pr("\n"); +} + +static void +pr_ship(struct shpstr *ship) +{ + int vec[I_MAX+1]; + struct natstr *natp; + + if ((natp = getnatp(ship->shp_own)) == 0) + return; + pr("%s (#%d) %s\n", natp->nat_cnam, (int)ship->shp_own, + prship(ship)); + pr("UID : %d\n", (int)ship->shp_uid); + pr("Owner : %d\t\t\t", (int)ship->shp_own); + pr("Location : %s\n", xyas(ship->shp_x, ship->shp_y, player->cnum)); + pr("Tech : %d\t\t\t", ship->shp_tech); + pr("Efficiency : %d\n", (int)ship->shp_effic); + pr("Mobility : %d\t\t\t", (int)ship->shp_mobil); + pr("Fleet : %c\n", ship->shp_fleet); + count_planes(ship); + pr("Helos : %d\n", (int)ship->shp_nchoppers); + pr("Xlight planes : %d\n", (int)ship->shp_nxlight); + pr("Planes

: %d\n", (int)ship->shp_nplane); + count_units(ship); + pr("Units : %d\n", (int)ship->shp_nland); + /* could depend on opt_FUEL - but a deity might want to set this + up before enabling the option */ + pr("Fuel : %d\n", (int)ship->shp_fuel); + pr("Retreat path : '%s'\t\tRetreat Flags : %d\n",ship->shp_rpath,(int)ship->shp_rflags); + getvec(VT_ITEM, vec, (s_char *)ship, EF_SHIP); + pr("Plague Stage : %d\n", getvar(V_PSTAGE, (s_char *)ship, EF_SHIP)); + pr("Plague Time : %d\n", getvar(V_PTIME, (s_char *)ship, EF_SHIP)); + pr("civ mil uw food shl gun pet irn dst oil lcm hcm rad\n"); + pr(" c m u f s g p i d o l h r\n"); + pr("%3d", vec[I_CIVIL]); + pr("%4d", vec[I_MILIT]); + pr("%4d", vec[I_UW]); + pr("%5d", vec[I_FOOD]); + pr("%4d", vec[I_SHELL]); + pr("%4d", vec[I_GUN]); + pr("%5d", vec[I_PETROL]); + pr("%5d", vec[I_IRON]); + pr("%5d", vec[I_DUST]); + pr("%5d", vec[I_OIL]); + pr("%5d", vec[I_LCM]); + pr("%5d", vec[I_HCM]); + pr("%4d", vec[I_RAD]); + pr("\n"); +} + +int +errcheck(int num, int min, int max) +{ + if (num < min) + return(min); + else if (num > max) + return(max); + return (num); +} + +int +getin(s_char **what, s_char **p, int *arg, s_char *buf) +{ + if (!(*what = getstarg(*p, "%c xxxxx -- thing value : ", buf))) { + return RET_SYN; + } + if (**what == '\0') + return END; + while (**what && isspace (**what)) + (*what) ++; + if (**what == '\0') + return RET_SYN; + for (*p = *what; **p && !isspace (**p); (*p) ++) /* skip non spaces */ + continue; + while (**p && isspace (**p)) + (*p) ++; + if (**p == '\0') + return RET_SYN; + *arg = atoi(*p); + return RET_OK; +} + + +int +doland(s_char op, int arg, struct sctstr *sect) +{ + natid newown, oldown; + int new, old; + switch (op) { + case 'C': + if (arg < 0) + return RET_SYN; + sect->sct_coastal = (arg ? 1 : 0); + pr("Coastal flag of %s changed to %d\n", + xyas(sect->sct_x, sect->sct_y, player->cnum), + sect->sct_coastal); + break; + case 'o': + if (arg < 0) + return RET_SYN; + newown = (natid) errcheck(arg, 0, MAXNOC-1); + pr("Owner of %s changed from %s (#%d) to %s (#%d).\n", + xyas(sect->sct_x, sect->sct_y, player->cnum), + cname(sect->sct_own), + sect->sct_own, cname(newown), newown); + if (sect->sct_own) { + makelost(EF_SECTOR, sect->sct_own, 0, sect->sct_x, sect->sct_y); + wu(player->cnum, sect->sct_own, + "Sector %s lost to deity intervention\n", + xyas(sect->sct_x, sect->sct_y, sect->sct_own)); + } + benefit(sect->sct_own, 0); + sect->sct_own = newown; + if (newown) { + makenotlost(EF_SECTOR, newown, 0, sect->sct_x, sect->sct_y); + wu(player->cnum, newown, + "Sector %s gained from deity intervention\n", + xyas(sect->sct_x, sect->sct_y, sect->sct_own)); + } + benefit(newown, 1); + break; + case 'O': + if (arg < 0) + return RET_SYN; + oldown = (natid) errcheck(arg, 0, MAXNOC-1); + pr("Old player->owner of %s changed from %s (#%d) to %s (#%d).\n", + xyas(sect->sct_x, sect->sct_y, player->cnum), + cname(sect->sct_oldown), + sect->sct_oldown, cname(oldown), oldown); + sect->sct_oldown = oldown; + break; + case 'e': + new = errcheck(arg, 0, 100); + noise(sect, 1, "Efficiency", (int) sect->sct_effic, new); + sect->sct_effic = (u_char) new; + break; + case 'm': + new = errcheck(arg, -127, 255); + noise(sect, 1, "Mobility", (int) sect->sct_mobil, new); + sect->sct_mobil = new; + break; + case 'i': + new = errcheck(arg, 0, 127); + noise(sect, 1, "Iron ore content", (int) sect->sct_min, new); + sect->sct_min = (u_char) new; + break; + case 'g': + new = errcheck(arg, 0, 127); + noise(sect, 1, "Gold content", (int) sect->sct_gmin, new); + sect->sct_gmin = (u_char) new; + break; + case 'f': + new = errcheck(arg, 0, 127); + noise(sect, 1, "Fertility", (int) sect->sct_fertil, new); + sect->sct_fertil = (u_char) new; + break; + case 'c': + new = errcheck(arg, 0, 127); + noise(sect, 1, "Oil content", (int) sect->sct_oil, new); + sect->sct_oil = (u_char) new; + break; + case 'u': + new = errcheck(arg, 0, 127); + noise(sect, 1, "Uranium content", (int) sect->sct_uran, new); + sect->sct_uran = (u_char) new; + break; + case 'w': + new = errcheck(arg, 0, 100); + noise(sect, 1, "Workforce percentage", + (int) sect->sct_work, new); + sect->sct_work = (u_char) new; + break; + case 'l': + new = errcheck(arg, 0, 127); + pr("Loyalty of %s changed from %d to %d%%\n", + xyas(sect->sct_x, sect->sct_y, player->cnum), + sect->sct_loyal, new); + sect->sct_loyal = (u_char) new; + break; + case 'x': + old = getvar(V_CHE, (s_char *)sect, EF_SECTOR); + new = errcheck(arg, 0, 65536); + pr("Guerillas in %s changed from %d to %d%\n", + xyas(sect->sct_x, sect->sct_y, player->cnum), old, new); + putvar(V_CHE, new, (s_char *)sect, EF_SECTOR); + break; + case 'p': + old = getvar(V_PSTAGE, (s_char *)sect, EF_SECTOR); + new = errcheck(arg, 0, PLG_EXPOSED); + pr("Plague stage of %s changed from %d to %d%\n", + xyas(sect->sct_x, sect->sct_y, player->cnum), old, new); + putvar(V_PSTAGE, new, (s_char *)sect, EF_SECTOR); + break; + case 't': + old = getvar(V_PTIME, (s_char *)sect, EF_SECTOR); + new = errcheck(arg, 0, 255); + pr("Plague time of %s changed from %d to %d%\n", + xyas(sect->sct_x, sect->sct_y, player->cnum), old, new); + putvar(V_PTIME, new, (s_char *)sect, EF_SECTOR); + break; + case 'F': + old = getvar(V_FALLOUT, (s_char *)sect, EF_SECTOR); + new = errcheck(arg, 0, 9999); + pr("Fallout for sector %s changed from %d to %d\n", + xyas(sect->sct_x, sect->sct_y, player->cnum), old, new); + putvar(V_FALLOUT, new, (s_char *)sect, EF_SECTOR); + break; + case 'a': + new = errcheck(arg, 0, 9999); + noise(sect, 1, "Available workforce", (int) sect->sct_avail, + new); + sect->sct_avail = new; + break; + case 'M': + putvar(V_MINE, arg, (s_char *)sect, EF_SECTOR); + pr("Mines changed to %d\n",arg); + break; + case 'X': + sect->sct_x = arg; + break; + case 'Y': + sect->sct_y = arg; + break; + case 'R': + if (arg > 100) + arg = 100; + if (arg < 0) + arg = 0; + noise(sect, 1, "Road percentage", (int) sect->sct_road, + arg); + sect->sct_road = arg; + break; + case 'r': + if (arg > 100) + arg = 100; + if (arg < 0) + arg = 0; + noise(sect, 1, "Rail percentage", (int) sect->sct_rail, + arg); + sect->sct_rail = arg; + break; + case 'd': + if (arg > 100) + arg = 100; + if (arg < 0) + arg = 0; + noise(sect, 1, "Defense percentage", (int) sect->sct_defense, + arg); + sect->sct_defense = arg; + break; + default: + pr("huh? (%c)\n",op); + return RET_SYN; + } + return RET_OK; +} + + + +int +docountry(s_char op, int arg, s_char *p, float farg, natid nat, struct natstr *np) +{ + extern int m_m_p_d; + coord newx, newy; + switch (op) { + case 'n': + pr("Country name changed from %s to %s\n", np->nat_cnam, p); + strncpy(np->nat_cnam, p, sizeof(np->nat_cnam)-1); + break; + case 'r': + pr("Country representative changed from %s to %s\n", + np->nat_pnam, p); + strncpy(np->nat_pnam, p, sizeof(np->nat_pnam)-1); + break; + case 't': + np->nat_tgms = arg; + break; + case 'b': + arg = errcheck(arg, 0, 1024); + pr("BTU's changed from %d to %d\n", np->nat_btu, arg); + np->nat_btu = arg; + break; + case 'm': + benefit(nat, np->nat_reserve < arg); + pr("Military Reserves changed from %d to %d\n", + np->nat_reserve, arg); + if (np->nat_stat == STAT_NORM) + wu(player->cnum, nat, + "Military Reserves changed from %d to %d by divine intervention.\n", + np->nat_reserve, arg); + np->nat_reserve = arg; + break; + case 'c': + if (!sarg_xy(p, &newx, &newy)) + return RET_SYN; + pr("Capital coordinates changed from %s to %s\n", + xyas(np->nat_xcap, np->nat_ycap, player->cnum), + xyas(newx, newy, player->cnum)); + np->nat_xcap = newx; + np->nat_ycap = newy; + break; + case 'o': + if (!sarg_xy(p, &newx, &newy)) + return RET_SYN; + pr("Origin coordinates changed from %s to %s\n", + xyas(np->nat_xorg, np->nat_yorg, player->cnum), + xyas(newx, newy, player->cnum)); + np->nat_xorg = newx; + np->nat_yorg = newy; + break; + case 's': + np->nat_stat = (s_char)errcheck(arg, 0, STAT_NEW); + break; + case 'u': + arg = errcheck(arg, 0, m_m_p_d); + pr("Number of minutes used changed from %d to %d.\n", + np->nat_minused, arg); + np->nat_minused = arg; + break; + case 'M': + pr("Money changed from %d to %d\n",np->nat_money, arg); + wu(player->cnum, nat, + "Money changed from %d to %d by divine intervention.\n", + np->nat_money, arg); + np->nat_money = arg; + break; + case 'T': + pr("Tech changed from %.2f to %.2f.\n", + np->nat_level[NAT_TLEV], farg); + np->nat_level[NAT_TLEV] = farg; + break; + case 'R': + pr("Research changed from %.2f to %.2f.\n", + np->nat_level[NAT_RLEV], farg); + np->nat_level[NAT_RLEV] = farg; + break; + case 'E': + pr("Education changed from %.2f to %.2f.\n", + np->nat_level[NAT_ELEV], farg); + np->nat_level[NAT_ELEV] = farg; + break; + case 'H': + pr("Happiness changed from %.2f to %.2f.\n", + np->nat_level[NAT_HLEV], farg); + np->nat_level[NAT_HLEV] = farg; + break; + case 'U': + np->nat_missed = arg; + break; + default: + pr("huh? (%c)\n",op); + break; + } + putnat(np); + return RET_OK; +} + + +int +doship(s_char op, int arg, s_char *p, struct shpstr *ship) +{ + coord newx, newy; + + newx = newy = 0; + switch (op) { + case 'a': + putvar(V_PSTAGE, arg, (s_char *)ship, EF_SHIP); + break; + case 'b': + putvar(V_PTIME, arg, (s_char *)ship, EF_SHIP); + break; + case 'R': + bcopy(p,ship->shp_rpath,10); + break; + case 'W': + ship->shp_rflags = arg; + break; + case 'H': + ship->shp_nchoppers = arg; + break; + case 'X': + ship->shp_nxlight = arg; + break; + case 'U': + ship->shp_uid = arg; + break; + case 'O': + if (ship->shp_own) + wu(player->cnum, ship->shp_own, + "%s taken from you by deity intervention!\n", + prship(ship)); + if (arg && arg < MAXNOC) { + wu(player->cnum, (natid)arg, + "%s given to you by deity intervention!\n", + prship(ship)); + makelost(EF_SHIP, ship->shp_own, ship->shp_uid, ship->shp_x, ship->shp_y); + ship->shp_own = (natid) arg; + makenotlost(EF_SHIP, ship->shp_own, ship->shp_uid, ship->shp_x, ship->shp_y); + } else if (!arg) { + ship->shp_effic = 0; + makelost(EF_SHIP, ship->shp_own, ship->shp_uid, ship->shp_x, ship->shp_y); + ship->shp_own = (natid) 0; + } + break; + case 'L': + if (!sarg_xy(p, &newx, &newy)) + return RET_SYN; + ship->shp_x = newx; + ship->shp_y = newy; + break; + case 'T': + ship->shp_tech = arg; + break; + case 'E': + ship->shp_effic = errcheck(arg, 0, 100); + if (arg < 10) { + ship->shp_effic = 0; + makelost(EF_SHIP, ship->shp_own, ship->shp_uid, ship->shp_x, ship->shp_y); + ship->shp_own = (natid) 0; + } + break; + case 'M': + ship->shp_mobil = arg; + break; + case 'B': + ship->shp_fuel = errcheck(arg, 0, 255); + break; + case 'F': + if (p[0] == '~') + ship->shp_fleet = ' '; + else if (isalpha(p[0])) + ship->shp_fleet = p[0]; + else { + pr("%c: invalid fleet\n",p[0]); + return RET_FAIL; + } + break; + case 'Y': + ship->shp_nland = errcheck(arg, 0, 100); + break; + case 'P': + ship->shp_nplane = errcheck(arg, 0, 100); + break; + case 'c': + if (!putvar(V_CIVIL, arg, (s_char *)ship, EF_SHIP)) { + pr("No room on ship!\n"); + return RET_FAIL; + } + break; + case 'm': + if (!putvar(V_MILIT, arg, (s_char *)ship, EF_SHIP)) { + pr("No room on ship!\n"); + return RET_FAIL; + } + break; + case 'u': + if (!putvar(V_UW, arg, (s_char *)ship, EF_SHIP)) { + pr("No room on ship!\n"); + return RET_FAIL; + } + break; + case 'f': + if (!putvar(V_FOOD, arg, (s_char *)ship, EF_SHIP)) { + pr("No room on ship!\n"); + return RET_FAIL; + } + break; + case 's': + if (!putvar(V_SHELL, arg, (s_char *)ship, EF_SHIP)) { + pr("No room on ship!\n"); + return RET_FAIL; + } + break; + case 'g': + if (!putvar(V_GUN, arg, (s_char *)ship, EF_SHIP)) { + pr("No room on ship!\n"); + return RET_FAIL; + } + break; + case 'p': + if (!putvar(V_PETROL, arg, (s_char *)ship, EF_SHIP)) { + pr("No room on ship!\n"); + return RET_FAIL; + } + break; + case 'i': + if (!putvar(V_IRON, arg, (s_char *)ship, EF_SHIP)) { + pr("No room on ship!\n"); + return RET_FAIL; + } + break; + case 'd': + if (!putvar(V_DUST, arg, (s_char *)ship, EF_SHIP)) { + pr("No room on ship!\n"); + return RET_FAIL; + } + break; + case 'o': + if (!putvar(V_OIL, arg, (s_char *)ship, EF_SHIP)) { + pr("No room on ship!\n"); + return RET_FAIL; + } + break; + case 'l': + if (!putvar(V_LCM, arg, (s_char *)ship, EF_SHIP)) { + pr("No room on ship!\n"); + return RET_FAIL; + } + break; + case 'h': + if (!putvar(V_HCM, arg, (s_char *)ship, EF_SHIP)) { + pr("No room on ship!\n"); + return RET_FAIL; + } + break; + case 'r': + if (!putvar(V_RAD, arg, (s_char *)ship, EF_SHIP)) { + pr("No room on ship!\n"); + return RET_FAIL; + } + break; + default: + pr("huh? (%c)\n",op); + return RET_FAIL; + } + return RET_OK; +} + +int +dounit(s_char op, int arg, s_char *p, struct lndstr *land) +{ + coord newx, newy; + + newx = newy = 0; + switch (op) { + case 'Y': + land->lnd_land = arg; + break; + case 'U': + land->lnd_uid = arg; + break; + case 'O': + if (land->lnd_own) + wu(player->cnum, land->lnd_own, + "%s taken from you by deity intervention!\n", + prland(land)); + + if (arg && arg < MAXNOC) { + wu(player->cnum, (natid)arg, + "%s given to you by deity intervention!\n", + prland(land)); + makelost(EF_LAND, land->lnd_own, land->lnd_uid, land->lnd_x, land->lnd_y); + land->lnd_own = (natid) arg; + makenotlost(EF_LAND, land->lnd_own, land->lnd_uid, land->lnd_x, land->lnd_y); + } else if (!arg) { + makelost(EF_LAND, land->lnd_own, land->lnd_uid, land->lnd_x, land->lnd_y); + land->lnd_effic = 0; + land->lnd_own = (natid) 0; + } + break; + case 'L': + if (!sarg_xy(p, &newx, &newy)) + return RET_SYN; + land->lnd_x = newx; + land->lnd_y = newy; + break; + case 'e': + land->lnd_effic = errcheck(arg, 0, 100); + if (arg < 10) { + makelost(EF_LAND, land->lnd_own, land->lnd_uid, land->lnd_x, land->lnd_y); + land->lnd_effic = 0; + land->lnd_own = (natid) 0; + } + break; + case 'M': + land->lnd_mobil = arg; + break; + case 't': + land->lnd_tech = arg; + break; + case 'a': + if (p[0] == '~') + land->lnd_army = ' '; + else if (isalpha(p[0])) + land->lnd_army = p[0]; + else { + pr("%c: invalid army\n",p[0]); + return RET_FAIL; + } + break; + case 'F': + land->lnd_harden = errcheck(arg, 0, 255); + break; + case 'B': + land->lnd_fuel = errcheck(arg, 0, 255); + break; + case 'X': + land->lnd_nxlight = arg; + break; + case 'S': + land->lnd_ship = arg; + break; + case 'P': + land->lnd_rad_max = arg; + break; + case 'Z': + land->lnd_retreat = arg; + break; + case 'R': + bcopy(p,land->lnd_rpath,10); + break; + case 'W': + land->lnd_rflags = arg; + break; + case 'c': + if (!putvar(V_CIVIL, arg, (s_char *)land, EF_LAND)) { + pr("No room on land unit!\n"); + return RET_FAIL; + } + break; + case 'm': + if (!putvar(V_MILIT, arg, (s_char *)land, EF_LAND)) { + pr("No room on land!\n"); + return RET_FAIL; + } + break; + case 'u': + if (!putvar(V_UW, arg, (s_char *)land, EF_LAND)) { + pr("No room on land!\n"); + return RET_FAIL; + } + break; + case 'f': + if (!putvar(V_FOOD, arg, (s_char *)land, EF_LAND)) { + pr("No room on land!\n"); + return RET_FAIL; + } + break; + case 's': + if (!putvar(V_SHELL, arg, (s_char *)land, EF_LAND)) { + pr("No room on land!\n"); + return RET_FAIL; + } + break; + case 'g': + if (!putvar(V_GUN, arg, (s_char *)land, EF_LAND)) { + pr("No room on land!\n"); + return RET_FAIL; + } + break; + case 'p': + if (!putvar(V_PETROL, arg, (s_char *)land, EF_LAND)) { + pr("No room on land!\n"); + return RET_FAIL; + } + break; + case 'i': + if (!putvar(V_IRON, arg, (s_char *)land, EF_LAND)) { + pr("No room on land!\n"); + return RET_FAIL; + } + break; + case 'd': + if (!putvar(V_DUST, arg, (s_char *)land, EF_LAND)) { + pr("No room on land!\n"); + return RET_FAIL; + } + break; + case 'o': + if (!putvar(V_OIL, arg, (s_char *)land, EF_LAND)) { + pr("No room on land!\n"); + return RET_FAIL; + } + break; + case 'l': + if (!putvar(V_LCM, arg, (s_char *)land, EF_LAND)) { + pr("No room on land!\n"); + return RET_FAIL; + } + break; + case 'h': + if (!putvar(V_HCM, arg, (s_char *)land, EF_LAND)) { + pr("No room on land!\n"); + return RET_FAIL; + } + break; + case 'r': + if (!putvar(V_RAD, arg, (s_char *)land, EF_LAND)) { + pr("No room on land!\n"); + return RET_FAIL; + } + break; + default: + pr("huh? (%c)\n",op); + return RET_FAIL; + } + return RET_OK; +} + + +int +doplane(s_char op, int arg, s_char *p, struct plnstr *plane) +{ + coord newx, newy; + + switch (op) { + case 'n': + plane->pln_nuketype = arg; + break; + case 'U': + plane->pln_uid = arg; + break; + case 'l': + if (!sarg_xy(p, &newx, &newy)) + return RET_SYN; + plane->pln_x = newx; + plane->pln_y = newy; + break; + case 'O': + if (plane->pln_own) + wu(player->cnum, plane->pln_own, + "%s taken from you by deity intervention!\n", + prplane(plane)); + if (arg && arg < MAXNOC) { + makelost(EF_PLANE, plane->pln_own, plane->pln_uid, plane->pln_x, plane->pln_y); + plane->pln_own = (natid) arg; + makenotlost(EF_PLANE, plane->pln_own, plane->pln_uid, plane->pln_x, plane->pln_y); + wu(player->cnum, plane->pln_own, + "%s given to you by deity intervention!\n", + prplane(plane)); + } else if (!arg) { + plane->pln_effic = 0; + makelost(EF_PLANE, plane->pln_own, plane->pln_uid, plane->pln_x, plane->pln_y); + plane->pln_own = (natid) 0; + } + break; + case 'e': + plane->pln_effic = errcheck(arg, 0, 100); + if (arg < 10) { + plane->pln_effic = 0; + makelost(EF_PLANE, plane->pln_own, plane->pln_uid, plane->pln_x, plane->pln_y); + plane->pln_own = (natid) 0; + } + break; + case 'm': + plane->pln_mobil = errcheck(arg, -127, 255); + break; + case 't': + plane->pln_tech = arg; + break; + case 'w': + if (p[0] == '~') + plane->pln_wing = ' '; + else if (isalpha(p[0])) + plane->pln_wing = p[0]; + else { + pr("%c: invalid wing\n",p[0]); + return RET_FAIL; + } + break; + case 'a': + plane->pln_att = (s_char) errcheck(arg, 0, 127); + break; + case 'd': + plane->pln_def = (s_char) arg; + break; + case 'r': + plane->pln_range = (u_char) arg; + break; + case 's': + plane->pln_ship = arg; + break; + case 'y': + plane->pln_land = arg; + break; + case 'f': + plane->pln_flags = arg; + break; + default: + pr("huh? (%c)\n",op); + return RET_FAIL; + } + return RET_OK; +} diff --git a/src/lib/commands/enab.c b/src/lib/commands/enab.c new file mode 100644 index 00000000..f0cdb449 --- /dev/null +++ b/src/lib/commands/enab.c @@ -0,0 +1,47 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * enab.c: Enable the updates (deity) + * + * Known contributors to this file: + * + */ + +#include +#include +#include "misc.h" +#include "commands.h" + +int +enab(void) +{ + extern s_char *disablefil; + + (void) unlink(disablefil); + pr("Updates are enabled\n"); + return RET_OK; +} diff --git a/src/lib/commands/enli.c b/src/lib/commands/enli.c new file mode 100644 index 00000000..519169e2 --- /dev/null +++ b/src/lib/commands/enli.c @@ -0,0 +1,147 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * enli.c: Enlist some military + * + * Known contributors to this file: + * + */ + +#include "misc.h" +#include "player.h" +#include "var.h" +#include "xy.h" +#include "sect.h" +#include "nsc.h" +#include "nat.h" +#include "treaty.h" +#include "file.h" +#include "commands.h" + +int +enli(void) +{ + struct nstr_sect nstr; + struct sctstr sect; + struct natstr *natp; + int civ; + int mil; + int newmil; + int milwant; + int totalmil; + long reserve; + s_char *p; + int quota; + s_char prompt[128]; + s_char buf[1024]; + + if (!snxtsct(&nstr, player->argp[1])) + return RET_SYN; + if (!trechk(player->cnum, 0, TRTENL)) + return RET_FAIL; + natp = getnatp(player->cnum); + newmil = 500; + sprintf(prompt, "Number to enlist (max %d) : ", newmil); + if ((p = getstarg(player->argp[2], prompt, buf)) == 0) + return RET_SYN; + if ((milwant = atoi(p)) > newmil) + milwant = newmil; + if (0 != (quota = (milwant < 0))) + milwant = -milwant; + totalmil = 0; + reserve = natp->nat_reserve; + if (reserve <= 0) { + pr("No military reserves left\n"); + return RET_OK; + } + while (nxtsct(&nstr, §)) { + if (!player->owner) + continue; + if (sect.sct_oldown != player->cnum) + continue; + civ = getvar(V_CIVIL, (s_char *)§, EF_SECTOR); + if (civ == 0) + continue; + if (sect.sct_loyal > 70) { + pr("civilians refuse to report in %s!\n", + xyas(sect.sct_x, sect.sct_y, player->cnum)); + continue; + } + if (sect.sct_mobil <= 0) { + pr("%s is out of mobility!\n", + xyas(sect.sct_x, sect.sct_y, player->cnum)); + } + mil = getvar(V_MILIT, (s_char *)§, EF_SECTOR); + newmil = civ * 0.5; + if (quota) { + if (newmil > milwant - mil) + newmil = milwant - mil; + if (newmil > 500) + newmil = 500; + } else if (newmil > milwant) + newmil = milwant; + if (newmil > 999 - mil) + newmil = 999 - mil; + if (newmil <= 0) + continue; + if (newmil > reserve) + newmil = reserve; + if (!putvar(V_MILIT, newmil + mil, (s_char *)§, EF_SECTOR)) { + pr("No room for military in %s\n", + xyas(sect.sct_x, sect.sct_y, player->cnum)); + continue; + } + reserve -= newmil; + totalmil += newmil; + putvar(V_CIVIL, civ - newmil, (s_char *)§, EF_SECTOR); + pr("%3d enlisted in %s (%d)\n", newmil, + xyas(sect.sct_x, sect.sct_y, player->cnum), mil + newmil); + if (sect.sct_mobil > 0) { + sect.sct_mobil = (u_char)((float)sect.sct_mobil * + (1.0 - (float)newmil / (float)civ)); + } + putsect(§); + if (totalmil >= 10000) { + pr("Rioting in induction center interrupts enlistment\n"); + break; + } + if (reserve == 0) { + pr("Military reserve exhausted\n"); + break; + } + } + pr("Total new enlistment : %d\n", totalmil); + pr("Military reserves stand at %d\n", reserve); + if (totalmil) { + natp->nat_reserve -= totalmil; + putnat(natp); + } + if ((player->btused += roundavg((float)totalmil * 0.02)) > 0) + pr("Paperwork at recruiting stations ... %d\n", + player->btused); + return RET_OK; +} diff --git a/src/lib/commands/expl.c b/src/lib/commands/expl.c new file mode 100644 index 00000000..ce4cd1f6 --- /dev/null +++ b/src/lib/commands/expl.c @@ -0,0 +1,343 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * expl.c: Take over unoccupied sectors + * + * Known contributors to this file: + * Jeff Wallace, 1989 + */ + +#include "misc.h" +#include "player.h" +#include "var.h" +#include "sect.h" +#include "xy.h" +#include "nsc.h" +#include "item.h" +#include "file.h" +#include "deity.h" +#include "nat.h" +#include "optlist.h" +#include "commands.h" + +static int explore_map(s_char *what, coord curx, coord cury, s_char *arg); + +extern int etu_per_update; +extern int sect_mob_neg_factor; + +int +explore(void) +{ + register int amount; + struct sctstr orig, sect; + struct sctstr endsect; + struct sctstr start; + struct sctstr chksect; + double weight; + int mcost, dam; + int infected; + int vtype; + int amt_src; + int amt_dst; + struct ichrstr *ip; + int work; + int loyal; + int own, mob; + int justtook; + coord x, y; + s_char *p; + int n; + int left; + s_char buf[1024]; + s_char prompt[128]; + + if ((ip = whatitem(player->argp[1], "explore with what? (civ/mil) ")) == 0) + return RET_SYN; + vtype = ip->i_vtype; + if ((vtype != V_CIVIL) && (vtype != V_MILIT)) { + pr("You can only explore with civs and mil.\n"); + return RET_FAIL; + } + if ((p = getstarg(player->argp[2], "from sector : ", buf)) == 0) + return RET_SYN; + if (!sarg_xy(p, &x, &y)) + return RET_SYN; + if (!getsect(x, y, §) || !player->owner) { + pr("Not yours\n"); + return RET_FAIL; + } + bcopy((s_char *)§,(s_char *)&orig,sizeof(struct sctstr)); + infected = getvar(V_PSTAGE, (s_char *)§, EF_SECTOR) == PLG_INFECT; + if ((amt_src = getvar(vtype, (s_char *)§, EF_SECTOR)) <= 0) { + pr("No %s in %s\n", ip->i_name, + xyas(sect.sct_x, sect.sct_y, player->cnum)); + return RET_SYN; + } + own = sect.sct_own; + mob = (int)sect.sct_mobil; + if (vtype == V_CIVIL && sect.sct_oldown != own) { + pr("You can't explore with conquered populace!\n"); + return RET_SYN; + } + if (mob <= 0) { + pr("No mobility in %s\n", + xyas(sect.sct_x, sect.sct_y, player->cnum)); + return RET_SYN; + } + if (vtype == V_CIVIL) { + work = sect.sct_work; + if (work != 100) + pr("Warning: civil unrest\n"); + loyal = sect.sct_loyal; + } else if (vtype == V_MILIT) { + work = 100; + loyal = 0; + } + sprintf(prompt, "Number of %s to explore with? (max %d) ", + ip->i_name, amt_src); + amount = onearg(player->argp[3], prompt); + if (!check_sect_ok(§)) + return RET_FAIL; + if (amount > amt_src) { + amount = amt_src; + pr("Only exploring with %d.\n", amount); + } + + if (!want_to_abandon(§, vtype, amount, 0)) { + pr("Explore cancelled.\n"); + return RET_FAIL; + } + + if (!check_sect_ok(§)) + return RET_FAIL; + + if (amount <= 0) + return RET_SYN; + weight = amount * ip->i_lbs; + /* remove commodities from source sector */ + getsect(x, y, &start); + amt_src = getvar(vtype, (s_char *)&start, EF_SECTOR); + amt_src -= amount; + if (amt_src < 0) { + pr("%s in %s are gone!\n", ip->i_name, + xyas(start.sct_x, start.sct_y, player->cnum)); + return RET_OK; + } + putvar(vtype, amt_src, (s_char *)&start, EF_SECTOR); + start.sct_flags |= MOVE_IN_PROGRESS; + putsect(&start); + /* + * Now parse the path and return ending sector. + */ + dam = 1; + mcost = move_ground((s_char *)ip, §, &endsect, + (double)sect.sct_mobil, weight, player->argp[4], + explore_map, 1, &dam); + + if (dam) { + left = effdamage(amount, dam); + if (left < amount) { + if (left) { + pr("%d of the %s you were exploring with were destroyed!\nOnly %d %s made it to %s\n", + amount - left, + ip->i_name, + left, + ip->i_name, + xyas(endsect.sct_x, endsect.sct_y, player->cnum)); + } else { + pr("All of the %s you were exploring with were destroyed!\n",ip->i_name); + } + amount = left; + } + } + if (mcost > 0) + pr("Total movement cost = %d",mcost); + else + pr("No mobility used"); + + if (mcost < 0) { + pr("\nExplore aborted"); + getsect(start.sct_x,start.sct_y,§); + sect.sct_mobil = (u_char)mob; + }else{ + /* Charge mobility */ + getsect(sect.sct_x, sect.sct_y, §); + n = sect.sct_mobil - mcost; + if (n < 0) + n = 0; + sect.sct_mobil = (u_char)n; + pr(", %d mob left in %s", sect.sct_mobil, + xyas(sect.sct_x,sect.sct_y,player->cnum)); + putsect(§); + getsect(endsect.sct_x, endsect.sct_y, §); + } + pr("\n"); + justtook = 0; + + /* + * Check for a multitude of problems + */ + getsect(endsect.sct_x, endsect.sct_y, &chksect); + if(chksect.sct_type == '.') { + pr("Bridge disappeared!\n"); + getsect(start.sct_x,start.sct_y,&start); + start.sct_flags &= ~MOVE_IN_PROGRESS; + putsect(&start); + return RET_FAIL; + } + if(!player->god && chksect.sct_own && chksect.sct_own != player->cnum + && chksect.sct_type != SCT_SANCT) { + pr("Somebody beat you there!\n"); + /* Send them xback home */ + getsect(start.sct_x,start.sct_y,§); + if (sect.sct_own != own) { + pr("Someone captured the sector you started from!\n"); + pr("Your exploring people die of disappointment!\n"); + sect.sct_flags &= ~MOVE_IN_PROGRESS; + putsect(§); + return RET_FAIL; + } + } + + if (!player->god && !player->owner && sect.sct_type != SCT_SANCT) { + (void) takeover(§, player->cnum); + justtook = 1; + sect.sct_oldown = own; + sect.sct_work = work; + sect.sct_loyal = loyal; + } + if (vtype == V_CIVIL && sect.sct_oldown != player->cnum) { + pr("Your civilians don't want to stay!\n"); + getsect(start.sct_x,start.sct_y,§); + if (sect.sct_own != own) { + pr("Someone captured the sector you started from!\n"); + pr("Your exploring people die of disappointment!\n"); + sect.sct_flags &= ~MOVE_IN_PROGRESS; + putsect(§); + return RET_FAIL; + } + } + getsect(start.sct_x,start.sct_y,&start); + start.sct_flags &= ~MOVE_IN_PROGRESS; + putsect(&start); + amt_dst = getvar(vtype, (s_char *)§, EF_SECTOR); + if (32767 - amt_dst < amount) { + amount = 32767 - amt_dst; + pr("Only %d can be left there.\n", amount); + if (amount <= 0) + getsect(start.sct_x,start.sct_y,§); + } + if (putvar(vtype, amount + amt_dst, (s_char *)§, EF_SECTOR) < 0) { + pr("No more room in %s.\n", + xyas(sect.sct_x, sect.sct_y, player->cnum)); + return RET_OK; + } + /* + * Now add commodities to destination sector, + * along with plague that came along for the ride. + * Takeover unowned sectors if not deity. + */ + if (!player->god && sect.sct_type != SCT_SANCT && justtook) { + pr("Sector %s is now yours.\n", + xyas(sect.sct_x, sect.sct_y, player->cnum)); + if (opt_MOB_ACCESS) { + time(§.sct_access); + sect.sct_mobil = -(etu_per_update / sect_mob_neg_factor); + } else { + sect.sct_mobil = 0; + } + } + if (infected && getvar(V_PSTAGE, (s_char *)§, EF_SECTOR) == 0) + putvar(V_PSTAGE, PLG_EXPOSED, (s_char *)§, EF_SECTOR); + if (vtype == V_CIVIL) { + if (opt_NEW_WORK) { + sect.sct_loyal =( (amt_dst * sect.sct_loyal) + + (amount * loyal) ) / (amt_dst+amount); + sect.sct_work =( (amt_dst * sect.sct_work) + + (amount * work) ) / (amt_dst+amount); + } else { /* ! NEW_WORK */ + + /* It only takes one bad apple... */ + if (sect.sct_loyal < loyal) + sect.sct_loyal = loyal; + if (sect.sct_work > work) + sect.sct_work = work; + } /* end NEW_WORK */ + } + putsect(§); + return RET_OK; +} + +/*ARGSUSED*/ +static int +explore_map(s_char *what, coord curx, coord cury, s_char *arg) +{ + struct nstr_sect ns; + struct natstr *np; + struct sctstr sect; + coord rel_x, rel_y; + s_char range[128]; + s_char view[7]; + int i; + int changed = 0; + + np = getnatp(player->cnum); + rel_x = xrel(np, curx); + rel_y = yrel(np, cury); + sprintf(range, "%d:%d,%d:%d", rel_x-2, rel_x+2, rel_y-1, rel_y+1); + if (!snxtsct(&ns, range)) + return RET_FAIL; + i = 0; + while (i < 7 && nxtsct(&ns, §)) { + view[i] = dchr[sect.sct_type].d_mnem; + switch (sect.sct_type) { + case SCT_WATER: + case SCT_RURAL: + case SCT_MOUNT: + case SCT_WASTE: + case SCT_PLAINS: + break; + default: + if (sect.sct_own != player->cnum && !player->god) + view[i] = '?'; + break; + } + changed += map_set(player->cnum, ns.x, ns.y, view[i], 0); + i++; + } + if (changed) + writemap(player->cnum); + if (!getsect(curx, cury, §)) + return RET_FAIL; + pr(" %c %c min gold fert oil uran\n", view[0], view[1]); + pr(" %c %c %c %3d %4d %4d %4d %4d\n", + view[2], view[3], view[4], + sect.sct_min, sect.sct_gmin, sect.sct_fertil, sect.sct_oil, + sect.sct_uran); + pr(" %c %c\n", view[5], view[6]); + return RET_OK; +} diff --git a/src/lib/commands/fina.c b/src/lib/commands/fina.c new file mode 100644 index 00000000..bed9cf3f --- /dev/null +++ b/src/lib/commands/fina.c @@ -0,0 +1,120 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * fina.c: Financial report on current status of loans to countries + * + * Known contributors to this file: + * Dave Pare, 1986 + * Steve McClure, 1996 + */ + +#include +#include "misc.h" +#include "player.h" +#include "loan.h" +#include "file.h" +#include "xy.h" +#include "nsc.h" +#include "nat.h" +#include "commands.h" +#include "optlist.h" + +/* + * format: fina + */ +int +fina(void) +{ + struct lonstr loan; + struct nstr_item ni; + time_t now; + int rdur; + int xdur; + double rate; + double amt; + time_t due; + time_t last; + + if (!opt_LOANS) { + pr("Loans are not enabled.\n"); + return RET_FAIL; + } + (void)time(&now); + pr("\n"); + pr(" -= Empire Financial Status Report =- \n"); + pr(" "); + prdate(); + pr("Loan From To Rate Dur Paid Total\n"); + snxtitem(&ni, EF_LOAN, "*"); + while (nxtitem(&ni, (s_char *)&loan)) { + if (loan.l_status != LS_SIGNED) + continue; + due = loan.l_duedate; + last = loan.l_lastpay; + rdur = 0; + xdur = 0; + if (now < due) { + rdur = now - last; + xdur = 0; + } + if (last < due && due < now) { + rdur = due - last; + xdur = now - due; + } + if (due < last) { + rdur = 0; + xdur = now - last; + } + if (loan.l_ldur == 0) { + logerror("loan #%d has zero duration", ni.cur); + continue; + } + rate = loan.l_irate / (loan.l_ldur * 8640000.0); + +/* changed following to avoid overflow 3/27/89 bailey@math-cs.kent.edu + amt = (rdur * rate + xdur * rate * 2.0 + 1.0) * loan.l_amtdue; + Begin overflow fix */ + amt = (rdur * rate + xdur * rate * 2.0 + 1.0); + if (((1 << 30) / amt) < loan.l_amtdue) + amt = (1 << 30); + else + amt *= loan.l_amtdue; +/* End overflow fix */ + + pr(" %-2d (%3d) %-8.8s (%3d) %-8.8s ", ni.cur, + loan.l_loner, cname(loan.l_loner), + loan.l_lonee, cname(loan.l_lonee)); + pr("%3d%% %3d %5d %7d", + loan.l_irate, loan.l_ldur, loan.l_amtpaid, (int) amt); + if (now > loan.l_duedate) + pr(" (in arrears)\n"); + else + pr("\n"); + } + pr("\n"); + return RET_OK; +} diff --git a/src/lib/commands/flash.c b/src/lib/commands/flash.c new file mode 100644 index 00000000..094b6275 --- /dev/null +++ b/src/lib/commands/flash.c @@ -0,0 +1,197 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * flash.c: Flash a message to another player + * + * Known contributors to this file: + * Ken Stevens, 1995 + * Steve McClure, 1998 + */ + +#if defined(Rel4) || defined(_WIN32) +#include +#else +#include +#endif /* Rel4 */ +#include "misc.h" +#include "player.h" +#include "nat.h" +#include "file.h" +#include "commands.h" + +int +flash(void) +{ + struct natstr *us; + struct natstr *to; + s_char buf[600]; + int tocn; + s_char *sp; + + us = getnatp(player->cnum); + if ((tocn = natarg(player->argp[1], "to which country? ")) < 0) + return RET_SYN; + if (!(to = getnatp((natid)tocn))) { + pr("Bad country number\n"); + return RET_SYN; + } + + if (us->nat_stat & STAT_GOD) { + /* We are gods, we can flash anyone */ + } else if (us->nat_stat == VIS) { + /* We are a visitor. We can only flash the gods. :) */ + if (!(to->nat_stat & STAT_GOD)) { + pr("Visitors can only flash the gods.\n"); + return RET_SYN; + } + } else { + /* Ok, we are a normal country, can we flash them? */ + if ((!(to->nat_stat & STAT_GOD)) && + (getrel(to, player->cnum) < FRIENDLY)) { + pr("%s is not a deity or friendly with us.\n", to->nat_cnam); + return RET_SYN; + } + } + + if (player->argp[2]) { + for (sp = &player->combuf[0]; *sp && *sp != ' '; ++sp); + for (++sp; *sp && *sp != ' '; ++sp); + sprintf(buf, ":%s", sp); + sendmessage(us, to, buf, 1); + } else { + sendmessage(us, to, "...", 1); + while (getstring("> ", buf)) { + if (*buf == '.') + break; + sendmessage(us, to, buf, 0); + } + sendmessage(us, to, "", 0); + } + return RET_OK; +} + +int +wall(void) +{ + struct natstr *us; + s_char buf[600]; + s_char *sp; + + us = getnatp(player->cnum); + if (player->argp[1]) { + for (sp = &player->combuf[0]; *sp && *sp != ' '; ++sp); + for (++sp; *sp && *sp != ' '; ++sp); + sprintf(buf, ":%s", sp); + sendmessage(us, 0, buf, 1); + } else { + sendmessage(us, 0, "...", 1); + while (getstring("> ", buf)) { + if (*buf == '.') + break; + sendmessage(us, 0, buf, 0); + } + sendmessage(us, 0, "", 0); + } + return RET_OK; +} + +int +sendmessage(struct natstr *us, struct natstr *to, char *message, int oneshot) +{ + struct player *other; + struct tm *tm; + char *p; + char c; + time_t now; + int sent = 0; + struct natstr *wto; + + for (p = message; 0 != (c = *p); p++) { + if (!isprint(c)) + *p = '*'; + } + if (strlen(message) > 60) { + s_char c = message[60]; + message[60] = '\0'; + sendmessage(us, to, message, oneshot); + message[60] = c; + sendmessage(us, to, &message[60], 0); + return 0; + } + time(&now); + tm = localtime(&now); + for (other = player_next(0); other != 0; other = player_next(other)) { + if (to && other->cnum != to->nat_cnum) + continue; + if (!(wto = getnatp(other->cnum))) + continue; + if (!to && !player->god && getrel(wto, player->cnum) != ALLIED) + continue; + if (!player->god && !(wto->nat_flags & NF_FLASH)) + continue; + if (player == other) + continue; + if (oneshot) + if (to) + pr_flash(other, "FLASH from %s (#%d) @ %02d:%02d%s\n", + us->nat_cnam, us->nat_cnum, tm->tm_hour, + tm->tm_min, message); + else + pr_flash(other, "BROADCAST from %s (#%d) @ %02d:%02d%s\n", + us->nat_cnam, us->nat_cnum, tm->tm_hour, + tm->tm_min, message); + + else + pr_flash(other, "%s (#%d): %s\n", + us->nat_cnam, us->nat_cnum, message); + player_wakeup(other); + sent++; + } + if (player->god) { + if (to) + if (sent) + pr("Flash sent to %s\n", to->nat_cnam); + else + pr("%s is not logged on\n", to->nat_cnam); + else + if (sent) + pr("Broadcast sent to %d players\n", sent); + else + pr("No-one is logged in\n"); + } + if (to && !player->god) { + /* If they are allied with us, we would normally see that + * they are logged in anyway, so just tell us */ + if ((getrel(to, player->cnum) == ALLIED) && !sent) { + if (to->nat_flags & NF_FLASH) + pr("%s is not logged on\n", to->nat_cnam); + else + pr("%s is not accepting flashes\n", to->nat_cnam); + } + } + return 0; +} diff --git a/src/lib/commands/flee.c b/src/lib/commands/flee.c new file mode 100644 index 00000000..2a84e0f6 --- /dev/null +++ b/src/lib/commands/flee.c @@ -0,0 +1,87 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * flee.c: Add ships to a fleet + * + * Known contributors to this file: + * + */ + +#include +#include "misc.h" +#include "player.h" +#include "var.h" +#include "ship.h" +#include "xy.h" +#include "nsc.h" +#include "file.h" +#include "nat.h" +#include "commands.h" + +int +flee(void) +{ + struct shpstr ship; + register int count; + s_char *cp; + s_char c; + struct nstr_item nstr; + struct nstr_item ni; + struct shpstr ship2; + int r; + s_char buf[1024]; + + cp = getstarg(player->argp[1], "fleet? ", buf); + if (cp == 0) + return RET_SYN; + c = *cp; + if (!isalpha(c) && c != '~') { + pr("Specify fleet, (1 alpha char or '~')\n"); + return RET_SYN; + } + if (c == '~') + c = ' '; + if (!snxtitem(&nstr, EF_SHIP, player->argp[2])) + return RET_SYN; + count = 0; + while (nxtitem(&nstr, (s_char *)&ship)) { + if (!player->owner) + continue; + ship.shp_fleet = c; + snxtitem(&ni, EF_SHIP, cp); + while((r=nxtitem(&ni, (s_char *)&ship2)) + && (ship2.shp_fleet != c)); + if (r){ + bcopy(ship2.shp_rpath, ship.shp_rpath,10); + ship.shp_rflags = ship2.shp_rflags; + } + putship(ship.shp_uid, &ship); + count++; + } + pr("%d ship%s added to fleet `%c'\n", count, splur(count), c); + return RET_OK; +} diff --git a/src/lib/commands/fly.c b/src/lib/commands/fly.c new file mode 100644 index 00000000..52965e15 --- /dev/null +++ b/src/lib/commands/fly.c @@ -0,0 +1,152 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * fly.c: fly a plane + * + * Known contributors to this file: + * Dave Pare, 1986 + * Steve McClure, 2000 + */ + +#include "misc.h" +#include "player.h" +#include "var.h" +#include "sect.h" +#include "ship.h" +#include "item.h" +#include "plane.h" +#include "nuke.h" +#include "xy.h" +#include "nsc.h" +#include "news.h" +#include "file.h" +#include "nat.h" +#include "path.h" +#include "commands.h" + +int +fly(void) +{ + s_char *p; + int mission_flags; + int tech; + coord tx, ty; + coord ax, ay; + int ap_to_target; + struct ichrstr *ip; + s_char flightpath[MAX_PATH_LEN]; + struct shpstr ship; + int cno; + struct nstr_item ni_bomb; + struct nstr_item ni_esc; + coord x, y; + struct sctstr target; + struct emp_qelem bomb_list; + struct emp_qelem esc_list; + int wantflags; + struct sctstr ap_sect; + int dst_type; + s_char *dst_ptr; + s_char buf[1024]; + + wantflags = 0; + if (!snxtitem(&ni_bomb, EF_PLANE, player->argp[1])) + return RET_SYN; + if (!snxtitem(&ni_esc, EF_PLANE, getstarg(player->argp[2], "escort(s)? ", buf))) + pr("No escorts...\n"); + if ((p = getstarg(player->argp[3], "assembly point? ", buf)) == 0 || *p == 0) + return RET_SYN; + if (!sarg_xy(p, &x, &y) || !getsect(x, y, &ap_sect)) + return RET_SYN; + if (ap_sect.sct_own && ap_sect.sct_own != player->cnum && + getrel(getnatp(ap_sect.sct_own), player->cnum) != ALLIED) { + pr("Assembly point not owned by you or an ally!\n"); + return RET_SYN; + } + ax = x; + ay = y; + if (getpath(flightpath, player->argp[4], ax, ay, 0, 0, + 0, P_FLYING) == 0 || *flightpath == 0) + return RET_SYN; + tx = ax; + ty = ay; + (void) pathtoxy(flightpath, &tx, &ty, fcost); + pr("Ending sector is %s\n", xyas(tx, ty, player->cnum)); + getsect(tx, ty, &target); + cno = -1; + ip = whatitem(player->argp[5], "transport what? "); + mission_flags = 0; + if (pln_onewaymission(&target, &cno, &wantflags) < 0) + return RET_SYN; + if (cno < 0) { + dst_ptr = (s_char *) ⌖ + dst_type = EF_SECTOR; + } else { + getship(cno, &ship); + dst_ptr = (s_char *) &ship; + dst_type = EF_SHIP; + } + ap_to_target = strlen(flightpath); + if (*(flightpath+strlen(flightpath)-1) == 'h') + ap_to_target--; + pr("range to target is %d\n", ap_to_target); + /* + * select planes within range + */ + pln_sel(&ni_bomb, &bomb_list, &ap_sect, ap_to_target, + 1, wantflags, P_M|P_O); + wantflags |= P_F; + wantflags |= P_ESC; + pln_sel(&ni_esc, &esc_list, &ap_sect, ap_to_target, + 1, wantflags, P_M|P_O); + /* + * now arm and equip the bombers, transports, whatever. + * tech is stored in high 16 bits of mission_flags. + * yuck. + */ + tech=0; + mission_flags |= P_X; /* stealth (shhh) */ + mission_flags |= P_H; /* gets turned off if not all choppers */ + mission_flags = pln_arm(&bomb_list, ap_to_target, 't', ip, 0, mission_flags,&tech); + if (QEMPTY(&bomb_list)) { + pr("No planes could be equipped for the mission.\n"); + return RET_FAIL; + } + mission_flags = pln_arm(&esc_list, ap_to_target, 't', ip, P_ESC|P_F, mission_flags,&tech); + ac_encounter(&bomb_list,&esc_list,ax,ay,flightpath,mission_flags,0,0,0); + if (QEMPTY(&bomb_list)) { + pr("No planes got through fighter defenses\n"); + } else { + getsect(tx, ty, &target); + pln_dropoff(&bomb_list, ip, tx, ty, dst_ptr, dst_type); + pln_newlanding(&bomb_list, tx, ty, cno); + pln_newlanding(&esc_list, tx, ty, cno); + } + pln_put(&bomb_list); + pln_put(&esc_list); + return RET_OK; +} diff --git a/src/lib/commands/foll.c b/src/lib/commands/foll.c new file mode 100644 index 00000000..a0d52a3a --- /dev/null +++ b/src/lib/commands/foll.c @@ -0,0 +1,112 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * foll.c: Set leader of a set of ships + * + * Known contributors to this file: + * Robert Forsman + */ + +#include +#include "misc.h" +#include "player.h" +#include "var.h" +#include "ship.h" +#include "xy.h" +#include "nsc.h" +#include "file.h" +#include "nat.h" +#include "commands.h" +#include "optlist.h" + +int +foll(void) +{ + struct shpstr ship; + s_char *cp; + int good,leader,count=0; + coord x,y; + struct nstr_item nstr; + s_char buf[1024]; + + if (!opt_SAIL) { + pr("The SAIL option is not enabled, so this command is not valid.\n"); + return RET_FAIL; + } + if (!snxtitem(&nstr, EF_SHIP, player->argp[1])) + return RET_SYN; + cp = getstarg(player->argp[2],"leader?", buf); + if (cp==0) cp=""; + good = sscanf(cp,"%d",&leader); + if (!good) + return RET_SYN; + getship(leader,&ship); + if (ship.shp_own!=player->cnum && + getrel(getnatp(ship.shp_own),player->cnum) < FRIENDLY) + { + pr("That ship won't let you follow.\n"); + return RET_FAIL; + } + x = ship.shp_x; + y = ship.shp_y; + while (nxtitem(&nstr, (s_char *)&ship)) { + if (!player->owner) + continue; + if ( ship.shp_x!=x || ship.shp_y!=y ) + { + pr("Ship #%d not in same sector as #%d\n",ship.shp_uid,leader); + continue; + } + if (ship.shp_uid==leader) + { + pr("Ship #%d can't follow itself!\n",leader); + continue; + } + if ((ship.shp_autonav & AN_AUTONAV) && !(ship.shp_autonav & AN_STANDBY)) + { + pr("Ship #%d has other orders!\n",ship.shp_uid); + continue; + } + count++; + ship.shp_mission = 0; + *ship.shp_path = 'f'; + ship.shp_path[1] = 0; +/* sprintf(ship.shp_path,"f%d",leader);*/ + ship.shp_follow = leader; + pr("Ship #%d follows #%d.\n",ship.shp_uid,leader); + putship(ship.shp_uid, &ship); + } + if (count == 0) { + if (player->argp[1]) + pr("%s: No ship(s)\n", player->argp[1]); + else + pr("%s: No ship(s)\n", ""); + return RET_FAIL; + }else + pr("%d ship%s\n", count, splur(count)); + return RET_OK; +} diff --git a/src/lib/commands/forc.c b/src/lib/commands/forc.c new file mode 100644 index 00000000..26d81eae --- /dev/null +++ b/src/lib/commands/forc.c @@ -0,0 +1,72 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * force.c: Force an update to occur (deity) + * + * Known contributors to this file: + * Dave Pare, 1994 + */ + +#include +#include "misc.h" +#include "player.h" +#include "empthread.h" +#include "commands.h" + +int +force(void) +{ + extern empth_sem_t *update_sem; + extern int update_pending; + extern int shutdown_pending; + int seconds; + time_t now; + + if (update_pending) { + pr("Update is pending\n"); + return RET_FAIL; + } + if (shutdown_pending) { + pr("Shutdown is pending\n"); + return RET_FAIL; + } + if (updates_disabled()) { + pr("Updates are disabled\n"); + return RET_FAIL; + } + seconds = onearg(player->argp[1], "Time until update [in seconds]? "); + if (seconds < 0) + return RET_FAIL; + if (seconds) { + time(&now); + pr("Waiting %d seconds...\n", seconds); + empth_sleep(now + seconds); + } + pr("Scheduling update now\n"); + empth_sem_signal(update_sem); + return RET_OK; +} diff --git a/src/lib/commands/fort.c b/src/lib/commands/fort.c new file mode 100644 index 00000000..ca683f14 --- /dev/null +++ b/src/lib/commands/fort.c @@ -0,0 +1,160 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * fort.c: Increase the fortification value of land units + * + * Known contributors to this file: + * Steve McClure, 1999 + * + */ + +#include "misc.h" +#include "player.h" +#include "var.h" +#include "xy.h" +#include "sect.h" +#include "land.h" +#include "nat.h" +#include "nsc.h" +#include "deity.h" +#include "file.h" +#include "commands.h" + +int +fort(void) +{ + int nunits; + struct nstr_item ni; + struct lndstr land; + int fort_amt, hard_amt, mob_used; + int eng; + s_char *p; + extern int land_mob_max; + s_char buf[1024]; + + if (!snxtitem(&ni, EF_LAND, player->argp[1])) + return RET_SYN; + p = getstarg(player->argp[2], "Amount: ", buf); + if (p == 0 || *p == 0) + return RET_SYN; + fort_amt = atoi(p); + if (fort_amt > land_mob_max) + fort_amt = land_mob_max; + nunits = 0; + while (nxtitem(&ni, (s_char *)&land)) { + if (!player->owner || land.lnd_own == 0) + continue; + if (land.lnd_type < 0 || land.lnd_type > lnd_maxno) { + pr("bad unit type %d (#%d)\n", + land.lnd_type, ni.cur); + continue; + } + + getland(land.lnd_uid,&land); + if (land.lnd_mobil < 0) + continue; + if (land.lnd_ship >= 0) { + pr("%s is on a ship and can't be fortified\n", + prland(&land)); + continue; + } + + hard_amt = fort_amt; + + /* This is use for things like "fort * -67" which will + use all mobility down to leaving 67 left. */ + if (hard_amt < 0) { + hard_amt = land.lnd_mobil + hard_amt; + if (hard_amt < 0) + continue; + } + + nunits++; + + hard_amt = min(land.lnd_mobil, hard_amt); + + if ((land.lnd_harden + hard_amt) > land_mob_max) + hard_amt = land_mob_max - land.lnd_harden; + + eng = is_engineer(land.lnd_x, land.lnd_y); + + if (eng) + hard_amt = ((float)hard_amt * 1.5); + + if ((land.lnd_harden + hard_amt) > land_mob_max) + hard_amt = land_mob_max - land.lnd_harden; + + /* Ok, set the mobility used */ + mob_used = hard_amt; + + /* Now, if an engineer helped, it's really only 2/3rds of + that */ + if (eng) + mob_used = (int)((float)mob_used / 1.5); + + /* If we increased it, but not much, we gotta take at least 1 + mob point. */ + if (mob_used <= 0 && hard_amt > 0) + mob_used = 1; + + land.lnd_mobil -= mob_used; + if (land.lnd_mobil < 0) + land.lnd_mobil = 0; + + land.lnd_harden += hard_amt; + land.lnd_harden = min(land.lnd_harden, land_mob_max); + + pr("%s hardened to %d\n", prland(&land), + land.lnd_harden); + + putland(land.lnd_uid,&land); + } + if (nunits == 0) { + if (player->argp[1]) + pr("%s: No unit(s)\n", player->argp[1]); + else + pr("%s: No unit(s)\n", ""); + return RET_FAIL; + }else + pr("%d unit%s\n", nunits, splur(nunits)); + return RET_OK; +} + +int +is_engineer(int x, int y) +{ + struct nstr_item ni; + struct lndstr land; + + snxtitem_xy(&ni, EF_LAND, x,y); + while(nxtitem(&ni, (s_char *)&land)){ + if (lchr[(int)land.lnd_type].l_flags & L_ENGINEER) + return 1; + } + + return 0; +} diff --git a/src/lib/commands/fuel.c b/src/lib/commands/fuel.c new file mode 100644 index 00000000..44c24cae --- /dev/null +++ b/src/lib/commands/fuel.c @@ -0,0 +1,498 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * fuel.c: fuel ships/land units + * + * Known contributors to this file: + * + */ + +#include "misc.h" +#include "player.h" +#include "var.h" +#include "xy.h" +#include "ship.h" +#include "plane.h" +#include "land.h" +#include "nat.h" +#include "nsc.h" +#include "deity.h" +#include "file.h" +#include "sect.h" +#include "optlist.h" +#include "commands.h" + + +union item_u { + struct shpstr ship; + struct lndstr land; +}; + +int +fuel(void) +{ + struct nstr_item ni; + union item_u item, item2; + int type; + struct mchrstr *mp; + struct lchrstr *lcp; + s_char *p; + int fueled; + int land_fuel, ship_fuel; + int oil_amt, pet_amt, fuel_amt, tot_fuel, max_amt; + int move_amt; + float extra; + struct sctstr sect; + struct natstr *natp; + int harbor,sector; + int fuelled_ship = -1; + struct nstr_item tender, ltender; + s_char prompt[128]; + s_char buf[1024]; + + if (opt_FUEL == 0) { + pr ("Option 'FUEL' not enabled\n"); + return RET_SYN; + } + if ((p = getstarg(player->argp[1], "Ship or land unit (s,l)? ", buf)) == 0) + return RET_SYN; + type = ef_byname(p); + if (type == EF_SECTOR) + type = EF_SHIP; + if (type != EF_SHIP && type != EF_LAND){ + pr("Ships or land units only! (s, l)\n" ); + return RET_SYN; + } + sprintf(prompt, "%s(s)? ", ef_nameof(type)); + p = getstarg(player->argp[2], prompt, buf); + if (!snxtitem(&ni, type, p)) + return RET_SYN; + if (isdigit(*p)) + fuelled_ship = atoi(p); + p = getstarg(player->argp[3], "Amount: ", buf); + if (p == 0 || *p == 0) + return RET_SYN; + fuel_amt = atoi(p); + if (fuel_amt <= 0){ + pr("Fuel amount must be positive!\n"); + return RET_FAIL; + } + + ni.flags &= ~(EFF_OWNER); + + while (nxtitem(&ni, (s_char *)&item)) { + fueled = 0; + if (type == EF_SHIP) { + if (item.ship.shp_own != player->cnum){ + int rel; + + if (item.ship.shp_uid != fuelled_ship) + continue; + natp=getnatp(player->cnum); + rel=getrel(natp,item.ship.shp_own); + if (rel < FRIENDLY) + continue; + } + if (!getsect(item.ship.shp_x, item.ship.shp_y, §)) + continue; + if (!item.ship.shp_own) + continue; + + if ((sect.sct_type != SCT_HARBR) && (sect.sct_type != SCT_WATER) && (sect.sct_type != SCT_BSPAN) && (!opt_BIG_CITY || sect.sct_type != SCT_CAPIT)){ + pr("Sector %s is not a harbor, bridge span, or sea.\n", + xyas(item.ship.shp_x, item.ship.shp_y, + item.ship.shp_own)); + continue; + } + + mp = &mchr[(int)item.ship.shp_type]; + + harbor=0; + if (sect.sct_type == SCT_HARBR || (opt_BIG_CITY && sect.sct_type == SCT_CAPIT)){ + harbor=1; + oil_amt = getvar(V_OIL, (s_char *)§, EF_SECTOR); + pet_amt = getvar(V_PETROL, (s_char *)§, EF_SECTOR); + if ((oil_amt+pet_amt) == 0) + harbor=0; + + if (sect.sct_effic < 2) { + pr("The harbor at %s is not 2%% efficient yet.\n", + xyas(item.ship.shp_x, + item.ship.shp_y, + player->cnum)); + harbor=0; + } + if ((sect.sct_own != player->cnum) && sect.sct_own) + harbor=0; + } + + if ((mp->m_fuelu == 0) && (item.ship.shp_own == player->cnum)){ + pr("%s does not use fuel!\n", prship(&item.ship)); continue; + } + + if (harbor){ + ship_fuel = item.ship.shp_fuel; + oil_amt = getvar(V_OIL, (s_char *)§, EF_SECTOR); + pet_amt = getvar(V_PETROL, (s_char *)§, EF_SECTOR); + max_amt = mp->m_fuelc-ship_fuel; + + if (max_amt == 0){ + pr("%s already has a full fuel load.\n",prship(&item.ship)); + continue; + } + tot_fuel = (oil_amt*50 + pet_amt*5); + if (tot_fuel == 0){ + pr("No fuel in the harbor at %s!\n", + xyas(sect.sct_x,sect.sct_y, + player->cnum)); + continue; + } + move_amt = min(tot_fuel, fuel_amt); + move_amt = min(move_amt, max_amt); + + if (move_amt == 0) + continue; + + item.ship.shp_fuel += move_amt; + + fueled=1; + if ((pet_amt*5) >= move_amt){ + extra = ((float)move_amt/5.0)-(move_amt/5); + if (extra > 0.0) + putvar(V_PETROL, + max((pet_amt-(move_amt/5))-1,0), + (s_char *)§, EF_SECTOR); + else + putvar(V_PETROL, + max((pet_amt-(move_amt/5)),0), + (s_char *)§, EF_SECTOR); + }else{ + putvar(V_PETROL, 0, (s_char *)§, EF_SECTOR); + move_amt -= pet_amt*5; + extra = ((float)move_amt/50.0)-(move_amt/50); + putvar(V_OIL, max(oil_amt-(move_amt/50), 0), + (s_char *)§, EF_SECTOR); + if (extra > 0.0) + putvar(V_OIL, + max((oil_amt-(move_amt/50))-1,0), + (s_char *)§, EF_SECTOR); + else + putvar(V_OIL, + max((oil_amt-(move_amt/50)),0), + (s_char *)§, EF_SECTOR); + } + + /* load plague */ + if (getvar(V_PSTAGE, (s_char *)§, EF_SECTOR) == + PLG_INFECT && getvar(V_PSTAGE, + (s_char *)&item.ship, EF_SHIP) == PLG_HEALTHY) + putvar(V_PSTAGE, PLG_EXPOSED, + (s_char *)&item.ship, EF_SHIP); + + putsect(§); + putship(item.ship.shp_uid, &item.ship); + } + else{ /* not in a harbor */ + if (!player->argp[4]) + pr("%s is not in a supplied, efficient harbor\n", prship(&item.ship)); + if (!snxtitem(&tender, EF_SHIP, getstarg(player->argp[4], "Oiler? ", buf))) + continue; + + if (!check_ship_ok(&item.ship)) + continue; + + if (!nxtitem(&tender, (s_char *)&item2)) + continue; + + if (!(mchr[(int)item2.ship.shp_type].m_flags & M_OILER)){ + pr("%s is not an oiler!\n", + prship(&item2.ship)); + continue; + } + if (item2.ship.shp_own != player->cnum){ + pr("You don't own that oiler!\n"); + continue; + } + + if ((item2.ship.shp_x != item.ship.shp_x) || + (item2.ship.shp_y != item.ship.shp_y)){ + pr("Not in the same sector!\n"); + continue; + } + ship_fuel = item.ship.shp_fuel; + oil_amt = getvar(V_OIL, (s_char *)&item2.ship, EF_SHIP); + pet_amt = getvar(V_PETROL, (s_char *)&item2.ship, EF_SHIP); + max_amt = mp->m_fuelc-ship_fuel; + + if (max_amt == 0){ + pr("%s already has a full fuel load.\n", prship(&item.ship)); + continue; + } + tot_fuel = oil_amt*50 + pet_amt*5; + move_amt = min(tot_fuel, fuel_amt); + move_amt = min(move_amt, max_amt); + + if (move_amt == 0) + continue; + + item.ship.shp_fuel += move_amt; + + fueled=1; + if ((pet_amt*5) >= move_amt){ + extra = ((float)move_amt/5.0)-(move_amt/5); + if (extra > 0.0) + putvar(V_PETROL, + max((pet_amt-(move_amt/5))-1,0), + (s_char *)&item2.ship, EF_SHIP); + else + putvar(V_PETROL, + max((pet_amt-(move_amt/5)),0), + (s_char *)&item2.ship, EF_SHIP); + }else{ + putvar(V_PETROL, 0, (s_char *)&item2.ship, EF_SHIP); + move_amt -= pet_amt*5; + extra = ((float)move_amt/50.0)-(move_amt/50); + putvar(V_OIL, max(oil_amt-(move_amt/50), 0), + (s_char *)&item2.ship, EF_SHIP); + if (extra > 0.0) + putvar(V_OIL, + max((oil_amt-(move_amt/50))-1,0), + (s_char *)&item2.ship, EF_SHIP); + else + putvar(V_OIL, + max((oil_amt-(move_amt/50)),0), + (s_char *)&item2.ship, EF_SHIP); + } + + /* load plague */ + if (getvar(V_PSTAGE, (s_char *)&item2.ship, EF_SHIP) == + PLG_INFECT && getvar(V_PSTAGE, + (s_char *)&item.ship, EF_SHIP) == PLG_HEALTHY) + putvar(V_PSTAGE, PLG_EXPOSED, + (s_char *)&item.ship, EF_SHIP); + + putship(item.ship.shp_uid, &item.ship); + /* quick hack -KHS */ + if (item.ship.shp_uid == item2.ship.shp_uid) + item2.ship.shp_fuel = item.ship.shp_fuel; + putship(item2.ship.shp_uid, &item2.ship); + } + pr("%s",prship(&item.ship)); + } + else { + if (item.land.lnd_own != player->cnum) + continue; + + if (!getsect(item.land.lnd_x, item.land.lnd_y, §)) + continue; + + if (!player->owner) + continue; + + lcp = &lchr[(int)item.land.lnd_type]; + + sector=1; + oil_amt = getvar(V_OIL, (s_char *)§, EF_SECTOR); + pet_amt = getvar(V_PETROL, (s_char *)§, EF_SECTOR); + + if ((oil_amt+pet_amt) == 0) + sector=0; + + if ((item.land.lnd_fuelu == 0) && (item.land.lnd_own == player->cnum)){ + pr("%s does not use fuel!\n", prland(&item.land)); + continue; + } + + if (sector){ + land_fuel = item.land.lnd_fuel; + oil_amt = getvar(V_OIL, (s_char *)§, + EF_SECTOR); + pet_amt = getvar(V_PETROL, (s_char *)§, + EF_SECTOR); + max_amt = item.land.lnd_fuelc-land_fuel; + + if (max_amt == 0){ + pr("%s already has a full fuel load.\n", prland(&item.land)); + continue; + } + tot_fuel = (oil_amt*50 + pet_amt*5); + if (tot_fuel == 0){ + pr("No fuel in the sector at %s!\n", + xyas(sect.sct_x,sect.sct_y, + player->cnum)); + continue; + } + move_amt = min(tot_fuel, fuel_amt); + move_amt = min(move_amt, max_amt); + + if (move_amt == 0) + continue; + + item.land.lnd_fuel += move_amt; + + fueled=1; + if ((pet_amt*5) >= move_amt){ + extra = ((float)move_amt/5.0)-(move_amt/5); + if (extra > 0.0) + putvar(V_PETROL, + max((pet_amt-(move_amt/5))-1,0), + (s_char *)§, EF_SECTOR); + else + putvar(V_PETROL, + max((pet_amt-(move_amt/5)),0), + (s_char *)§, EF_SECTOR); + }else{ + putvar(V_PETROL, 0, (s_char *)§, EF_SECTOR); + move_amt -= pet_amt*5; + extra = ((float)move_amt/50.0)-(move_amt/50); + putvar(V_OIL, max(oil_amt-(move_amt/50), 0), + (s_char *)§, EF_SECTOR); + if (extra > 0.0) + putvar(V_OIL, + max((oil_amt-(move_amt/50))-1,0), + (s_char *)§, EF_SECTOR); + else + putvar(V_OIL, + max((oil_amt-(move_amt/50)),0), + (s_char *)§, EF_SECTOR); + } + + /* load plague */ + if (getvar(V_PSTAGE, (s_char *)§, EF_SECTOR) == + PLG_INFECT && getvar(V_PSTAGE, + (s_char *)&item.land, EF_LAND) == PLG_HEALTHY) + putvar(V_PSTAGE, PLG_EXPOSED, + (s_char *)&item.land, EF_LAND); + + putsect(§); + putland(item.land.lnd_uid, &item.land); + } + else{ /* not in a sector */ + if (!player->argp[4]) + pr("%s is not in a supplied sector\n", + prland(&item.land)); + if (!snxtitem(<ender, EF_LAND, + getstarg(player->argp[4], "Supply unit? ", buf))) + continue; + + if (!check_land_ok(&item.land)) + continue; + + if (!nxtitem(<ender, (s_char *)&item2)) + continue; + + if (!(lchr[(int)item2.land.lnd_type].l_flags & L_SUPPLY)){ + pr("%s is not a supply unit!\n", + prland(&item2.land)); + continue; + } + if (item2.land.lnd_own != player->cnum){ + pr("You don't own that unit!\n"); + continue; + } + + if ((item2.land.lnd_x != item.land.lnd_x) || + (item2.land.lnd_y != item.land.lnd_y)){ + pr("Not in the same sector!\n"); + continue; + } + land_fuel = item.land.lnd_fuel; + oil_amt = getvar(V_OIL, (s_char *)&item2.land, EF_LAND); + pet_amt = getvar(V_PETROL, (s_char *)&item2.land, EF_LAND); + max_amt = item.land.lnd_fuelc-land_fuel; + + if (max_amt == 0){ + pr("%s already has a full fuel load.\n", prland(&item.land)); + continue; + } + tot_fuel = oil_amt*50 + pet_amt*5; + move_amt = min(tot_fuel, fuel_amt); + move_amt = min(move_amt, max_amt); + + if (move_amt == 0) + continue; + + item.land.lnd_fuel += move_amt; + + fueled=1; + if ((pet_amt*5) >= move_amt){ + extra = ((float)move_amt/5.0)-(move_amt/5); + if (extra > 0.0) + putvar(V_PETROL, + max((pet_amt-(move_amt/5))-1,0), + (s_char *)&item2.land, EF_LAND); + else + putvar(V_PETROL, + max((pet_amt-(move_amt/5)),0), + (s_char *)&item2.land, EF_LAND); + }else{ + putvar(V_PETROL, 0, (s_char *)&item2.land, EF_LAND); + move_amt -= pet_amt*5; + extra = ((float)move_amt/50.0)-(move_amt/50); + putvar(V_OIL, max(oil_amt-(move_amt/50), 0), + (s_char *)&item2.land, EF_LAND); + if (extra > 0.0) + putvar(V_OIL, + max((oil_amt-(move_amt/50))-1,0), + (s_char *)&item2.land, EF_LAND); + else + putvar(V_OIL, + max((oil_amt-(move_amt/50)),0), + (s_char *)&item2.land, EF_LAND); + } + + /* load plague */ + if (getvar(V_PSTAGE, (s_char *)&item2.land, EF_LAND) == + PLG_INFECT && getvar(V_PSTAGE, + (s_char *)&item.land, EF_LAND) == PLG_HEALTHY) + putvar(V_PSTAGE, PLG_EXPOSED, + (s_char *)&item.land, EF_LAND); + + putland(item.land.lnd_uid, &item.land); + /* quick hack -KHS */ + if (item2.land.lnd_uid == item.land.lnd_uid) + item2.land.lnd_fuel = item.land.lnd_fuel; + putland(item2.land.lnd_uid, &item2.land); + } + pr("%s",prland(&item.land)); + } + if (fueled){ + pr(" takes on %d fuel in %s\n", + move_amt, + xyas(item.ship.shp_x, item.ship.shp_y , player->cnum)); + if (player->cnum != item.ship.shp_own) + wu(0, item.ship.shp_own, + "%s takes on %d fuel in %s courtesy of %s\n", + prship(&item.ship), + move_amt, + xyas(item.ship.shp_x, item.ship.shp_y , + item.ship.shp_own), + cname(player->cnum)); + } + } + return RET_OK; +} diff --git a/src/lib/commands/give.c b/src/lib/commands/give.c new file mode 100644 index 00000000..0c65e4a5 --- /dev/null +++ b/src/lib/commands/give.c @@ -0,0 +1,105 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * give.c: give stuff to countries (deity) + * + * Known contributors to this file: + * David Muir Sharnoff + * Steve McClure, 1997 + */ + +#include "misc.h" +#include "player.h" +#include "var.h" +#include "sect.h" +#include "nat.h" +#include "news.h" +#include "xy.h" +#include "nsc.h" +#include "item.h" +#include "deity.h" +#include "file.h" +#include "commands.h" +#include "optlist.h" + +/* + * format: give + */ +int +give(void) +{ + struct sctstr sect; + int amt; + struct ichrstr *ip; + int m, n; + s_char *p; + struct nstr_sect nstr; + s_char buf[1024]; + + if (!(ip = whatitem(player->argp[1], "which commodity? "))) + return RET_SYN; + if (!snxtsct(&nstr, player->argp[2])) + return RET_SYN; + while (nxtsct(&nstr, §) > 0) { + p = getstarg(player->argp[3], "how much : ", buf); + if (p == 0 || *p == '\0') + return RET_SYN; + if ((amt = atoi(p)) == 0) + return RET_SYN; + n = getvar(ip->i_vtype, (s_char *)§, EF_SECTOR); + if (amt < 0 && -amt > n) { + m = 0; + } else if (amt > 0 && amt+n > 9990) { + m = 9990; + } else + m = n + amt; + if (putvar(ip->i_vtype, m, (s_char *)§, EF_SECTOR) < 0) { + pr("No room to store %s in %s\n", ip->i_name, + xyas(sect.sct_x, sect.sct_y, player->cnum)); + return RET_FAIL; + } + putsect(§); + if (sect.sct_own != 0 && m != n) { + if (m > n) { + if (opt_GODNEWS) + nreport(player->cnum, N_GIFT, sect.sct_own, 1); + wu(player->cnum, sect.sct_own, "%s gave you %d %s in %s\n", + cname(player->cnum), m-n, ip->i_name, + xyas(sect.sct_x, sect.sct_y, sect.sct_own)); + } else { + if (opt_GODNEWS) + nreport(sect.sct_own, N_TAKE, player->cnum, 1); + wu(player->cnum, sect.sct_own, "%s stole %d %s from %s\n", + cname(player->cnum), n-m, ip->i_name, + xyas(sect.sct_x, sect.sct_y, sect.sct_own)); + } + } + pr("%d %s in %s\n", m, ip->i_name, + xyas(sect.sct_x, sect.sct_y, player->cnum)); + } + return RET_OK; +} diff --git a/src/lib/commands/grin.c b/src/lib/commands/grin.c new file mode 100644 index 00000000..d437578d --- /dev/null +++ b/src/lib/commands/grin.c @@ -0,0 +1,96 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * grin.c: Grind gold bars into dust + * + * Known contributors to this file: + * + */ + +#include "misc.h" +#include "player.h" +#include "var.h" +#include "xy.h" +#include "sect.h" +#include "nat.h" +#include "nsc.h" +#include "deity.h" +#include "file.h" +#include "product.h" +#include "commands.h" + +int +grin(void) +{ + struct nstr_sect nstr; + int vec[I_MAX+1]; + struct sctstr sect; + s_char *p; + int i,n,qty; + int avail; + s_char buf[1024]; + + if ((p = getstarg(player->argp[1], "Sectors? ", buf)) == 0) + return RET_SYN; + if (!snxtsct(&nstr, p)) + return RET_SYN; + if ((p = getstarg(player->argp[2], "amount : ", buf)) == 0 || *p == 0) + return RET_SYN; + qty = atoi(p); + if(qty < 0) + return RET_SYN; + while (nxtsct(&nstr, §)) { + if (!player->owner) + continue; +/* getsect(item.sct_x, item.sct_y, §); */ + if (sect.sct_effic < 60 || sect.sct_own != player->cnum) + continue; + getvec(VT_ITEM, vec, (s_char *)§, EF_SECTOR); + n = (vec[I_BAR] >= qty) ? qty : vec[I_BAR]; + avail = n * 5.0; + if(avail > sect.sct_avail) { + n = sect.sct_avail / 5; + avail = sect.sct_avail; + if(n == 0) + continue; + } + if (n) { + vec[I_BAR] -= n; + pr("%d bars ground up in %s\n", n, + xyas(sect.sct_x, sect.sct_y, player->cnum)); + for (i = 0; i < pchr[P_BAR].p_nv; i++) { + vec[unitem(pchr[P_BAR].p_vtype[i])] += (int)((n * + pchr[P_BAR].p_vamt[i]) * 0.8); + } + putvec(VT_ITEM, vec, (s_char *)§, EF_SECTOR); + sect.sct_avail -= avail; + putsect(§); + } + } + return RET_OK; +} + diff --git a/src/lib/commands/hard.c b/src/lib/commands/hard.c new file mode 100644 index 00000000..48a069f0 --- /dev/null +++ b/src/lib/commands/hard.c @@ -0,0 +1,121 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * hard.c: Increases the silo protection of a given missile + * + * Known contributors to this file: + * Dave Pare, 1986 + */ + +#include "misc.h" +#include "player.h" +#include "var.h" +#include "sect.h" +#include "item.h" +#include "plane.h" +#include "nuke.h" +#include "ship.h" +#include "xy.h" +#include "nsc.h" +#include "nat.h" +#include "file.h" +#include "commands.h" + +/* + * harden + */ +int +hard(void) +{ + struct plchrstr *pcp; + struct plnstr pln; + int level; + s_char *p; + int hcm; + int n; + struct nstr_item ni; + struct sctstr sect; + s_char buf[1024]; + long cash; + struct natstr *natp; + + if (!snxtitem(&ni, EF_PLANE, player->argp[1])) + return RET_SYN; + if ((p = getstarg(player->argp[2], "Increase by? ", buf)) == 0 || *p == 0) + return RET_SYN; + level = atoi(p); + if (level < 0) + return RET_SYN; + natp = getnatp(player->cnum); + cash = natp->nat_money; + while (nxtitem(&ni, (s_char *)&pln)) { + if (!player->owner) + continue; + pcp = &plchr[(int)pln.pln_type]; + if ((pcp->pl_flags & P_M) == 0) { + pr("%s isn't a missile!\n", prplane(&pln)); + continue; + } + if (pln.pln_ship >= 0) /* can't harden ssbns ... */ + continue; + n = level; + if (level + pln.pln_harden > 127) + n = 127 - pln.pln_harden; + if (n <= 0) { + pr("%s is already completely hardened!\n", prplane(&pln)); + continue; + } + if (!getsect(pln.pln_x, pln.pln_y, §)) + continue; + if (sect.sct_own != player->cnum) { + pr("%s: you don't own %s!\n", + prplane(&pln), + xyas(pln.pln_x, pln.pln_y, player->cnum)); + continue; + } + hcm = getvar(V_HCM, (s_char *)§, EF_SECTOR); + if (hcm == 0) { + pr("No hcm in %s\n", + xyas(pln.pln_x, pln.pln_y, player->cnum)); + continue; + } + if (player->dolcost + 5.0 * n > cash) { + pr("You don't have enough money to harden %s!\n", + prplane(&pln)); + continue; + } + if (hcm <= n) + n = hcm; + pln.pln_harden += n; + player->dolcost += (5.0 * n); + putplane(pln.pln_uid, &pln); + putvar(V_HCM, hcm - n, (s_char *)§, EF_SECTOR); + putsect(§); + pr("%s hardened to %d\n", prplane(&pln), pln.pln_harden); + } + return RET_OK; +} diff --git a/src/lib/commands/head.c b/src/lib/commands/head.c new file mode 100644 index 00000000..b84a13fa --- /dev/null +++ b/src/lib/commands/head.c @@ -0,0 +1,258 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * head.c: Print headlines of the Empire News + * + * Known contributors to this file: + * + */ + +#include "misc.h" +#include "player.h" +#include "news.h" +#include "nat.h" +#include "file.h" +#include "xy.h" +#include "nsc.h" +#include "commands.h" + +struct histstr { + int h_past; + int h_recent; +}; + +static s_char *head_meanwhile(int val); +static s_char *head_describe(struct histstr *hp, int what); +static int head_printscoop(struct histstr (*hist)[MAXNOC], natid ano, natid vno); +static int head_findscoop(struct histstr (*hist)[MAXNOC], register natid maxcnum, natid *ano, natid *vno); + +int +head(void) +{ + register int i; + register struct histstr *hp; + register natid maxcnum; + time_t now; + int severity; + int scoop; + time_t news_per; + time_t news_age; + struct histstr hist[MAXNOC][MAXNOC]; + struct natstr *natp; + struct nwsstr news; + natid actor; + natid victim; + struct nstr_item nstr; + int n; + + (void) time(&now); + natp = getnatp(player->cnum); + if (player->argp[1] != 0 && *player->argp[1] != 0) { + news_per = days(atoi(player->argp[1])); + if (news_per > days(3)) + news_per = days(3); + } else + /* replaced the following line with the one under it to + * fix headlines which never change. + * 3/3/90 bailey@math-cs.kent.edu + */ +/* news_per = natp->nat_newstim; */ + news_per = now - natp->nat_newstim; + pr("\n -=[ EMPIRE NEWS ]=-\n"); + pr("::::::::::::::::::::::::::::::::::::::::::::::::::\n"); + pr("! \"All the news that fits, we print.\" !\n"); + pr("::::::::::::::::::::::::::::::::::::::::::::::::::\n"); + pr(" %s", ctime(&now)); + pr("\n"); + bzero((s_char *)hist, sizeof (hist)); + snxtitem_all(&nstr, EF_NEWS); + maxcnum = 0; + while (nxtitem(&nstr, (s_char *)&news)) { + news_age = now - news.nws_when; + if (news_age > news_per) + continue; + if (news.nws_ano == news.nws_vno) + continue; + if ((i = rpt[(int)news.nws_vrb].r_good_will) == 0) + continue; + if (news_age > (news_per / 2)) + hist[news.nws_ano][news.nws_vno].h_past += i; + else + hist[news.nws_ano][news.nws_vno].h_recent += i; + if (maxcnum < news.nws_ano) + maxcnum = news.nws_ano; + if (maxcnum < news.nws_vno) + maxcnum = news.nws_vno; + } + for (n=0; n<5; n++) { + if ((scoop = head_findscoop(hist, maxcnum, &actor, &victim))<10) + break; + severity = head_printscoop(hist, actor, victim); + hp = &hist[actor][victim]; + severity = hp->h_recent - hp->h_past; + if (severity <= -scoop/2 || severity >= scoop/2) { + pr("\t%s\n", head_meanwhile(severity)); + (void) head_printscoop(hist, victim, actor); + } + } + if (n <= 1) + pr("\nRelative calm prevails.\n"); + return RET_OK; +} + +static +int +head_printscoop(struct histstr (*hist)[MAXNOC], natid ano, natid vno) +{ + register struct histstr *hp; + int severity; + + hp = &hist[ano][vno]; + severity = abs(hp->h_past) > abs(hp->h_recent) ? 1 : 0; + severity += (hp->h_past >= 0) ? 2 : 0; + severity += (hp->h_recent >= 0) ? 4 : 0; + pr(head_describe(hp, severity), cname(ano), cname(vno)); + pr("\n"); + hp->h_past = 0; + hp->h_recent = 0; + return severity; +} + +static +s_char * +head_meanwhile(int val) +{ + switch (val & 03) { + case 0: + return "Meanwhile"; + case 1: + return "On the other hand"; + case 2: + return "At the same time"; + case 3: + return "Although"; + } + /*NOTREACHED*/ + return ""; +} + +static +s_char * +head_describe(struct histstr *hp, int what) +{ + s_char *cp; + + cp = 0; + switch (what) { + case 0: + if (hp->h_recent > hp->h_past/2) + cp = "Bad relations between %s and %s worsen!"; + else + cp = "Carnage wrought by %s on %s continues unabated!"; + break; + case 1: + if (hp->h_recent < -16) + cp = "%s agression against %s has lessened slightly"; + else + cp = "Peace talks may occur between %s & %s"; + break; + case 2: + if (hp->h_recent < -16) { + if (hp->h_past > 0) + cp = " ! WAR ! Reversal of prior %s -- %s relations"; + else if (hp->h_recent >= -25) + cp = "VIOLENCE ERUPTS! -- %s wages war on %s"; + else + cp = "%s wreaks havoc on %s!"; + } else + cp = "Breakdown in communication between %s & %s"; + break; + case 3: + cp = "FLASH! %s turns on former ally, %s!"; + break; + case 4: + cp = "%s \"makes friends\" with %s"; + break; + case 5: + if (hp->h_past >= -25) + cp = "%s seems to have forgotten earlier disagreement with %s"; + else + cp = "Tensions ease as %s attacks on %s seem at an end"; + break; + case 6: + cp = "%s good deeds further growing alliance with %s"; + break; + case 7: + if (hp->h_recent - hp->h_past < 12) + cp = "Honeymoon appears to be over between %s & %s"; + else + cp = "Friendly relations between %s & %s have cooled"; + break; + } + return cp; +} + +/* + * returns 9 if no scoops were found + * Pretty strange. + */ +static +int +head_findscoop(struct histstr (*hist)[MAXNOC], register natid maxcnum, natid *ano, natid *vno) +{ + register struct histstr *hp; + register int i; + register int j; + register int k; + int scoop; + natid actor; + natid victim; + + scoop = 9; + actor = 0; + victim = 0; + for (i = 1; i < maxcnum; i++) { + for (j = 1; j < maxcnum; j++) { + hp = &hist[i][j]; + k = abs(hp->h_recent / 2); + if (k > scoop) { + scoop = k; + actor = (natid) i; + victim = (natid) j; + } + k = abs(hp->h_recent - hp->h_past); + if (k > scoop) { + scoop = k; + actor = (natid) i; + victim = (natid) j; + } + } + } + *ano = actor; + *vno = victim; + return scoop; +} diff --git a/src/lib/commands/hidd.c b/src/lib/commands/hidd.c new file mode 100644 index 00000000..7064eb83 --- /dev/null +++ b/src/lib/commands/hidd.c @@ -0,0 +1,92 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * hidd.c: Do a hidden values report (deity) + * + * Known contributors to this file: + * Jeff Wallace, 1989 + * Pat Loney, 1998 + * Steve McClure, 1998 + */ + +#include "misc.h" +#include "player.h" +#include "var.h" +#include "sect.h" +#include "xy.h" +#include "nsc.h" +#include "nat.h" +#include "deity.h" +#include "file.h" +#include "commands.h" + +int +hidd(void) +{ + struct sctstr sect; + int nsect; + struct nstr_sect nstr; + int cond[I_MAX+1]; + + if (!snxtsct(&nstr, player->argp[1])) + return RET_SYN; + prdate(); + nsect = 0; + while (nxtsct(&nstr, §)) { + if (!player->owner) + continue; + if (nsect++ == 0) { + if (player->god) + pr(" "); + pr("HIDDEN VALUES old che------- plague----\n"); + if (player->god) + pr("own "); + pr(" sect eff own loyal cnum value stage time mines\n"); + } + if (player->god) + pr("%3d ", sect.sct_own); + getvec(VT_COND, cond, (s_char *)§, EF_SECTOR); + prxy("%4d,%-4d", nstr.x, nstr.y, player->cnum); + pr(" %c %3d%% %3d %3d %3d %3d %3d %3d %3d", + dchr[sect.sct_type].d_mnem, sect.sct_effic, + sect.sct_oldown, sect.sct_loyal, + get_che_cnum(cond[C_CHE]), + get_che_value(cond[C_CHE]), + cond[C_PSTAGE], cond[C_PTIME], + cond[C_MINE]); + pr("\n"); + } + if (nsect == 0) { + if (player->argp[1]) + pr("%s: No sector(s)\n", player->argp[1]); + else + pr("%s: No sector(s)\n", ""); + return RET_FAIL; + }else + pr("%d sector%s\n", nsect, splur(nsect)); + return 0; +} diff --git a/src/lib/commands/improve.c b/src/lib/commands/improve.c new file mode 100644 index 00000000..643ea5f8 --- /dev/null +++ b/src/lib/commands/improve.c @@ -0,0 +1,202 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * improve.c: Improve the infrastructure of a sector + * + * Known contributors to this file: + * Steve McClure, 1996-2000 + */ + +#ifdef Rel4 +#include +#endif /* Rel4 */ +#include "misc.h" +#include "player.h" +#include "var.h" +#include "xy.h" +#include "sect.h" +#include "nsc.h" +#include "nat.h" +#include "deity.h" +#include "path.h" +#include "file.h" +#include "optlist.h" +#include "commands.h" + +char *prompt[] = { + "Improve what ('road' or 'rail')? ", + "Improve what ('road', 'rail' or 'defense')? " }; + +int +improve(void) +{ + struct sctstr sect; + int nsect; + struct nstr_sect nstr; + s_char *p; + s_char buf[1024]; + s_char inbuf[128]; + int type; + int vec[I_MAX+1]; + int value; + int ovalue; + int maxup; + struct natstr *natp; + int lneeded; + int hneeded; + int mneeded; + int dneeded; + int wanted; + + if (!(p = getstarg(player->argp[1], + prompt[opt_DEFENSE_INFRA], buf)) || + !*p) + return RET_SYN; + if (!strncmp(p, "ro", 2)) + type = INT_ROAD; + else if (!strncmp(p, "ra", 2)) + type = INT_RAIL; + else if (!strncmp(p, "de", 2) && opt_DEFENSE_INFRA) + type = INT_DEF; + else + return RET_SYN; + if (!snxtsct(&nstr, player->argp[2])) + return RET_SYN; + prdate(); + nsect = 0; + while (nxtsct(&nstr, §)) { + if (!player->owner) + continue; + if (type == INT_ROAD) + value = sect.sct_road; + else if (type == INT_RAIL) + value = sect.sct_rail; + else if (type == INT_DEF) + value = sect.sct_defense; + sprintf(inbuf, "Sector %s has a %s of %d%%. Improve how much? ", + xyas(sect.sct_x, sect.sct_y, player->cnum), + intrchr[type].in_name, value); + if (!(p = getstarg(player->argp[3], inbuf, buf)) || !*p) + continue; + if (!check_sect_ok(§)) + continue; + getvec(VT_ITEM, vec, (s_char *)§, EF_SECTOR); + maxup = 100 - value; + wanted = atoi(p); + if (wanted < 0) + continue; + if (wanted < maxup) + maxup = wanted; + if (!maxup) + continue; + lneeded = intrchr[type].in_lcms * maxup; + if (opt_NO_LCMS) lneeded = 0; + if (vec[I_LCM] < lneeded) { + lneeded = vec[I_LCM]; + maxup = lneeded / intrchr[type].in_lcms; + if (maxup <= 0) { + pr("Not enough lcms in %s\n", + xyas(sect.sct_x, sect.sct_y, player->cnum)); + continue; + } + } + hneeded = intrchr[type].in_hcms * maxup; + if (opt_NO_HCMS) hneeded = 0; + if (vec[I_HCM] < hneeded) { + hneeded = vec[I_HCM]; + maxup = hneeded / intrchr[type].in_hcms; + if (maxup <= 0) { + pr("Not enough hcms in %s\n", + xyas(sect.sct_x, sect.sct_y, player->cnum)); + continue; + } + } + mneeded = intrchr[type].in_mcost * maxup; + if ((sect.sct_mobil - 1) < mneeded) { + mneeded = sect.sct_mobil - 1; + if (mneeded < 0) + mneeded = 0; + maxup = mneeded / intrchr[type].in_mcost; + if (maxup <= 0) { + pr("Not enough mobility in %s\n", + xyas(sect.sct_x, sect.sct_y, player->cnum)); + continue; + } + } + dneeded = intrchr[type].in_dcost * maxup; + natp = getnatp(player->cnum); + if ((natp->nat_money - 1) < dneeded) { +/* Nasty - leave 'em with a buck. :) */ + dneeded = natp->nat_money - 1; + if (dneeded < 0) + dneeded = 0; + maxup = dneeded / intrchr[type].in_dcost; + if (maxup <= 0) { + pr("Not enough money left to improve %s\n", + xyas(sect.sct_x, sect.sct_y, player->cnum)); + continue; + } + } + if (maxup <= 0) + continue; + lneeded = intrchr[type].in_lcms * maxup; + hneeded = intrchr[type].in_hcms * maxup; + mneeded = intrchr[type].in_mcost * maxup; + dneeded = intrchr[type].in_dcost * maxup; + player->dolcost += dneeded; + if (!opt_NO_LCMS) vec[I_LCM] -= lneeded; + if (!opt_NO_HCMS) vec[I_HCM] -= hneeded; + sect.sct_mobil -= mneeded; + putvec(VT_ITEM, vec, (s_char *)§, EF_SECTOR); + ovalue = value; + value += maxup; + if (value > 100) + value = 100; + pr("Sector %s %s increased from %d%% to %d%%\n", + xyas(sect.sct_x, sect.sct_y, player->cnum), + intrchr[type].in_name, ovalue, value); + if (type == INT_ROAD) + sect.sct_road = value; + else if (type == INT_RAIL) + sect.sct_rail = value; + else if (type == INT_DEF) + sect.sct_defense = value; + putsect(§); + nsect++; + } + if (nsect == 0) { + if (player->argp[2]) + pr("%s: No sector(s)\n", player->argp[1]); + else + pr("%s: No sector(s)\n", ""); + return RET_FAIL; + }else + pr("%d sector%s\n", nsect, splur(nsect)); + return 0; +} + + diff --git a/src/lib/commands/info.c b/src/lib/commands/info.c new file mode 100644 index 00000000..4874e282 --- /dev/null +++ b/src/lib/commands/info.c @@ -0,0 +1,575 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * info.c: display an info page + * + * Known contributors to this file: + * Dave Pare, 1986 + * Mike Wise, 1997 - added apropos and case insensitivity + * Doug Hay, 1998 + * Steve McClure, 1998-2000 + */ + +#include "misc.h" +#include "player.h" +#ifdef Rel4 +#include +#endif /* Rel4 */ +#include +#include +#if !defined(_WIN32) +#include +#else +#include +#endif +#ifdef solaris +#include +#endif +#include "commands.h" + +#if 0 +static int fileselect(struct dirent *dp); +static int printdir(void); +#endif + +static +s_char * +lowerit(s_char *buf, int n, s_char *orig) /* converts a string to lower case */ + /* lower case output buffer */ + /* size of output buffer */ + /* input strig */ +{ + int i; + s_char *tmp; + tmp = buf; + memset( buf, 0, n ); + for ( i=0; ic2) return 1; + else if (c1argp[1] == 0 || !*player->argp[1]) + bp = "TOP"; +#if 0 + /* Note that we generate an "all" file now, which contains + * this list, so we don't do printdir. */ + else if (!strcmp(player->argp[1], "all")) + return printdir(); +#endif + /* + * don't let sneaky people go outside the info directory + */ + else if (NULL != (bp = rindex(player->argp[1], '/'))) + bp++; + else + bp = player->argp[1]; + sprintf(filename, "%s/%s", infodir, bp); + fp = fopen(filename, "r"); + if (fp == NULL) { + int len = strlen(bp); + /* may be a "partial" request. */ + info_dp = opendir(infodir); + if (info_dp == 0) { + pr("Can't open info dir \"%s\"\n", infodir); + return RET_SYS; + } + rewinddir(info_dp); + while ((dp = readdir(info_dp)) != 0 && fp == 0) { + if (strnccmp(bp, dp->d_name, len) != 0) + continue; + sprintf(filename, "%s/%s", infodir, dp->d_name); + fp = fopen(filename, "r"); + } + closedir(info_dp); + if (fp == NULL) { + pr("Sorry, there is no info on %s\n", bp); + return RET_FAIL; + } + } + if (fstat(fileno(fp), &statb) < 0) { + pr("Cannot read info page for \"%s\" (%s)\n", + dp->d_name, sys_errlist[errno]); + fclose(fp); + return RET_SYS; + } + if ((statb.st_mode & S_IFREG) == 0) { + pr("There is no available information on \"%s\"\n", + dp->d_name); + fclose(fp); + return RET_FAIL; + } + pr("Information on: %s Last modification date: %s", + bp, ctime(&statb.st_mtime)); + while (fgets(buf, sizeof(buf), fp) != 0) + pr("%s", buf); + (void) fclose(fp); + return RET_OK; +} + +#if 0 +static int biggest; + +static +int +fileselect(struct dirent *dp) +{ + int l; + if (*dp->d_name == '.') + return 0; + + if ((l = strlen (dp->d_name)) > biggest) + biggest = l; + return 1; +} + +#ifdef solaris +static +int +alphasort(struct dirent *d1, struct dirent *d2) +{ + return strcmp(d1->d_name, d2->d_name); +} + +static int +scandir(char *dir, struct dirent ***dpp, int (*select)(), int (*sort)()) + /* directory to read */ + /* directory entry pointer pointer */ +{ + DIR *dirp; + int nsize; + int nents; + struct dirent *d, *tmp; + + d = (struct dirent *)malloc(sizeof(struct dirent) + pathconf(".", _PC_NAME_MAX) +1); + if ( (dirp = opendir(dir)) == NULL) + return -1; + nsize = 100; + *dpp = (struct dirent **)malloc(nsize * sizeof(struct dirent *)); + if ( (*dpp) == NULL ) + { + closedir(dirp); + return -1; + } + nents = 0; + while ( (d = readdir_r(dirp, d)) != NULL) + { + if ( select != NULL && !(*select)(d) ) + continue; + tmp = (struct dirent *)malloc(sizeof(struct dirent) + strlen(d->d_name) + 1); + if ( tmp == NULL ) + return -1; + tmp->d_ino = d->d_ino; + tmp->d_reclen = d->d_reclen; + strcpy(tmp->d_name, d->d_name); + if ( nents > nsize ) + { + *dpp = (struct dirent **)realloc((char *)*dpp, nsize * sizeof(struct dirent *)); + if ( *dpp == NULL ) + return -1; + } + (*dpp)[nents++] = tmp; + } + closedir(dirp); + if (nents > 0 && sort != NULL ) + qsort(*dpp, nents, sizeof(struct dirent *), sort); + return nents; +} +#endif + +static int +printdir(void) +{ +#if !defined(solaris) && !defined(ALPHA) && !defined(__linux__) + extern int alphasort(const struct dirent *const *, const struct dirent *const *); +#endif + extern s_char *infodir; + static time_t lastmodtime; + static int number; + static struct dirent **dp; + struct stat st; + int count; + int i; + int npl; + + if (stat(infodir, &st) == -1) + return RET_FAIL; + pr("Available topics are:\n"); + if (lastmodtime < st.st_mtime) { + if (dp) + free((s_char *)dp); + biggest = 0; + number = scandir(infodir, &dp, fileselect, alphasort); + lastmodtime = st.st_mtime; + } + count = 79 / (biggest + 1) - 1; + for(i = 0, npl = 0; i < number; i++) { + pr("%-*.*s%c", biggest, strlen (dp[i]->d_name), + dp[i]->d_name, npl == count ? '\n' : ' '); + if (npl == count) + npl = 0; + else + npl++; + } + if (npl != 0) + pr("\n"); + return 0; +} +#endif + +int +apro(void) +{ + extern s_char *infodir; + FILE *fp; + s_char *bp,*lbp; + s_char *fbuf; + s_char *lbuf; + struct dirent *dp; + s_char filename[1024]; + DIR *info_dp; + long nf,nhf,nl,nlhl,nhl,nll; + int alreadyhit; + int lhitlim; + + if (player->argp[1] == 0 || !*player->argp[1]) { + pr("Apropos what?\n"); + return RET_FAIL; + } + + lhitlim = 100; + if (player->argp[2] ) { + lhitlim = atoi(player->argp[2]); + if (lhitlim<=0) lhitlim = 100; + } + + info_dp = opendir(infodir); + if (info_dp == 0) { + pr("Can't open info dir \"%s\"\n", infodir); + return RET_SYS; + } + + fbuf = (s_char *) malloc(256); + lbuf = (s_char *) malloc(256); + lbp = (s_char *) malloc(256); + + /* + * lower case search string into lbp + */ + bp = player->argp[1]; + lowerit( lbp,256,bp ); + + /* + * search + */ + nf = nhf = nl = nhl = 0; + rewinddir(info_dp); + while ((dp = readdir(info_dp)) != 0) { + sprintf(filename, "%s/%s", infodir, dp->d_name); + fp = fopen(filename, "r"); + alreadyhit = 0; + nll = nlhl = 0; + if (fp != NULL) { + while (fgets(fbuf,256,fp)){ + lowerit(lbuf,256,fbuf); + if (strstr(lbuf,lbp)){ + if (!alreadyhit){ + pr("*** %s ***\n",dp->d_name); + alreadyhit = 1; + nhf++; + } + fbuf[74] = '\n'; + fbuf[75] = 0; + pr(" %s",fbuf); + nlhl++; + /* + * break if too many lines + */ + if ((nhl+nlhl)>lhitlim) break; + } + nll++; + } + fclose( fp ); + } + nhl += nlhl; + nl += nll; + nf++; + if (nhl>lhitlim) break; + } + closedir(info_dp); + + free(fbuf); + free(lbuf); + free(lbp); + + if ((nhl)>lhitlim){ + pr("Limit of %ld lines exceeded\n",lhitlim); + } + pr("Found %s in %ld of %ld files and in %ld of %ld lines\n", + bp, nhf,nf, nhl,nl ); + return RET_OK; +} + +#else + +int +info(void) +{ + extern int errno; + extern s_char *infodir; + s_char buf[255]; + FILE *fp; + s_char *bp; + s_char *bp2; + s_char filename[1024]; + + if (player->argp[1] == 0 || !*player->argp[1]) + bp = "TOP"; +#if 0 + /* Note that we generate an "all" file now, which contains + * this list, so we don't do printdir. */ + else if (!strcmp(player->argp[1], "all")) + return printdir(); +#endif + else { + /* + * don't let sneaky people go outside the info directory + */ + bp = player->argp[1]; + if (NULL != (bp2 = rindex(bp, '/'))) + bp = ++bp2; + if (NULL != (bp2 = rindex(bp, '\\'))) + bp = ++bp2; + if (NULL != (bp2 = rindex(bp, ':'))) + bp = ++bp2; + if (!*bp) + bp = "TOP"; + } + + strncpy(filename, infodir, sizeof(filename)-2); + strcat(filename, "//"); + strncat(filename, bp, sizeof(filename)-1-strlen(filename)); + fp = fopen(filename, "r"); + if (fp == NULL) { + /* may be a "partial" request. */ + HANDLE hDir; + WIN32_FIND_DATA fData; + int len = strlen(bp); + strncat(filename, "*", sizeof(filename)-1-strlen(filename)); + hDir = FindFirstFile(filename, &fData); + if (hDir == INVALID_HANDLE_VALUE) { + pr("Can't open info dir \"%s\"\n", infodir); + return RET_SYS; + } + do { + if ((fData.dwFileAttributes == FILE_ATTRIBUTE_NORMAL) && + (strnccmp(bp, fData.cFileName, len) == 0)) + { + strncpy(filename, infodir, sizeof(filename)-2); + strcat(filename, "//"); + strncat(filename, fData.cFileName, + sizeof(filename)-1-strlen(filename)); + fp = fopen(filename, "r"); + } + } while (!fp && FindNextFile(hDir, &fData)); + FindClose(hDir); + if (fp == NULL) { + pr("Sorry, there is no info on %s\n", bp); + return RET_FAIL; + } + } + pr("Information on: %s", bp); + while (fgets(buf, sizeof(buf), fp) != 0) + pr("%s", buf); + (void) fclose(fp); + return RET_OK; +} + +#if 0 +static int +printdir(void) +{ + extern s_char *infodir; + HANDLE hDir; + WIN32_FIND_DATA fData; + int count; + int i; + int npl; + s_char filename[1024]; + + strncpy(filename, infodir, sizeof(filename)-3); + strcat(filename, "//*"); + + hDir = FindFirstFile(filename, &fData); + if (hDir == INVALID_HANDLE_VALUE) { + return RET_FAIL; + } + + pr("Available topics are:\n"); + do { + if (fData.dwFileAttributes == FILE_ATTRIBUTE_NORMAL) + { + /* Yes, we could do multi-column work here. */ + pr("%s\n", fData.cFileName); + } + } while (FindNextFile(hDir, &fData)); + FindClose(hDir); + + return 0; +} +#endif + +int +apro(void) +{ + extern s_char *infodir; + HANDLE hDir; + WIN32_FIND_DATA fData; + FILE *fp; + s_char *bp,*lbp; + s_char *fbuf; + s_char *lbuf; + s_char filename[1024]; + long nf,nhf,nl,nlhl,nhl,nll; + int alreadyhit; + int lhitlim; + + if (player->argp[1] == 0 || !*player->argp[1]) { + pr("Apropos what?\n"); + return RET_FAIL; + } + + lhitlim = 100; + if (player->argp[2] ) { + lhitlim = atoi(player->argp[2]); + if (lhitlim<=0) lhitlim = 100; + } + + strncpy(filename, infodir, sizeof(filename)-3); + strcat(filename, "//*"); + hDir = FindFirstFile(filename, &fData); + if (hDir == INVALID_HANDLE_VALUE) { + return RET_FAIL; + } + + fbuf = (s_char *) malloc(256); + lbuf = (s_char *) malloc(256); + lbp = (s_char *) malloc(256); + + /* + * lower case search string into lbp + */ + bp = player->argp[1]; + lowerit( lbp,256,bp ); + + /* + * search + */ + nf = nhf = nl = nhl = 0; + do { + strncpy(filename, infodir, sizeof(filename)-3); + strcat(filename, "//"); + strncat(filename, fData.cFileName, + sizeof(filename)-1-strlen(filename)); + fp = fopen(filename, "r"); + alreadyhit = 0; + nll = nlhl = 0; + if (fp != NULL) { + while (fgets(fbuf,256,fp)){ + lowerit(lbuf,256,fbuf); + if (strstr(lbuf,lbp)){ + if (!alreadyhit){ + pr("*** %s ***\n",fData.cFileName); + alreadyhit = 1; + nhf++; + } + fbuf[74] = '\n'; + fbuf[75] = 0; + pr(" %s",fbuf); + nlhl++; + /* + * break if too many lines + */ + if ((nhl+nlhl)>lhitlim) break; + } + nll++; + } + fclose( fp ); + } + nhl += nlhl; + nl += nll; + nf++; + if (nhl>lhitlim) break; + } while (FindNextFile(hDir, &fData)); + FindClose(hDir); + + free(fbuf); + free(lbuf); + free(lbp); + + if ((nhl)>lhitlim) { + pr("Limit of %ld lines exceeded\n",lhitlim); + } + pr("Found %s in %ld of %ld files and in %ld of %ld lines\n", + bp, nhf,nf, nhl,nl ); + return RET_OK; +} + +#endif diff --git a/src/lib/commands/land.c b/src/lib/commands/land.c new file mode 100644 index 00000000..cb285f24 --- /dev/null +++ b/src/lib/commands/land.c @@ -0,0 +1,118 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * land.c: List land units + * + * Known contributors to this file: + * Steve McClure, 1998 + */ + +#include "misc.h" +#include "player.h" +#include "var.h" +#include "xy.h" +#include "sect.h" +#include "land.h" +#include "nat.h" +#include "nsc.h" +#include "deity.h" +#include "file.h" +#include "optlist.h" +#include "commands.h" + +int +land(void) +{ + int nunits; + struct nstr_item ni; + struct lndstr land; + int vec[I_MAX+1]; + s_char *mission_short_name(); + + if (!snxtitem(&ni, EF_LAND, player->argp[1])) + return RET_SYN; + + nunits = 0; + while (nxtitem(&ni, (s_char *)&land)) { + if (land.lnd_own == 0) + continue; + if (!player->owner && !player->god) + continue; + if (land.lnd_type < 0 || land.lnd_type > lnd_maxno) { + pr("bad unit type %d (#%d)\n", + land.lnd_type, ni.cur); + continue; + } + count_land_planes(&land); + lnd_count_units(&land); + + if (nunits++ == 0) { + if (player->god) + pr("own "); +pr(" # unit type x,y a eff mil frt mu fd"); + if (opt_FUEL) + pr(" fl"); + pr(" tch retr rd"); + pr(" xl"); + pr(" ln"); + pr(" l/s\n"); + } + if (player->god) + pr("%3d ", land.lnd_own); + pr("%4d ", ni.cur); + pr("%-15.15s", lchr[(int)land.lnd_type].l_name); + prxy(" %4d,%-4d", land.lnd_x, land.lnd_y, player->cnum); + pr("%c", land.lnd_army); + pr("%4d%%", land.lnd_effic); + pr("%4d", lnd_getmil(&land)); + pr("%4d", land.lnd_harden); + pr("%4d", land.lnd_mobil); + getvec(VT_ITEM, vec, (s_char *)&land, EF_LAND); + pr("%4d", vec[I_FOOD]); + if (opt_FUEL) + pr("%3d",land.lnd_fuel); + pr("%4d ", land.lnd_tech); + pr("%3d%%", land.lnd_retreat); + pr("%3d", land.lnd_rad_max); + pr("%3d",land.lnd_nxlight); + pr("%3d",land.lnd_nland); + if (land.lnd_ship >= 0) + pr(" S%4d", land.lnd_ship); + else if (land.lnd_land >= 0) + pr(" L%4d", land.lnd_land); + pr("\n"); + } + if (nunits == 0) { + if (player->argp[1]) + pr("%s: No unit(s)\n", player->argp[1]); + else + pr("%s: No unit(s)\n", ""); + return RET_FAIL; + }else + pr("%d unit%s\n", nunits, splur(nunits)); + return RET_OK; +} diff --git a/src/lib/commands/laun.c b/src/lib/commands/laun.c new file mode 100644 index 00000000..ed67b2c9 --- /dev/null +++ b/src/lib/commands/laun.c @@ -0,0 +1,453 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * laun.c: Launch missiles from land or sea + * + * Known contributors to this file: + * Dave Pare, 1986 + * Ken Stevens, 1995 + * Steve McClure, 1998-2000 + */ + +#include "misc.h" +#include "player.h" +#include "xy.h" +#include "var.h" +#include "sect.h" +#include "item.h" +#include "plane.h" +#include "nuke.h" +#include "news.h" +#include "retreat.h" +#include "mission.h" +#include "ship.h" +#include "nsc.h" +#include "nat.h" +#include "path.h" +#include "file.h" +#include "optlist.h" +#include "damage.h" +#include "commands.h" + +static int launch_as(struct plnstr *pp); +static int launch_missile(struct plnstr *pp, int sublaunch); +static int launch_sat(struct plnstr *pp, int sublaunch); + +/* + * laun + */ +int +laun(void) +{ + struct nstr_item nstr; + struct plnstr plane; + struct shpstr ship; + struct sctstr sect; + int sublaunch; + struct plchrstr *pcp; + int rel; + struct natstr *natp; + + if (!snxtitem(&nstr, EF_PLANE, player->argp[1])) + return RET_SYN; + while (nxtitem(&nstr, (s_char *)&plane)) { + if (plane.pln_own != player->cnum) + continue; + pcp = &plchr[(int)plane.pln_type]; + if ((pcp->pl_flags & (P_M|P_O)) == 0) { + pr("%s isn't a missile!\n", prplane(&plane)); + continue; + } + if (pcp->pl_flags & P_F) { + pr("%s is a surface-to-air missile!\n", + prplane(&plane)); + continue; + } + if (pcp->pl_flags & P_N) { + pr("%s is an anti-ballistic-missile missile!\n", + prplane(&plane)); + continue; + } + if ((plane.pln_flags & PLN_LAUNCHED) && (pcp->pl_flags & P_O)) { + pr("%s already in orbit!\n", prplane(&plane)); + continue; + } + if (opt_MARKET) { + if (ontradingblock(EF_PLANE,(int *) &plane)) { + pr("plane #%d inelligible - it's for sale.\n", plane.pln_uid); + continue; + } + } + + sublaunch = 0; + if (plane.pln_ship >= 0) { + getship(plane.pln_ship, &ship); + if (!ship.shp_own) { + pr("%s: ship #%d was sunk!\n", + prplane(&plane), + ship.shp_uid); + makelost(EF_PLANE, plane.pln_own, plane.pln_uid, plane.pln_x, plane.pln_y); + plane.pln_own = 0; + putplane(plane.pln_uid, &plane); + continue; + } + natp = getnatp(ship.shp_own); + rel = getrel(natp, player->cnum); + if (ship.shp_own != player->cnum && rel != ALLIED) { + pr("%s: you or an ally do not own ship #%d\n", + prplane(&plane), ship.shp_uid); + makelost(EF_PLANE, plane.pln_own, plane.pln_uid, plane.pln_x, plane.pln_y); + plane.pln_own = 0; + putplane(plane.pln_uid, &plane); + continue; + } + if (mchr[(int)ship.shp_type].m_flags & M_SUB) + sublaunch = 1; + } else { + sublaunch = 0; + getsect(plane.pln_x, plane.pln_y, §); + natp = getnatp(sect.sct_own); + rel = getrel(natp, player->cnum); + if (sect.sct_own && sect.sct_own != player->cnum && rel != ALLIED) { + pr("%s: you or an ally do not own sector %s!\n", + prplane(&plane), + xyas(plane.pln_x, plane.pln_y, player->cnum)); + continue; + } + } + if (plane.pln_effic < 60) { + pr("%s is damaged (%d%%)\n", + prplane(&plane), plane.pln_effic); + continue; + } + pr("%s at %s; range %d, eff %d%%\n", prplane(&plane), + xyas(plane.pln_x, plane.pln_y, player->cnum), + plane.pln_range, + plane.pln_effic); + if (!(pcp->pl_flags & P_O)) { + if (launch_missile(&plane, sublaunch) < 0) + continue; + } else if ((pcp->pl_flags & (P_M|P_O)) == (P_M|P_O)) { + if (launch_as(&plane) < 0) /* anti-sat */ + continue; + } else { /* satellites */ + if (launch_sat(&plane, sublaunch) < 0) + continue; + } + makelost(EF_PLANE, plane.pln_own, plane.pln_uid, plane.pln_x, plane.pln_y); + plane.pln_own = 0; + putplane(plane.pln_uid, &plane); + } + return RET_OK; +} + +/* + * Launch an anti-sat weapon. + * Return -1 on failure, 0 on success (even if missile explodes). + */ + +static int +launch_as(struct plnstr *pp) +{ + coord sx, sy; + s_char *cp, buf[1024]; + struct plnstr plane; + struct nstr_item ni; + int goodtarget; + int dam, nukedam; + natid oldown; + + if (msl_equip(pp) < 0) { + pr("%s not enough petrol or shells!\n", prplane(pp)); + return -1; + } + for (;;) { + cp = getstarg(player->argp[2], "Target sector? ", buf); + if (!check_plane_ok(pp)) + return -1; + player->argp[2] = 0; + if (!cp || !*cp) + return -1; + if (!sarg_xy(cp, &sx, &sy)) { + pr("Bad sector designation; try again!\n"); + continue; + } + if (mapdist(pp->pln_x, pp->pln_y, sx, sy) > + pp->pln_range) { + pr("Range too great; try again!\n"); + continue; + } + break; + } + goodtarget=0; + snxtitem_dist(&ni, EF_PLANE, sx, sy, 0); + while (!goodtarget && nxtitem(&ni, (caddr_t)&plane)) { + if (!plane.pln_own) + continue; + if (!(plane.pln_flags & PLN_LAUNCHED)) + continue; + goodtarget = 1; + + } + if (!goodtarget) { + pr("No satellites there!\n"); + return -1; + } + if (msl_hit(pp, plane.pln_def, EF_PLANE, N_SAT_KILL, N_SAT_KILL, prplane(&plane), sx, sy, plane.pln_own)) { + dam = pln_damage(pp,sx,sy,'p',&nukedam,1); + oldown = plane.pln_own; + planedamage(&plane, dam); + pr("Hit satellite for %d%% damage!\n", dam); + mpr(oldown, + "%s anti-sat did %d%% damage to %s over %s\n", + cname(player->cnum), dam, prplane(&plane), + xyas(plane.pln_x, plane.pln_y, plane.pln_own)); + putplane(plane.pln_uid,&plane); + if (!plane.pln_own) + mpr(oldown, "Satellite shot down\n"); + } + return 0; +} + +/* + * Launch a missile + * Return -1 on failure, 0 on success (even if missile explodes). + */ +static int +launch_missile(struct plnstr *pp, int sublaunch) +{ + struct plchrstr *pcp = plchr + pp->pln_type; + coord sx, sy; + int n, dam; + s_char *cp; + struct mchrstr *mcp; + struct shpstr target_ship; + struct sctstr sect; + int nukedam; + int rel; + struct natstr *natp; + s_char buf[1024]; + + for (;;) { + if (pcp->pl_flags & P_MAR) + cp = getstarg(player->argp[2], "Target ship? ", buf); + else + cp = getstarg(player->argp[2], "Target sector? ", buf); + player->argp[2] = 0; + if (!cp || !*cp) + return -1; + if (!check_plane_ok(pp)) + return -1; + if (opt_PINPOINTMISSILE && sarg_type(cp) == NS_LIST) { + if (!(pcp->pl_flags & P_MAR)) { + pr("Missile not designed to attack ships!\n"); + continue; + } + n = atoi(cp); + if ((n < 0) || !getship(n,&target_ship) || + !target_ship.shp_own) { + pr("Bad ship number; try again!\n"); + continue; + } + sx = target_ship.shp_x; + sy = target_ship.shp_y; + mcp = &mchr[(int)target_ship.shp_type]; + if (mcp->m_flags & M_SUB) { + pr("Bad ship number; try again!\n"); + continue; + } + } /* not PINPOINTMISSILE for ships */ + else if (!sarg_xy(cp, &sx, &sy)) { + pr("That's no good! try again!\n"); + continue; + } + else if (opt_PINPOINTMISSILE) + { + if (pcp->pl_flags & P_MAR) { + pr("Missile designed to attack ships!\n"); + continue; + } + } /* end PINPOINTMISSILE */ + + if (mapdist(pp->pln_x, pp->pln_y, sx, sy) > + pp->pln_range) { + pr("Range too great; try again!\n"); + continue; + } + break; + } + if (msl_equip(pp) < 0) { + pr("%s not enough shells!\n", prplane(pp)); + return -1; + } + if (opt_PINPOINTMISSILE == 0 || !(pcp->pl_flags & P_MAR)) + { + getsect(sx,sy,§); + if (opt_SLOW_WAR) { + natp = getnatp(player->cnum); + rel = getrel(natp,sect.sct_own); + if ((rel != AT_WAR) && (sect.sct_own != player->cnum) && + (sect.sct_own) && (sect.sct_oldown != player->cnum)){ + pr("You are not at war with the player->owner of the target sector!\n"); + pr_beep(); + pr("Kaboom!!!\n"); + pr("Missile monitoring officer destroys RV before detonation.\n"); + return 0; + } + } + if (!msl_hit(pp, SECT_HARDTARGET, EF_SECTOR, N_SCT_MISS, + N_SCT_SMISS, "sector", sx, sy, sect.sct_own)) { + /* + dam = pln_damage(pp, sect.sct_x, sect.sct_y, 's', &nukedam, 0); + collateral_damage(sect.sct_x, sect.sct_y, dam, 0); + */ + return 0; + } + dam = pln_damage(pp, sect.sct_x, sect.sct_y, 's', &nukedam, 1); + if (!nukedam) { + pr("did %d damage in %s\n", PERCENT_DAMAGE(dam), + xyas(sx, sy, player->cnum)); + if (sect.sct_own != 0) { + if (sublaunch) + wu(0, sect.sct_own, + "Sub missile attack did %d damage in %s\n", + dam, xyas(sx, sy, sect.sct_own)); + else + wu(0, sect.sct_own, + "%s missile attack did %d damage in %s\n", + cname(player->cnum), dam, + xyas(sx, sy, sect.sct_own)); + } + sectdamage(§, dam, 0); + putsect(§); + } + } /* end PINPOINTMISSILE conditional */ + else if (opt_PINPOINTMISSILE) + { /* else */ + if (!msl_hit(pp, shp_hardtarget(&target_ship), EF_SHIP, + N_SHP_MISS, N_SHP_SMISS, prship(&target_ship), + target_ship.shp_x, target_ship.shp_y, + target_ship.shp_own)) { + pr("splash\n"); + /* + dam = pln_damage(pp,target_ship.shp_x,target_ship.shp_y,'p',&nukedam, 0); + collateral_damage(target_ship.shp_x, target_ship.shp_y, dam, 0); + */ + return 0; + } + dam = pln_damage(pp,target_ship.shp_x,target_ship.shp_y,'p',&nukedam, 1); + if (!nukedam) { + check_retreat_and_do_shipdamage(&target_ship, dam); + if (target_ship.shp_effic < SHIP_MINEFF) + pr("\t%s sunk!\n", prship(&target_ship)); + putship(target_ship.shp_uid, &target_ship); + } + getship(n, &target_ship); + if (!target_ship.shp_own) + pr("%s sunk!\n", prship(&target_ship)); + } + /* end PINPOINTMISSILE */ + return 0; +} + +/* + * Launch a satellite. + * Return -1 on error, 0 on success (even if the satellite fails). + */ +static int +launch_sat(struct plnstr *pp, int sublaunch) +{ + struct plchrstr *pcp = plchr + pp->pln_type; + coord sx, sy; + int i; + int dist; + int dir; + s_char *cp; + s_char *p; + s_char buf[1024]; + + pr("\n"); + while (1) { + cp = getstarg(player->argp[2], "Target sector? ", buf); + if (!check_plane_ok(pp)) + return -1; + player->argp[2] = 0; + if (!cp || !*cp) + return -1; + if (!sarg_xy(cp, &sx, &sy)) { + pr("Bad sector designation; try again!\n"); + continue; + } + if ((dist = mapdist(pp->pln_x, pp->pln_y, sx, sy)) > + pp->pln_range) { + pr("Range too great; try again!\n"); + continue; + } + break; + } + if (opt_ORBIT) { + p = getstring("Geostationary orbit? ", buf); + if (p == 0) + return -1; + if (!check_plane_ok(pp)) + return -1; + pp->pln_theta = 0; + pp->pln_flags |= PLN_SYNCHRONOUS; + if (*p == 0 || *p == 'n') + pp->pln_flags &= ~(PLN_SYNCHRONOUS); + } /* end opt_ORBIT */ + + pr("3... 2... 1... Blastoff!!!\n"); + if (chance(0.07 + (100 - pp->pln_effic)/100.0)) { + pr("KABOOOOM! Range safety officer detonates booster!\n"); + makelost(EF_PLANE, pp->pln_own, pp->pln_uid, pp->pln_x, pp->pln_y); + pp->pln_own = 0; + return 0; + } + i = pp->pln_tech + pp->pln_effic; + if (chance(1.0 - (i/(i+50.0)))) { + dir = (random() % 6) + 1; + sx += diroff[dir][0]; + sy += diroff[dir][1]; + pr("Your trajectory was a little off.\n"); + } + nreport(player->cnum, N_LAUNCH, 0, 1); + pr("%s positioned over %s", prplane(pp), + xyas(sx, sy, player->cnum)); + if (msl_intercept(sx, sy, pp->pln_own, pcp->pl_def, sublaunch, P_O, 0)) { + return 0; + } + pp->pln_x = sx; + pp->pln_y = sy; + pp->pln_flags |= PLN_LAUNCHED; + pp->pln_mobil = (pp->pln_mobil > dist) ? + (pp->pln_mobil - dist) : 0; + putplane(pp->pln_uid, pp); + pr(", will be ready for use in %d time units\n", + 127 - pp->pln_mobil); + return -1; +} diff --git a/src/lib/commands/lboard.c b/src/lib/commands/lboard.c new file mode 100644 index 00000000..faa71d28 --- /dev/null +++ b/src/lib/commands/lboard.c @@ -0,0 +1,157 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * lboard.c: Board an enemy land unit (heavily borrowing from boar.c) + * + * Known contributors to this file: + * Steve McClure, 1998 + */ + +#include +#include "misc.h" +#include "player.h" +#include "file.h" +#include "var.h" +#include "sect.h" +#include "path.h" +#include "news.h" +#include "treaty.h" +#include "nat.h" +#include "xy.h" +#include "land.h" +#include "nsc.h" +#include "mission.h" +#include "ship.h" +#include "combat.h" +#include "retreat.h" +#include "commands.h" + +int +lboa(void) +{ + struct combat off[1]; /* boarding sector */ + struct combat def[1]; /* defending land unit */ + struct emp_qelem olist; /* boarding units */ + struct emp_qelem dlist; /* defending units */ + int ototal; /* total boarding strength */ + int a_engineer = 0; /* boarder engineers are present */ + int a_spy = 0; /* the best boarder scout */ + struct sctstr sect; + struct lndstr land; + s_char *p; + s_char buf[1024]; + + att_combat_init(def, EF_LAND); + /* + * Collect input from the boarder + */ + + /* What are we boarding? */ + + if (!(p = getstarg(player->argp[1], "Victim land unit #? ", buf)) || + (def->lnd_uid = atoi(p)) < 0) + return RET_SYN; + + /* + * Ask the boarder what sector they want to board with + */ + + /* Note: if we allow land units to board other land units, we need + * to make sure the code will allow that */ + if (!(p = getstarg(player->argp[2], "Boarding party from? ", buf))) + return RET_SYN; + if (issector(p)) { + att_combat_init(off, EF_SECTOR); + if (!sarg_xy(p, &off->x, &off->y)) + return RET_SYN; + getsect(off->x, off->y, §); + if (sect.sct_own != player->cnum) { + pr("You don't own %s!\n", + xyas(off->x, off->y, player->cnum)); + return RET_SYN; + } + if (sect.sct_mobil <= 0) { + pr("You don't have any mobility in %s!\n", + xyas(off->x, off->y, player->cnum)); + return RET_SYN; + } + } else { + pr("You can only board land units from a sector.\n"); + return RET_SYN; + } + if (att_abort(A_LBOARD, off, def)) { + pr("Land unit boarding aborted\n"); + return RET_OK; + } + + /* Show what we're boarding */ + + if (att_show(def)) + return RET_FAIL; + + /* Ask the player what he wants to board with */ + + att_ask_offense(A_LBOARD, off, def, &olist, &a_spy, &a_engineer); + if (att_abort(A_LBOARD, off, def)) { + pr("Land unit boarding aborted\n"); + att_empty_attack(A_LBOARD, 0, def); + return att_free_lists(&olist, 0); + } + + /* + * Estimate the defense strength and give the player a chance to abort + */ + + ototal = att_estimate_defense(A_LBOARD, off, &olist, def, a_spy); + if (att_abort(A_LBOARD, off, def)) { + pr("Land unit boarding aborted\n"); + att_empty_attack(A_LBOARD, 0, def); + return att_free_lists(&olist, 0); + } + + /* + * We have now got all the answers from the boarder. From this point + * forward, we can assume that this battle is the _only_ thing + * happening in the game. + */ + + /* Get the real defense */ + + att_get_defense(&olist, def, &dlist, a_spy, ototal); + + /* + * Death, carnage, and destruction. + */ + + if (!(att_fight(A_LBOARD,off,&olist,1.0,def,&dlist,1.0))) { + getland(def->lnd_uid, &land); + /* Now what? Don't bother retreating? No flag for it (yet) */ + } + + return RET_OK; +} + diff --git a/src/lib/commands/ldump.c b/src/lib/commands/ldump.c new file mode 100644 index 00000000..2d6f728b --- /dev/null +++ b/src/lib/commands/ldump.c @@ -0,0 +1,299 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * ldump.c: Dump land unit information + * + * Known contributors to this file: + * John Yockey, 1997 + * Steve McClure, 1998 + */ + +#include "misc.h" +#include "player.h" +#include "xy.h" +#include "sect.h" +#include "land.h" +#include "nat.h" +#include "nsc.h" +#include "deity.h" +#include "file.h" +#include "optlist.h" +#include "var.h" +#include "commands.h" + +int +ldump(void) +{ + int nunits; + int field[128]; + struct nstr_item ni; + struct lndstr land; + int vec[I_MAX+1]; + s_char *mission_short_name(); + int n,i; + struct natstr *np; + time_t now; + + if (!snxtitem(&ni, EF_LAND, player->argp[1])) + return RET_SYN; + prdate(); + nunits = 0; + + if (!player->argp[2]) { + for (n = 1; n <= 39; n++) field[n-1] = n; + field[n-1] = 0; + } else { + n = 2; + i = 0; + while (player->argp[n]) { + if (!strcmp("type",player->argp[n])) { + field[i++] = 1; + } else if (!strcmp("x",player->argp[n])) { + field[i++] = 2; + } else if (!strcmp("y",player->argp[n])) { + field[i++] = 3; + } else if (!strcmp("army",player->argp[n])) { + field[i++] = 4; + } else if (!strcmp("eff",player->argp[n])) { + field[i++] = 5; + } else if (!strcmp("mil",player->argp[n])) { + field[i++] = 6; + } else if (!strcmp("fort",player->argp[n])) { + field[i++] = 7; + } else if (!strcmp("mob",player->argp[n])) { + field[i++] = 8; + } else if (!strcmp("food",player->argp[n])) { + field[i++] = 9; + } else if (!strcmp("fuel",player->argp[n])) { + field[i++] = 10; + } else if (!strcmp("tech",player->argp[n])) { + field[i++] = 11; + } else if (!strcmp("retr",player->argp[n])) { + field[i++] = 12; + } else if (!strcmp("react",player->argp[n])) { + field[i++] = 13; + } else if (!strcmp("xl",player->argp[n])) { + field[i++] = 14; + } else if (!strcmp("nland",player->argp[n])) { + field[i++] = 15; + } else if (!strcmp("land",player->argp[n])) { + field[i++] = 16; + } else if (!strcmp("ship",player->argp[n])) { + field[i++] = 17; + } else if (!strcmp("shell",player->argp[n])) { + field[i++] = 18; + } else if (!strcmp("gun",player->argp[n])) { + field[i++] = 19; + } else if (!strcmp("petrol",player->argp[n])) { + field[i++] = 20; + } else if (!strcmp("iron",player->argp[n])) { + field[i++] = 21; + } else if (!strcmp("dust",player->argp[n])) { + field[i++] = 22; + } else if (!strcmp("bar",player->argp[n])) { + field[i++] = 23; + } else if (!strcmp("oil",player->argp[n])) { + field[i++] = 24; + } else if (!strcmp("lcm",player->argp[n])) { + field[i++] = 25; + } else if (!strcmp("hcm",player->argp[n])) { + field[i++] = 26; + } else if (!strcmp("rad",player->argp[n])) { + field[i++] = 27; + } else if (!strcmp("att",player->argp[n])) { + field[i++] = 28; + } else if (!strcmp("def",player->argp[n])) { + field[i++] = 29; + } else if (!strcmp("vul",player->argp[n])) { + field[i++] = 30; + } else if (!strcmp("spd",player->argp[n])) { + field[i++] = 31; + } else if (!strcmp("vis",player->argp[n])) { + field[i++] = 32; + } else if (!strcmp("spy",player->argp[n])) { + field[i++] = 33; + } else if (!strcmp("radius",player->argp[n])) { + field[i++] = 34; + } else if (!strcmp("frg",player->argp[n])) { + field[i++] = 35; + } else if (!strcmp("acc",player->argp[n])) { + field[i++] = 36; + } else if (!strcmp("dam",player->argp[n])) { + field[i++] = 37; + } else if (!strcmp("amm",player->argp[n])) { + field[i++] = 38; + } else if (!strcmp("aaf",player->argp[n])) { + field[i++] = 39; + } else { + pr("Unrecognized field %s\n",player->argp[n]); + } + if (n++ > 100) { + pr("Too many fields\n"); + return RET_FAIL; + } + } + field[i] = 0; + } + + if (player->god) + pr(" "); + time(&now); + pr("DUMP LAND UNITS %d\n", now); + if (player->god) + pr("own "); + pr("id"); + n = 0; + while (field[n]) { + switch (field[n]) { + case 1: pr(" type"); break; + case 2: pr(" x"); break; + case 3: pr(" y"); break; + case 4: pr(" army"); break; + case 5: pr(" eff"); break; + case 6: pr(" mil"); break; + case 7: pr(" fort"); break; + case 8: pr(" mob"); break; + case 9: pr(" food"); break; + case 10: pr(" fuel"); break; + case 11: pr(" tech"); break; + case 12: pr(" retr"); break; + case 13: pr(" react"); break; + case 14: pr(" xl"); break; + case 15: pr(" nland"); break; + case 16: pr(" land"); break; + case 17: pr(" ship"); break; + case 18: pr(" shell"); break; + case 19: pr(" gun"); break; + case 20: pr(" petrol"); break; + case 21: pr(" iron"); break; + case 22: pr(" dust"); break; + case 23: pr(" bar"); break; + case 24: pr(" oil"); break; + case 25: pr(" lcm"); break; + case 26: pr(" hcm"); break; + case 27: pr(" rad"); break; + case 28: pr(" att"); break; + case 29: pr(" def"); break; + case 30: pr(" vul"); break; + case 31: pr(" spd"); break; + case 32: pr(" vis"); break; + case 33: pr(" spy"); break; + case 34: pr(" radius"); break; + case 35: pr(" frg"); break; + case 36: pr(" acc"); break; + case 37: pr(" dam"); break; + case 38: pr(" amm"); break; + case 39: pr(" aaf"); break; + } + n++; + } + pr("\n"); + + np = getnatp(player->cnum); + while (nxtitem(&ni, (s_char *)&land)) { + if (land.lnd_own == 0) + continue; + if (!player->owner && !player->god) + continue; + if (land.lnd_type < 0 || land.lnd_type > lnd_maxno) { + pr("bad unit type %d (#%d)\n", + land.lnd_type, ni.cur); + continue; + } + count_land_planes(&land); + lnd_count_units(&land); + + nunits++; + if (player->god) + pr("%3d ", land.lnd_own); + pr("%d", ni.cur); + n = 0; + getvec(VT_ITEM, vec, (s_char *)&land, EF_LAND); + while (field[n]) { + switch (field[n++]) { + case 1: pr(" %0.4s",lchr[(int)land.lnd_type].l_name); break; + case 2: pr(" %d", xrel(np, land.lnd_x)); break; + case 3: pr(" %d", yrel(np, land.lnd_y)); break; + case 4: if (land.lnd_army == ' ') + pr(" ~"); + else + pr(" %c", land.lnd_army); + break; + case 5: pr(" %d", land.lnd_effic); break; + case 6: pr(" %d", lnd_getmil(&land)); break; + case 7: pr(" %d", land.lnd_harden); break; + case 8: pr(" %d", land.lnd_mobil); break; + case 9: pr(" %d", vec[I_FOOD]); break; + case 10: if (opt_FUEL) + pr(" %d",land.lnd_fuel); + else + pr(" 0"); + break; + case 11: pr(" %d", land.lnd_tech); break; + case 12: pr(" %d", land.lnd_retreat); break; + case 13: pr(" %d", land.lnd_rad_max); break; + case 14: pr(" %d", land.lnd_nxlight); break; + case 15: pr(" %d", land.lnd_nland); break; + case 16: pr(" %d", land.lnd_land); break; + case 17: pr(" %d", land.lnd_ship); break; + case 18: pr(" %d", vec[I_SHELL]); break; + case 19: pr(" %d", vec[I_GUN]); break; + case 20: pr(" %d", vec[I_PETROL]); break; + case 21: pr(" %d", vec[I_IRON]); break; + case 22: pr(" %d", vec[I_DUST]); break; + case 23: pr(" %d", vec[I_BAR]); break; + case 24: pr(" %d", vec[I_OIL]); break; + case 25: pr(" %d", vec[I_LCM]); break; + case 26: pr(" %d", vec[I_HCM]); break; + case 27: pr(" %d", vec[I_RAD]); break; + case 28: pr(" %1.2f", (float)land.lnd_att); break; + case 29: pr(" %1.2f", (float)land.lnd_def); break; + case 30: pr(" %d", land.lnd_vul); break; + case 31: pr(" %d", land.lnd_spd); break; + case 32: pr(" %d", land.lnd_vis); break; + case 33: pr(" %d", land.lnd_spy); break; + case 34: pr(" %d", land.lnd_rad); break; + case 35: pr(" %d", land.lnd_frg); break; + case 36: pr(" %d", land.lnd_acc); break; + case 37: pr(" %d", land.lnd_dam); break; + case 38: pr(" %d", land.lnd_ammo); break; + case 39: pr(" %d", land.lnd_aaf); break; + } + } + pr("\n"); + } + if (nunits == 0) { + if (player->argp[1]) + pr("%s: No unit(s)\n", player->argp[1]); + else + pr("%s: No unit(s)\n", ""); + return RET_FAIL; + }else + pr("%d unit%s\n", nunits, splur(nunits)); + return RET_OK; +} + diff --git a/src/lib/commands/ledg.c b/src/lib/commands/ledg.c new file mode 100644 index 00000000..e964c93c --- /dev/null +++ b/src/lib/commands/ledg.c @@ -0,0 +1,68 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * ledg.c: Get a report of the current ledger + * + * Known contributors to this file: + * Steve McClure, 1996 + */ + +#include "misc.h" +#include "player.h" +#include "loan.h" +#include "file.h" +#include "xy.h" +#include "nsc.h" +#include "nat.h" +#include "commands.h" +#include "optlist.h" + +int +ledg(void) +{ + struct nstr_item nstr; + struct lonstr loan; + int nloan; + + if (!opt_LOANS) { + pr("Loans are not enabled.\n"); + return RET_FAIL; + } + if (!snxtitem(&nstr, EF_LOAN, player->argp[1])) + return RET_SYN; + pr("\n... %s Ledger ...\n", cname(player->cnum)); + nloan = 0; + while (nxtitem(&nstr, (s_char *)&loan)) { + if (disloan(nstr.cur, &loan) > 0) + nloan++; + } + if (!nloan) + pr("No loans found\n"); + else + pr("%d loan%s outstanding.\n", nloan, splur(nloan)); + return RET_OK; +} diff --git a/src/lib/commands/leve.c b/src/lib/commands/leve.c new file mode 100644 index 00000000..bb3d655f --- /dev/null +++ b/src/lib/commands/leve.c @@ -0,0 +1,98 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * leve.c: Do a distribution threshold level report + * + * Known contributors to this file: + * David Muir Sharnoff, 1987 + */ + +#include "misc.h" +#include "player.h" +#include "var.h" +#include "sect.h" +#include "xy.h" +#include "nsc.h" +#include "nat.h" +#include "deity.h" +#include "file.h" +#include "path.h" +#include "commands.h" + +int +leve(void) +{ + struct sctstr sect; + int nsect; + struct nstr_sect nstr; + int dist[I_MAX+1]; + + if (!snxtsct(&nstr, player->argp[1])) + return RET_SYN; + prdate(); + nsect = 0; + while (nxtsct(&nstr, §)) { + if (!player->owner) + continue; + if (nsect++ == 0) { + pr("DISTRIBUTION LEVELS\n"); + if (player->god) + pr("own"); + pr(" sect dst civ mil uw food sh gun pet iron dust bar oil lcm hcm rad\n"); + } + if (player->god) + pr("%2d ", sect.sct_own); + getvec(VT_DIST, dist, (s_char *)§, EF_SECTOR); + prxy("%3d,%-3d", nstr.x, nstr.y, player->cnum); + pr(" %c ", dchr[sect.sct_type].d_mnem); + prxy("%3d,%-3d", sect.sct_dist_x,sect.sct_dist_y,player->cnum); + pr(" %4d", dist[I_CIVIL]); + pr("%4d", dist[I_MILIT]); + pr("%4d", dist[I_UW]); + pr("%5d", dist[I_FOOD]); + pr("%4d", dist[I_SHELL]); + pr("%4d", dist[I_GUN]); + pr("%4d", dist[I_PETROL]); + pr("%5d", dist[I_IRON]); + pr("%5d", dist[I_DUST]); + pr("%4d", dist[I_BAR]); + pr("%4d", dist[I_OIL]); + pr("%4d", dist[I_LCM]); + pr("%4d", dist[I_HCM]); + pr("%4d", dist[I_RAD]); + pr("\n"); + } + if (nsect == 0) { + if (player->argp[1]) + pr("%s: No sector(s)\n", player->argp[1]); + else + pr("%s: No sector(s)\n", ""); + return RET_FAIL; + }else + pr("%d sector%s\n", nsect, splur(nsect)); + return 0; +} diff --git a/src/lib/commands/load.c b/src/lib/commands/load.c new file mode 100644 index 00000000..17b31bd5 --- /dev/null +++ b/src/lib/commands/load.c @@ -0,0 +1,1229 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * load.c: load/unload goods from a sector onto a ship or land unit + * + * Known contributors to this file: + * David Sharnoff, 1987 + * Ken Stevens, 1995 (rewritten) + * Steve McClure, 1998-2000 + */ + +#ifdef Rel4 +#include +#endif /* Rel4 */ +#include "misc.h" +#include "player.h" +#include "xy.h" +#include "file.h" +#include "var.h" +#include "sect.h" +#include "ship.h" +#include "plane.h" +#include "land.h" +#include "item.h" +#include "nsc.h" +#include "nat.h" +#include "optlist.h" +#include "commands.h" + +/* + * The values 1 and -1 are important below, don't change them. + */ +#define LOAD 1 +#define UNLOAD -1 + +void gift(int givee, int giver, s_char *ptr, int type, s_char *mesg); +static int load_plane_ship(struct sctstr *sectp, struct shpstr *sp, int noisy, int load_unload, int *nshipsp); +static int load_land_ship(struct sctstr *sectp, struct shpstr *sp, int noisy, int load_unload, int *nshipsp); +static int load_comm_ship(struct sctstr *sectp, struct shpstr *sp, struct ichrstr *ich, int load_unload, int *nshipsp); +static int load_plane_land(struct sctstr *sectp, struct lndstr *lp, int noisy, int load_unload, int *nunitsp); +static int load_land_land(struct sctstr *sectp, struct lndstr *lp, int noisy, int load_unload, int *nunitsp); +static int load_comm_land(struct sctstr *sectp, struct lndstr *lp, struct ichrstr *ich, int load_unload, int *nunitsp); + +int +load(void) +{ + int noisy; + int load_unload; + int type; + struct nstr_item nbst; + struct ichrstr *ich; + int nships; + struct sctstr sect; + struct shpstr ship; + int retval; + s_char *p; + s_char buf[1024]; + + if (!(p = getstarg(player->argp[1], + "What commodity (or 'plane' or 'land')? ", buf)) || !*p) + return RET_SYN; + + if (!strncmp(p, "plane", 5)) + type = EF_PLANE; + else if (!strncmp(p, "land", 4)) + type = EF_LAND; + else if (NULL != (ich = whatitem(p, (s_char *)0))) + type = EF_SECTOR; + else { + pr("Bad commodity.\n"); + return RET_SYN; + } + + if (!(p = getstarg(player->argp[2], "Ship(s): ", buf)) || !*p) + return RET_SYN; + + noisy = isdigit(*p); + + if (!snxtitem(&nbst, EF_SHIP, p)) + return RET_SYN; + + nbst.flags &= ~(EFF_OWNER); + + load_unload = **player->argp == 'l' ? LOAD : UNLOAD; + + nships = 0; + while (nxtitem(&nbst, (s_char *)&ship)) { + if (!ship.shp_own) + continue; + if (!player->owner && (load_unload == UNLOAD)) { + continue; + } + if (opt_MARKET) { + if (ontradingblock(EF_SHIP, (int *)&ship)) { + pr("You cannot load/unload an item on the trading block!\n"); + continue; + } + } + + if (ship.shp_own != player->cnum) { + if (!noisy) + continue; + if (getrel(getnatp(player->cnum),ship.shp_own) < FRIENDLY) + continue; + } + if (!getsect(ship.shp_x, ship.shp_y, §)) /* XXX */ + continue; + if ((sect.sct_own != player->cnum) && + (ship.shp_own != player->cnum)) + continue; + if (!player->owner && + sect.sct_type != SCT_HARBR && + (!opt_BIG_CITY || sect.sct_type != SCT_CAPIT)) + continue; + if (!sect.sct_own) + continue; + if ((sect.sct_own != player->cnum) && (load_unload == LOAD)) { + if (noisy) + pr("You don't own %s \n", + xyas(ship.shp_x, ship.shp_y, player->cnum)); + continue; + } + if (sect.sct_type != SCT_HARBR && + (!opt_BIG_CITY || sect.sct_type != SCT_CAPIT)) { + if (noisy) + pr("Sector %s is not a harbor%s.\n", + xyas(ship.shp_x, ship.shp_y, player->cnum), + opt_BIG_CITY?" or a city":""); + continue; + } + if (sect.sct_own != player->cnum && load_unload == UNLOAD && getrel(getnatp(sect.sct_own), player->cnum) < FRIENDLY) { + if (noisy) + pr("You can't unload into an unfriendly %s\n", + dchr[sect.sct_type].d_name); + continue; + } + if (sect.sct_effic < 2) { + if (noisy) + pr("The %s at %s is not 2%% efficient yet.\n", + dchr[sect.sct_type].d_name, + xyas(ship.shp_x, ship.shp_y, player->cnum)); + continue; + } + switch (type) { + case EF_PLANE: + if (0 != (retval=load_plane_ship(§, &ship, noisy, load_unload, &nships))) + return retval; + break; + case EF_LAND: + if (0 != (retval=load_land_ship(§, &ship, noisy, load_unload, &nships))) + return retval; + break; + case EF_SECTOR: + if (0 != (retval=load_comm_ship(§, &ship, ich, load_unload, &nships))) + return retval; + } + /* load/unload plague */ + if (getvar(V_PSTAGE, (s_char *)§, EF_SECTOR) == PLG_INFECT && + getvar(V_PSTAGE, (s_char *)&ship, EF_SHIP) == PLG_HEALTHY) + putvar(V_PSTAGE, PLG_EXPOSED, (s_char *)&ship, EF_SHIP); + if (getvar(V_PSTAGE, (s_char *)&ship, EF_SHIP) == PLG_INFECT && + getvar(V_PSTAGE, (s_char *)§, EF_SECTOR) == PLG_HEALTHY) + putvar(V_PSTAGE, PLG_EXPOSED, (s_char *)§, EF_SECTOR); + putsect(§); + putship(ship.shp_uid, &ship); + } + if (!nships) + pr("No ships affected\n"); + else + pr("%d ship%s %sloaded\n", nships, splur(nships), + load_unload == UNLOAD ? "un" : ""); + return RET_OK; +} + +int +lload(void) +{ + int noisy; + int load_unload; + int type; + struct nstr_item nbst; + struct ichrstr *ich; + int nunits; + struct sctstr sect; + struct lndstr land; + int retval; + s_char *p; + s_char buf[1024]; + + if (!(p = getstarg(player->argp[1], + "What commodity (or 'plane' or 'land')? ", buf)) || !*p) + return RET_SYN; + if (!strncmp(p, "plane", 5)) + type = EF_PLANE; + else if (!strncmp(p, "land", 4)) + type = EF_LAND; + else if (NULL != (ich = whatitem(p, (s_char *)0))) + type = EF_SECTOR; + else { + pr("Bad commodity.\n"); + return RET_SYN; + } + + if (!(p = getstarg(player->argp[2], "Unit(s): ", buf)) || !*p) + return RET_SYN; + + noisy = isdigit(*p); + + if (!snxtitem(&nbst, EF_LAND, p)) + return RET_SYN; + + load_unload = *(*player->argp+1) == 'l' ? LOAD : UNLOAD; + + nbst.flags &= ~(EFF_OWNER); + + nunits = 0; + while (nxtitem(&nbst, (s_char *)&land)) { + if (land.lnd_own == 0) + continue; + + if (player->cnum != land.lnd_own && + getrel(getnatp(player->cnum), land.lnd_own) != ALLIED) + continue; + + if (!getsect(land.lnd_x, land.lnd_y, §)) /* XXX */ + continue; + + if (sect.sct_own != player->cnum && + land.lnd_own != player->cnum) + continue; + if (opt_MARKET) { + if (ontradingblock(EF_LAND, (int *)&land)) { + pr("You cannot load/unload an item on the trading block!\n"); + continue; + } + } + + if (sect.sct_own != player->cnum && + getrel(getnatp(sect.sct_own), land.lnd_own) != ALLIED) { + pr("Sector %s is not yours.\n", + xyas(land.lnd_x, land.lnd_y, player->cnum)); + continue; + } + switch (type) { + case EF_LAND: + if (0 != (retval=load_land_land(§, &land, noisy, load_unload, &nunits))) + return retval; + break; + case EF_PLANE: + if (0 != (retval=load_plane_land(§, &land, noisy, load_unload, &nunits))) + return retval; + break; + case EF_SECTOR: + if (0 != (retval=load_comm_land(§, &land, ich, load_unload, &nunits))) + return retval; + } + /* load/unload plague */ + if (getvar(V_PSTAGE, (s_char *)§, EF_SECTOR) == PLG_INFECT && + getvar(V_PSTAGE, (s_char *)&land, EF_LAND) == PLG_HEALTHY) + putvar(V_PSTAGE, PLG_EXPOSED, (s_char *)&land, EF_LAND); + if (getvar(V_PSTAGE, (s_char *)&land, EF_LAND) == PLG_INFECT && + getvar(V_PSTAGE, (s_char *)§, EF_SECTOR) == PLG_HEALTHY) + putvar(V_PSTAGE, PLG_EXPOSED, (s_char *)§, EF_SECTOR); + + putsect(§); + putland(land.lnd_uid, &land); + } + if (nunits == 0) + pr("No units affected\n"); + else + pr("%d unit%s %sloaded\n", nunits, splur(nunits), + load_unload == UNLOAD ? "un" : ""); + return RET_OK; +} + +void +gift(int givee, int giver, s_char *ptr, int type, s_char *mesg) +{ + s_char *p, line[256]; + + if (giver == givee) + return; + + + switch(type) { + case EF_SHIP: p = prship((struct shpstr *)ptr); + break; + case EF_PLANE: p = prplane((struct plnstr *)ptr); + break; + case EF_LAND: p = prland((struct lndstr *)ptr); + break; + } + + sprintf(line,"%s %s %s\n",cname(giver),p,mesg); + wu(0,givee,line); +} + +static int +still_ok_ship(struct sctstr *sectp, struct shpstr *shipp) +{ + if (!check_sect_ok(sectp)) + return 0; + if (!check_ship_ok(shipp)) + return 0; + return 1; +} + +static int +still_ok_land(struct sctstr *sectp, struct lndstr *landp) +{ + if (!check_sect_ok(sectp)) + return 0; + if (!check_land_ok(landp)) + return 0; + return 1; +} + +static int +load_plane_ship(struct sctstr *sectp, struct shpstr *sp, int noisy, int load_unload, int *nshipsp) +{ + struct nstr_item ni; + struct plnstr pln; + int loaded = 0; + s_char buf[1024]; + s_char *p; + s_char prompt[512]; + struct mchrstr *mcp = mchr + sp->shp_type; + + if (!(mcp->m_flags & (M_CHOPPER|M_XLIGHT|M_FLY|M_MSL))) { + if (noisy) + pr("%s cannot carry planes\n", prship(sp)); + return 0; + } + count_planes(sp); + if (load_unload==LOAD && + sp->shp_nchoppers >= mcp->m_nchoppers && + sp->shp_nxlight >= mcp->m_nxlight && + sp->shp_nplane >= mcp->m_nplanes) { + if (noisy) + pr("%s doesn't have room for any more planes\n", + prship(sp)); + return 0; + } + sprintf(prompt, "Plane(s) to %s %s? ", + load_unload==LOAD?"load onto":"unload from", + prship(sp)); + if (!snxtitem(&ni, EF_PLANE, p=getstarg(player->argp[3], prompt, buf))) + return RET_SYN; + + if (!still_ok_ship(sectp, sp)) + return RET_SYN; + + if (p && *p) + noisy &= isdigit(*p); + + while(nxtitem(&ni, (s_char *)&pln)) { + if (pln.pln_own != player->cnum) + continue; + if (!(plchr[(int)pln.pln_type].pl_flags & P_L) + && !(plchr[(int)pln.pln_type].pl_flags & P_E) + && !(plchr[(int)pln.pln_type].pl_flags & P_K) + && !(plchr[(int)pln.pln_type].pl_flags & P_M) + ) { + if (noisy) + pr("You can only load light planes, helos, xtra-light, or missiles onto ships.\n"); + continue; + } + if (load_unload == LOAD && pln.pln_ship > -1) { + if (noisy) + pr("%s is already on ship #%d!\n", + prplane(&pln), pln.pln_ship); + continue; + } + if (load_unload == LOAD && pln.pln_land > -1) { + if (noisy) + pr("%s is already on land unit #%d!\n", + prplane(&pln), pln.pln_land); + continue; + } + + /* Plane sanity done */ + /* Find the right ship */ + if (load_unload == UNLOAD) { + if (pln.pln_ship != sp->shp_uid) + continue; + } else if (sp->shp_x != pln.pln_x + || sp->shp_y != pln.pln_y) + continue; + + /* ship to (plane or missle) sanity */ + if (!can_be_on_ship(pln.pln_uid, sp->shp_uid)) { + if (plchr[(int)pln.pln_type].pl_flags & P_L) { + strcpy(buf, "planes"); + } else if (plchr[(int)pln.pln_type].pl_flags & P_K) { + strcpy(buf, "choppers"); + } else if (plchr[(int)pln.pln_type].pl_flags & P_M) { + strcpy(buf, "missiles"); + } else if (plchr[(int)pln.pln_type].pl_flags & P_E) { + strcpy(buf, "extra light planes"); + } /* else impossible */ + if (noisy) + pr("%s cannot carry %s.\n", + prship(sp), + buf); + continue; + } + /* Fit plane on ship */ + if (load_unload == LOAD){ + if (!put_plane_on_ship(&pln,sp)){ + if (noisy) + pr("Can't put plane %d on this ship!\n",pln.pln_uid); + continue; + } + sprintf(buf, "loaded on your %s at %s", + prship(sp),xyas(sp->shp_x, + sp->shp_y, sp->shp_own)); + gift(sp->shp_own, player->cnum, (s_char *)&pln, + EF_PLANE, buf); + makelost(EF_PLANE, pln.pln_own, pln.pln_uid, pln.pln_x, pln.pln_y); + pln.pln_own = sp->shp_own; + makenotlost(EF_PLANE, pln.pln_own, pln.pln_uid, pln.pln_x, pln.pln_y); + pln.pln_mission = 0; + putplane(pln.pln_uid,&pln); + } else { + if (!take_plane_off_ship(&pln,sp)) { + pr("Unable to take plane off ship!\n"); + logerror("load: plane %d could not be taken off ship %d\n",pln.pln_uid,sp->shp_uid); + continue; + } + sprintf(buf, "unloaded in your %s at %s", + dchr[sectp->sct_type].d_name, + xyas(sectp->sct_x,sectp->sct_y, + sectp->sct_own)); + gift(sectp->sct_own, player->cnum, (s_char *)&pln, + EF_PLANE, buf); + makelost(EF_PLANE, pln.pln_own, pln.pln_uid, pln.pln_x, pln.pln_y); + pln.pln_own = sectp->sct_own; + makenotlost(EF_PLANE, pln.pln_own, pln.pln_uid, pln.pln_x, pln.pln_y); + putplane(pln.pln_uid,&pln); + } + pr("%s %s %s at %s.\n", + prplane(&pln), + (load_unload==UNLOAD)? + "unloaded from":"loaded onto", + prship(sp), + xyas(sp->shp_x, sp->shp_y, player->cnum)); + loaded = 1; + } + *nshipsp += loaded; + return 0; +} + +static int +load_land_ship(struct sctstr *sectp, struct shpstr *sp, int noisy, int load_unload, int *nshipsp) +{ + struct nstr_item pni, ni; + struct lndstr land; + struct plnstr plane; + int loaded = 0; + s_char *p; + s_char prompt[512]; + s_char buf[1024]; + int load_spy = 0; + + count_units(sp); + if (load_unload == LOAD) { + if (opt_LANDSPIES) { + if ((mchr[(int)sp->shp_type].m_flags & M_SUB) && + (mchr[(int)sp->shp_type].m_nland == 0)) { + if (sp->shp_nland >= 2) { + pr("Non-land unit carrying subs can only carry up to two spy units.\n"); + return 0; + } + /* Eh, let 'em load a spy only */ + load_spy = 1; + } + } + if ((!load_spy) && + (sp->shp_nland >= mchr[(int)sp->shp_type].m_nland)) { + if (noisy) { + if (mchr[(int)sp->shp_type].m_nland) + pr("%s doesn't have room for any more land units!\n",prship(sp)); + else + pr("%s cannot carry land units!\n",prship(sp)); + } + return 0; + } + } + sprintf(prompt, "Land unit(s) to %s %s? ", + load_unload==LOAD?"load onto":"unload from", + prship(sp)); + if (!snxtitem(&ni, EF_LAND, p=getstarg(player->argp[3], prompt, buf))) + return RET_SYN; + + if (!still_ok_ship(sectp, sp)) + return RET_SYN; + + if (p && *p) + noisy &= isdigit(*p); + + while(nxtitem(&ni, (s_char *)&land)) { + if (land.lnd_own != player->cnum) + continue; + + if (load_unload == LOAD) { + if (land.lnd_ship > -1) { + if (noisy) + pr("%s is already on ship #%d!\n", + prland(&land), land.lnd_ship); + continue; + } + if (land.lnd_land > -1) { + if (noisy) + pr("%s is already on land #%d!\n", + prland(&land), land.lnd_land); + continue; + } + lnd_count_units(&land); + if (land.lnd_nland > 0) { + if (noisy) + pr("%s cannot be loaded since it is carrying units\n", + prland(&land)); + continue; + } + if (lchr[(int)land.lnd_type].l_flags & L_HEAVY) { + if (noisy) + pr("%s is too heavy to load.\n", prland(&land)); + continue; + } + if (load_spy && !(lchr[(int)land.lnd_type].l_flags & L_SPY)) { + if (noisy) + pr("Subs can only carry spy units.\n"); + continue; + } + } + + /* Unit sanity done */ + /* Find the right ship */ + if (load_unload == UNLOAD) { + if (land.lnd_ship != sp->shp_uid) + continue; + if (land.lnd_land > -1) + continue; + } else if (sp->shp_x != land.lnd_x + || sp->shp_y != land.lnd_y) + continue; + + if ((!(lchr[(int)land.lnd_type].l_flags & L_LIGHT)) && + (!((mchr[(int)sp->shp_type].m_flags & M_SUPPLY) && + (!(mchr[(int)sp->shp_type].m_flags & M_SUB))))) { + if (noisy) { + pr("You can only load light units onto ships,\n"); + pr("unless the ship is a non-sub supply ship\n"); + pr("%s not loaded\n", prland(&land)); + } + continue; + } + /* Fit unit on ship */ + if (load_unload == LOAD) { + count_units(sp); + /* We have to check again, since it may have changed */ + if (opt_LANDSPIES) { + if ((mchr[(int)sp->shp_type].m_flags & M_SUB) && + (mchr[(int)sp->shp_type].m_nland == 0)) { + if (sp->shp_nland >= 2) { + pr("Non-land unit carrying subs can only carry up to two spy units.\n"); + return 0; + } + /* Eh, let 'em load a spy only */ + load_spy = 1; + } + } + if ((!load_spy) && + (sp->shp_nland >= mchr[(int)sp->shp_type].m_nland)) { + if (noisy) { + if (mchr[(int)sp->shp_type].m_nland) + pr("%s doesn't have room for any more land units!\n",prship(sp)); + else + pr("%s cannot carry land units!\n",prship(sp)); + } + return 0; + } +#if 0 + if (sp->shp_nland >= mchr[(int)sp->shp_type].m_nland) { + if (noisy) + if (mchr[(int)sp->shp_type].m_nland) + pr("%s doesn't have room for any more land units!\n",prship(sp)); + else + pr("%s cannot carry land units!\n",prship(sp)); + break; + } +#endif + sprintf(buf, "loaded on your %s at %s", + prship(sp),xyas(sp->shp_x,sp->shp_y, + sp->shp_own)); + gift(sp->shp_own,player->cnum,(s_char *)&land, + EF_LAND, buf); + makelost(EF_LAND, land.lnd_own, land.lnd_uid, land.lnd_x, + land.lnd_y); + land.lnd_own = sp->shp_own; + makenotlost(EF_LAND, land.lnd_own, land.lnd_uid, land.lnd_x, + land.lnd_y); + land.lnd_ship = sp->shp_uid; + land.lnd_harden = 0; + land.lnd_mission = 0; + resupply_all(&land); + sp->shp_nland++; + putland(land.lnd_uid,&land); + if (!has_supply(&land)) + pr("WARNING: %s is out of supply!\n", + prland(&land)); + putship(sp->shp_uid,sp); + snxtitem_xy(&pni,EF_PLANE,land.lnd_x,land.lnd_y); + while (nxtitem(&pni, (s_char *)&plane)){ + if (plane.pln_flags & PLN_LAUNCHED) + continue; + if (plane.pln_land != land.lnd_uid) + continue; + sprintf(buf, "loaded on %s", + prship(sp)); + gift(sp->shp_own,player->cnum,(s_char *)&plane, + EF_PLANE, buf); + makelost(EF_PLANE, plane.pln_own, plane.pln_uid, plane.pln_x, + plane.pln_y); + plane.pln_own = sp->shp_own; + makenotlost(EF_PLANE, plane.pln_own, plane.pln_uid, + plane.pln_x, plane.pln_y); + plane.pln_mission = 0; + putplane(plane.pln_uid,&plane); + } + } else { + sprintf(buf, "unloaded in your %s at %s", + dchr[sectp->sct_type].d_name, + xyas(sectp->sct_x,sectp->sct_y, + sectp->sct_own)); + + /* Spies are unloaded quietly, others aren't */ + if (!(lchr[(int)land.lnd_type].l_flags & L_SPY)) { + gift(sectp->sct_own,player->cnum,(s_char *)&land, + EF_LAND, buf); + makelost(EF_LAND, land.lnd_own, land.lnd_uid, + land.lnd_x, land.lnd_y); + land.lnd_own = sectp->sct_own; + makenotlost(EF_LAND, land.lnd_own, land.lnd_uid, + land.lnd_x, land.lnd_y); + } + + land.lnd_ship = (-1); + sp->shp_nland--; + putland(land.lnd_uid,&land); + putship(sp->shp_uid,sp); + + /* Spies are unloaded quietly, others aren't, and + in the off chance they can carry a plane (missile?) + they are quietly unloaded too. */ + if (!(lchr[(int)land.lnd_type].l_flags & L_SPY)) { + snxtitem_xy(&pni,EF_PLANE,land.lnd_x,land.lnd_y); + while (nxtitem(&pni, (s_char *)&plane)){ + if (plane.pln_flags & PLN_LAUNCHED) + continue; + if (plane.pln_land != land.lnd_uid) + continue; + sprintf(buf, "unloaded at %s", + xyas(plane.pln_x,plane.pln_y, + sectp->sct_own)); + gift(sectp->sct_own,player->cnum,(s_char *)&plane, + EF_PLANE, buf); + makelost(EF_PLANE, plane.pln_own, plane.pln_uid, + plane.pln_x, plane.pln_y); + plane.pln_own = sectp->sct_own; + makenotlost(EF_PLANE, plane.pln_own, plane.pln_uid, + plane.pln_x, plane.pln_y); + plane.pln_mission = 0; + putplane(plane.pln_uid,&plane); + } + } + } + pr("%s %s %s at %s.\n", + prland(&land), + (load_unload==UNLOAD)? + "unloaded from":"loaded onto", + prship(sp), + xyas(sp->shp_x, sp->shp_y, player->cnum)); + loaded = 1; + } + *nshipsp += loaded; + return 0; +} + +static int +load_comm_ship(struct sctstr *sectp, struct shpstr *sp, struct ichrstr *ich, int load_unload, int *nshipsp) +{ + register int item = ich->i_vtype; + register int max_amt; + register int move_amt; + register int ship_amt; + register int sect_amt; + int amount; + int upto=0, abs_max; + s_char prompt[512]; + s_char *p; + s_char buf[1024]; + + sprintf(prompt, "Number of %s to %s %s at %s? ", + ich->i_name, + (load_unload==UNLOAD)? + "unload from":"load onto", + prship(sp), + xyas(sp->shp_x, sp->shp_y, player->cnum)); + if (!(p = getstarg(player->argp[3], prompt, buf)) || + !*p) + return RET_SYN; + + if (!still_ok_ship(sectp, sp)) + return RET_SYN; + + amount = atoi(p); + if (amount < 0) { + /* We want to load up to this amount */ + upto = -(amount); + load_unload = LOAD; + } else if (!amount) + return 0; + ship_amt = getvar(item, (s_char *)sp, EF_SHIP); + sect_amt = getvar(item, (s_char *)sectp, EF_SECTOR); + if (sectp->sct_oldown != player->cnum && + item == V_CIVIL) { + pr("%s civilians refuse to %s at %s!\n", + load_unload == UNLOAD ? "Your" : "Foreign", + load_unload == UNLOAD ? + "disembark" : "board", + xyas(sectp->sct_x, sectp->sct_y, player->cnum)); + return 0; + } + if (load_unload == UNLOAD) { + abs_max = max_amt = min(9999 - sect_amt, ship_amt); + } else { + struct mchrstr *vbase; + vbase = &mchr[(int)sp->shp_type]; + abs_max = max_amt = vl_find(item, vbase->m_vtype, + vbase->m_vamt, (int) vbase->m_nv); + max_amt = min(sect_amt, max_amt - ship_amt); + } + if (max_amt <= 0 && !upto) + return 0; + if (upto) { + move_amt = upto - ship_amt; + if (move_amt > sect_amt) + move_amt = sect_amt; + if (ship_amt+move_amt > abs_max) + move_amt = abs_max - ship_amt; + } else + move_amt = load_unload * min(amount, max_amt); + if (!move_amt) + return 0; + + if (!want_to_abandon(sectp, item, move_amt, 0)) + return RET_FAIL; + if (!still_ok_ship(sectp, sp)) + return RET_SYN; + putvar(item, sect_amt - move_amt, (s_char *)sectp, EF_SECTOR); + putvar(item, ship_amt + move_amt, (s_char *)sp, EF_SHIP); + if (load_unload == LOAD) { + pr("%d %s loaded onto %s at %s\n", + move_amt, + ich->i_name, + prship(sp), + xyas(sp->shp_x, sp->shp_y, player->cnum)); + if (sp->shp_own != player->cnum) { + sprintf(buf,"%s loaded %d %s onto %s at %s\n", + cname(player->cnum), + move_amt, + ich->i_name, + prship(sp), + xyas(sp->shp_x, sp->shp_y, + sp->shp_own)); + wu(0, sp->shp_own, buf); + } + } else { + pr("%d %s unloaded from %s at %s\n", + -move_amt, + ich->i_name, + prship(sp), + xyas(sp->shp_x, sp->shp_y, player->cnum)); + if (sectp->sct_own != player->cnum) { + sprintf(buf,"%s unloaded %d %s from %s at %s\n", + cname(player->cnum), + -move_amt, + ich->i_name, + prship(sp), + xyas(sp->shp_x, sp->shp_y, + sectp->sct_own)); + wu(0, sectp->sct_own, buf); + } + } + ++(*nshipsp); + return 0; +} + +static int +load_plane_land(struct sctstr *sectp, struct lndstr *lp, int noisy, int load_unload, int *nunitsp) +{ + struct nstr_item ni; + struct plnstr pln; + int loaded = 0; + s_char *p; + s_char prompt[512]; + s_char buf[1024]; + + if (!(lchr[(int)lp->lnd_type].l_flags & L_XLIGHT)) { + if (noisy) + pr("%s cannot carry extra-light planes.\n", + prland(lp)); + return 0; + } + count_land_planes(lp); + if (load_unload==LOAD && + lp->lnd_nxlight >= lp->lnd_maxlight) { + if (noisy) + pr("%s doesn't have room for any more extra-light planes\n", + prland(lp)); + return 0; + } + sprintf(prompt, "Plane(s) to %s %s? ", + load_unload==LOAD?"load onto":"unload from", + prland(lp)); + if (!snxtitem(&ni, EF_PLANE, p=getstarg(player->argp[3], prompt, buf))) + return RET_SYN; + + if (!still_ok_land(sectp, lp)) + return RET_SYN; + + if (p && *p) + noisy &= isdigit(*p); + + if (sectp->sct_own != player->cnum && load_unload == LOAD) { + pr("Sector %s is not yours.\n", + xyas(lp->lnd_x, lp->lnd_y, player->cnum)); + return 0; + } + + while(nxtitem(&ni, (s_char *)&pln)) { + if (pln.pln_own != player->cnum) + continue; + + if (!(plchr[(int)pln.pln_type].pl_flags & P_E)) { + if (noisy) + pr("You can only load xlight planes onto units.\n"); + continue; + } + + if (load_unload == LOAD && pln.pln_ship > -1) { + if (noisy) + pr("%s is already on ship #%d!\n", + prplane(&pln), pln.pln_ship); + continue; + } + if (load_unload == LOAD && pln.pln_land > -1) { + if (noisy) + pr("%s is already on unit #%d!\n", + prplane(&pln), pln.pln_land); + continue; + } + /* Plane sanity done */ + /* Find the right unit */ + if (load_unload == UNLOAD) { + if (pln.pln_land != lp->lnd_uid) + continue; + } else if (lp->lnd_x != pln.pln_x + || lp->lnd_y != pln.pln_y) + continue; + + /* Fit plane on unit */ + if (load_unload == LOAD){ + if (!put_plane_on_land(&pln,lp)){ + if (noisy) + pr("Can't put plane %d on this unit!\n",pln.pln_uid); + continue; + } + sprintf(buf, "loaded on %s at %s", + prland(lp), xyas(lp->lnd_x, + lp->lnd_y, lp->lnd_own)); + gift(lp->lnd_own,player->cnum,(s_char *)&pln, + EF_PLANE, buf); + makelost(EF_PLANE, pln.pln_own, pln.pln_uid, pln.pln_x, pln.pln_y); + pln.pln_own = lp->lnd_own; + makenotlost(EF_PLANE, pln.pln_own, pln.pln_uid, pln.pln_x, pln.pln_y); + putplane(pln.pln_uid,&pln); + }else{ + if (!take_plane_off_land(&pln,lp)){ + pr("Unable to take plane off unit!\n"); + logerror("load: plane %d could not be taken off unit %d\n",pln.pln_uid,lp->lnd_uid); + continue; + } + sprintf(buf, "unloaded at your sector at %s", + xyas(sectp->sct_x,sectp->sct_y, + sectp->sct_own)); + gift(sectp->sct_own,player->cnum,(s_char *)&pln, + EF_PLANE, buf); + makelost(EF_PLANE, pln.pln_own, pln.pln_uid, pln.pln_x, pln.pln_y); + pln.pln_own = sectp->sct_own; + makenotlost(EF_PLANE, pln.pln_own, pln.pln_uid, pln.pln_x, pln.pln_y); + putplane(pln.pln_uid,&pln); + } + pr("%s %s %s at %s.\n", + prplane(&pln), + (load_unload==UNLOAD)? + "unloaded from":"loaded onto", + prland(lp), + xyas(lp->lnd_x, lp->lnd_y, player->cnum)); + loaded = 1; + } + *nunitsp += loaded; + return 0; +} + +static int +load_comm_land(struct sctstr *sectp, struct lndstr *lp, struct ichrstr *ich, int load_unload, int *nunitsp) +{ + register int item = ich->i_vtype; + register int max_amt; + register int move_amt; + register int land_amt; + register int sect_amt; + int amount; + int upto=0, abs_max; + s_char prompt[512]; + s_char *p; + s_char buf[1024]; + + sprintf(prompt, "Number of %s to %s %s at %s? ", + ich->i_name, + (load_unload==UNLOAD)? + "unload from":"load onto", + prland(lp), + xyas(lp->lnd_x, lp->lnd_y, player->cnum)); + if (!(p = getstarg(player->argp[3], prompt, buf)) || + !*p) + return RET_SYN; + + if (!still_ok_land(sectp, lp)) + return RET_SYN; + + amount = atoi(p); + if (amount < 0) { + /* We want to load up to this amount */ + upto = -(amount); + load_unload = LOAD; + } else if (!amount) + return 0; + + if (sectp->sct_own != player->cnum && load_unload == LOAD) { + pr("Sector %s is not yours.\n", + xyas(lp->lnd_x, lp->lnd_y, player->cnum)); + return 0; + } + + land_amt = getvar(item, (s_char *)lp, EF_LAND); + sect_amt = getvar(item, (s_char *)sectp, EF_SECTOR); + if (sectp->sct_oldown != player->cnum && item == V_CIVIL) { + pr("%s civilians refuse to %s at %s!\n", + load_unload == UNLOAD ? "Your" : "Foreign", + load_unload == UNLOAD ? + "disembark" : "board", + xyas(sectp->sct_x, sectp->sct_y, player->cnum)); + return 0; + } + if (load_unload == UNLOAD) { + abs_max = max_amt = min(9999 - sect_amt, land_amt); + } else { + struct lchrstr *vbase; + vbase = &lchr[(int)lp->lnd_type]; + abs_max = max_amt = vl_find(item, vbase->l_vtype, + vbase->l_vamt, (int) vbase->l_nv); + max_amt = min(sect_amt, max_amt - land_amt); + } + if ((max_amt <= 0) && (upto == 0)) + return 0; + if (upto){ + move_amt = upto - land_amt; + if (land_amt+move_amt > abs_max) + move_amt = abs_max - land_amt; + if (move_amt > sect_amt) + move_amt = sect_amt; + }else + move_amt = load_unload * min(amount, max_amt); + if (move_amt == 0) + return 0; + putvar(item, sect_amt - move_amt, (s_char *)sectp, EF_SECTOR); + putvar(item, land_amt + move_amt, (s_char *)lp, EF_LAND); + + /* Did we put mils onto this unit? If so, reset the fortification */ + if (item == V_MILIT && move_amt > 0) + lp->lnd_harden = 0; + if (load_unload == LOAD) { + pr("%d %s loaded onto %s at %s\n", + move_amt, + ich->i_name, + prland(lp), + xyas(lp->lnd_x, lp->lnd_y, player->cnum)); + if (lp->lnd_own != player->cnum) { + sprintf(buf,"%s loaded %d %s onto %s at %s\n", + cname(player->cnum), + move_amt, + ich->i_name, + prland(lp), + xyas(lp->lnd_x, lp->lnd_y, + lp->lnd_own)); + wu(0, lp->lnd_own, buf); + } + } else { + pr("%d %s unloaded from %s at %s\n", + -move_amt, + ich->i_name, + prland(lp), + xyas(lp->lnd_x, lp->lnd_y, player->cnum)); + if (sectp->sct_own != player->cnum) { + sprintf(buf,"%s unloaded %d %s from %s at %s\n", + cname(player->cnum), + -move_amt, + ich->i_name, + prland(lp), + xyas(lp->lnd_x, lp->lnd_y, + sectp->sct_own)); + wu(0, sectp->sct_own, buf); + } + } + + ++(*nunitsp); + return 0; +} + +static int +load_land_land(struct sctstr *sectp, struct lndstr *lp, int noisy, int load_unload, int *nunitsp) +{ + struct nstr_item pni, ni; + struct lndstr land; + struct plnstr plane; + int loaded = 0; + s_char *p; + s_char prompt[512]; + s_char buf[1024]; + + lnd_count_units(lp); + + if (load_unload==LOAD && + lp->lnd_nland >= lp->lnd_maxland) { + if (noisy) { + if (lp->lnd_nland) + pr("%s doesn't have room for any more land units!\n",prland(lp)); + else + pr("%s cannot carry land units!\n",prland(lp)); + } + return 0; + } + sprintf(prompt, "Land unit(s) to %s %s? ", + load_unload==LOAD?"load onto":"unload from", + prland(lp)); + if (!snxtitem(&ni, EF_LAND, p=getstarg(player->argp[3], prompt, buf))) + return RET_SYN; + + if (!still_ok_land(sectp, lp)) + return RET_SYN; + + if (p && *p) + noisy &= isdigit(*p); + + while(nxtitem(&ni, (s_char *)&land)) { + + if (land.lnd_own != player->cnum) + continue; + + if (load_unload == LOAD) { + if (land.lnd_ship > -1) { + if (noisy) + pr("%s is already on ship #%d!\n", + prland(&land), land.lnd_ship); + continue; + } + if (land.lnd_land > -1) { + if (noisy) + pr("%s is already on land #%d!\n", + prland(&land), land.lnd_land); + continue; + } + lnd_count_units(&land); + if (land.lnd_nland > 0) { + if (noisy) + pr("%s cannot be loaded since it is carrying units\n", + prland(&land)); + continue; + } + if (land.lnd_uid == lp->lnd_uid) { + if (noisy) + pr("%s can't be loaded onto itself!\n", prland(&land)); + continue; + } + if (lchr[(int)land.lnd_type].l_flags & L_HEAVY) { + if (noisy) + pr("%s is too heavy to load.\n", prland(&land)); + continue; + } + } + + /* Unit sanity done */ + /* Find the right ship */ + if (load_unload == UNLOAD) { + if (land.lnd_land != lp->lnd_uid) + continue; + if (land.lnd_ship > -1) + continue; + } else if (lp->lnd_x != land.lnd_x + || lp->lnd_y != land.lnd_y) + continue; + + /* Fit unit on ship */ + if (load_unload == LOAD) { + lnd_count_units(lp); + if (lp->lnd_nland >= lp->lnd_maxland) { + if (noisy) { + if (lp->lnd_nland) + pr("%s doesn't have room for any more land units!\n",prland(lp)); + else + pr("%s cannot carry land units!\n",prland(lp)); + } + break; + } + sprintf(buf, "loaded on your %s at %s", + prland(lp),xyas(lp->lnd_x,lp->lnd_y, + lp->lnd_own)); + gift(lp->lnd_own,player->cnum,(s_char *)&land, + EF_LAND, buf); + makelost(EF_LAND, land.lnd_own, land.lnd_uid, land.lnd_x, land.lnd_y); + land.lnd_own = lp->lnd_own; + makenotlost(EF_LAND, land.lnd_own, land.lnd_uid, land.lnd_x, land.lnd_y); + land.lnd_land = lp->lnd_uid; + land.lnd_harden = 0; + land.lnd_mission = 0; + resupply_all(&land); + lp->lnd_nland++; + putland(land.lnd_uid,&land); + if (!has_supply(&land)) + pr("WARNING: %s is out of supply!\n", + prland(&land)); + putland(lp->lnd_uid,lp); + snxtitem_xy(&pni,EF_PLANE,land.lnd_x,land.lnd_y); + while (nxtitem(&pni, (s_char *)&plane)){ + if (plane.pln_flags & PLN_LAUNCHED) + continue; + if (plane.pln_land != land.lnd_uid) + continue; + sprintf(buf, "loaded on %s", + prland(lp)); + gift(lp->lnd_own,player->cnum,(s_char *)&plane, + EF_PLANE, buf); + makelost(EF_PLANE, plane.pln_own, plane.pln_uid, plane.pln_x, plane.pln_y); + plane.pln_own = lp->lnd_own; + makenotlost(EF_PLANE, plane.pln_own, plane.pln_uid, plane.pln_x, plane.pln_y); + plane.pln_mission = 0; + putplane(plane.pln_uid,&plane); + } + } else { + sprintf(buf, "unloaded in your %s at %s", + dchr[sectp->sct_type].d_name, + xyas(sectp->sct_x,sectp->sct_y, + sectp->sct_own)); + gift(sectp->sct_own,player->cnum,(s_char *)&land, + EF_LAND, buf); + makelost(EF_LAND, land.lnd_own, land.lnd_uid, land.lnd_x, land.lnd_y); + land.lnd_own = sectp->sct_own; + makenotlost(EF_LAND, land.lnd_own, land.lnd_uid, land.lnd_x, land.lnd_y); + land.lnd_land = (-1); + lp->lnd_nland--; + putland(land.lnd_uid,&land); + putland(lp->lnd_uid,lp); + snxtitem_xy(&pni,EF_PLANE,land.lnd_x,land.lnd_y); + while (nxtitem(&pni, (s_char *)&plane)){ + if (plane.pln_flags & PLN_LAUNCHED) + continue; + if (plane.pln_land != land.lnd_uid) + continue; + sprintf(buf, "unloaded at %s", + xyas(plane.pln_x,plane.pln_y, + sectp->sct_own)); + gift(sectp->sct_own,player->cnum,(s_char *)&plane, + EF_PLANE, buf); + makelost(EF_PLANE, plane.pln_own, plane.pln_uid, plane.pln_x, plane.pln_y); + plane.pln_own = sectp->sct_own; + makenotlost(EF_PLANE, plane.pln_own, plane.pln_uid, plane.pln_x, plane.pln_y); + plane.pln_mission = 0; + putplane(plane.pln_uid,&plane); + } + } + pr("%s %s %s at %s.\n", + prland(&land), + (load_unload==UNLOAD)? + "unloaded from":"loaded onto", + prland(lp), + xyas(lp->lnd_x, lp->lnd_y, player->cnum)); + loaded = 1; + } + *nunitsp += loaded; + return 0; +} + diff --git a/src/lib/commands/look.c b/src/lib/commands/look.c new file mode 100644 index 00000000..57447ee2 --- /dev/null +++ b/src/lib/commands/look.c @@ -0,0 +1,321 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * look.c: Lookout from a ship or land unit + * + * Known contributors to this file: + * + */ + +#include "misc.h" +#include "player.h" +#include "var.h" +#include "xy.h" +#include "sect.h" +#include "ship.h" +#include "land.h" +#include "plane.h" +#include "nsc.h" +#include "nat.h" +#include "path.h" +#include "file.h" +#include +#include "commands.h" +#include "optlist.h" + +static void look_ship(register struct shpstr *lookship); + +int +look(void) +{ + register int i; + struct nstr_item ni; + struct shpstr myship; + struct sctstr sect; + int x, y; + int civ; + int mil; + u_char *bitmap; + int changed = 0; + + if (!snxtitem(&ni, EF_SHIP, player->argp[1])) + return RET_SYN; + if ((bitmap = (u_char *)malloc((WORLD_X * WORLD_Y) / 8)) == 0) { + logerror("malloc failed in look\n"); + pr("Memory error. Tell the deity.\n"); + return RET_FAIL; + } + bzero((s_char *)bitmap, (WORLD_X * WORLD_Y) / 8); + while (nxtitem(&ni, (s_char *)&myship)) { + if (!player->owner) + continue; + look_ship(&myship); + for (i = 0; i <= 6; i++) { + x = diroff[i][0] + myship.shp_x; + y = diroff[i][1] + myship.shp_y; + if (emp_getbit(x, y, bitmap)) + continue; + emp_setbit(x, y, bitmap); + getsect(x, y, §); + if (sect.sct_type == SCT_WATER) + continue; + if (player->owner) + pr("Your "); + else + pr("%s (#%d) ", cname(sect.sct_own), + sect.sct_own); + pr(dchr[sect.sct_type].d_name); + changed += map_set(player->cnum, x, y, + dchr[sect.sct_type].d_mnem, 0); + pr(" %d%% efficient ", player->owner ? sect.sct_effic : + roundintby((int)sect.sct_effic, 10)); + civ = getvar(V_CIVIL, (s_char *)§, EF_SECTOR); + mil = getvar(V_MILIT, (s_char *)§, EF_SECTOR); + if (civ) + pr("with %s%d civ ", player->owner ? "" : "approx ", + player->owner ? civ : roundintby(civ, 10)); + if (mil) + pr("with %s%d mil ", player->owner ? "" : "approx ", + player->owner ? mil : roundintby(mil, 10)); + pr("@ %s\n", xyas(x, y, player->cnum)); + if (opt_HIDDEN) { + setcont(player->cnum, sect.sct_own, FOUND_LOOK); + } + } + } + if (changed) + writemap(player->cnum); + free((s_char *)bitmap); + return RET_OK; +} + +static void +look_ship(register struct shpstr *lookship) +{ + register struct shpstr *sp; + register struct mchrstr *smcp; + register struct mchrstr *tmcp; + extern int ship_max_interdiction_range; + struct sctstr sect; + int range; + int vrange; + int i; + int dist; + + range = (int) techfact(lookship->shp_tech, + (double) mchr[(int)lookship->shp_type].m_vrnge); + range = range * (lookship->shp_effic / 100.0); + smcp = &mchr[(int)lookship->shp_type]; + if (smcp->m_flags & M_SUB) + range = min(range, 1); + for (i=0; NULL != (sp = getshipp(i)); i++) { + if (sp->shp_own == player->cnum || sp->shp_own == 0) + continue; + dist = mapdist(sp->shp_x, sp->shp_y, + lookship->shp_x, lookship->shp_y); + if (dist > ship_max_interdiction_range) + continue; + tmcp = &mchr[(int)sp->shp_type]; + if (smcp->m_flags & M_SUB) + vrange = (int)(sp->shp_visib * range/30.0); + else + vrange = (int)(sp->shp_visib * range/20.0); + getsect(sp->shp_x, sp->shp_y, §); + if (sect.sct_type != SCT_WATER) + vrange = max(1, vrange); + if (dist > vrange) + continue; + if (smcp->m_flags & M_SUB) { + if (tmcp->m_flags & M_SONAR && dist < 2) { + if(sp->shp_own != 0) + wu(0, sp->shp_own, + "%s detected surfacing noises in %s.\n", + prship(sp), + xyas(lookship->shp_x, lookship->shp_y, + sp->shp_own)); + } + if (dist == 0 && (tmcp->m_flags & M_SUB) == 0) + if(sp->shp_own != 0) + wu(0, sp->shp_own, + "Periscope spotted in %s by %s\n", + xyas(lookship->shp_x, lookship->shp_y, + sp->shp_own), + prship(sp)); + } + /* subs at sea only seen by sonar */ + if (tmcp->m_flags & M_SUB && sect.sct_type == SCT_WATER) + continue; + pr("%s (#%d) %s @ %s\n", + cname(sp->shp_own), sp->shp_own, prship(sp), + xyas(sp->shp_x, sp->shp_y, player->cnum)); + } +} + +static void look_land(register struct lndstr *lookland); + +int +llook(void) +{ + register int i; + struct nstr_item ni; + struct lndstr myland; + struct sctstr sect; + int x, y; + int civ; + int mil; + u_char *bitmap; + int changed = 0; + + if (!snxtitem(&ni, EF_LAND, player->argp[1])) + return RET_SYN; + if ((bitmap = (u_char *)malloc((WORLD_X * WORLD_Y) / 8)) == 0) { + logerror("malloc failed in llook\n"); + pr("Memory error. Tell the deity.\n"); + return RET_FAIL; + } + bzero((s_char *)bitmap, (WORLD_X * WORLD_Y) / 8); + while (nxtitem(&ni, (s_char *)&myland)) { + if (!player->owner) + continue; + if (myland.lnd_ship >= 0) + continue; + if (myland.lnd_land >= 0) + continue; + /* Spies don't need military to do a "llook". Other + units do */ + if ((lnd_getmil(&myland) <= 0) && + !(lchr[(int)myland.lnd_type].l_flags & L_SPY)) + continue; + look_land(&myland); + for (i = 0; i <= 6; i++) { + x = diroff[i][0] + myland.lnd_x; + y = diroff[i][1] + myland.lnd_y; + if (emp_getbit(x, y, bitmap)) + continue; + emp_setbit(x, y, bitmap); + getsect(x, y, §); + if (sect.sct_type == SCT_WATER) + continue; + if (player->owner) + pr("Your "); + else + pr("%s (#%d) ", cname(sect.sct_own), + sect.sct_own); + pr(dchr[sect.sct_type].d_name); + changed += map_set(player->cnum, x, y, + dchr[sect.sct_type].d_mnem, 0); + pr(" %d%% efficient ", player->owner ? sect.sct_effic : + roundintby((int)sect.sct_effic, 10)); + civ = getvar(V_CIVIL, (s_char *)§, EF_SECTOR); + mil = getvar(V_MILIT, (s_char *)§, EF_SECTOR); + if (civ) + pr("with %s%d civ ", player->owner ? "" : + "approx ", + player->owner ? civ : roundintby(civ, 10)); + if (mil) + pr("with %s%d mil ", player->owner ? "" : + "approx ", + player->owner ? mil : roundintby(mil, 10)); + pr("@ %s\n", xyas(x, y, player->cnum)); + if (opt_HIDDEN) { + setcont(player->cnum, sect.sct_own, FOUND_LOOK); + } + } + } + if (changed) + writemap(player->cnum); + free((s_char *)bitmap); + return RET_OK; +} + +static void +look_land(register struct lndstr *lookland) +{ + register struct plnstr *pp; + register struct lndstr *lp; + double drange; + int range; + int vrange; + int i; + int dist; + double techfact(int, double); + double odds; + + drange = techfact(lookland->lnd_tech, + (double) lookland->lnd_spy); + drange = (drange * ((double)lookland->lnd_effic / 100.0)); + range = ldround(drange,1); + + if (range == 0) + return; + + for (i=0; NULL != (lp = getlandp(i)); i++) { + if (lp->lnd_own == player->cnum || lp->lnd_own == 0) + continue; + if (lp->lnd_ship >= 0) + continue; + /* Don't always see spies */ + if (lchr[(int)lp->lnd_type].l_flags & L_SPY) { + /* If it's on a ship or unit, assume it's hidden + enough not to be seen */ + if (lp->lnd_ship >= 0 || lp->lnd_land >= 0) + continue; + odds = (double)(100 - lp->lnd_effic) + 0.10; + if (!(chance(odds))) + continue; + } + vrange = ldround((double)((lp->lnd_vis + * range)/20.0),1); + dist = mapdist(lp->lnd_x, lp->lnd_y, + lookland->lnd_x, lookland->lnd_y); + if (dist > vrange) + continue; + + pr("%s (#%d) %s (approx %d mil) @ %s\n", + cname(lp->lnd_own), lp->lnd_own, + prland(lp), ldround((double)total_mil(lp), 20), + xyas(lp->lnd_x, lp->lnd_y, player->cnum)); + } + for (i=0; NULL != (pp = getplanep(i)); i++) { + if (pp->pln_own == player->cnum || pp->pln_own == 0) + continue; + if (pp->pln_ship >= 0) + continue; + if (pp->pln_flags & PLN_LAUNCHED) + continue; + vrange = ldround((double)((10* range)/20.0),1); + dist = mapdist(pp->pln_x, pp->pln_y, + lookland->lnd_x, lookland->lnd_y); + if (dist > vrange) + continue; + + pr("%s (#%d) %s @ %s\n", + cname(pp->pln_own), pp->pln_own, + prplane(pp), + xyas(pp->pln_x, pp->pln_y, player->cnum)); + } +} diff --git a/src/lib/commands/lost.c b/src/lib/commands/lost.c new file mode 100644 index 00000000..f4cb4356 --- /dev/null +++ b/src/lib/commands/lost.c @@ -0,0 +1,85 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * lost.c: List lost items + * + * Known contributors to this file: + * Steve McClure, 1997 + */ + +#include "player.h" +#include "nat.h" +#include "nsc.h" +#include "file.h" +#include "lost.h" +#include "optlist.h" +#include "commands.h" + +int +lost(void) +{ + int nlost; + struct nstr_item ni; + struct loststr lost; + time_t now; + + if (!player->argp[1]) { + if (!snxtitem(&ni, EF_LOST, "*")) + return RET_SYN; + } else { + if (!snxtitem(&ni, EF_LOST, player->argp[1])) + return RET_SYN; + } + + prdate(); + nlost = 0; + time(&now); + pr("DUMP LOST ITEMS %d\n", now); + if (player->god) + pr("owner "); + pr("type id x y timestamp\n"); + while (nxtitem(&ni, (s_char *)&lost)) { + if (lost.lost_owner == 0) + continue; + if (lost.lost_owner != player->cnum && !player->god) + continue; + if (player->god) + pr("%d ", lost.lost_owner); + pr("%d %d ", lost.lost_type, lost.lost_id); + prxy("%d %d ", lost.lost_x, lost.lost_y, player->cnum); + pr("%d\n", lost.lost_timestamp); + nlost++; + } + if (nlost == 0) { + if (player->argp[1]) + pr("%s: Nothing lost.\n", player->argp[1]); + else + pr("%s: Nothing lost.\n", ""); + } else + pr("%d lost item%s.\n", nlost, splur(nlost)); + return RET_OK; +} diff --git a/src/lib/commands/lstat.c b/src/lib/commands/lstat.c new file mode 100644 index 00000000..f6a7d5f6 --- /dev/null +++ b/src/lib/commands/lstat.c @@ -0,0 +1,109 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * lstat.c: Show the stats of your land units + * + * Known contributors to this file: + * Steve McClure, 1996 + */ + +#include "misc.h" +#include "player.h" +#include "var.h" +#include "xy.h" +#include "sect.h" +#include "land.h" +#include "nat.h" +#include "nsc.h" +#include "deity.h" +#include "file.h" +#include "optlist.h" +#include "commands.h" + +int +lstats(void) +{ + int nunits; + struct nstr_item ni; + struct lndstr land; + s_char *mission_short_name(); + + if (!snxtitem(&ni, EF_LAND, player->argp[1])) + return RET_SYN; + + nunits = 0; + while (nxtitem(&ni, (s_char *)&land)) { + if (!player->owner || land.lnd_own == 0) + continue; + if (land.lnd_type < 0 || land.lnd_type > lnd_maxno) { + pr("bad unit type %d (#%d)\n", + land.lnd_type, ni.cur); + continue; + } + count_land_planes(&land); + + if (nunits++ == 0) { +pr(" %16.16s s v s r r a f a a\n", ""); +pr(" %16.16s p i p a n c i m a\n", ""); +pr("lnd# %16.16s x,y eff tech att def vul d s y d g c r m f\n", "unit-type"); + } + pr("%4d %-16.16s ", + land.lnd_uid, + lchr[(int)land.lnd_type].l_name); + prxy("%4d,%-4d", + land.lnd_x, + land.lnd_y, + player->cnum); + pr(" %3d%% %3d %1.1f %1.1f %3d ", + land.lnd_effic, + land.lnd_tech, + (float)land.lnd_att, + (float)land.lnd_def, + land.lnd_vul); + pr("%2d %2d %2d %2d ", + land.lnd_spd, + land.lnd_vis, + land.lnd_spy, + land.lnd_rad); + pr("%2d %2d %2d %2d %2d ", + land.lnd_frg, + land.lnd_acc, + land.lnd_dam, + land.lnd_ammo, + land.lnd_aaf); + pr("\n"); + } + if (nunits == 0) { + if (player->argp[1]) + pr("%s: No unit(s)\n", player->argp[1]); + else + pr("%s: No unit(s)\n", ""); + return RET_FAIL; + }else + pr("%d unit%s\n", nunits, splur(nunits)); + return RET_OK; +} diff --git a/src/lib/commands/lten.c b/src/lib/commands/lten.c new file mode 100644 index 00000000..6bcee531 --- /dev/null +++ b/src/lib/commands/lten.c @@ -0,0 +1,175 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * lten.c: Transfer commodity from a ship to a land unit the ship is + * carrying + * + * Known contributors to this file: + * Dave Pare, 1986 + * Thomas Ruschak + * Ken Stevens, 1995 + * Steve McClure, 1998 + */ + +#include "misc.h" +#include "player.h" +#include "var.h" +#include "xy.h" +#include "file.h" +#include "ship.h" +#include "item.h" +#include "nsc.h" +#include "nat.h" +#include "plane.h" +#include "nuke.h" +#include "land.h" +#include "genitem.h" +#include "commands.h" + +static void expose_land(struct shpstr *s1, struct lndstr *l1); + +int +ltend(void) +{ + struct nstr_item targets; + struct nstr_item tenders; + struct shpstr tender; + struct lndstr target; + struct ichrstr *ip; + struct mchrstr *vbase; + struct lchrstr *lbase; + int amt; + int ontender; + int ontarget; + int maxtender; + int maxtarget; + int transfer; + int total; + s_char *p; + s_char buf[1024]; + + if (!(ip = whatitem(player->argp[1], "Transfer what commodity? "))) + return RET_SYN; + + if (!snxtitem(&tenders, EF_SHIP, getstarg(player->argp[2], "Tender(s)? ", buf))) + return RET_SYN; + while (nxtitem(&tenders, (s_char *)&tender)) { + if (!player->owner) + continue; + if ((p = getstarg(player->argp[3], "Amount to transfer? ", buf)) == 0) + break; + if (!check_ship_ok(&tender)) + return RET_FAIL; + if ((amt = atoi(p)) == 0) + break; + ontender = getvar(ip->i_vtype, (s_char *)&tender, EF_SHIP); + if (ontender == 0 && amt > 0) { + pr("No %s on %s\n", ip->i_name, prship(&tender)); + return RET_FAIL; + } + vbase = &mchr[(int)tender.shp_type]; + maxtender = vl_find(ip->i_vtype, vbase->m_vtype, + vbase->m_vamt, (int)vbase->m_nv); + if (maxtender == 0) { + pr("A %s cannot hold any %s\n", + mchr[(int)tender.shp_type].m_name, + ip->i_name); + break; + } + if (!snxtitem(&targets, EF_LAND, + getstarg(player->argp[4], "Units to be tended? ", buf))) + break; + if (!check_ship_ok(&tender)) + return RET_FAIL; + total = 0; + while (tend_nxtitem(&targets, (s_char *)&target)) { + if (!player->owner) + continue; + + if (target.lnd_ship != tender.shp_uid) + continue; + ontarget = getvar(ip->i_vtype,(s_char *)&target, EF_LAND); + if (ontarget == 0 && amt < 0) { + pr("No %s on %s\n", + ip->i_name, prship((struct shpstr *)&target)); + continue; + } + lbase = &lchr[(int)target.lnd_type]; + maxtarget = vl_find(ip->i_vtype, lbase->l_vtype, + lbase->l_vamt, (int)lbase->l_nv); + if (amt < 0) { + if (!player->owner) + amt=0; + + /* take from target and give to tender */ + transfer = min(ontarget, -amt); + transfer = min(maxtender - ontender, transfer); + if (transfer == 0) + continue; + putvar(ip->i_vtype, ontarget - transfer, + (s_char *)&target, EF_LAND); + ontender += transfer; + total += transfer; + } else { + /* give to target from tender */ + transfer = min(ontender, amt); + transfer = min(transfer, maxtarget - ontarget); + if (transfer == 0) + continue; + putvar(ip->i_vtype, ontarget + transfer, + (s_char *)&target, EF_LAND); + ontender -= transfer; + total += transfer; + } + expose_land(&tender, &target); + putland(target.lnd_uid, &target); + if (amt > 0 && ontender == 0) { + pr("%s out of %s\n", prship(&tender), + ip->i_name); + break; + } + } + pr("%d total %s transferred %s %s\n", + total, ip->i_name, (amt > 0) ? "off of" : "to", + prship(&tender)); + putvar(ip->i_vtype, ontender, (s_char *)&tender, EF_SHIP); + tender.shp_mission = 0; + putship(tender.shp_uid, &tender); + } + return RET_OK; +} + +static void +expose_land(struct shpstr *s1, struct lndstr *l1) +{ + if (getvar(V_PSTAGE, (s_char *)s1, EF_SHIP) == PLG_INFECT && + getvar(V_PSTAGE, (s_char *)l1, EF_LAND) == PLG_HEALTHY) + putvar(V_PSTAGE, PLG_EXPOSED, (s_char *)l1, EF_LAND); + if (getvar(V_PSTAGE, (s_char *)l1, EF_LAND) == PLG_INFECT && + getvar(V_PSTAGE, (s_char *)s1, EF_SHIP) == PLG_HEALTHY) + putvar(V_PSTAGE, PLG_EXPOSED, (s_char *)s1, EF_SHIP); +} diff --git a/src/lib/commands/map.c b/src/lib/commands/map.c new file mode 100644 index 00000000..02c38b2b --- /dev/null +++ b/src/lib/commands/map.c @@ -0,0 +1,145 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * map.c: Display a map of sectors. + * + * Known contributors to this file: + * Dave Pare, 1986 + * Ken Stevens, 1995 + */ + +#include "misc.h" +#include "nat.h" +#include "file.h" +#include "player.h" +#include "map.h" +#include "ship.h" +#include "land.h" +#include "plane.h" +#include "xy.h" +#include "nsc.h" +#include "commands.h" +#include "optlist.h" + +int +map(void) +{ + register s_char *b; + int unit_type = 0; + int bmap = 0; + struct natstr *np; + s_char *str; + struct nstr_sect ns; + s_char origin = '\0'; + int as_country; + int map_flags = 0; + int i; + int where = 2; + s_char what[64]; + s_char buf[1024]; + + if (**player->argp != 'm') { + if (**player->argp == 'b') + bmap = EF_BMAP; + else if (**player->argp == 'n') + bmap = EF_NMAP; + else { + if (**player->argp == 'l') + unit_type = EF_LAND; + else if (**player->argp == 'p') + unit_type = EF_PLANE; + else if (**player->argp == 's') + unit_type = EF_SHIP; + else { + logerror("map: bad player->argp[0]"); + return RET_SYN; + } + if (player->argp[0][1] == 'b') + bmap = EF_BMAP; + } + } + + if (player->argp[1] == (s_char *) 0) { + if ((str = getstring("(sects)? ", buf)) == 0) + return RET_SYN; + } else { + str = player->argp[1]; + } + + np = getnatp(player->cnum); + if (*str == '*') { + sprintf(what, "%d:%d,%d:%d", + -WORLD_X/2, WORLD_X/2-1, + -WORLD_Y/2, WORLD_Y/2-1); + if (!snxtsct(&ns, what)) + return RET_FAIL; + } else if (!snxtsct(&ns, str)) { + i=atoi(str); + if (unit_map(unit_type, i, &ns, &origin)) + return RET_FAIL; + } + b = player->argp[2]; + while (b != (s_char *)0 && (*b)){ + where = 3; + switch(*b){ + case 's': + case 'S': map_flags |= MAP_SHIP; break; + case 'l': + case 'L': map_flags |= MAP_LAND; break; + case 'p': + case 'P': map_flags |= MAP_PLANE; break; + case '*': map_flags |= MAP_ALL; break; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': where = 2; break; + case 't': bmap = EF_MAP; *(b+1)=0;break; + case 'r': bmap = EF_MAP + EF_BMAP;*(b+1)=0;break; + default: pr("Bad flag %c!\n",*b); + break; + } + b++; + } + + as_country = player->cnum; + if (player->god){ + if (player->argp[where] != (s_char *) 0) { + as_country=atoi(player->argp[where]); + if ((as_country < 0) || (as_country > MAXNOC)){ + as_country = player->cnum; + } + } + } + + return draw_map(bmap, origin, map_flags, &ns, as_country); +} diff --git a/src/lib/commands/marc.c b/src/lib/commands/marc.c new file mode 100644 index 00000000..5a235dd3 --- /dev/null +++ b/src/lib/commands/marc.c @@ -0,0 +1,201 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * marc.c: March units around + * + * Known contributors to this file: + * Thomas Ruschak + * Ken Stevens, 1995 (rewrite) + */ + +#include +#include "misc.h" +#include "player.h" +#include "var.h" +#include "land.h" +#include "sect.h" +#include "news.h" +#include "xy.h" +#include "nsc.h" +#include "nat.h" +#include "path.h" +#include "deity.h" +#include "file.h" +#include "map.h" +#include "commands.h" + +static int set_leader(struct emp_qelem *list, struct lndstr **leaderp); + +int +march(void) +{ + struct nstr_item ni_land; + struct emp_qelem land_list; + double minmob, maxmob; + int together; + s_char *cp = 0; + struct lndstr *lnd = 0; /* leader */ + struct nstr_sect ns; + s_char origin; + int dir; + int stopping = 0; + int skip = 0; + s_char buf[1024]; + s_char prompt[128]; + + if (!snxtitem(&ni_land, EF_LAND, player->argp[1])) + return RET_SYN; + lnd_sel(&ni_land, &land_list); + lnd_mar(&land_list, &minmob, &maxmob, &together, player->cnum); + if (QEMPTY(&land_list)) { + pr("No lands\n"); + return RET_FAIL; + } + set_leader(&land_list, &lnd); + if (player->argp[2]) { + strcpy(buf, player->argp[2]); + if (!(cp = lnd_path(together, lnd, buf))) + cp = player->argp[2]; + } + + while (!QEMPTY(&land_list)) { + s_char *bp,dp[80]; + + if (cp == 0 || *cp == '\0' || stopping) { + stopping = 0; + lnd_mar(&land_list, &minmob, &maxmob, &together, player->cnum); + if (QEMPTY(&land_list)) { + pr("No lands left\n"); + return RET_OK; + } + if (set_leader(&land_list, &lnd)) { + stopping = 1; + continue; + } + if (!skip) + nav_map(lnd->lnd_x, lnd->lnd_y, 1); + else + skip=0; + sprintf(prompt, "<%.1f:%.1f: %s> ", maxmob, + minmob, xyas(lnd->lnd_x, lnd->lnd_y, player->cnum)); + cp = getstring(prompt, buf); +/* Just in case any of our lands were shelled while we were at the + * prompt, we call lnd_mar() again. + */ + lnd_mar(&land_list, &minmob, &maxmob, &together, player->cnum); + if (QEMPTY(&land_list)) { + pr("No lands left\n"); + return RET_OK; + } + if (set_leader(&land_list, &lnd)) { + stopping = 1; + continue; + } + } + if (cp == 0 || *cp == '\0') + cp = &dirch[DIR_STOP]; + if (*cp == 'M' || + *cp == 'B' || + *cp == 'f' || + *cp == 'i' || + *cp == 'm') { + ++cp; + if (cp[-1] == 'M') { + unit_map(EF_LAND, lnd->lnd_uid, &ns, &origin); + draw_map(0, origin, 0, &ns, player->cnum); + skip = 1; + } else if (cp[-1] == 'B') { + unit_map(EF_LAND, lnd->lnd_uid, &ns, &origin); + draw_map(EF_BMAP, origin, 0, &ns, player->cnum); + skip = 1; + } else if (cp[-1] == 'f') { + struct emp_qelem *qp; + qp = land_list.q_back; + emp_remque(land_list.q_back); + emp_insque(qp, &land_list); + set_leader(&land_list, &lnd); + } else if (cp[-1] == 'i') { + lnd_list(&land_list); + } else { + lnd_sweep(&land_list, 1, 1, player->cnum); + stopping |= lnd_check_mines(&land_list); + } + continue; + } else if (*cp == 'r' || + *cp == 'l') { + bp=++cp; + while((*bp != ' ') && (*bp)) bp++; + while((*bp == ' ') && (*bp)) bp++; + if ((bp != (s_char *)0) && (*bp)) + player->argp[1] = bp; + else { + sprintf(dp,"%d",lnd->lnd_uid); + player->argp[1] = dp; + } + if (cp[-1] == 'r') { + player->argp[0] = "lradar"; + rada(); + skip = 1; + } else + llook(); + *cp = 0; + player->btused++; + continue; + } else { + dir = chkdir(*cp++, DIR_STOP, DIR_LAST); + if (dir == -1) { + if (NULL != (cp = lnd_path(together, lnd, buf))) + continue; + direrr("`%c' to stop", 0 , 0); + pr(", `i' to list units, `f' to change leader,\n"); + pr("`r' to radar, `l' to look, `M' to map, `B' to bmap,\n"); + pr("and `m' to minesweep\n"); + stopping = 1; + continue; + } + } + stopping |= lnd_mar_one_sector(&land_list, dir, player->cnum, together); + } + return RET_OK; +} + +static int +set_leader(struct emp_qelem *list, struct lndstr **leaderp) +{ + struct llist *llp = (struct llist *)(list->q_back); + + if (!*leaderp) + pr("Leader is "); + else if ((*leaderp)->lnd_uid != llp->land.lnd_uid) + pr("Changing leader to "); + else + return 0; + *leaderp = &llp->land; + pr("%s\n", prland(&llp->land)); + return 1; +} + diff --git a/src/lib/commands/mark.c b/src/lib/commands/mark.c new file mode 100644 index 00000000..7be9e5f8 --- /dev/null +++ b/src/lib/commands/mark.c @@ -0,0 +1,165 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * mark.c: Display report for commodities + * + * Known contributors to this file: + * Dave Pare, 1986 + * Pat Loney, 1992 + * Steve McClure, 1996 + */ + +#include "misc.h" +#include "nat.h" +#include "var.h" +#include "item.h" +#include "deity.h" +#include "commodity.h" +#include "player.h" +#include "file.h" +#include "commands.h" +#include "optlist.h" + +int +mark(void) +{ + if (!opt_MARKET) { + pr("The market is disabled.\n"); + return RET_FAIL; + } + if (player->argp[1] && *(player->argp[1])) + return display_mark(player->argp[1]); + else + return display_mark(" "); +} + +void +pr_mark(struct comstr *comm) +{ + time_t now; + double tleft; + extern int MARK_DELAY; + + (void) time(&now); + tleft = MARK_DELAY / 3600.0 - (now - comm->com_markettime) / 3600.0; + if (tleft < 0.0) + tleft = 0.0; + pr(" %3d $%12.2f %2d %5.2f hrs (%3d) %c %6d ", + comm->com_uid, + comm->com_maxprice, + comm->com_maxbidder, + tleft, + comm->com_owner, + comm->com_type, + comm->com_amount); + if (comm->com_owner == player->cnum || player->god) + pr("%s", xyas(comm->sell_x, comm->sell_y, player->cnum)); + pr("\n"); +} + +int +display_mark(s_char *arg) +{ + struct comstr comm; + struct comstr comm2; + int sellers = 0; + int cnt = 0; + char c; + s_char *p; + struct ichrstr *ip; + s_char buf[1024]; + int cheapest_items[I_MAX + 2]; + int i; + int all = 0; + +/* First, we execute all trades, so that we can only buy what is available. */ + check_market(); + check_trade(); + + p = getstarg(arg, "What commodity (or 'all')? ", buf); + c = (char)0; + if (p && *p) + c = *p; + for (ip = &ichr[0]; ip && ip->i_mnem; ip++) + if (ip->i_mnem == c) + break; + c = ip->i_mnem; + + pr("\n Empire Market Report\n "); + prdate(); + pr(" lot high bid/unit by time left owner item amount sector\n"); + pr(" --- ------------- -- --------- ----- ---- ------ ------\n"); + + if (arg) { + if (strcmp(arg, "all")) + all = 1; + } + if (all && !c) { + /* Ok, just printing the lowest of all of them */ + for (i = 0; i < I_MAX + 2; i++) + cheapest_items[i] = -1; + for (sellers = 0; getcomm(sellers, &comm); sellers++) { + if (comm.com_owner == 0) + continue; + for (i = 0, ip = &ichr[0]; ip && ip->i_mnem; ip++, i++) + if (ip->i_mnem == comm.com_type) + break; + if (!ip->i_mnem) + continue; + if (cheapest_items[i] != -1) { + getcomm(cheapest_items[i], &comm2); + if (comm.com_maxprice < comm2.com_maxprice) { + cheapest_items[i] = sellers; + } + } else { + cheapest_items[i] = sellers; + } + } + for (i = 0; i < I_MAX + 2; i++) { + if (cheapest_items[i] == -1) + continue; + getcomm(cheapest_items[i], &comm); + cnt = 1; + pr_mark(&comm); + } + } else { + /* Ok, print them all, or all of this type */ + for (sellers = 0; getcomm(sellers, &comm); sellers++) { + if (comm.com_owner == 0) + continue; + if (c && comm.com_type != c) + continue; + cnt = 1; + pr_mark(&comm); + } + } + if (cnt <= 0) + pr("\nHmmmm, the market seems to be empty today.\n"); + else + pr("\nLooks just like Christmas at K-mart, doesn't it!\n"); + return RET_OK; +} diff --git a/src/lib/commands/mfir.c b/src/lib/commands/mfir.c new file mode 100644 index 00000000..c18eb545 --- /dev/null +++ b/src/lib/commands/mfir.c @@ -0,0 +1,1072 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * multifire.c: Fire at other sectors/ships + * + * Known contributors to this file: + * Steve McClure, 2000 + * + */ + +#include "misc.h" +#include "player.h" +#include "var.h" +#include "xy.h" +#include "treaty.h" +#include "nat.h" +#include "ship.h" +#include "land.h" +#include "sect.h" +#include "retreat.h" +#include "news.h" +#include "nsc.h" +#include "file.h" +#include "queue.h" +#include +#include "options.h" +#include "optlist.h" +#include "damage.h" +#include "commands.h" + +enum targ_type { + targ_land, targ_ship, targ_sub, targ_unit, targ_bogus +}; + +struct flist{ + struct emp_qelem queue; /* list of fired things */ + int type; /* ship? otherwise sector */ + int uid; /* ship uid */ + coord x,y; /* sector coords */ + int defdam; /* damage defenders did */ + int victim; /* who I was shooting at */ +}; + +union item_u { + struct shpstr ship; + struct sctstr sect; + struct lndstr land; +}; + +static int defend(struct emp_qelem *al, + struct emp_qelem *dl, + enum targ_type target, + enum targ_type attacker, + struct sctstr *vsect, + struct sctstr *fsect, + struct shpstr *vship, + struct shpstr *fship, + int fx, + int fy, + int *nd); + +int +multifire(void) +{ + s_char vbuf[20]; + s_char *ptr; + double range2, range; + int trange; + coord fx; + coord fy; + coord x; + coord y; + int mil; + int gun; + int shell; + int shots; + double guneff; + int dam; + int totaldefdam=0; + int fshipno; + int vshipno; + double prb; + natid vict; + struct shpstr fship; + struct lndstr fland; + struct sctstr fsect; + struct shpstr vship; + struct sctstr vsect; + enum targ_type target, attacker, orig_attacker; + int rel; + struct natstr *natp; + struct nstr_item nbst; + int type; + s_char *p; + int nfiring=0; + int ndefending=0; + union item_u item; + struct emp_qelem fired, defended; + double odds; + s_char buf[1024]; +#if defined(_WIN32) + time_t now; +#endif + + emp_initque(&fired); + emp_initque(&defended); + type=(-1); + while ((type != EF_SECTOR) && (type != EF_SHIP) && (type != EF_LAND)){ + if (!(p = getstarg(player->argp[1], + "Firing from ship(s), sect(s), or land unit(s)? ", buf))) + return RET_SYN; + player->argp[1]=0; + type = ef_byname(p); + if (type == EF_SECTOR){ + if (opt_NO_FORT_FIRE) { + pr("Fort firing is disabled.\n"); + return RET_FAIL; + } + orig_attacker = attacker=targ_land; + shots = 1; + } + else if (type == EF_SHIP) { + orig_attacker = attacker=targ_ship; + } + else if (type == EF_LAND) { + orig_attacker = attacker=targ_unit; + } + else + pr("Please type 'sh', 'l', or 'se'!\n"); + } + if ((ptr = getstarg(player->argp[2], "Firing from? ", buf)) == 0 || *ptr == '\0') + return RET_SYN; + + if (!snxtitem(&nbst, type, ptr)) + return RET_SYN; + + if (player->aborted){ + pr("Fire aborted.\n"); + return RET_OK; + } + while(nxtitem(&nbst, (s_char *)&item)){ + attacker = orig_attacker; + if (attacker == targ_unit){ + if (!getland(item.land.lnd_uid, &fland)) + continue; + if (!getsect(item.land.lnd_x,item.land.lnd_y,&fsect)) + continue; + if (item.land.lnd_own != player->cnum) + continue; + + if (fland.lnd_frg == 0){ + pr("Unit %d cannot fire!\n",fland.lnd_uid); + continue; + } + if (lnd_getmil(&fland) < 1) { + pr("Unit %d cannot fire because it has no military!\n", + fland.lnd_uid); + continue; + } + if (fland.lnd_ship >= 0){ + pr("Unit %d cannot fire because it is on a ship!\n", + fland.lnd_uid); + continue; + } + if (fland.lnd_land >= 0){ + pr("Unit %d cannot fire because it is on a land unit!\n", + fland.lnd_uid); + continue; + } + if (fland.lnd_effic < LAND_MINFIREEFF){ + pr("Unit %d cannot fire because it is less than %d%% efficient\n",fland.lnd_uid, LAND_MINFIREEFF); + continue; + } + resupply_commod(&fland,I_SHELL); /* Get more shells */ + putland(fland.lnd_uid,&fland); + if (getvar(V_SHELL, (s_char *)&fland, EF_LAND) == 0){ + pr("%s -- not enough shells\n", + prland(&fland)); + continue; + } + } + else if (attacker == targ_ship){ + if (!getship(item.ship.shp_uid, &fship)) + continue; + if (item.ship.shp_own != player->cnum) + continue; + if (getvar(V_MILIT, (s_char *)&item.ship, EF_SHIP) < 1){ + pr("Not enough mil on ship #%d\n",item.ship.shp_uid); + continue; + } + gun = getvar(V_GUN, (s_char *)&item.ship, EF_SHIP); + gun = min(gun, item.ship.shp_glim); + if (item.ship.shp_frnge == 0){ + pr("Ships %d cannot fire guns!\n",item.ship.shp_uid); + continue; + } + if (gun == 0){ + pr("Not enough guns on ship #%d\n",item.ship.shp_uid); + continue; + } + if (getvar(V_SHELL, (s_char *)&item.ship, EF_SHIP) == 0){ + pr("Not enough shells on ship #%d\n",item.ship.shp_uid); + continue; + } + if (item.ship.shp_effic < 60){ + pr("Ship #%d is crippled!\n",item.ship.shp_uid); + continue; + } + fshipno=fship.shp_uid; + } + else if (attacker == targ_land){ + if (!getsect(item.sect.sct_x,item.sect.sct_y, &fsect)) + continue; + if (item.sect.sct_own != player->cnum) + continue; + if (item.sect.sct_type != SCT_FORTR) + continue; + if (item.sect.sct_effic < ((u_char)FORTEFF)){ + pr("Fort not efficient enough to fire!\n"); + continue; + } + if (getvar(V_GUN, (s_char *)&item.sect, EF_SECTOR) == 0){ + pr("Not enough guns in sector %s!\n",xyas(item.sect.sct_x,item.sect.sct_y,player->cnum)); + continue; + } + if (getvar(V_SHELL, (s_char *)&item.sect, EF_SECTOR) == 0){ + pr("Not enough shells in sector %s!\n",xyas(item.sect.sct_x,item.sect.sct_y,player->cnum)); + continue; + } + if (getvar(V_MILIT, (s_char *)&item.sect, EF_SECTOR) < 5){ + pr("Not enough military in sector %s!\n",xyas(item.sect.sct_x,item.sect.sct_y,player->cnum)); + continue; + } + pr("\nSector %s firing\n", + xyas(item.sect.sct_x,item.sect.sct_y,player->cnum)); + } + if ((ptr = getstarg(player->argp[3], "Firing at? ", buf)) == 0 || *ptr == '\0') + continue; + if (player->aborted){ + pr("Fire aborted.\n"); + continue; + } + ptr[19] = 0; + (void)strcpy(vbuf, ptr); + if (issector(vbuf)) + target = targ_land; + else + target = targ_ship; + if (target == targ_ship) { + vshipno = atoi(vbuf); + if (vshipno < 0 || !getship(vshipno, &vship) || + (!vship.shp_own)) { + pr("No such ship exists!\n"); + continue; + } + target = (mchr[(int)vship.shp_type].m_flags & M_SUB) ? + targ_sub : targ_ship; + vict = vship.shp_own; + x = vship.shp_x; + y = vship.shp_y; + if (!getsect(x, y, &vsect)) { + pr("No such sector exists!\n"); + continue; + } + } else { + if (!sarg_xy(vbuf, &x, &y) || !getsect(x, y, &vsect)) { + pr("No such sector exists!\n"); + continue; + } + /* We check the sector type, but we only use it for damage, not + reporting. That way, you don't get extra information you wouldn't + normally get. Besides, what if they want to slam water? :) */ + if (vsect.sct_type == SCT_SANCT || + vsect.sct_type == SCT_WATER) + target = targ_bogus; + else + target = targ_land; + vict = vsect.sct_own; + x = vsect.sct_x; + y = vsect.sct_y; + } + if (attacker == targ_ship) { + shots = -1; /* convert to max later */ + if (fship.shp_own != player->cnum) { + pr("Not your ship!\n"); + continue; + } + if (target == targ_sub || target == targ_ship) { + if (fship.shp_uid == vship.shp_uid) { + pr("You can't fire upon yourself!\n"); + continue; + } + } + fx = fship.shp_x; + fy = fship.shp_y; +/* + attacker = (mchr[fship.shp_type].m_flags & M_SUB) ? + targ_sub : targ_ship; + if (attacker == targ_sub){ + pr("Subs may not fire normally.. use torpedo.\n"); + continue; + } +*/ + attacker = targ_ship; + if ((mil = getvar(V_MILIT, (s_char *)&fship, EF_SHIP)) < 1) { + pr("Not enough military for firing crew.\n"); + continue; + } + gun = getvar(V_GUN, (s_char *)&fship, EF_SHIP); + gun = min(gun, fship.shp_glim); + if (fship.shp_frnge == 0 || gun == 0) { + pr("Insufficient arms.\n"); + continue; + } + shell = getvar(V_SHELL, (s_char *)&fship, EF_SHIP); + if (shell < 2) + shell+=supply_commod(fship.shp_own,fship.shp_x, + fship.shp_y,I_SHELL,2-shell); + if (shell <= 0){ + pr("Klick! ...\n"); + continue; + } + if (fship.shp_effic < 60) { + pr("Ship #%d is crippled (%d%%)\n", fshipno, + fship.shp_effic); + continue; + } + range = techfact(fship.shp_tech, + (double)fship.shp_frnge / 2.0); + range2 = (double)roundrange(range); + pr("range is %.2f (%.2f)\n", range2, range); + if (target == targ_sub) { + if ((mchr[(int)fship.shp_type].m_flags & M_DCH) == 0) { + pr("A %s can't drop depth charges!\n", + mchr[(int)fship.shp_type].m_name); + continue; + } + if (shell < 2) { + pr("Not enough shells for depth charge!\n"); + continue; + } + } + gun = min(gun, shell*2); + gun = min(gun, mil / 2); + gun = max(gun, 1); + if (shots > gun || shots < 0) + shots = gun; + else if (shots == 0) { + pr("No shots fired.\n"); + continue; + } + guneff = seagun(fship.shp_effic, shots); + dam = (int)guneff; + shell -= ldround(((double)shots)/2.0,1); + putvar(V_SHELL, shell, (s_char *)&fship, EF_SHIP); + putship(fship.shp_uid,&fship); + if (opt_NOMOBCOST == 0) + fship.shp_mobil = max(fship.shp_mobil - 15, -100); + } else if (attacker == targ_unit) { + if (fland.lnd_own != player->cnum) { + pr("Not your unit!\n"); + continue; + } + + if (target == targ_land) { + if (fland.lnd_x == vsect.sct_x && fland.lnd_y == vsect.sct_y) { + pr("You can't fire upon yourself!\n"); + continue; + } + } + + fx = fland.lnd_x; + fy = fland.lnd_y; + + if (fland.lnd_frg == 0){ + pr("Unit %d cannot fire!\n",fland.lnd_uid); + continue; + } + if (getvar(V_SHELL, (s_char *)&fland, EF_LAND) == 0){ + pr("%s -- not enough shells\n", prland(&fland)); + continue; + } + + shell = getvar(V_SHELL,(s_char *)&fland, EF_LAND); + + range = techfact((int)fland.lnd_tech, + (double)fland.lnd_frg / 2.0); + range2 = (double)roundrange(range); + pr("range is %.2f (%.2f)\n", range2, range); + if (target == targ_sub) { + pr("A %s can't drop depth charges!\n", + lchr[(int)fland.lnd_type].l_name); + continue; + } + + gun = getvar(V_GUN, (s_char *)&fland, EF_LAND); + if (gun <= 0) { + pr("%s -- not enough guns\n", prland(&fland)); + continue; + } + + dam = (int)landunitgun(fland.lnd_effic, fland.lnd_dam, gun, + fland.lnd_ammo, shell); + if (target == targ_ship){ + if (chance(((double)fland.lnd_acc)/100.0)) + dam = ldround(((double)dam/2.0),1); + } + use_supply(&fland); + resupply_commod(&fland,I_SHELL); /* Get more shells */ + putland(fland.lnd_uid,&fland); + } else { + fx=fsect.sct_x; + fy=fsect.sct_y; + if (fsect.sct_own != player->cnum || + fsect.sct_type != SCT_FORTR) { + pr("No fortress at %s\n", xyas(fsect.sct_x, + fsect.sct_y,player->cnum)); + continue; + } + if (target == targ_land) { + if (fsect.sct_x == vsect.sct_x && fsect.sct_y == vsect.sct_y) { + pr("You can't fire upon yourself!\n"); + continue; + } + } + attacker = targ_land; + if ((gun = getvar(V_GUN, (s_char *)&fsect, EF_SECTOR)) == 0) { + pr("Insufficient arms.\n"); + continue; + } + shell = getvar(V_SHELL, (s_char *)&fsect, EF_SECTOR); + if (shell <= 0) + shell+=supply_commod(fsect.sct_own,fsect.sct_x, + fsect.sct_y,I_SHELL,1); + if (shell <= 0){ + pr("Klick! ...\n"); + continue; + } + if (getvar(V_MILIT, (s_char *)&fsect, EF_SECTOR) < 5) { + pr("Not enough military for firing crew.\n"); + continue; + } + if (target == targ_sub) { + pr("Target ship not sighted!\n"); + continue; + } + if (gun>7) + gun = 7; + range = tfactfire(player->cnum, 7.0); + if (fsect.sct_effic > 59) + range++; + range2 = (double)roundrange(range); + pr("range is %.2f (%.2f)\n", range2, range); + guneff = landgun((int)fsect.sct_effic, gun); + dam = (int)guneff; + shell--; + putvar(V_SHELL, shell, (s_char *)&fsect, EF_SECTOR); + putsect(&fsect); + } + trange = mapdist(x, y, fx, fy); + if (trange > range2){ + pr("Target out of range.\n"); +/* + switch (target) { + case targ_land: + case targ_bogus: + pr("Target out of range. Thud.\n"); + break ; + default: + pr("Target ship out of range. Splash.\n"); + break ; + } + */ + switch (attacker) { + case targ_land: + putsect(&fsect); + break ; + case targ_unit: + fland.lnd_mission = 0; + putland(fland.lnd_uid, &fland); + break; + default: + fship.shp_mission = 0; + putship(fship.shp_uid, &fship); + } + continue; + } +/* + if (target == targ_bogus) { + if (vsect.sct_type == SCT_SANCT) { + pr("%s is a %s!!\n", vbuf, + dchr[SCT_SANCT].d_name); + continue; + } else if (vsect.sct_type == SCT_WATER) { + pr("You must specify a ship in sector %s!\n", + vbuf); + continue; + } + } +*/ + switch (target) { + case targ_ship: + if (!trechk(player->cnum, vict, SEAFIR)) + continue; + break; + case targ_sub: + if (!trechk(player->cnum, vict, SUBFIR)) + continue; + break; + case targ_unit: + case targ_land: + if (!trechk(player->cnum, vict, LANFIR)) + continue; + break; + default: + break; + } + + if (opt_SLOW_WAR) { + if (target == targ_land){ + natp = getnatp(player->cnum); + rel = getrel(natp,vict); + if ((rel != AT_WAR) && (player->cnum != vict) && + (vict) && (vsect.sct_oldown != player->cnum)){ + pr("You're not at war with them!\n"); + continue; + } + } + } + nfiring++; + switch (target) { + case targ_sub: + pr_beep(); + pr("Kawhomp!!!\n"); + if (vship.shp_rflags & RET_DCHRGED) + retreat_ship(&vship,'d'); + break ; + default: + pr_beep(); + pr("Kaboom!!!\n"); + prb = (double)(range2?(trange / range2):1.0); + prb *= prb; +#if !defined(_WIN32) + srandom(random()); +#else + (void) time(&now); + (void) srand(now); +#endif + if (chance(prb)) { + pr("Wind deflects shell%s.\n", splur(shots)); +/* dam = (int)((double)dam / 2.0);*/ + dam = (int)((double)dam * (double)((double)(90 - (random() % 11)) / 100.0)); + if (dam < 0) + dam = 0; + } + break ; + } + switch (target) { + case targ_bogus: + case targ_land: + nreport(player->cnum, N_SCT_SHELL, vict, 1); + if (vict && vict != player->cnum) + wu(0, vict, + "Country #%d shelled sector %s for %d damage.\n", + player->cnum, xyas(x, y, vict), dam); + pr("Shell%s hit sector %s for %d damage.\n", + splur(shots), xyas(x, y, player->cnum), dam); + /* Ok, it wasn't a bogus target, so do damage. */ + if (target != targ_bogus) + sectdamage(&vsect, dam, 0); + break ; + case targ_ship: + nreport(player->cnum, N_SHP_SHELL, vict, 1); + default: + if ((target != targ_sub) || + ((vship.shp_rflags & RET_DCHRGED) == 0)) + check_retreat_and_do_shipdamage(&vship, dam); + else + shipdamage(&vship, dam); + if (vict) { + wu(0, vict, + "Country #%d shelled %s in %s for %d damage.\n", + player->cnum, prship(&vship), + xyas(vship.shp_x, vship.shp_y, vict), + dam); + } + pr("Shell%s hit %s in %s for %d damage.\n", + splur(shots), prsub(&vship), + xyas(vship.shp_x, vship.shp_y, player->cnum), + dam); + + if (vship.shp_effic < SHIP_MINEFF) + pr("%s sunk!\n", prsub(&vship)); + + break ; + } + /* Ok, now, check if we had a bogus target. If so, + just continue on, since there is no defender. */ + if (target == targ_bogus) + continue; + if (attacker == targ_unit){ + attacker = targ_land; + getsect(fland.lnd_x,fland.lnd_y,&fsect); + } + totaldefdam=defend(&fired,&defended,target,attacker,&vsect,&fsect,&vship,&fship,fx,fy,&ndefending); + switch (target) { + case targ_land: + putsect(&vsect); + break ; + default: + putship(vship.shp_uid, &vship); + break ; + } + if ((totaldefdam == 0) && (target == targ_ship)) + if (vship.shp_rflags & RET_INJURED) + retreat_ship(&vship,'h'); + switch (attacker) { + case targ_land: + putsect(&fsect); + break ; + default: + if ((target == targ_ship) || (target == targ_sub)) { + if (fship.shp_effic > SHIP_MINEFF) { + shp_missdef(&fship, vict); + }; + }; + putship(fship.shp_uid, &fship); + break ; + } + } + + use_ammo(&defended); + if (nfiring) + odds = ((double)ndefending)/((double)nfiring); + else + odds = 1.0; + do_defdam(&fired, odds); + return RET_OK; +} + +static int +defend(struct emp_qelem *al, struct emp_qelem *dl, enum targ_type target, enum targ_type attacker, struct sctstr *vsect, struct sctstr *fsect, struct shpstr *vship, struct shpstr *fship, int fx, int fy, int *nd) +{ + + int dam; + int vict, nfiring=0; + struct flist *fp; + int aown; + + if (attacker == targ_land) + aown = fsect->sct_own; + else + aown = fship->shp_own; + + if (target == targ_land) + vict = vsect->sct_own; + else + vict = vship->shp_own; + + if (0 != (dam = quiet_bigdef(attacker,dl,vict,aown,fx,fy,&nfiring))) { + if (nfiring > *nd) + *nd = nfiring; + fp = (struct flist *)malloc(sizeof(struct flist)); + bzero((s_char *)fp,sizeof(struct flist)); + fp->defdam = dam; + fp->victim = vict; + switch (attacker) { + case targ_land: + fp->x = fsect->sct_x; + fp->y = fsect->sct_y; + fp->type = targ_land; + break ; + default: + fp->type = targ_ship; + fp->uid = fship->shp_uid; + break ; + } + emp_insque(&fp->queue,al); + } + + return(dam); +} + +void +do_defdam(struct emp_qelem *list, double odds) +{ + + int dam, vict,first=1; + struct flist *fp; + struct shpstr ship; + struct sctstr sect; + struct emp_qelem *qp, *next; + + for (qp = list->q_forw; qp != list; qp = next){ + next = qp->q_forw; + fp = (struct flist *)qp; + if (fp->type == targ_ship) { + if (!getship(fp->uid, &ship) || + !ship.shp_own) + continue; + } + if (first){ + pr_beep(); + pr("\nDefenders fire back!\n"); + first=0; + } + dam = (odds * (double)fp->defdam); + + if (fp->type == targ_ship){ + vict = fp->victim; + pr( + "Return fire hit %s in %s for %d damage.\n", + prship(&ship), + xyas(ship.shp_x, ship.shp_y, player->cnum), + dam); + if (vict) + wu(0, vict, + "Return fire hit %s in %s for %d damage.\n", + prsub(&ship), + xyas(ship.shp_x, ship.shp_y, vict), + dam); + shipdamage(&ship, dam); + putship(ship.shp_uid,&ship); + }else{ + getsect(fp->x, fp->y, §); + vict = fp->victim; + pr("Return fire hit sector %s for %d damage.\n", + xyas(fp->x, fp->y, player->cnum), dam); + sectdamage(§, dam, 0); + putsect(§); + if (vict) + wu(0, vict, "Return fire hit sector %s for %d damage.\n", + xyas(fp->x, fp->y, vict), dam); + } + emp_remque(&fp->queue); + free((s_char *)fp); + } +} + +int +quiet_bigdef(int attacker, struct emp_qelem *list, natid own, natid aown, coord ax, coord ay, int *nfiring) +{ + int nshot; + double range, erange, hitchance; + struct shpstr ship; + struct lndstr land; + struct nstr_item ni; + int vec[I_MAX+1]; + int dam, dam2, rel, rel2; + double tech; + struct sctstr firing; + struct nstr_sect ns; + struct flist *fp; + double techfact(int, double); + extern int torpedo_damage; + int gun; + + if (own == 0) + return 0; + dam = 0; + snxtitem_dist(&ni, EF_SHIP, ax, ay, 8); + while (nxtitem(&ni, (caddr_t)&ship)){ + if (ship.shp_own == 0) + continue; + + if ((mchr[(int)ship.shp_type].m_flags & M_SUB) && + (attacker == targ_land)) + continue; + + rel = getrel(getnatp(ship.shp_own),own); + rel2 = getrel(getnatp(ship.shp_own),aown); + if ((ship.shp_own != own) && + ((rel != ALLIED) || (rel2 != AT_WAR))) + continue; + /* Don't shoot yourself */ + if (ship.shp_own == aown) + continue; + if (ship.shp_effic < 60) + continue; + if (getvec(VT_ITEM, vec, (caddr_t)&ship, EF_SHIP) < 0) + continue; + + if (vec[I_MILIT] < 1) + continue; + + if (mchr[(int)ship.shp_type].m_flags & M_SUB){ + if (vec[I_SHELL] < 3) + vec[I_SHELL] += supply_commod(ship.shp_own, + ship.shp_x,ship.shp_y,I_SHELL, + 3-vec[I_SHELL]); + if (vec[I_SHELL] < 3) + continue; + if (vec[I_GUN] < 1) + continue; +/* + if (ship.shp_mobil <= 0) + continue; +*/ + erange = ship.shp_effic* + techfact(ship.shp_tech, + ((double)ship.shp_frnge)) + / 100.0; + erange = (double)roundrange(erange); + range = mapdist(ship.shp_x, ship.shp_y, ax, ay); + if (range > erange) + continue; + if (!line_of_sight((s_char **)0, ship.shp_x, ship.shp_y, ax, ay)) + continue; + + (*nfiring)++; + fp = (struct flist *)malloc(sizeof(struct flist)); + bzero((s_char *)fp,sizeof(struct flist)); + fp->type = targ_ship; + fp->uid = ship.shp_uid; + add_to_fired_queue(&fp->queue, list); +/* + nreport(ship.shp_own, N_FIRE_BACK, player->cnum, 1); +*/ + hitchance = DTORP_HITCHANCE(range, ship.shp_visib); + if (!chance(hitchance)) + continue; + + dam += TORP_DAMAGE(); + }else{ + range = techfact(ship.shp_tech, + ship.shp_frnge * ship.shp_effic / 200.0); + range = (double)roundrange(range); + if (range < ni.curdist) + continue; + /* must have gun, shell, and milit to fire */ + if (vec[I_SHELL] < 1) + vec[I_SHELL] += supply_commod(ship.shp_own, + ship.shp_x,ship.shp_y,I_SHELL,1); + /* only need 1 shell, so don't check that */ + if (vec[I_SHELL] < 1) + continue; + nshot = min(vec[I_GUN],vec[I_MILIT]); + nshot = min(nshot, ship.shp_glim); + if (nshot == 0) + continue; + (*nfiring)++; + fp = (struct flist *)malloc(sizeof(struct flist)); + bzero((s_char *)fp,sizeof(struct flist)); + fp->type = targ_ship; + fp->uid = ship.shp_uid; + add_to_fired_queue(&fp->queue, list); + nreport(ship.shp_own, N_FIRE_BACK, player->cnum, 1); + dam += seagun(ship.shp_effic,nshot); + } + } + snxtitem_dist(&ni, EF_LAND, ax, ay, 8); + while (nxtitem(&ni, (caddr_t)&land)){ + if (land.lnd_own == 0) + continue; + if (land.lnd_effic < LAND_MINFIREEFF) + continue; + /* Can't fire if on a ship */ + if (land.lnd_ship >= 0) + continue; + if (land.lnd_land >= 0) + continue; + /* Gotta have military */ + if (lnd_getmil(&land) < 1) + continue; + /* Don't shoot yourself */ + if (land.lnd_own == aown) + continue; + + rel = getrel(getnatp(land.lnd_own),own); + rel2 = getrel(getnatp(land.lnd_own),aown); + + if ((land.lnd_own != own) && + ((rel != ALLIED) || (rel2 != AT_WAR))) + continue; + + + range = techfact((int)land.lnd_tech, + (double)land.lnd_frg / 2.0); + range = (double)roundrange(range); + if (range < ni.curdist) + continue; + + resupply_all(&land); + if (!has_supply(&land)) + continue; + + if (getvec(VT_ITEM, vec, (caddr_t)&land, EF_LAND) < 0) + continue; + + if (vec[I_MILIT] == 0 || vec[I_SHELL] == 0 || vec[I_GUN] == 0) + continue; + + dam2 = (int)landunitgun(land.lnd_effic, land.lnd_dam, vec[I_GUN], + land.lnd_ammo, vec[I_SHELL]); + + (*nfiring)++; + fp = (struct flist *)malloc(sizeof(struct flist)); + bzero((s_char *)fp,sizeof(struct flist)); + fp->type = targ_unit; + fp->uid = land.lnd_uid; + add_to_fired_queue(&fp->queue, list); + use_supply(&land); + putland(land.lnd_uid, &land); + nreport(land.lnd_own, N_FIRE_BACK, player->cnum, 1); + dam += dam2; + } + + /* + * Determine if any nearby gun-equipped sectors are within + * range and able to fire at an attacker. Firing sectors + * need to have guns, shells, and military. Sector being + * attacked is x,y -- attacker is at ax,ay. + */ + + if (!opt_NO_FORT_FIRE) { + snxtsct_dist(&ns, ax, ay, 8); + while (nxtsct(&ns, &firing)){ + + if (firing.sct_type != SCT_FORTR) + continue; + if (firing.sct_own == 0) + continue; + rel = getrel(getnatp(firing.sct_own),own); + rel2 = getrel(getnatp(firing.sct_own),aown); + + if ((firing.sct_own != own) && + ((rel != ALLIED) || (rel2 != AT_WAR))) + continue; + /* Don't shoot yourself */ + if (firing.sct_own == aown) + continue; + tech = tfactfire(firing.sct_own, 1.0); + range = tech * 7.0; + if (firing.sct_effic > 59) /* fort bonus */ + range++; + range = (double)roundrange(range); + if (range < ns.curdist) + continue; + if (getvec(VT_ITEM, vec, (caddr_t)&firing, EF_SECTOR) < 0) + continue; + if (vec[I_SHELL] < 1) + vec[I_SHELL] += supply_commod(firing.sct_own, + firing.sct_x,firing.sct_y,I_SHELL,1); + if (vec[I_GUN] == 0 || vec[I_MILIT] < 5 || vec[I_SHELL] == 0) + continue; + (*nfiring)++; + fp = (struct flist *)malloc(sizeof(struct flist)); + bzero((s_char *)fp,sizeof(struct flist)); + fp->x = firing.sct_x; + fp->y = firing.sct_y; + fp->type = targ_land; + add_to_fired_queue(&fp->queue, list); + nreport(firing.sct_own, N_FIRE_BACK, player->cnum, 1); + gun = vec[I_GUN]; + if (gun > 7) + gun = 7; + dam += landgun((int)firing.sct_effic,gun); + } + } + + return ((*nfiring) == 0 ? 0 : (dam/(*nfiring))); +} + +void +use_ammo(struct emp_qelem *list) +{ + struct emp_qelem *qp, *next; + struct flist *fp; + struct shpstr ship; + struct lndstr land; + struct sctstr sect; + int shell, type; + s_char *ptr; + double mobcost; + struct mchrstr *mcp; + + /* use 1 shell from everyone */ + for (qp = list->q_forw; qp != list; qp = next){ + next = qp->q_forw; + fp = (struct flist *)qp; + if (fp->type == targ_ship){ + getship(fp->uid,&ship); + ptr = (s_char *)&ship; + type = EF_SHIP; + if (mchr[(int)ship.shp_type].m_flags & M_SUB){ + shell = getvar(V_SHELL, ptr, type); + shell--; + if (shell<0) + shell=0; + putvar(V_SHELL, shell, ptr, type); + putship(ship.shp_uid, &ship); + mcp = &mchr[(int)ship.shp_type]; + mobcost = ship.shp_effic * 0.01 * ship.shp_speed; + mobcost = (480.0 / (mobcost + + techfact(ship.shp_tech, mobcost))); + /* mob cost = 1/2 a sect's mob */ + mobcost /= 2.0; + ship.shp_mobil -= mobcost; + } + }else if (fp->type == targ_land){ + getsect(fp->x,fp->y,§); + ptr = (s_char *)§ + type = EF_SECTOR; + }else{ + getland(fp->uid,&land); + ptr = (s_char *)&land; + type = EF_LAND; + } + shell = getvar(V_SHELL, ptr, type); + shell--; + if (shell<0) + shell=0; + putvar(V_SHELL, shell, ptr, type); + if (fp->type == targ_ship) + putship(ship.shp_uid,&ship); + else if (fp->type == targ_land) + putsect(§); + else + putland(land.lnd_uid,&land); + + emp_remque(&fp->queue); + free((s_char *)fp); + } + +} + +void +add_to_fired_queue(struct emp_qelem *elem, struct emp_qelem *list) +{ + struct emp_qelem *qp; + struct flist *fp, *ep; + int bad=0; + + ep = (struct flist *)elem; + + /* Don't put them on the list if they're already there */ + for (qp = list->q_forw; qp != list; qp = qp->q_forw){ + fp = (struct flist *)qp; + if ((fp->type == targ_ship) && (fp->uid == ep->uid)) + bad=1; + if ((fp->type != targ_ship) && (fp->x == ep->x) && + (fp->y == ep->y)) + bad=1; + } + + if (!bad) + emp_insque(elem, list); +} diff --git a/src/lib/commands/mine.c b/src/lib/commands/mine.c new file mode 100644 index 00000000..8aae81ce --- /dev/null +++ b/src/lib/commands/mine.c @@ -0,0 +1,175 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * mine.c: Lay mines from ships or units + * + * Known contributors to this file: + * + */ + +#include "misc.h" +#include "player.h" +#include "var.h" +#include "ship.h" +#include "land.h" +#include "sect.h" +#include "nat.h" +#include "xy.h" +#include "nsc.h" +#include "file.h" +#include "commands.h" + +/* + * format: mine + */ +int +mine(void) +{ + struct shpstr ship; + struct sctstr sect; + struct mchrstr *mp; + struct nstr_item ni; + int mines; + int shells; + int mines_avail; + int mines_there; + + if (!snxtitem(&ni, EF_SHIP, player->argp[1])) + return RET_SYN; + mines = onearg(player->argp[2], "Drop how many mines from each ship? "); + if (mines <= 0) + return RET_SYN; + while (nxtitem(&ni, (s_char *)&ship)) { + if (!player->owner) + continue; + mp = &mchr[(int)ship.shp_type]; + if ((mp->m_flags & M_MINE) == 0) + continue; + if ((shells = getvar(V_SHELL, (s_char *)&ship, EF_SHIP)) == 0) + continue; + mines_avail = min(shells, mines); + if (getsect(ship.shp_x, ship.shp_y, §) == 0 || + (sect.sct_type != SCT_WATER && + sect.sct_type != SCT_BSPAN)) { + pr("You can't lay mines there!!\n"); + continue; + } + mines_there = getvar(V_MINE, (s_char *)§, EF_SECTOR); + putvar(V_SHELL, shells - mines_avail, (s_char *)&ship, EF_SHIP); + putvar(V_MINE, mines_avail + mines_there, (s_char *)§, + EF_SECTOR); + putsect(§); + ship.shp_mission = 0; + putship(ship.shp_uid, &ship); + pr("Laying %d mines from %s\n", mines_avail, prship(&ship)); + if (mines_avail && + map_set(player->cnum, sect.sct_x, sect.sct_y, 'X', 0)) + writemap(player->cnum); + } + return RET_OK; +} + +/* + * format: landmine + */ +int +landmine(void) +{ + struct lndstr land; + struct sctstr sect; + struct lchrstr *lp; + struct nstr_item ni; + int shells; + int mines_there; + int mines_wanted; + int mines_laid; + int total_mines_laid; + s_char prompt[128]; + + if (!snxtitem(&ni, EF_LAND, player->argp[1])) + return RET_SYN; + while (nxtitem(&ni, (s_char *)&land)) { + if (!player->owner) + continue; + lp = &lchr[(int)land.lnd_type]; + if (!(lp->l_flags & L_ENGINEER)) + continue; + if (land.lnd_mobil < 1) { + pr("Unit %d is out of mobility\n", land.lnd_uid); + continue; + } + resupply_commod(&land,I_SHELL); + if (!(shells = getvar(V_SHELL, (s_char *)&land, EF_LAND))) + continue; + shells = min(shells, land.lnd_mobil); + if (!getsect(land.lnd_x, land.lnd_y, §) || + sect.sct_type == SCT_WATER || + sect.sct_type == SCT_BSPAN) { + pr("You can't lay mines there!!\n"); + continue; + } + mines_there = getvar(V_MINE, (s_char *)§, EF_SECTOR); + if (sect.sct_own == sect.sct_oldown) + pr("There are currently %d mines in %s\n", + mines_there,xyas(sect.sct_x,sect.sct_y,player->cnum)); + sprintf(prompt, "Drop how many mines from %s? ", + prland(&land)); + mines_wanted = onearg(player->argp[2], prompt); + if (!check_land_ok(&land)) + continue; + if (mines_wanted <= 0) + continue; + land.lnd_mission = 0; + total_mines_laid = 0; + while (shells > 0 && total_mines_laid < mines_wanted) { + mines_laid = min(shells, mines_wanted - total_mines_laid); + putvar(V_SHELL, shells - mines_laid, (s_char *)&land, EF_LAND); + land.lnd_mobil -= mines_laid; + putland(land.lnd_uid, &land); + resupply_commod(&land, I_SHELL); + putland(land.lnd_uid, &land); + total_mines_laid += mines_laid; + shells = getvar(V_SHELL, (s_char *)&land, EF_LAND); + shells = min(shells, land.lnd_mobil); + } + getsect(sect.sct_x, sect.sct_y, §); + putvar(V_MINE, total_mines_laid + mines_there, (s_char *)§, + EF_SECTOR); + putsect(§); + if (shells) + pr("%s laid a total of %d mines in %s\n", + prland(&land), total_mines_laid, + xyas(sect.sct_x,sect.sct_y,land.lnd_own)); + else + pr("%s ran out of %s before it could finish the job\nOnly %d mines were laid in %s\n", + prland(&land), + land.lnd_mobil > 0 ? "supply" : "mobility", + total_mines_laid, + xyas(sect.sct_x,sect.sct_y,land.lnd_own)); + } + return RET_OK; +} diff --git a/src/lib/commands/miss.c b/src/lib/commands/miss.c new file mode 100644 index 00000000..98c42a4a --- /dev/null +++ b/src/lib/commands/miss.c @@ -0,0 +1,342 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * miss.c: set missions for ships/planes/units + * + * Known contributors to this file: + * Thomas Ruschak, 1992 + * Steve McClure, 2000 + */ + +#include "options.h" +#include "misc.h" +#include "player.h" +#include "var.h" +#include "xy.h" +#include "sect.h" +#include "retreat.h" +#include "ship.h" +#include "land.h" +#include "plane.h" +#include "nat.h" +#include "nsc.h" +#include "deity.h" +#include "file.h" +#include "path.h" +#include "mission.h" +#include "genitem.h" +#include "commands.h" + +/* + * mission [] + */ +int +mission(void) +{ + s_char *p; + int type; + int mission; + coord x, y; + int size, desired_radius, radius; + struct sctstr opsect; + s_char *block; + struct genitem *gp; + int num=0, mobmax, mobused, dist; + struct nstr_item ni; + extern int ship_mob_max; + extern int land_mob_max; + extern int plane_mob_max; + extern double mission_mob_cost; + s_char *nameofitem(); + s_char prompt[128]; + s_char buf[1024]; + + if ((p = getstarg(player->argp[1], "Ship, plane or land unit (p,sh,la)? ", buf)) == 0) + return RET_SYN; + type = ef_byname(p); + if (type == EF_SECTOR) + type = EF_SHIP; + if (type != EF_SHIP && type != EF_LAND && type != EF_PLANE){ + pr("Ships, land units or planes only! (s, l, p)\n"); + return RET_SYN; + } + sprintf(prompt, "%s(s)? ", ef_nameof(type)); + p = getstarg(player->argp[2], prompt, buf); + if (!snxtitem(&ni, type, p)) + return RET_SYN; + + if ((p = getstarg(player->argp[3], "Mission (int, sup, osup, dsup, esc, res, air, query, clear)? ", buf)) == 0) + return RET_SYN; + +/* + * 'i' interdiction + * 's' support + * 'o' support attacks + * 'd' support defenders + * 'e' escort + * 'r' defensive reserve + * 'a' air defense (intercepts) + */ + switch(*p){ + case 'I': + case 'i': mission = MI_INTERDICT; break; + case 'O': + case 'o': mission = MI_OSUPPORT; break; + case 'D': + case 'd': mission = MI_DSUPPORT; break; + case 'S': + case 's': mission = MI_SUPPORT; break; + case 'C': + case 'c': mission = 0; break; + case 'E': + case 'e': mission = MI_ESCORT; break; + case 'R': + case 'r': mission = MI_RESERVE; break; + case 'A': + case 'a': mission = MI_AIR_DEFENSE; break; + case 'q': show_mission(type,&ni); + return RET_OK; + default: pr("bad condition\n"); + pr("i\tinterdiction (any)\n"); + pr("s\tsupport (tactical planes only)\n"); + pr("o\toffensive support (tactical planes only)\n"); + pr("d\tdefensive support (tactical planes only)\n"); + pr("r\treserve (land units only)\n"); + pr("e\tescort (tactical or escort planes only)\n"); + pr("a\tair defense (intercept planes only)\n"); + pr("c\tclear mission\n"); + pr("q\tquery\n"); + return RET_SYN; + } + + if (mission && !cando(mission,type)){ + pr("A %s cannot do that mission!\n",ef_nameof(type)); + pr("i\tinterdiction (any)\n"); + pr("s\tsupport (planes only)\n"); + pr("o\toffensive support (planes only)\n"); + pr("d\tdefensive support (planes only)\n"); + pr("r\treserve (land units only)\n"); + pr("e\tescort (planes only)\n"); + pr("a\tair defense (planes only)\n"); + return RET_FAIL; + } + + if (mission && ((mission != MI_RESERVE) && (mission != MI_ESCORT))){ + if ((p=getstarg(player->argp[4],"operations point? ", buf)) == 0 || *p == 0) + return RET_SYN; + + if (*p != '.'){ + if (!sarg_xy(p, &x, &y)) + return RET_SYN; + + if (!getsect(x, y, &opsect)) + return RET_FAIL; + } + }else{ + x=0; + y=0; + } + + if (player->argp[5] != (s_char *)0){ + desired_radius = atoi(player->argp[5]); + if (desired_radius < 0){ + pr("Radius must be greater than zero!\n"); + return RET_FAIL; + } + } else { + desired_radius=9999; + } + + size = max(sizeof(struct lndstr),sizeof(struct plnstr)); + size = max(size,sizeof(struct shpstr)); + block = (s_char *)malloc(size); + switch (type){ + case EF_SHIP: mobmax = ship_mob_max; break; + case EF_LAND: mobmax = land_mob_max; break; + case EF_PLANE: mobmax = plane_mob_max; break; + } + + mobused = ldround((mission_mob_cost * (double)mobmax),1); + + while (nxtitem(&ni, block)) { + gp = (struct genitem *)block; + + if (!player->owner || gp->own == 0) + continue; + + if ((mission && (gp->mobil < mobused)) && mission_mob_cost) { + pr("%s #%d: not enough mobility! (needs %d)\n", + ef_nameof(type), gp->uid, mobused); + continue; + } + if (mission == MI_RESERVE && !lnd_can_attack((struct lndstr *)gp)) { + pr("%s is not designed to fight ground troops\n", prland((struct lndstr *)gp)); + continue; + } + if (*p == '.'){ + x = gp->x; + y = gp->y; + if (!getsect(x, y, &opsect)) + return RET_FAIL; + } + + dist = mapdist(gp->x, gp->y, x, y); + radius = 999; + if ((mission == MI_INTERDICT || mission == MI_SUPPORT || + mission == MI_OSUPPORT || mission == MI_DSUPPORT || + mission == MI_AIR_DEFENSE) && + (oprange(gp,type,&radius) < dist)){ + pr("%s #%d: out of range! (range %d)\n", + ef_nameof(type), gp->uid, + oprange(gp,type,&radius)); + continue; + } + + if (radius > desired_radius) + radius = desired_radius; + +/* + if (mission && (gp->effic < 60)){ + pr("%s #%d: not efficient enough! (must be>=60%)\n", + ef_nameof(type), gp->uid); + continue; + } + */ + + if ((mission == MI_INTERDICT) && (type == EF_SHIP)) + if (mchr[(int)gp->type].m_frnge < 1){ + pr("%s #%d: cannot fire at range!\n", + ef_nameof(type), gp->uid); + continue; + } + + if ((mission == MI_INTERDICT) && (type == EF_LAND)) + if (lchr[(int)gp->type].l_frg < 1){ + pr("%s #%d: cannot fire at range!\n", + ef_nameof(type), gp->uid); + continue; + } + + if ((mission == MI_INTERDICT) && (type == EF_PLANE)){ + struct plchrstr *pcp; + + pcp = &plchr[(int)gp->type]; + if (!(pcp->pl_flags & P_T)){ + pr("Only planes with the tactical ability can interdict.\n%s #%d is ineligible\n", pcp->pl_name,gp->uid); + continue; + } + } + + if ((mission == MI_AIR_DEFENSE) && (type == EF_PLANE)){ + struct plchrstr *pcp; + + pcp = &plchr[(int)gp->type]; + if (!(pcp->pl_flags & P_F)){ + pr("Only planes with the intercept abilities can perform air defense.\n%s #%d is ineligible\n", pcp->pl_name,gp->uid); + continue; + } + } + + if ((mission == MI_ESCORT) && (type == EF_PLANE)){ + struct plchrstr *pcp; + + pcp = &plchr[(int)gp->type]; + if (!(pcp->pl_flags & P_ESC) && !(pcp->pl_flags & P_F)){ + pr("Only planes with the escort or intercept abilities can escort.\n%s #%d is ineligible\n", pcp->pl_name,gp->uid); + continue; + } + } + + if ((mission == MI_SUPPORT || mission == MI_OSUPPORT || + mission == MI_DSUPPORT) && (type == EF_PLANE)){ + struct plchrstr *pcp; + + pcp = &plchr[(int)gp->type]; + if (!(pcp->pl_flags & P_T)){ + pr("Only planes with the tactical ability can support.\n%s #%d is ineligible\n", pcp->pl_name,gp->uid); + continue; + } + } + + num++; /* good one.. go with it */ + + if (mission == MI_INTERDICT || mission == MI_SUPPORT || + mission == MI_OSUPPORT || mission == MI_DSUPPORT || + mission == MI_AIR_DEFENSE) + gp->radius = radius; + else + gp->radius = 0; + + if (mission == MI_SUPPORT || mission == MI_OSUPPORT || + mission == MI_DSUPPORT || mission == MI_INTERDICT || + mission == MI_AIR_DEFENSE) { + pr("%s on %s mission, centered on %s, radius %d\n", + nameofitem(buf, gp,type), mission_name(mission), + xyas(x,y,player->cnum), gp->radius); + } else if (mission == MI_RESERVE) { + int plus = 2; + + if (((struct lndstr *)gp)->lnd_rad_max == 0) { + plus = 0; + } else { + getsect(gp->x, gp->y, &opsect); + if ((opsect.sct_type == SCT_HEADQ) && (opsect.sct_effic >= 60)) + plus++; + plus += ((struct lndstr *)gp)->lnd_rad_max; + } + + pr("%s on %s mission with maximum reaction radius %d\n", nameofitem(buf, gp, type), + mission_name(mission), plus); + } else if (mission) { + pr("%s on %s mission\n", nameofitem(buf, gp, type), + mission_name(mission)); + } + + if (mission) + gp->mobil -= mobused; + gp->mission = mission; + gp->opx = x; + gp->opy = y; + switch (type){ + case EF_SHIP: + putship(gp->uid,block); + break; + case EF_LAND: + putland(gp->uid,block); + break; + case EF_PLANE: + putplane(gp->uid,block); + break; + } + } + if (num == 0) { + pr("No %s%s\n", ef_nameof(type), splur(num)); + return RET_FAIL; + } + pr("%d %s%s\n", num, ef_nameof(type), splur(num)); + return RET_OK; +} diff --git a/src/lib/commands/mobq.c b/src/lib/commands/mobq.c new file mode 100644 index 00000000..b33ae6bd --- /dev/null +++ b/src/lib/commands/mobq.c @@ -0,0 +1,123 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * mobq.c: Set the sailing mobility quota for a ship + * + * Known contributors to this file: + * Robert Forsman + */ + +#include +#include "misc.h" +#include "player.h" +#include "var.h" +#include "ship.h" +#include "xy.h" +#include "nsc.h" +#include "file.h" +#include "nat.h" +#include "commands.h" +#include "optlist.h" + + +int +mobq(void) +{ + extern int ship_mob_max; + extern float ship_mob_scale; + extern int etu_per_update; + struct shpstr ship; + s_char *cp,*oldmq; + int good,mobquota,count=0; + struct nstr_item nstr; + s_char buf[1024]; + + if (!opt_SAIL) { + pr("The SAIL option is not enabled, so this command is not valid.\n"); + return RET_FAIL; + } +/* getstarg(player->argp[1], "ships? ");*/ + if (!snxtitem(&nstr, EF_SHIP, player->argp[1])) + return RET_SYN; + oldmq = player->argp[2]; + if (oldmq) + { + good = sscanf(oldmq,"%d",&mobquota); + if (!good) + return RET_SYN; + if (mobquota<0 || mobquota>ship_mob_max) + { + pr("Bad mobility quota value %d.\n",mobquota); + return RET_SYN; + } + if (mobquota+(ship_mob_scale*(float)etu_per_update) > ship_mob_max) + { + pr("warning: %d less than optimal\n",mobquota); + } + } + while (nxtitem(&nstr, (s_char *)&ship)) { + if (!player->owner) + continue; + if (!oldmq) + pr("Ship #%d at %s. Old value %d.\n",ship.shp_uid,xyas(ship.shp_x,ship.shp_y,player->cnum),ship.shp_mobquota); + cp = getstarg(player->argp[2],"mobility quota?", buf); + if (!cp) + return RET_SYN; + if (!check_ship_ok(&ship)) + continue; + good = sscanf(cp,"%d",&mobquota); + if (!good) + { + pr("Huh?\n"); + continue; + } + if (!oldmq) + { + if (mobquota<0 || mobquota>ship_mob_max) + { + pr("Bad mobility quota value %d.\n",mobquota); + continue; + } + if (mobquota+(ship_mob_scale*(float)etu_per_update)> ship_mob_max) + { + pr("warning: %d less than optimal\n",mobquota); + } + } + ship.shp_mobquota = mobquota; + count ++; + putship(ship.shp_uid, &ship); + } + if (count == 0) { + if (player->argp[1]) + pr("%s: No ship(s)\n", player->argp[1]); + else + pr("%s: No ship(s)\n", ""); + return RET_FAIL; + }else + pr("%d ship%s\n", count, splur(count)); + return RET_OK; +} diff --git a/src/lib/commands/mobu.c b/src/lib/commands/mobu.c new file mode 100644 index 00000000..ad51e118 --- /dev/null +++ b/src/lib/commands/mobu.c @@ -0,0 +1,116 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * mobu.c: Adjust mobility updating + * + * Known contributors to this file: + * Steve McClure, 1996 + */ + +#include "misc.h" +#include "player.h" +#include "var.h" +#include "xy.h" +#include "sect.h" +#include "nsc.h" +#include "nat.h" +#include "deity.h" +#include "path.h" +#include "file.h" +#include "commands.h" +#include "optlist.h" +#include "prototypes.h" + +#include + +int +mobupdate(void) +{ + FILE *fp; + long minites; + extern int updating_mob; + struct mob_acc_globals timestamps; + long now; + extern s_char *timestampfil; + + if (!opt_MOB_ACCESS) { + pr("Command invalid - MOB_ACCESS is not enabled.\n"); + return RET_FAIL; + } + if (!player->argp[1]) + return RET_SYN; + if (*player->argp[1] == 'c') + minites = -1; + else + minites = atol(player->argp[1]) * 60; + time(&now); +#if !defined(_WIN32) + if ((fp = fopen(timestampfil, "r+")) == NULL) { +#else + if ((fp = fopen(timestampfil, "r+b")) == NULL) { +#endif + logerror("Unable to edit timestamp file."); + } else { + rewind(fp); + fread(×tamps, sizeof(timestamps), 1, fp); + if (minites < 0) { + fclose(fp); + if (updating_mob) + pr("Mobility updating is enabled."); + else { + pr("Mobility updating will come back on around %s", + ctime(×tamps.starttime)); + pr("within 3 minutes, depending on when the server checks."); + } + return 0; + } + timestamps.timestamp = now; + timestamps.starttime = now + minites; + rewind(fp); + fwrite(×tamps, sizeof(timestamps), 1, fp); + fclose(fp); + if (now >= timestamps.starttime) { + pr("Turning on mobility updating."); + update_all_mob(); + updating_mob = 1; + } else if (updating_mob == 1) { + pr("Turning off mobility updating.\n\r"); + pr("Mobility updating will come back on around %s", + ctime(×tamps.starttime)); + pr("within 3 minutes, depending on when the server checks."); + update_all_mob(); + updating_mob = 0; + } else if (updating_mob == 0) { + pr("Mobility updating is already off.\n\r"); + pr("Mobility updating will come back on around %s", + ctime(×tamps.starttime)); + pr("within 3 minutes, depending on when the server checks."); + } + } + + return 0; +} diff --git a/src/lib/commands/mora.c b/src/lib/commands/mora.c new file mode 100644 index 00000000..055ec142 --- /dev/null +++ b/src/lib/commands/mora.c @@ -0,0 +1,84 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * mora.c: Edit morale of a land unit + * + * Known contributors to this file: + * Jeff Bailey + */ + +#include "misc.h" +#include "player.h" +#include "var.h" +#include "xy.h" +#include "land.h" +#include "nsc.h" +#include "file.h" +#include "nat.h" +#include "deity.h" +#include "commands.h" + +extern int morale_base; + +int +morale(void) +{ + struct nstr_item np; + struct lndstr land; + struct natstr *natp; + int i,min; + s_char *p; + s_char mess[128]; + double techfact(int, double); + s_char buf[1024]; + + if (!snxtitem(&np, EF_LAND, player->argp[1])) + return RET_SYN; + while (!player->aborted && nxtitem(&np, (s_char *)&land)) { + if (!player->owner || land.lnd_own == 0) + continue; + natp=getnatp(land.lnd_own); + min = morale_base-(int)natp->nat_level[NAT_HLEV]; + sprintf(mess, "New retreat percentage for %s (min %d%%)? ", + prland(&land), min); + p = getstarg(player->argp[2], mess, buf); + if (!check_land_ok(&land)) + continue; + if (player->aborted) + continue; + if (!p || (i = atoi(p)) < 0) + continue; + land.lnd_retreat = ((i < min) ? min : i); + if (land.lnd_retreat > 100) + land.lnd_retreat = 100; + pr("Unit %d retreat percentage changed to %d\n", + land.lnd_uid, land.lnd_retreat); + putland(land.lnd_uid,&land); + } + + return RET_OK; +} diff --git a/src/lib/commands/move.c b/src/lib/commands/move.c new file mode 100644 index 00000000..fe67a8ee --- /dev/null +++ b/src/lib/commands/move.c @@ -0,0 +1,436 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * move.c: Move commodities around + * + * Known contributors to this file: + * + */ + +#include "misc.h" +#include "player.h" +#include "var.h" +#include "sect.h" +#include "item.h" +#include "file.h" +#include "deity.h" +#include "xy.h" +#include "nat.h" +#include "nsc.h" +#include "land.h" +#include "optlist.h" +#include "path.h" +#include "commands.h" + + +static int cmd_move_map(s_char *what, coord curx, coord cury, s_char *arg); + +int +move(void) +{ + register int amount; + struct sctstr sect; + struct sctstr endsect; + struct sctstr start; + struct sctstr tsct; + int packing; + double weight; + int left; + int mcost, dam; + int infected; + int stype; + int vtype; + int amt_src; + int amt_dst; + struct dchrstr *dp; + struct ichrstr *ip; + int work; + int loyal; + int own, mob; + int istest=0; + int n; + coord x, y; + s_char *p; + s_char prompt[1024]; + s_char buf[1024]; + + + istest = *player->argp[0] == 't'; + if ((ip = whatitem(player->argp[1], "move what? ")) == 0) + return RET_SYN; + vtype = ip->i_vtype; + if (!(p = getstarg(player->argp[2], "from sector : ", buf))) + return RET_SYN; + if (!sarg_xy(p, &x, &y)) + return RET_SYN; + if (!getsect(x, y, §) || !player->owner) { + pr("Not yours\n"); + return RET_FAIL; + } + /* + * military control necessary to move + * goodies in occupied territory. + */ + if (!istest && + sect.sct_oldown != player->cnum && + vtype != V_MILIT) { + int tot_mil=0; + struct nstr_item ni; + struct lndstr land; + snxtitem_xy(&ni, EF_LAND, sect.sct_x, sect.sct_y); + while (nxtitem(&ni, (s_char *)&land)){ + if (land.lnd_own == player->cnum) + tot_mil += total_mil(&land); + } + if ((getvar(V_MILIT, (s_char *)§, EF_SECTOR)+tot_mil) * 10 + < getvar(V_CIVIL, (s_char *)§, EF_SECTOR)) { + pr("Military control required to move goods.\n"); + return RET_FAIL; + } + } + stype = sect.sct_type; + dp = &dchr[stype]; + infected = getvar(V_PSTAGE, (s_char *)§, EF_SECTOR) == PLG_INFECT; + amt_src = getvar(vtype, (s_char *)§, EF_SECTOR); + if (!istest && amt_src <= 0) { + pr("No %s in %s\n", ip->i_name, + xyas(sect.sct_x, sect.sct_y, player->cnum)); + return RET_FAIL; + } + own = sect.sct_own; + mob = (int)sect.sct_mobil; + if (!istest && vtype == V_CIVIL && sect.sct_oldown != own) { + pr("You can't move conquered populace!\n"); + return RET_FAIL; + } + if (mob <= 0) { + pr("No mobility in %s\n", + xyas(sect.sct_x, sect.sct_y, player->cnum)); + return RET_SYN; + } + if (vtype == V_CIVIL) { + work = sect.sct_work; + if (work != 100) + pr("Warning: civil unrest\n"); + loyal = sect.sct_loyal; + } else if (vtype == V_MILIT) { + work = 100; + loyal = 0; + } + if (istest) + sprintf(prompt, "Number of %s to test move? ", ip->i_name); + else + sprintf(prompt, "Number of %s to move? (max %d) ", + ip->i_name, + amt_src); + if ((amount = onearg(player->argp[3], prompt)) < 0) + return RET_FAIL; + if (!check_sect_ok(§)) + return RET_FAIL; + if (amount > amt_src) { + if (istest) { + pr("Note: there are actually only %d %s in %s,\nbut the test will be made for %d %s as you requested.\n", + amt_src, ip->i_name, + xyas(sect.sct_x, sect.sct_y, player->cnum), + amount, ip->i_name); + } else { + amount = amt_src; + pr("Only moving %d.\n", amount); + } + } + + if (!want_to_abandon(§, vtype, amount, 0)) { + pr("Move cancelled.\n"); + return RET_FAIL; + } + + if (!check_sect_ok(§)) + return RET_FAIL; + + if (amount <= 0) + return RET_SYN; + packing = ip->i_pkg[dp->d_pkg]; + if (packing > 1 && sect.sct_effic < 60) + packing = 1; + weight = (double)amount * ip->i_lbs / packing; + /* + * First remove commodities from source sector + */ + if (!istest){ + getsect(x, y, &start); + if (start.sct_own != player->cnum) { + pr("Somebody has captured that sector!\n"); + return RET_FAIL; + } + amt_src = getvar(vtype, (s_char *)&start, EF_SECTOR); + if (amt_src < amount) { + pr("Only %d %s left in %s!\n", amt_src, + ip->i_name,xyas(start.sct_x,start.sct_y,player->cnum)); + amount = amt_src; + amt_src = 0; + }else + amt_src -= amount; + + putvar(vtype, amt_src, (s_char *)&start, EF_SECTOR); + start.sct_flags |= MOVE_IN_PROGRESS; + putsect(&start); + } + + /* + * Now parse the path and return ending sector. + */ + dam = (istest ? 0 : 1); + if (dam && !chance(weight / 200.0)) + dam = 0; + mcost = move_ground((s_char *)ip, §, &endsect, + (double)sect.sct_mobil, weight, player->argp[4], cmd_move_map, 0, &dam); + + if (dam) { + left = commdamage(amount, dam, ip->i_vtype); + if (left < amount) { + if (left) { + pr("%d of the %s you were moving were destroyed!\nOnly %d %s made it to %s\n", + amount - left, + ip->i_name, + left, + ip->i_name, + xyas(endsect.sct_x, endsect.sct_y, player->cnum)); + } else { + pr("All of the %s you were moving were destroyed!\n",ip->i_name); + } + amount = left; + } + } + + if (mcost > 0) + pr("Total movement cost = %d\n",mcost); + else + pr("No mobility used\n"); + + left=0; + if (mcost < 0) { + pr("Move aborted\n"); + getsect(x,y,§); + sect.sct_mobil = (u_char)mob; + left = mob; + } else if (!istest) { + /* + * decrement mobility appropriately. + */ + getsect(x, y, &start); + mob = start.sct_mobil; + if (mob < mcost) { + if (mob > 0) + mob = 0; + } else + mob -= mcost; + start.sct_mobil = (u_char)mob; + left = start.sct_mobil; + putsect(&start); + getsect(endsect.sct_x, endsect.sct_y, §); + } + + /* + * Check for lotsa stuff + */ + if (sect.sct_own != player->cnum) { + if (sect.sct_own != 0) + pr("Somebody has captured that sector!\n"); + getsect(x,y,§); + } + if (vtype == V_CIVIL && getvar(V_CIVIL, (s_char *)§, EF_SECTOR) && + sect.sct_oldown != player->cnum) { + pr("Your civilians don't want to stay!\n"); + getsect(x,y,§); + } + + amt_dst = getvar(vtype, (s_char *)§, EF_SECTOR); + if (32767 - amt_dst < amount) { + pr("Only enough room for %d in %s. The goods will be returned.\n", + 32767 - amt_dst, xyas(sect.sct_x, sect.sct_y, player->cnum)); + getsect(x,y,§); + } + + if (!istest) + pr("%d mob left in %s\n", left, + xyas(start.sct_x,start.sct_y,player->cnum)); + +/* If the sector that things are going to is no longer + owned by the player, and was the starting sector, + try to find somewhere to dump the stuff. If nowhere + to dump it, it disappears. */ + if (sect.sct_own != player->cnum && + sect.sct_x == x && sect.sct_y == y) { + pr("Can't return the goods, since the starting point is no longer\n"); + pr("owned by you.\n"); + /* First lets see if there is one with room */ + for (n = DIR_FIRST; n <= DIR_LAST; n++) { + getsect(x + diroff[n][0], y + diroff[n][1], &tsct); + if (tsct.sct_own != player->cnum) + continue; + amt_dst = getvar(vtype, (s_char *)&tsct, EF_SECTOR); + if (32767 - amt_dst < amount) + continue; + n = -1; + break; + } + if (n > -1) { + /* Find any sector if none with room */ + for (n = DIR_FIRST; n <= DIR_LAST; n++) { + getsect(x + diroff[n][0], y + diroff[n][1], &tsct); + if (tsct.sct_own != player->cnum) + continue; + n = -1; + break; + } + if (n > -1) { + pr("The goods had nowhere to go, and were destroyed.\n"); + sect.sct_flags &= ~MOVE_IN_PROGRESS; + putsect(§); + return RET_OK; + } + } + pr("The goods were dumped into %s.\n", + xyas(tsct.sct_x, tsct.sct_y, player->cnum)); + getsect(tsct.sct_x, tsct.sct_y, §); + } + + amt_dst = getvar(vtype, (s_char *)§, EF_SECTOR); + if (32767 - amt_dst < amount) { + amount = 32767 - amt_dst; + pr("Only room for %d, the rest were lost.\n", amount); + } + if (istest) + return RET_OK; + if (putvar(vtype, amount + amt_dst, (s_char *)§, EF_SECTOR) < 0) { + pr("No more room in %s. The goods were lost.\n", + xyas(sect.sct_x, sect.sct_y, player->cnum)); + /* charge the player mobility anyway */ + amount = 0; + } + /* + * Now add commodities to destination sector, + * along with plague that came along for the ride. + * Takeover unowned sectors if not deity. + */ + if (infected && getvar(V_PSTAGE, (s_char *)§, EF_SECTOR) == 0) + putvar(V_PSTAGE, PLG_EXPOSED, (s_char *)§, EF_SECTOR); + if (vtype == V_CIVIL) { + if (opt_NEW_WORK) { + sect.sct_loyal =( (amt_dst * sect.sct_loyal) + + (amount * loyal) ) / (amt_dst+amount); + sect.sct_work =( (amt_dst * sect.sct_work) + + (amount * work) ) / (amt_dst+amount); + } else { /* ! NEW_WORK */ + + /* It only takes one bad apple... */ + if (sect.sct_loyal < loyal) + sect.sct_loyal = loyal; + if (sect.sct_work > work) + sect.sct_work = work; + } /* end NEW_WORK */ + } + putsect(§); + getsect(x, y, &start); + start.sct_flags &= ~MOVE_IN_PROGRESS; + putsect(&start); + return RET_OK; +} + +/* + * Pretty tacky, but it works. + * If more commands start doing this, then + * rewrite map to do the right thing. + */ +/* I think this is no longer used, check subs/move.c:move_ground() */ +/*ARGSUSED*/ +static int +cmd_move_map(s_char *what, coord curx, coord cury, s_char *arg) +{ + player->argp[1] = arg; + player->argp[2] = ""; + player->argp[3] = ""; + player->argp[4] = ""; + player->argp[5] = ""; + player->condarg = 0; + return map(); +} + +int +want_to_abandon(struct sctstr *sp, int vtype, int amnt, struct lndstr *lp) +{ + char prompt[80]; + + /* First, would we be abandoning it? If not, just return that it's + ok to move out */ + if (!would_abandon(sp, vtype, amnt, lp)) + return 1; + + sprintf(prompt, "Do you really want to abandon %s [yn]? ", + xyas(sp->sct_x, sp->sct_y, player->cnum)); + + /* now, if they say yes that it's ok, just return 1 */ + if (askyn(prompt)) + return 1; + + /* Nope, not ok */ + return 0; +} + +int +would_abandon(struct sctstr *sp, int vtype, int amnt, struct lndstr *lp) +{ + struct sctstr sect; + int mil, civs, loyalcivs; + + if ((vtype != V_CIVIL) && (vtype != V_MILIT)) + return 0; + + bcopy((s_char *)sp,(s_char *)§,sizeof(struct sctstr)); + + mil = getvar(V_MILIT, (s_char *)sp, EF_SECTOR); + civs = getvar(V_CIVIL, (s_char *)sp, EF_SECTOR); + + if (vtype == V_MILIT) + mil -= amnt; + + if (vtype == V_CIVIL) + civs -= amnt; + + if (sp->sct_own == sp->sct_oldown) + loyalcivs = civs; + else + loyalcivs = 0; + + /* If they have a military unit there, they still own it */ + if (sp->sct_own != 0 && ((loyalcivs == 0) && (mil == 0) && + (has_units(sp->sct_x, sp->sct_y, sp->sct_own, lp) == 0))) + return 1; + + return 0; +} + diff --git a/src/lib/commands/mult.c b/src/lib/commands/mult.c new file mode 100644 index 00000000..3c22642e --- /dev/null +++ b/src/lib/commands/mult.c @@ -0,0 +1,122 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * mult.c: Set per-nation list of price multipliers + * + * Known contributors to this file: + * Dave Pare, 1986 + */ + +#include "misc.h" +#include "player.h" +#include "var.h" +#include "nat.h" +#include "file.h" +#include "xy.h" +#include "nsc.h" +#include "commands.h" +#include "optlist.h" +#include /* bailey@math-cs.kent.edu */ + +static void multsingle(natid us, natid them, struct natstr *natp); + +int +mult(void) +{ + struct nstr_item ni; + struct natstr nat; + int nats; + + if (!opt_MARKET) { + pr("The market is disabled.\n"); + return RET_FAIL; + } + pr("The mult command is no longer used.\n"); + if (!snxtitem(&ni, EF_NATION, player->argp[1])) + return RET_SYN; + if (commread() < 0) { + pr("Unable to read commodity file; get help!\n"); + return RET_SYS; + } + nats = 0; + while (!player->aborted && nxtitem(&ni, (s_char *)&nat)) { + if ((nat.nat_stat & STAT_NORM) == 0) + continue; + multsingle(player->cnum, (natid)ni.cur, &nat); + nats++; + } + pr("%d nation multipliers changed\n", nats); + return RET_OK; +} + +/* + * Set the multipler for a single country. + */ +static void +multsingle(natid us, natid them, struct natstr *natp) +{ + extern double minmult; + extern double maxmult; + double price; + s_char *p; + s_char prompt[128]; + s_char buf[1024]; + + sprintf(prompt, "%s (%7.3f) : ", natp->nat_cnam, multread(us, them)); + p = getstarg(player->argp[2], prompt, buf); + if (p == 0 || *p == 0) + return; + if ((price = atof(p)) == 0.0) + return; +#if defined(HUGE) + if ((price == HUGE) || (price > 1000000.0)) /* Inf causes overflow. */ +#else + if (price > 1000000.0) +#endif + price = 1000000.0; /* bailey@math-cs.kent.edu */ + /* + * no free lunches! + */ + if (price <= minmult) + price = minmult; + if (price >= maxmult) + price = maxmult; + if (!commlock()) { + pr("Unable to lock commodity file; get help!\n"); + return; + } + if (commread() < 0) { + (void) communlock(); + pr("Unable to re-read commodity file; get help!\n"); + return; + } + multset(them, price); + if (commwrite() < 0) { + pr("Unable to write out commodity file; get help!\n"); + } + (void) communlock(); +} diff --git a/src/lib/commands/name.c b/src/lib/commands/name.c new file mode 100644 index 00000000..ba12fa19 --- /dev/null +++ b/src/lib/commands/name.c @@ -0,0 +1,86 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * name.c: Name a ship + * + * Known contributors to this file: + * Jeff Bailey + */ + +#include "misc.h" +#include "player.h" +#include "var.h" +#include "sect.h" +#include "ship.h" +#include "xy.h" +#include "nsc.h" +#include "nat.h" +#include "deity.h" +#include "file.h" +#include "path.h" +#include "commands.h" +#include "optlist.h" + +/* + * name + */ +int +name(void) +{ + struct shpstr ship; + s_char *p; + struct nstr_item nb; + s_char buf[1024]; + + if (!opt_SHIPNAMES) { + pr("Ship naming is not enabled.\n"); + return RET_FAIL; + } + if (!snxtitem(&nb, EF_SHIP, player->argp[1])) + return RET_SYN; + while (nxtitem(&nb, (s_char *)&ship)) { + if (!player->owner) + continue; + p = getstarg(player->argp[2], "Name? ", buf); + if (!check_ship_ok(&ship)) + return RET_FAIL; + if (p == 0 || *p == 0) + return RET_SYN; + if (!strcmp(p,"~")) { + ship.shp_name[0] = 0; + } + else + { + strncpy(ship.shp_name,p,MAXSHPNAMLEN - 1); + ship.shp_name[MAXSHPNAMLEN - 1] = 0; + } + putship(ship.shp_uid,&ship); + } + + return RET_OK; +} + diff --git a/src/lib/commands/nati.c b/src/lib/commands/nati.c new file mode 100644 index 00000000..f79eb059 --- /dev/null +++ b/src/lib/commands/nati.c @@ -0,0 +1,125 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * nati.c: List nation information + * + * Known contributors to this file: + * + */ + +#include "misc.h" +#include "player.h" +#include "var.h" +#include "nat.h" +#include "sect.h" +#include "file.h" +#include "xy.h" +#include "optlist.h" +#include "commands.h" + +int +nati(void) +{ + extern int etu_per_update; + extern double obrate, uwbrate; + struct natstr *natp; + struct sctstr sect; + float hap; + int mil; + int civ; + int poplimit, safepop, uwpop; + double pfac; + + if ((natp = getnatp(player->cnum)) == 0) { + pr("Bad country number %d\n", player->cnum); + return RET_SYN; + } + pr("\n(#%i) %s Nation Report\t", player->cnum, cname(player->cnum)); + prdate(); + pr("Nation status is %s", natstate(natp)); + pr(" Bureaucratic Time Units: %d\n", natp->nat_btu); + if (natp->nat_stat & STAT_INUSE) { + getsect(natp->nat_xcap, natp->nat_ycap, §); + if (!player->owner || (sect.sct_type != SCT_CAPIT && + sect.sct_type != SCT_MOUNT && + sect.sct_type != SCT_SANCT)) + pr("No capital. (was at %s)\n", + xyas(sect.sct_x, sect.sct_y, player->cnum)); + else { + civ = getvar(V_CIVIL, (s_char *)§, EF_SECTOR); + mil = getvar(V_MILIT, (s_char *)§, EF_SECTOR); + pr("%d%% eff %s at %s has %d civilian%s & %d military\n", + sect.sct_effic, + (sect.sct_type == SCT_CAPIT ? "capital" : "mountain capital"), + xyas(sect.sct_x, sect.sct_y, player->cnum), civ, + splur(civ), mil); + } + } + pr(" The treasury has $%.2f", (double) natp->nat_money); + pr(" Military reserves: %d\n", natp->nat_reserve); + pr("Education..........%6.2f Happiness.......%6.2f\n", + (double) natp->nat_level[NAT_ELEV], + (double) natp->nat_level[NAT_HLEV]); + pr("Technology.........%6.2f Research........%6.2f\n", + (double) natp->nat_level[NAT_TLEV], + (double) natp->nat_level[NAT_RLEV]); + pr("Technology factor :%6.2f%%", tfact(player->cnum, 100.)); + + if (opt_NO_PLAGUE) + pfac = 0.0; + else + pfac = ((double) natp->nat_level[NAT_TLEV] + 100.) / + ((double) natp->nat_level[NAT_RLEV] + 100.); + pr(" Plague factor : %6.2f%%\n", pfac); + pr("\n"); + + poplimit = 999; + if (opt_RES_POP) + poplimit = max_pop(natp->nat_level[NAT_RLEV], 0); + pr("Max population : %d\n", poplimit); + + safepop = (int)((double)poplimit/(1.0 + obrate*(double)etu_per_update)); + uwpop = (int)((double)poplimit/(1.0 + uwbrate*(double)etu_per_update)); + safepop++; + if (((double)safepop*(1.0 + obrate*(double)etu_per_update)) > ((double)poplimit+0.0000001)) + safepop--; + uwpop++; + if (((double)uwpop*(1.0 + uwbrate*(double)etu_per_update)) > ((double)poplimit+0.0000001)) + uwpop--; + + pr("Max safe population for civs/uws: %d/%d\n",safepop,uwpop); + + hap = ((natp->nat_level[NAT_TLEV]-40)/40.0 + + natp->nat_level[NAT_ELEV]/3.0); + + if (hap > 0.0) + pr("Happiness needed is %f\n",hap); + else + pr("No happiness needed\n"); + + return RET_OK; +} diff --git a/src/lib/commands/navi.c b/src/lib/commands/navi.c new file mode 100644 index 00000000..1bb684ed --- /dev/null +++ b/src/lib/commands/navi.c @@ -0,0 +1,311 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * navi.c: Navigate ships and such + * + * Known contributors to this file: + * Ken Stevens, 1995 (rewritten) + */ + +#include +#include "misc.h" +#include "player.h" +#include "var.h" +#include "ship.h" +#include "sect.h" +#include "news.h" +#include "xy.h" +#include "nsc.h" +#include "nat.h" +#include "path.h" +#include "deity.h" +#include "file.h" +#include "map.h" +#include "commands.h" +#include "optlist.h" + +static int set_flagship(struct emp_qelem *list, struct shpstr **flagshipp); + +int +navi(void) +{ + struct nstr_item ni_ship; + struct emp_qelem ship_list; + double minmob, maxmob; + int together; + s_char *cp = 0; + struct shpstr *shp = 0; /* flagship */ + struct nstr_sect ns; + s_char origin; + int dir; + int stopping = 0; + int skip = 0; + s_char buf[1024]; + s_char prompt[128]; + s_char pathtaken[1024]; /* Doubtful we'll have a path longer than this */ + s_char *pt = pathtaken; + + if (!snxtitem(&ni_ship, EF_SHIP, player->argp[1])) + return RET_SYN; + shp_sel(&ni_ship, &ship_list); + shp_nav(&ship_list, &minmob, &maxmob, &together, player->cnum); + player->condarg = 0; /* conditions don't apply to nav_map() */ + if (QEMPTY(&ship_list)) { + pr("No ships\n"); + return RET_FAIL; + } + set_flagship(&ship_list, &shp); + if (player->argp[2]) { + strcpy(buf, player->argp[2]); + if (!(cp = shp_path(together, shp, buf))) + cp = player->argp[2]; + } + + *pt = '\0'; + while (!QEMPTY(&ship_list)) { + s_char *bp,dp[80]; + + if (cp == 0 || *cp == '\0' || stopping) { + stopping = 0; + shp_nav(&ship_list, &minmob, &maxmob, &together, player->cnum); + if (QEMPTY(&ship_list)) { + pr("No ships left\n"); + if (strlen(pathtaken) > 0) { + pathtaken[strlen(pathtaken)-1] = '\0'; + if (strlen(pathtaken) > 0) + pr("Path taken: %s\n", pathtaken); + } + return RET_OK; + } + if (set_flagship(&ship_list, &shp)) { + stopping = 1; + continue; + } + if (!skip) + nav_map(shp->shp_x, shp->shp_y, + !(mchr[(int)shp->shp_type].m_flags&M_SUB)); + else + skip=0; + sprintf(prompt, "<%.1f:%.1f: %s> ", maxmob, + minmob, xyas(shp->shp_x, shp->shp_y, player->cnum)); + cp = getstring(prompt, buf); + /* Just in case any of our ships were shelled while we were at the + * prompt, we call shp_nav() again. + */ + shp_nav(&ship_list, &minmob, &maxmob, &together, player->cnum); + if (QEMPTY(&ship_list)) { + pr("No ships left\n"); + if (strlen(pathtaken) > 0) { + pathtaken[strlen(pathtaken)-1] = '\0'; + if (strlen(pathtaken) > 0) + pr("Path taken: %s\n", pathtaken); + } + return RET_OK; + } + if (set_flagship(&ship_list, &shp)) { + stopping = 1; + continue; + } + } + radmapnopr(shp->shp_x, shp->shp_y, (int)shp->shp_effic, + (int)techfact(shp->shp_tech, + (double)mchr[(int)shp->shp_type].m_vrnge), + (double)((mchr[(int)shp->shp_type].m_flags + & M_SONAR) + ? techfact(shp->shp_tech, 1.0) : 0.0)); + if (cp == 0 || *cp == '\0') + cp = &dirch[DIR_STOP]; + if (*cp == 'M' || + *cp == 'B' || + *cp == 'f' || + *cp == 'i' || + *cp == 'm') { + ++cp; + if (cp[-1] == 'M') { + unit_map(EF_SHIP, shp->shp_uid, &ns, &origin); + draw_map(0, origin, MAP_SHIP, &ns, player->cnum); + skip = 1; + } else if (cp[-1] == 'B') { + unit_map(EF_SHIP, shp->shp_uid, &ns, &origin); + draw_map(EF_BMAP, origin, MAP_SHIP, &ns, player->cnum); + skip = 1; + } else if (cp[-1] == 'f') { + struct emp_qelem *qp; + qp = ship_list.q_back; + emp_remque(ship_list.q_back); + emp_insque(qp, &ship_list); + set_flagship(&ship_list, &shp); + } else if (cp[-1] == 'i') { + shp_list(&ship_list); + } else { + stopping |= shp_sweep(&ship_list, 1, player->cnum); + } + continue; + } else if (*cp == 'r' || + *cp == 'l' || + *cp == 's') { + bp=++cp; + while((*bp != ' ') && (*bp)) bp++; + while((*bp == ' ') && (*bp)) bp++; + if ((bp != (s_char *)0) && (*bp)) + player->argp[1] = bp; + else { + sprintf(dp,"%d",shp->shp_uid); + player->argp[1] = dp; + } + if (cp[-1] == 'r') { + rada(); + skip = 1; + } else if (cp[-1] == 'l') + look(); + else { + player->argp[2] = 0; + sona(); + skip = 1; + } + *cp = 0; + player->btused++; + continue; + } else { + dir = chkdir(*cp++, DIR_STOP, DIR_VIEW); + if (dir == -1) { + if (NULL != (cp = shp_path(together, shp, buf))) + continue; + direrr("`%c' to stop", ", `%c' to view, ", 0); + pr("`i' to list ships, `f' to change flagship,\n"); + pr("`r' to radar, `s' to sonar, `l' to look, `M' to map, `B' to bmap,\n"); + pr("and `m' to minesweep\n"); + stopping = 1; + continue; + } else if (dir == DIR_VIEW) { + shp_view(&ship_list); + continue; + } + } + stopping |= shp_nav_one_sector(&ship_list, dir, player->cnum, together); + if (stopping != 2) { + *pt++ = dirch[dir]; + *pt = '\0'; + } + } + if (strlen(pathtaken) > 0) { + pathtaken[strlen(pathtaken)-1] = '\0'; + if (strlen(pathtaken) > 0) + pr("Path taken: %s\n", pathtaken); + } + return RET_OK; +} + +int +nav_map(int x, int y, int show_designations) +{ + register s_char *ptr; + struct nstr_sect ns; + struct natstr *np; + struct sctstr sect; + struct range range; + int i; + /* Note this is not re-entrant anyway, so we keep the buffers + around */ + static u_char *bitmap = (u_char *)0; + static s_char *wmapbuf = (s_char *)0; + static s_char **wmap = (s_char **)0; + s_char what[64]; + int changed = 0; + + np = getnatp(player->cnum); + sprintf(what, "%d:%d,%d:%d",xrel(np,x-2),xrel(np,x+2),yrel(np,y-1), + yrel(np,y+1)); + if (!snxtsct(&ns, what)) + return RET_FAIL; + if (!wmapbuf) + wmapbuf = (s_char *)malloc((WORLD_Y * MAPWIDTH(1)) * sizeof(s_char)); + if (!wmap) { + wmap = (s_char **)malloc(WORLD_Y * sizeof(s_char *)); + if (wmap && wmapbuf) { + for (i = 0; i < WORLD_Y; i++) + wmap[i] = &wmapbuf[MAPWIDTH(1) * i]; + } else if (wmap) { + free((s_char *)wmap); + wmap = (s_char **)0; + } + } + if (!bitmap) + bitmap = (u_char *)malloc((WORLD_X * WORLD_Y) / 8); + if (!wmapbuf || !wmap || !bitmap) { + pr("Memory error, tell the deity.\n"); + logerror("malloc failed in navi\n"); + return RET_FAIL; + } + bzero((s_char *)bitmap, (WORLD_X * WORLD_Y) / 8); + /* zap any conditionals */ + ns.ncond = 0; + xyrelrange(np, &ns.range, &range); + blankfill((s_char *)wmapbuf, &ns.range, 1); + while (nxtsct(&ns, §)){ + ptr = &wmap[ns.dy][ns.dx]; + *ptr = dchr[sect.sct_type].d_mnem; + if (!show_designations && + sect.sct_own != player->cnum && + sect.sct_type != SCT_WATER && + sect.sct_type != SCT_BSPAN && + sect.sct_type != SCT_HARBR) + *ptr = '?'; + changed += map_set(player->cnum, sect.sct_x, sect.sct_y, *ptr, 0); + /* + * We do it this way so that 'x' and 'X' + * bdesignations will show up. This can + * be used to mark mined sectors. So, the + * player will see the current des, UNLESS + * they've marked the sector 'x' or 'X', + * in which case they'll see that. + * --ts + */ + *ptr = player->bmap[sctoff(sect.sct_x, sect.sct_y)]; + } + if (changed) + writemap(player->cnum); + for (i=0; i < ns.range.height; i++) + pr("%s\n", wmap[i]); + return RET_OK; +} + +static int +set_flagship(struct emp_qelem *list, struct shpstr **flagshipp) +{ + struct mlist *mlp = (struct mlist *)(list->q_back); + + if (!*flagshipp) + pr("Flagship is "); + else if ((*flagshipp)->shp_uid != mlp->ship.shp_uid) + pr("Changing flagship to "); + else + return 0; + *flagshipp = &mlp->ship; + pr("%s\n", prship(&mlp->ship)); + return 1; +} diff --git a/src/lib/commands/ndump.c b/src/lib/commands/ndump.c new file mode 100644 index 00000000..b02663cf --- /dev/null +++ b/src/lib/commands/ndump.c @@ -0,0 +1,92 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * ndump.c: Dump nuke information + * + * Known contributors to this file: + * John Yockey, 1997 + * Steve McClure, 1998 + */ + +#include "misc.h" +#include "player.h" +#include "var.h" +#include "sect.h" +#include "nuke.h" +#include "xy.h" +#include "nsc.h" +#include "nat.h" +#include "deity.h" +#include "file.h" +#include "commands.h" + +int +ndump(void) +{ + register int i; + struct nstr_item nstr; + struct nukstr nuk; + time_t now; + int nnukes; + + if (!snxtitem(&nstr, EF_NUKE, player->argp[1])) + return RET_SYN; + prdate(); + if (player->god) pr(" "); + time(&now); + pr("DUMP NUKES %d\n", now); + if (player->god) pr("own "); + pr("id x y num type\n"); + nnukes = 0; + while (nxtitem(&nstr, (s_char *)&nuk)) { + if (!player->god && !player->owner) + continue; + if (nuk.nuk_own == 0) + continue; + nnukes++; + for (i = 0; i < N_MAXNUKE; i++) { + if (nuk.nuk_types[i] > 0) { + if (player->god) pr("%3d ", nuk.nuk_own); + pr("%d ", nuk.nuk_uid); + prxy("%d %d", nuk.nuk_x, nuk.nuk_y, player->cnum); + pr(" %d", nuk.nuk_types[i]); + pr(" %0.5s", nchr[i].n_name); + pr("\n"); + } + } + } + if (nnukes == 0) { + if (player->argp[1]) + pr("%s: No nuke(s)\n", player->argp[1]); + else + pr("%s: No nuke(s)\n", ""); + return RET_FAIL; + } else + pr("%d nuke%s\n", nnukes, splur(nnukes)); + + return RET_OK; +} diff --git a/src/lib/commands/new.c b/src/lib/commands/new.c new file mode 100644 index 00000000..409b4bba --- /dev/null +++ b/src/lib/commands/new.c @@ -0,0 +1,396 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * new.c: Create a new capital for a player + * + * Known contributors to this file: + * Dave Pare, 1986 + */ + +#include "misc.h" +#include "player.h" +#include "var.h" +#include "nat.h" +#include "sect.h" +#include "path.h" +#include "file.h" +#include "xy.h" +#include "tel.h" +#include "land.h" +#include "nsc.h" +#include "options.h" +#include "optlist.h" +#include "commands.h" + + +#include + +extern float start_education, start_happiness; +extern float start_technology, start_research; +extern int morale_base; + +static void ok(s_char *map, int x, int y); +static int isok(int x, int y); + +static struct range defrealm = {-8, -5, 10, 5, 0, 0}; + +#define MAXAVAIL 300 + +int +new(void) +{ + extern int max_btus; + extern int players_at_00; + extern int at_least_one_100; +#ifdef START_UNITS + extern int start_unit_type[START_UNITS]; +#endif /* START_UNITS */ + struct sctstr sect; + struct natstr *natp; + struct boundstr newrealms; + struct range absrealm; + natid num; + time_t now; + coord x, y; + int i; + s_char *p; + int n; + extern int startmob; + s_char buf[1024]; + + natp = getnatp(player->cnum); + if (natp->nat_xorg != 0 || natp->nat_yorg != 0) { + pr("Must be at 0,0 to add a new country\n"); + return 0; + } + if ((n = natarg(player->argp[1], "Country? ")) < 0) { + pr("Bad country number\n"); + return 0; + } + num = n; + natp = getnatp(num); + if ((natp->nat_stat & STAT_NEW) == 0) { + pr("Country #%d (%s) isn't a new country!\n", + num, cname(num)); + return RET_SYN; + } + if (player->argp[2] != 0) { + if ((p = getstarg(player->argp[2], "sanctuary pair : ", buf)) == 0) + return RET_SYN; + if (!sarg_xy(p, &x, &y) || !getsect(x, y, §)) + return RET_SYN; + if (sect.sct_type != SCT_RURAL) { + pr("%s is a %s; try again...\n", + xyas(x, y, player->cnum), dchr[sect.sct_type].d_name); + return RET_SYN; + } + getsect(x + 2, y, §); + if (sect.sct_type != SCT_RURAL) { + pr("%s is a %s; try again...\n", + xyas(x, y, player->cnum), dchr[sect.sct_type].d_name); + return RET_SYN; + } + } else { + (void) time(&now); +#if !defined(_WIN32) + (void) srandom(now); +#else + (void) srand(now); +#endif + for (i = 0; i < 300 && !player->aborted; i++) { + /* Both x and y should be either odd or even */ + x = (random() % WORLD_X)-(WORLD_X/2); + y = (((random() % WORLD_Y)-(WORLD_Y/2)) & ~1) | (x & 1); + /* + * If either of the two potential + * sanctuary sectors are already + * owned by someone else, pick + * another place on the map. + */ + getsect(x, y, §); + if (sect.sct_type == SCT_WATER || sect.sct_own != 0) + continue; + getsect(x+2, y, §); + if (sect.sct_type == SCT_WATER || sect.sct_own != 0) + continue; + if (isok(x, y)) + break; + } + if (i == 300) { + pr("couldn't find an empty slot!\n"); + return RET_FAIL; + } + } + + if (player->aborted) + return RET_FAIL; + pr("added country %d at %s\n", num, xyas(x, y, player->cnum)); + getsect(x, y, §); + sect.sct_own = num; + sect.sct_type = SCT_SANCT; + sect.sct_newtype = SCT_SANCT; + sect.sct_effic = 100; + sect.sct_road = 0; + sect.sct_rail = 0; + sect.sct_defense = 0; + if (!opt_DEFENSE_INFRA) + sect.sct_defense = sect.sct_effic; + sect.sct_mobil = startmob; + sect.sct_work = 100; + sect.sct_oldown = num; + if (at_least_one_100) { + sect.sct_oil = 100; + sect.sct_fertil = 100; + sect.sct_uran = 100; + sect.sct_min = 100; + sect.sct_gmin = 100; + } + if (opt_RES_POP) + putvar(V_CIVIL, 550, (s_char *)§, EF_SECTOR); + else + putvar(V_CIVIL, 999, (s_char *)§, EF_SECTOR); + putvar(V_MILIT, 55, (s_char *)§, EF_SECTOR); + putvar(V_FOOD, 1000, (s_char *)§, EF_SECTOR); + putvar(V_UW, 75, (s_char *)§, EF_SECTOR); + putsect(§); + getsect(x + 2, y, §); + sect.sct_own = num; + sect.sct_type = SCT_SANCT; + sect.sct_newtype = SCT_SANCT; + sect.sct_effic = 100; + sect.sct_road = 0; + sect.sct_rail = 0; + sect.sct_defense = 0; + if (!opt_DEFENSE_INFRA) + sect.sct_defense = sect.sct_effic; + sect.sct_work = 100; + sect.sct_oldown = num; + sect.sct_mobil = startmob; + if (at_least_one_100) { + sect.sct_oil = 100; + sect.sct_fertil = 100; + sect.sct_uran = 100; + sect.sct_min = 100; + sect.sct_gmin = 100; + } + if (opt_RES_POP) + putvar(V_CIVIL, 550, (s_char *)§, EF_SECTOR); + else + putvar(V_CIVIL, 999, (s_char *)§, EF_SECTOR); + putvar(V_FOOD, 100, (s_char *)§, EF_SECTOR); + putvar(V_MILIT, 55, (s_char *)§, EF_SECTOR); + putvar(V_UW, 75, (s_char *)§, EF_SECTOR); + putsect(§); + natp->nat_btu = max_btus; + natp->nat_stat &= ~STAT_NEW; + natp->nat_stat |= STAT_SANCT; + natp->nat_xstart = x; + natp->nat_ystart = y; + natp->nat_xcap = x; + natp->nat_ycap = y; + if (players_at_00) { + natp->nat_xorg = 0; + natp->nat_yorg = 0; + } else { + natp->nat_xorg = x; + natp->nat_yorg = y; + } + xyabsrange(natp, &defrealm, &absrealm); + newrealms.b_xl = absrealm.lx; + newrealms.b_xh = absrealm.hx; + newrealms.b_yl = absrealm.ly; + newrealms.b_yh = absrealm.hy; + natp->nat_money = START_CASH; + natp->nat_level[NAT_HLEV] = start_happiness; + natp->nat_level[NAT_RLEV] = start_research; + natp->nat_level[NAT_TLEV] = start_technology; + natp->nat_level[NAT_ELEV] = start_education; + for (i = 0; i < MAXNOR; i++) + natp->nat_b[i] = newrealms; + natp->nat_tgms = 0; + (void) close(open(mailbox(buf, num), O_RDWR|O_TRUNC|O_CREAT, 0660)); +#ifdef START_UNITS + for(n=0;ncnum), nowned, nfree, navail); + pr("min: %d, oil: %d, gold: %d, uranium: %d\n", + nmin, noil, ngold, nur); + p = getstring("This setup ok? ", buf); + if (p == 0 || *p != 'y') + return 0; + return 1; +} + +static void +ok(s_char *map, int x, int y) +{ + struct sctstr sect; + int dir; + int id; + + if (navail > MAXAVAIL) + return; + id = sctoff(x, y); + if (map[id]) + return; + if (!ef_read(EF_SECTOR, id, (s_char *)§)) + return; + if (sect.sct_type == SCT_WATER || sect.sct_type == SCT_BSPAN) + return; + navail++; + if (navail >= MAXAVAIL) { + pr("At least %d...\n", MAXAVAIL); + return; + } + if (sect.sct_type != SCT_MOUNT && + sect.sct_type != SCT_PLAINS) { + if (sect.sct_own == 0) + nfree++; + else + nowned++; + if (sect.sct_min > 9) + nmin++; + if (sect.sct_gmin > 9) + ngold++; + if (sect.sct_uran > 9) + nur++; + if (sect.sct_oil > 9) + noil++; + } + map[id] = 1; + for (dir = DIR_FIRST; dir <= DIR_LAST; dir++) + ok(map, diroff[dir][0] + x, diroff[dir][1] + y); +} + +int +deity_build_land(int type, coord x, coord y, natid own, int tlev) +{ + extern int land_mob_max; + struct lndstr land; + struct lchrstr *lp; + struct nstr_item nstr; + struct natstr *natp; + double techfact(int, double); + int lvec[I_MAX+1]; + int extend = 1; + + natp = getnatp(own); + + snxtitem_all(&nstr, EF_LAND); + while (nxtitem(&nstr, (s_char *)&land)) { + if (land.lnd_own == 0) { + extend = 0; + break; + } + } + if (extend) + ef_extend(EF_LAND, 50); + land.lnd_x = x; + land.lnd_y = y; + land.lnd_own = own; + land.lnd_mission = 0; + land.lnd_type = type; + land.lnd_effic = 100; + land.lnd_mobil = land_mob_max; + land.lnd_sell = 0; + land.lnd_tech = tlev; + land.lnd_uid = nstr.cur; + land.lnd_army = ' '; + land.lnd_flags = 0; + land.lnd_ship = -1; + land.lnd_land = -1; + land.lnd_nland = 0; + land.lnd_harden = 0; + time(&land.lnd_access); + + land.lnd_retreat = morale_base; + + lp = &lchr[type]; + land.lnd_fuel = lp->l_fuelc; + land.lnd_nxlight = 0; + land.lnd_rflags = 0; + bzero((s_char *)land.lnd_rpath,10); + land.lnd_rad_max = lp->l_rad; + land.lnd_nv = 0; + + land.lnd_att = (float)LND_ATTDEF(lp->l_att, tlev - lp->l_tech); + land.lnd_def = (float)LND_ATTDEF(lp->l_def, tlev - lp->l_tech); + land.lnd_vul = (int)LND_VUL(lp->l_vul, tlev - lp->l_tech); + land.lnd_spd = (int)LND_SPD(lp->l_spd, tlev - lp->l_tech); + land.lnd_vis = (int)LND_VIS(lp->l_vis, tlev - lp->l_tech); + land.lnd_spy = (int)LND_SPY(lp->l_spy, tlev - lp->l_tech); + land.lnd_rad = (int)LND_RAD(lp->l_rad, tlev - lp->l_tech); + land.lnd_frg = (int)LND_FRG(lp->l_frg, tlev - lp->l_tech); + land.lnd_acc = (int)LND_ACC(lp->l_acc, tlev - lp->l_tech); + land.lnd_dam = (int)LND_DAM(lp->l_dam, tlev - lp->l_tech); + land.lnd_ammo = (int)LND_AMM(lp->l_ammo, lp->l_dam, tlev - lp->l_tech); + land.lnd_aaf = (int)LND_AAF(lp->l_aaf, tlev - lp->l_tech); + land.lnd_fuelc = (int)LND_FC(lp->l_fuelc, tlev - lp->l_tech); + land.lnd_fuelu = (int)LND_FU(lp->l_fuelu, tlev - lp->l_tech); + land.lnd_maxlight = (int)LND_XPL(lp->l_nxlight, tlev - lp->l_tech); + land.lnd_maxland = (int)LND_MXL(lp->l_mxland, tlev - lp->l_tech); + + bzero((s_char *)lvec, sizeof(lvec)); + getvec(VT_ITEM, lvec, (s_char *)&land, EF_LAND); + lvec[I_FOOD] += vl_find(V_FOOD,lp->l_vtype,lp->l_vamt,(int)lp->l_nv); + lvec[I_MILIT] = lp->l_mil; + putvec(VT_ITEM, lvec, (s_char *)&land, EF_LAND); + + putland(land.lnd_uid, &land); + makenotlost(EF_LAND, land.lnd_own, land.lnd_uid, land.lnd_x, land.lnd_y); + pr("%s", prland(&land)); + pr(" built in sector %s\n", xyas(x, y, player->cnum)); + return 1; +} diff --git a/src/lib/commands/newe.c b/src/lib/commands/newe.c new file mode 100644 index 00000000..dc72a667 --- /dev/null +++ b/src/lib/commands/newe.c @@ -0,0 +1,170 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * newe.c: Show new sector efficiency (projected) + * + * Known contributors to this file: + * Thomas Ruschak, 1993 + */ + +#include "misc.h" +#include "player.h" +#include "var.h" +#include "xy.h" +#include "nsc.h" +#include "sect.h" +#include "product.h" +#include "nat.h" +#include "item.h" +#include "file.h" +#include "commands.h" + +int +newe(void) +{ + extern double obrate, uwbrate; + extern int etu_per_update; + struct natstr *natp; + struct sctstr sect; + struct nstr_sect nstr; + double work, wforce, lcms, hcms; + int items[I_MAX+1]; + int nsect; + int civs=0; + int uws=0; + int bwork; + int twork; + int type; + int eff; + int maxpop; + + if (!snxtsct(&nstr, player->argp[1])) + return RET_SYN; + player->simulation = 1; + prdate(); + nsect = 0; + while (nxtsct(&nstr, §)) { + if (!player->owner) + continue; + if (!sect.sct_off) { + getvec(VT_ITEM, items, (s_char *)§, EF_SECTOR); + + civs = min(999, (int) ((obrate * (double) etu_per_update + 1.0) + * (double) items[I_CIVIL])); + uws = min(999, (int) ((uwbrate * (double) etu_per_update + 1.0) + * (double) items[I_UW])); + natp = getnatp(sect.sct_own); + maxpop = max_pop((float)natp->nat_level[NAT_RLEV], §); + civs = min(civs, maxpop); + uws = min(uws, maxpop); + /* This isn't quite right, since research might rise/fall */ + /* during the update, but it's the best we can really do */ + wforce = (int) + ((civs * sect.sct_work) / 100.0 + + uws + items[I_MILIT] * 2 / 5.0); + + work = etu_per_update * wforce / 100.0; + bwork = work/2; + + type = sect.sct_type; + eff = sect.sct_effic; + if(sect.sct_newtype != type) { + twork = (eff+3)/4; + if(twork > bwork) { + twork = bwork; + } + work -= twork; + bwork -= twork; + eff -= twork*4; + if(eff <= 0) { + type = sect.sct_newtype; + eff = 0; + } + + twork = 100 - eff; + if(twork > bwork) { + twork = bwork; + } + if (dchr[type].d_lcms>0){ + lcms = items[I_LCM]; + lcms = (int)(lcms/dchr[type].d_lcms); + if (twork > lcms) + twork = lcms; + } + if (dchr[type].d_hcms>0){ + hcms = items[I_HCM]; + hcms = (int)(hcms/dchr[type].d_hcms); + if (twork > hcms) + twork = hcms; + } + work -= twork; + eff += twork; + } + else if(eff < 100) { + twork = 100 - eff; + if(twork > bwork) { + twork = bwork; + } + if (dchr[type].d_lcms>0){ + lcms = items[I_LCM]; + lcms = (int)(lcms/dchr[type].d_lcms); + if (twork > lcms) + twork = lcms; + } + if (dchr[type].d_hcms>0){ + hcms = items[I_HCM]; + hcms = (int)(hcms/dchr[type].d_hcms); + if (twork > hcms) + twork = hcms; + } + work -= twork; + eff += twork; + } + } else { + eff = sect.sct_effic; + type = sect.sct_type; + } + if (nsect++ == 0) { + pr("EFFICIENCY SIMULATION\n"); + pr(" sect des projected eff\n"); + } + prxy("%4d,%-4d", nstr.x, nstr.y, player->cnum); + pr(" %c", dchr[type].d_mnem); + pr(" %3d%%\n", eff); + } + player->simulation = 0; + if (nsect == 0) { + if (player->argp[1]) + pr("%s: No sector(s)\n", player->argp[1]); + else + pr("%s: No sector(s)\n", ""); + return RET_FAIL; + }else + pr("%d sector%s\n", nsect, splur(nsect)); + return RET_OK; +} + diff --git a/src/lib/commands/news.c b/src/lib/commands/news.c new file mode 100644 index 00000000..7ebadf04 --- /dev/null +++ b/src/lib/commands/news.c @@ -0,0 +1,215 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * news.c: Show current Empire news + * + * Known contributors to this file: + * + */ + +#include "misc.h" +#include "player.h" +#include "nat.h" +#include "news.h" +#include "file.h" +#include "xy.h" +#include "nsc.h" +#include "deity.h" +#include "commands.h" +#include "optlist.h" + +static void preport(register struct nwsstr *np); + +int +news(void) +{ + extern s_char *page_headings[]; + struct natstr *natp; + time_t now; + int page; + time_t then; + time_t delta; + struct nwsstr nws; + struct nstr_item nstr; + int page_has_news[N_MAX_PAGE+1]; + int there_is_news = 0; + short sectors_taken[MAXNOC][MAXNOC]; + short sectors_delta; + short max_delta = -1; + short abs_delta; + short k; + int sectors_were_taken = 0; + natid i,j; + s_char num[128]; + s_char *verb; + + bzero((s_char *)page_has_news, sizeof(page_has_news)); + bzero((s_char *)sectors_taken, sizeof(sectors_taken)); + (void) head(); + (void) time(&now); + natp = getnatp(player->cnum); + then = natp->nat_newstim; + if (!opt_HIDDEN) { + if (player->argp[1] != 0 && isdigit(*player->argp[1])) { + delta = days(atoi(player->argp[1])); + then = now - delta; + } + } + natp->nat_newstim = now; +/* if (then < now - days(3)) + then = now - days(3); +*/ + snxtitem(&nstr, EF_NEWS, "*"); + pr("\nThe details of Empire news since %s", ctime(&then)); + while (nxtitem(&nstr, (s_char *)&nws)) { + if (nws.nws_when < then) + continue; + if (opt_HIDDEN) { + if (!player->god && + !(getcontact(getnatp(player->cnum), nws.nws_ano) && + getcontact(getnatp(player->cnum), nws.nws_vno))) + continue; + } + ++page_has_news[rpt[(int)nws.nws_vrb].r_newspage]; + ++there_is_news; + } + for (page = 1; page <= N_MAX_PAGE; page++) { + if (!page_has_news[page]) + continue; + pr("\n\t === %s ===\n", page_headings[page]); + snxtitem_rewind(&nstr); + while (nxtitem(&nstr, (s_char *)&nws)) { + if (rpt[(int)nws.nws_vrb].r_newspage != page) + continue; + if (nws.nws_when < then) + continue; + if (nws.nws_ntm == 0) + nws.nws_ntm = 1; + if (opt_HIDDEN) { + if (!player->god && + !(getcontact(getnatp(player->cnum), nws.nws_ano) && + getcontact(getnatp(player->cnum), nws.nws_vno))) + continue; + } + if (page == N_FRONT && + (nws.nws_vrb == N_WON_SECT || + nws.nws_vrb == N_AWON_SECT || + nws.nws_vrb == N_PWON_SECT)) { + sectors_taken[nws.nws_ano][nws.nws_vno] += nws.nws_ntm; + sectors_were_taken += nws.nws_ntm; + } + preport(&nws); + } + } + if (sectors_were_taken) { + for (i = 0; i < MAXNOC; ++i) { + for (j = 0; j < i; ++j) { + sectors_delta = sectors_taken[i][j] - + sectors_taken[j][i]; + if (max_delta < abs(sectors_delta)) + max_delta = abs(sectors_delta); + } + } + pr("\n\t === The Bottom Line ==\n"); + for (k = max_delta; k > 0; --k) { + for (i = 0; i < MAXNOC; ++i) { + for (j = 0; j < i; ++j) { + sectors_delta = sectors_taken[i][j] - + sectors_taken[j][i]; + abs_delta = abs(sectors_delta); + if (abs_delta != k) + continue; + if (abs_delta == 1) + verb = "stole"; + else if (abs_delta < 4) + verb = "took"; + else if (abs_delta < 8) + verb = "captured"; + else + verb = "seized"; + if (sectors_delta > 0) { + numstr(num, abs_delta); + pr("%s %s %s sector%s from %s\n", cname(i), verb, num, splur(sectors_delta), cname(j)); + } else if (sectors_delta < 0) { + numstr(num, abs_delta); + pr("%s %s %s sector%s from %s\n", cname(j), verb, num, splur(-sectors_delta), cname(i)); + } + } + } + } + } + if (!there_is_news) + pr("\nNo news at the moment...\n"); + return 0; +} + +static void +preport(register struct nwsstr *np) +{ + register s_char *cp; + register int i; + s_char buf[255]; + s_char num[128]; + s_char *ptr; + + cp = buf; + sprintf(buf, "%-16.16s ", ctime(&np->nws_when)); + cp += strlen(cp); + ptr = numstr(num, np->nws_ntm); + /* + * vary the order of the printing of "%d times " + */ + if ((random() & 3) == 0 && np->nws_ntm > 1) { + sprintf(cp, "%s times ", ptr); + cp += strlen(cp); + np->nws_ntm = 1; + } + strcpy(cp, cname(np->nws_ano)); + cp += strlen(cp); + *cp++ = ' '; + if (np->nws_vrb < 1 || np->nws_vrb > N_MAX_VERB) + np->nws_vrb = 0; + sprintf(cp, rpt[(int)np->nws_vrb].r_newstory[random() % NUM_RPTS], + cname(np->nws_vno)); + cp += strlen(cp); + if (np->nws_ntm != 1) { + sprintf(cp, " %s times", ptr); + cp += strlen(cp); + } + if (*buf >= 'a' && *buf <= 'z') + *buf += 'A' - 'a'; + if (cp - buf > 80) { + for (i=80; --i > 60; ) + if (buf[i] == ' ') break; + buf[i] = '\0'; + pr("%s\n\t\t %s\n", buf, &buf[i+1]); + } else { + pr("%s\n", buf); + } + np->nws_ntm = 0; + return; +} diff --git a/src/lib/commands/nuke.c b/src/lib/commands/nuke.c new file mode 100644 index 00000000..c1092309 --- /dev/null +++ b/src/lib/commands/nuke.c @@ -0,0 +1,110 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * nuke.c: Display a listing of your nuclear arsenal + * + * Known contributors to this file: + * Dave Pare, 1986 + */ + +#include "misc.h" +#include "player.h" +#include "var.h" +#include "sect.h" +#include "nuke.h" +#include "xy.h" +#include "nsc.h" +#include "nat.h" +#include "deity.h" +#include "file.h" +#include "commands.h" + +int +nuke(void) +{ + register int first_line = 0; + register int first_nuke; + register int show_comm; + register int i; + struct nstr_item nstr; + struct nukstr nuk; + struct sctstr sect; + int item[I_MAX+1]; + + if (!snxtitem(&nstr, EF_NUKE, player->argp[1])) + return RET_SYN; + + while (nxtitem(&nstr, (s_char *)&nuk)) { + if (!player->god && !player->owner) + continue; + if (nuk.nuk_own == 0) + continue; + if (first_line++ == 0) { + if (player->god) + pr("own "); + pr(" sect eff num nuke-type lcm hcm oil rad avail\n"); + } + getsect(nuk.nuk_x, nuk.nuk_y, §); + getvec(VT_ITEM, item, (s_char *)§, EF_SECTOR); + first_nuke = 1; + show_comm = 0; + if (sect.sct_type == SCT_NUKE && sect.sct_effic >= 60) + show_comm = 1; + for (i = 0; i < N_MAXNUKE; i++) { + if (nuk.nuk_types[i] > 0) { + if (first_nuke) { + if (player->god) + pr("%-3d ", nuk.nuk_own); + prxy("%4d,%-4d", sect.sct_x, sect.sct_y, player->cnum); + pr(" %c", dchr[sect.sct_type].d_mnem); + if (sect.sct_newtype != sect.sct_type) + pr("%c", dchr[sect.sct_newtype].d_mnem); + else + pr(" "); + pr("%4d%%", sect.sct_effic); + first_nuke = 0; + } else { + pr(" "); + } + + pr("%3d ", nuk.nuk_types[i]); + pr("%-16.16s ", nchr[i].n_name); + + if (show_comm) { + pr("%5d ", item[I_LCM]); + pr("%5d ", item[I_HCM]); + pr("%5d ", item[I_OIL]); + pr("%5d ", item[I_RAD]); + pr("%5d", sect.sct_avail); + show_comm = 0; + } + pr("\n"); + } + } + } + return RET_OK; +} diff --git a/src/lib/commands/offe.c b/src/lib/commands/offe.c new file mode 100644 index 00000000..3af0c4c4 --- /dev/null +++ b/src/lib/commands/offe.c @@ -0,0 +1,245 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * offe.c: Offer a loan or treaty + * + * Known contributors to this file: + * Pat Loney, 1992 + * Steve McClure, 1996 + */ + +#include "misc.h" +#include "player.h" +#include "xy.h" +#include "nsc.h" +#include "nat.h" +#include "loan.h" +#include "treaty.h" +#include "file.h" +#include "commands.h" +#include "optlist.h" + +static int do_treaty(void); +static int do_loan(void); + +int +offe(void) +{ + register s_char *cp; + s_char buf[1024]; + + if (!(cp = getstarg(player->argp[1], "loan or treaty? ", buf)) || !*cp) + return RET_SYN; + + switch (*cp) { + case 'l': + if (!opt_LOANS) { + pr("Loans are not enabled.\n"); + return RET_FAIL; + } + return do_loan(); + case 't': + if (!opt_TREATIES) { + pr("Treaties are not enabled.\n"); + return RET_FAIL; + } + return do_treaty(); + default: + pr("You must specify \"loan\" as there are no treaties.\n"); + return RET_SYN; + } +} + +static int +do_treaty(void) +{ + register s_char *cp; + register int ourcond; + register int theircond; + register int j; + struct tchrstr *tcp; + struct trtstr trty; + struct nstr_item nstr; + natid recipient; + time_t now; + int n; + struct natstr *natp; + s_char prompt[128]; + s_char buf[1024]; + + if ((n = natarg(player->argp[2], "Treaty offered to? ")) < 0) + return RET_SYN; + recipient = n; + if (recipient == player->cnum) { + pr("You can't sign a treaty with yourself!\n"); + return RET_FAIL; + } + natp = getnatp(recipient); + if (player->cnum && (getrejects(player->cnum,natp) & REJ_TREA)) { + pr("%s is rejecting your treaties.\n", + cname(recipient)); + return RET_SYN; + } + pr("Terms for %s:\n", cname(recipient)); + theircond = 0; + for (tcp = tchr; tcp && tcp->t_cond; tcp++) { + sprintf(prompt, "%s? ", tcp->t_name); + if ((cp = getstring(prompt, buf)) == 0) + return RET_FAIL; + if (*cp == 'y') + theircond |= tcp->t_cond; + } + pr("Terms for you:\n"); + ourcond = 0; + for (tcp = tchr; tcp && tcp->t_cond; tcp++) { + sprintf(prompt, "%s? ", tcp->t_name); + if ((cp = getstring(prompt, buf)) == 0) + return RET_FAIL; + if (*cp == 'y') + ourcond |= tcp->t_cond; + } + if (ourcond == 0 && theircond == 0) { + pr("Treaties with no clauses aren't very useful, boss!\n"); + return RET_SYN; + } + cp = getstring("Proposed treaty duration? (days) ", buf); + if (cp == 0) + return RET_FAIL; + j = atopi(cp); + if (j == 0) { + pr("Bad treaty duration.\n"); + return RET_SYN; + } + (void) time(&now); + snxtitem_all(&nstr,EF_TREATY); + while (nxtitem(&nstr, (s_char *)&trty)) { + if (trty.trt_status == TS_FREE) { + break; + } + } + trty.trt_acond = ourcond; + trty.trt_bcond = theircond; + trty.trt_status = TS_PROPOSED; + trty.trt_cna = player->cnum; + trty.trt_cnb = recipient; + trty.trt_exp = j * SECS_PER_DAY + now; + if (!puttre(nstr.cur,&trty)) { + pr("Couldn't save treaty; get help.\n"); + return RET_SYS; + } + wu(0, recipient, "Treaty #%d proposed to you by %s\n", + nstr.cur, cname(player->cnum)); + pr("You have proposed treaty #%d\n", nstr.cur); + return RET_OK; +} + +static int +do_loan(void) +{ + register int amt, irate, dur, maxloan; + struct nstr_item nstr; + struct natstr *natp; + struct lonstr loan; + natid recipient; + int n; + s_char prompt[128]; + + if ((n = natarg(player->argp[2], "Lend to? ")) < 0) + return RET_SYN; + recipient = n; + if (recipient == player->cnum) { + pr("You can't loan yourself money!\n"); + return RET_FAIL; + } + natp = getnatp(recipient); + if (player->cnum && (getrejects(player->cnum,natp) & REJ_LOAN)) { + pr("%s is rejecting your loans.\n", + cname(recipient)); + return RET_SYN; + } + natp = getnatp(player->cnum); + if (natp->nat_money + 100 > MAXLOAN) + maxloan = MAXLOAN; + else + maxloan = natp->nat_money - 100; + if (maxloan < 0) { + pr("You don't have enough money to loan!\n"); + return RET_FAIL; + } + sprintf(prompt, "Size of loan for country #%d? (max %d) ", + recipient, maxloan); + amt = onearg(player->argp[3], prompt); + if (amt <= 0) + return RET_FAIL; + if (amt > MAXLOAN) { + pr("You can only loan $%d at a time.\n",MAXLOAN); + return RET_FAIL; + } + if (amt > maxloan) { + pr("You can't afford that much.\n"); + return RET_FAIL; + } + dur = onearg(player->argp[4], "Duration? (days, max 7) "); + if (dur <= 0) + return RET_FAIL; + if (dur >7) return RET_FAIL; + irate = onearg(player->argp[5], "Interest rate? (from 5 to 25%) "); + if (irate >25) return RET_FAIL; + if (irate < 5) + return RET_FAIL; + snxtitem_all(&nstr, EF_LOAN); + while (nxtitem(&nstr, (s_char *) &loan)) { + if ((loan.l_status == LS_SIGNED) && (loan.l_lonee == player->cnum) && + (loan.l_loner == recipient)) { + pr("You already owe HIM money - how about repaying your loan?\n"); + return RET_FAIL; + } + } + snxtitem_all(&nstr, EF_LOAN); + while (nxtitem(&nstr, (s_char *) &loan)) { + if (loan.l_status == LS_FREE) + break; + } + loan.l_loner = player->cnum; + loan.l_lonee = recipient; + loan.l_status = LS_PROPOSED; + loan.l_irate = min(irate, 127); + loan.l_ldur = min(dur, 127); + loan.l_amtpaid = 0; + loan.l_amtdue = amt; + (void) time(&loan.l_lastpay); + loan.l_duedate = loan.l_ldur * SECS_PER_DAY + loan.l_lastpay; + loan.l_uid = nstr.cur; + if (!putloan(nstr.cur, &loan)) { + pr("Couldn't save loan; get help!\n"); + return RET_SYS; + } + pr("You have offered loan %d\n", nstr.cur); + wu(0, recipient, "Country #%d has offered you a loan (#%d)\n", + player->cnum, nstr.cur); + return RET_OK; +} diff --git a/src/lib/commands/offs.c b/src/lib/commands/offs.c new file mode 100644 index 00000000..c2698a1d --- /dev/null +++ b/src/lib/commands/offs.c @@ -0,0 +1,80 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * offs.c: Diety set mapping offset. + * + * Known contributors to this file: + * + */ + +#include +#include "misc.h" +#include "player.h" +#include "file.h" +#include "nat.h" +#include "commands.h" + +int +offs(void) +{ + register int i; + struct natstr *natp; + coord xorg, yorg; + coord dx, dy; + s_char *cp; + struct natstr *np; + s_char buf[1024]; + + natp = getnatp(player->cnum); + xorg = natp->nat_xorg; + yorg = natp->nat_yorg; + if (!(cp = getstarg(player->argp[1], "sector or nation? ", buf))) + return RET_SYN; + if (index(cp, ',')) { /* x, y pair for offset */ + if (!sarg_xy(cp, &dx, &dy)) { + pr("Bad sector designation.\n"); + return RET_SYN; + } + xorg = dx; + yorg = dy; + } else { + /* actually nation name */ + if ((i = natarg(cp, (s_char *)0)) < 0) + return RET_SYN; + np = getnatp(i); + xorg = np->nat_xorg; + yorg = np->nat_yorg; + } + np = getnatp(player->cnum); + /* NOTE: it's OK to use %d,%d here, because we want abs coords */ + pr("Old offset was %d,%d\n", np->nat_xorg, np->nat_yorg); + np->nat_xorg = xorg; + np->nat_yorg = yorg; + putnat(np); + pr("New offset was %d,%d\n", xorg, yorg); + return RET_OK; +} diff --git a/src/lib/commands/orde.c b/src/lib/commands/orde.c new file mode 100644 index 00000000..d2378137 --- /dev/null +++ b/src/lib/commands/orde.c @@ -0,0 +1,536 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * orde.c: Turn on/off autonavigation + * + * Known contributors to this file: + * Chad Zabel, 1994 + * Steve McClure, 2000 + */ + +#ifdef Rel4 +#include +#endif /* Rel4 */ +#include +#include "misc.h" +#include "player.h" +#include "var.h" +#include "ship.h" +#include "sect.h" +#include "news.h" +#include "xy.h" +#include "nsc.h" +#include "nat.h" +#include "path.h" +#include "deity.h" +#include "file.h" +#include "item.h" +#include "commands.h" +#include "optlist.h" + +/* +** Command syntax: +** +** ORDER Show orders +** ORDER c[ancel] Cancel orders +** ORDER s[top] Suspend orders +** ORDER r[esume] Resume orders +** ORDER d[eclare] Set destination +** d[eclare] +** ORDER l[evel] +** +** +** New syntax: +** qorder display cargo levels +** sorder display statistical info + */ + +int +orde(void) +{ + int nships=0; + int diffeachship = 0; + int orders,sub,level; + int scuttling = 0; + struct nstr_item nb; + struct shpstr ship; + struct shpstr start; /* Used for checking database */ + struct ichrstr *i1; + coord p0x, p0y, p1x, p1y; + int i; + s_char *p,*p1, *dest; + s_char buf1[128]; + s_char buf[1024]; + s_char prompt[128]; + + if (!snxtitem(&nb, EF_SHIP, player->argp[1])) return RET_SYN; + while (!player->aborted && nxtitem(&nb, (s_char *)(&ship))) { + if (!player->owner || ship.shp_own == 0) + continue; + if (ship.shp_type < 0 || ship.shp_type > shp_maxno) { + pr("bad ship type %d (#%d)\n", + ship.shp_type, nb.cur); + continue; + } + if (opt_SAIL) { + if (*ship.shp_path) { + if (!diffeachship) + pr("Ship #%d has a \"sail\" path!\n", + ship.shp_uid); + continue; + } + } + memcpy(&start, &ship, sizeof(struct shpstr)); + sprintf(prompt, "Ship #%d, declare, cancel, suspend, resume, level? ", + ship.shp_uid); + p = getstarg(player->argp[2], prompt, buf); + if (player->aborted || !p) + return RET_FAIL; + if (!*p) { + if (!diffeachship) + return RET_FAIL; + else + continue; + } + switch (*p) { + default: + pr("Bad order type!\n"); + return RET_SYN; + case 'c': /* clear ship fields */ + ship.shp_mission = 0; + ship.shp_autonav &= ~(AN_AUTONAV+AN_STANDBY+AN_LOADING); + for (i=0;iargp[3],"Destination? ", buf))==0 || *p==0) + return RET_SYN; + if (!sarg_xy(p, &p0x, &p0y)) + return RET_SYN; + p1x = p0x; + p1y = p0y; + + + + if (!orders) { + p = getstarg(player->argp[4],"Second dest? ", buf); + if (!p || !*p || !strcmp (p, "-")) { + orders = 1; + pr("A one-way order has been accepted.\n"); + } else if (!strncmp(p, "s", 1)) { + if (opt_TRADESHIPS) { + if (!(mchr[(int)ship.shp_type].m_flags & M_TRADE)) { + pr("You can't auto-scuttle that ship!\n"); + return RET_SYN; + } + } else { + pr("You can't auto-scuttle that ship!\n"); + return RET_SYN; + } + pr("A scuttle order has been accepted.\n"); + scuttling = 1; + } else { + if (!sarg_xy(p, &p1x, &p1y)) + return RET_SYN; + pr("A circular order has been accepted.\n"); + } + } + + /* + * Set new destination and trade type fields. + */ + ship.shp_mission = 0; + ship.shp_destx[1] = p1x; + ship.shp_desty[1] = p1y; + ship.shp_destx[0] = p0x; + ship.shp_desty[0] = p0y; + + ship.shp_autonav &= ~(AN_STANDBY+AN_SAILDIR+AN_LOADING); + ship.shp_autonav |= AN_AUTONAV; + + if (scuttling) + ship.shp_autonav |= AN_SCUTTLE; + break; + + /* set cargo levels on the ship */ + + case 'l' : + /* convert player->argp[3] to an integer */ + if (player->argp[3]) + sub = atoi(player->argp[3]); + else { + sprintf(buf1,"Field (1-%d) ",TMAX); + if (getstarg(player->argp[3],buf1, buf) == 0) + return RET_SYN; + sub = atoi(buf); + } + /* check to make sure value in within range. */ + if (sub>TMAX || sub<1 ) { + pr("Value must range from 1 to %d\n",TMAX); + break; } + + /* to keep sub in range of our arrays + subtract 1 so the new range is 0-(TMAX-1) + */ + sub = sub - 1; ; + + if (ship.shp_autonav & AN_AUTONAV ) { + orders=1; + dest = getstarg(player->argp[4],"Start or End? ", buf); + if (orders) { /* before dest check */ + if (!dest) + break; + switch (*dest) { + default: + pr("You must enter 'start' or 'end'\n"); + return RET_SYN; + case 'e' : + case 'E' : + i1 = whatitem(player->argp[5],"Commodity? "); + if (!i1) + break; + else { + p1 = getstarg(player->argp[6],"Amount? ", buf); + if (!p1) + return RET_SYN; + level = atoi(p1); + } + if (level < 0) { + level = 0; /* prevent negatives. */ + pr("You must use positive number! Level set to 0.\n"); + } + ship.shp_tstart[sub] = (s_char)i1->i_mnem; + ship.shp_lstart[sub] = level; + pr("Order Set \n"); + break; + case 's' : + case 'S' : + i1 = whatitem(player->argp[5],"Commodity? "); + if (!i1) + break; + else { + p1 = getstarg(player->argp[6],"Amount? ", buf); + if (!p1) + return RET_SYN; + level = atoi(p1); + } + if (level < 0 ) { + level = 0; + pr("You must use positive number! Level set to 0.\n"); + } + ship.shp_tend[sub] = (s_char)i1->i_mnem; + ship.shp_lend[sub] = level; + pr("Order Set \n"); + break; + } + } + } + else + pr("You need to 'declare' a ship path first, see 'info order'\n"); + + break; + } /* end of switch (*p) */ + + + + /* + * Set loading flag if ship is already in one + * of the specified harbors and a cargo has been + * specified. + */ + + if ( ((ship.shp_x == ship.shp_destx[0]) + && (ship.shp_y == ship.shp_desty[0]) + && (ship.shp_lstart[0] != ' ')) + || ((ship.shp_x == ship.shp_desty[1]) + && (ship.shp_y == ship.shp_desty[1]) + && (ship.shp_lstart[1] != ' ')) ) { + + coord tcord; + s_char tcomm[TMAX]; + short lev[TMAX]; + int i; + + ship.shp_autonav |= AN_LOADING; + + /* swap variables, this keeps + the load_it() procedure happy. CZ + */ + tcord = ship.shp_destx[0]; + ship.shp_destx[0] = ship.shp_destx[1]; + ship.shp_destx[1] = tcord; + tcord = ship.shp_desty[0]; + ship.shp_desty[0] = ship.shp_desty[1]; + ship.shp_desty[1] = tcord; + + for(i=0;ishp_type]; + mobcost = sp->shp_effic * 0.01 * sp->shp_speed; + mobcost = 480.0 / (mobcost + techfact(sp->shp_tech, mobcost)); + mobil = sp->shp_mobil; + while (i) { + if (mobil > 0) { + mobil -= mobcost; + i--; + } else { + mobil += (ship_mob_scale * (float)etu_per_update); + (*nupdates)++; + } + } +} + +int +qorde(void) +{ + int nships=0; + int i; + struct nstr_item nb; + struct shpstr ship; + + if (!snxtitem(&nb, EF_SHIP, player->argp[1])) return RET_SYN; + while (nxtitem(&nb, (s_char *)(&ship))) { + if (!player->owner || ship.shp_own==0) + continue; + if (ship.shp_type < 0 || ship.shp_type > shp_maxno) { + pr("bad ship type %d (#%d)\n", + ship.shp_type, nb.cur); + continue; + } + + if ((ship.shp_autonav & AN_AUTONAV) || + (ship.shp_path[0] && opt_SAIL)) { + if (!nships) { /* 1st ship, print banner */ + if (player->god) pr("own "); + pr("shp# ship type "); + pr("[Starting] (Ending) \n"); + } + nships++; + if (player->god) pr("%3d ", ship.shp_own); + pr("%4d", nb.cur); + pr(" %-16.16s", mchr[(int)ship.shp_type].m_name); + } + if (ship.shp_autonav & AN_AUTONAV){ + + pr(" ["); + for (i=0;igod) + pr(" "); + pr(" %s\n",ship.shp_name); + } + } + } + } + if (!nships) { + if (player->argp[1]) + pr("%s: No ship(s)\n", player->argp[1]); + else + pr("%s: No ship(s)\n", ""); + return RET_FAIL; + } else + pr("%d ship%s\n", nships, splur(nships)); + return RET_OK; +} +/* Chad Zabel 1-15-94 + * New command added to display autonav stats. + */ + +int +sorde(void) +{ + int nships=0; + int len, updates; + s_char *c; + struct nstr_item nb; + struct shpstr ship; + s_char buf[1024]; + + if (!snxtitem(&nb, EF_SHIP, player->argp[1])) return RET_SYN; + while (nxtitem(&nb, (s_char *)(&ship))) { + if (!player->owner || ship.shp_own==0) + continue; + if (ship.shp_type < 0 || ship.shp_type > shp_maxno) { + pr("bad ship type %d (#%d)\n", + ship.shp_type, nb.cur); + continue; + } + if ((ship.shp_autonav & AN_AUTONAV) || + (ship.shp_path[0] && opt_SAIL)) { + if (!nships) { /* 1st ship, print banner */ + if (player->god) pr("own "); + pr("shp# ship type x,y "); + pr("start end "); + pr("len eta\n"); + } + nships++; + if (player->god) pr("%3d ", ship.shp_own); + pr("%4d", nb.cur); + pr(" %-16.16s", mchr[(int)ship.shp_type].m_name); + prxy(" %3d,%-3d", ship.shp_x, ship.shp_y, player->cnum); + } + if (ship.shp_autonav & AN_AUTONAV){ + /* Destination 1 */ + prxy(" %3d,%-3d", ship.shp_destx[1], + ship.shp_desty[1], player->cnum); + + /* Destination 2 */ + if ( (ship.shp_destx[1]!=ship.shp_destx[0]) + || (ship.shp_desty[1]!=ship.shp_desty[0]) ) { + prxy(" %2d,%-2d",ship.shp_destx[0], + ship.shp_desty[0], player->cnum); + } else pr(" "); + + if (ship.shp_autonav & AN_STANDBY) + pr(" suspended"); + else if (ship.shp_autonav & AN_LOADING) + pr(" loading"); + else { + /* ETA calculation */ + + c = BestShipPath(buf, ship.shp_x, + ship.shp_y, ship.shp_destx[0], + ship.shp_desty[0], ship.shp_own); + if (!c || !*c) + pr("no route possible"); + else if (*c == 'h') + pr("has arrived"); + else if (*c == '?') + pr("route too long"); + else { + /* distance to destination */ + eta_calc(&ship, c, &len, &updates); + pr(" %3d %4d", len, updates); + } + } + if (ship.shp_autonav & AN_SCUTTLE) + pr(" (scuttling)"); + pr("\n"); + } + if (opt_SHIPNAMES) { + if ((ship.shp_autonav & AN_AUTONAV) || + (ship.shp_path[0] && opt_SAIL)) { + if (!(ship.shp_autonav & AN_AUTONAV)) + pr("\n"); + if (ship.shp_name[0] != 0) { + if (player->god) + pr(" "); + pr(" %s\n",ship.shp_name); + } + } + } + } + if (!nships) { + if (player->argp[1]) + pr("%s: No ship(s)\n", player->argp[1]); + else + pr("%s: No ship(s)\n", ""); + return RET_FAIL; + } else + pr("%d ship%s\n", nships, splur(nships)); + return RET_OK; +} + + diff --git a/src/lib/commands/orig.c b/src/lib/commands/orig.c new file mode 100644 index 00000000..c50eb7d4 --- /dev/null +++ b/src/lib/commands/orig.c @@ -0,0 +1,65 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * orig.c: Move your origin + * + * Known contributors to this file: + * Shelley Louie, 1988 + */ + +#include "misc.h" +#include "player.h" +#include "sect.h" +#include "xy.h" +#include "nat.h" +#include "file.h" +#include "commands.h" + +int +orig(void) +{ + struct sctstr sect; + s_char *p; + coord x, y; + s_char buf[1024]; + struct natstr *np; + + if ((p = getstarg(player->argp[1], "New origin location : ", buf)) == 0) { + return RET_SYN; + } + if (!sarg_xy(p, &x, &y)) + return RET_SYN; + if (!getsect(x, y, §)) + return RET_SYN; + pr("Origin at %s (old system) is now at 0,0 (new system).\n", + xyas(sect.sct_x, sect.sct_y, player->cnum)); + np = getnatp(player->cnum); + np->nat_xorg = sect.sct_x; + np->nat_yorg = sect.sct_y; + putnat(np); + return RET_OK; +} diff --git a/src/lib/commands/para.c b/src/lib/commands/para.c new file mode 100644 index 00000000..58fe5998 --- /dev/null +++ b/src/lib/commands/para.c @@ -0,0 +1,213 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * para.c: Drop paratroopers onto a sector + * + * Known contributors to this file: + * Dave Pare, 1986 + * Ken Stevens, 1995 + */ + +#include "misc.h" +#include "player.h" +#include "var.h" +#include "sect.h" +#include "ship.h" +#include "item.h" +#include "plane.h" +#include "land.h" +#include "nuke.h" +#include "xy.h" +#include "nsc.h" +#include "news.h" +#include "file.h" +#include "nat.h" +#include "path.h" +#include "treaty.h" +#include "mission.h" +#include "combat.h" +#include "commands.h" + +static int paradrop(struct emp_qelem *list, coord x, coord y); + +int +para(void) +{ + s_char *p; + int mission_flags; + int tech; + coord tx, ty; + coord ax, ay; + int ap_to_target; + s_char flightpath[MAX_PATH_LEN]; + struct nstr_item ni_bomb; + struct nstr_item ni_esc; + coord x, y; + struct sctstr target; + struct emp_qelem bomb_list; + struct emp_qelem esc_list; + int wantflags; + struct sctstr ap_sect; + s_char buf[1024]; + + wantflags = P_P; + if (!snxtitem(&ni_bomb, EF_PLANE, player->argp[1])) + return RET_SYN; + if (!snxtitem(&ni_esc, EF_PLANE, getstarg(player->argp[2], "escort(s)? ", buf))) + pr("No escorts...\n"); + if ((p = getstarg(player->argp[3], "assembly point? ", buf)) == 0 || *p == 0) + return RET_SYN; + if (!sarg_xy(p, &x, &y) || !getsect(x, y, &ap_sect)) + return RET_SYN; + if (ap_sect.sct_own && ap_sect.sct_own != player->cnum && + getrel(getnatp(ap_sect.sct_own), player->cnum) != ALLIED) { + pr("Assembly point not owned by you or an ally!\n"); + return RET_SYN; + } + ax = x; + ay = y; + if (getpath(flightpath, player->argp[4], ax, ay, 0, + 0, 0, P_FLYING) == 0 || *flightpath == 0) + return RET_SYN; + tx = ax; + ty = ay; + (void) pathtoxy(flightpath, &tx, &ty, fcost); + getsect(tx, ty, &target); + pr("LZ is %s\n", xyas(tx, ty, player->cnum)); + ap_to_target = strlen(flightpath); + if (*(flightpath+strlen(flightpath)-1) == 'h') + ap_to_target--; + pr("range to target is %d\n", ap_to_target); + /* + * select planes within range + */ + pln_sel(&ni_bomb, &bomb_list, &ap_sect, ap_to_target, + 2, P_C|wantflags, P_M|P_O); + pln_sel(&ni_esc, &esc_list, &ap_sect, ap_to_target, + 2, P_ESC|P_F, P_M|P_O); + /* + * now arm and equip the bombers, transports, whatever. + * tech is stored in high 16 bits of mission_flags. + * yuck. + */ + tech=0; + mission_flags = 0; + mission_flags |= P_X; /* stealth (shhh) */ + mission_flags |= P_H; /* gets turned off if not all choppers */ + mission_flags = pln_arm(&bomb_list, 2*ap_to_target, 'a', &ichr[I_MILIT], + 0, mission_flags,&tech); + if (QEMPTY(&bomb_list)) { + pr("No planes could be equipped for the mission.\n"); + return RET_FAIL; + } + mission_flags = pln_arm(&esc_list, 2*ap_to_target, 'a', &ichr[I_MILIT], + P_ESC|P_F, mission_flags,&tech); + ac_encounter(&bomb_list,&esc_list,ax,ay,flightpath,mission_flags,0,0,0); + if (QEMPTY(&bomb_list)) { + pr("No planes got through fighter defenses\n"); + } else { + getsect(tx, ty, &target); + paradrop(&bomb_list, tx, ty); + } + pln_put(&bomb_list); + pln_put(&esc_list); + return RET_OK; +} + +static int +paradrop(struct emp_qelem *list, coord x, coord y) +{ + struct combat off[1]; /* assaulting ship or sector */ + struct combat def[1]; /* defending ship */ + struct emp_qelem olist; /* assaulting units */ + struct emp_qelem dlist; /* defending units */ + int ototal; /* total assaulting strength */ + int a_engineer = 0; /* assaulter engineers are present */ + int a_spy = 0; /* the best assaulter scout */ + double osupport = 1.0; /* assault support */ + double dsupport = 1.0; /* defense support */ + struct plist *plp; + struct emp_qelem *qp; + + /* Check for valid attack */ + + att_combat_init(def, EF_SECTOR); + def->x = x; + def->y = y; + if (att_abort(A_PARA, 0, def)) + return RET_FAIL; + + /* Show what we're air-assaulting, and check treaties */ + + if (att_show(def)) + return RET_FAIL; + + /* set what we're air-assaulting with */ + + emp_initque(&olist); + att_combat_init(off, EF_PLANE); + for (qp = list->q_forw; qp != list; qp = qp->q_forw) { + plp = (struct plist *) qp; + if (plp->pcp->pl_flags & (P_V|P_C)) + off->troops += plp->misc; + } + off->mil = off->troops; + if (att_abort(A_PARA, off, def)) { + pr("Air-Assault aborted\n"); + return RET_OK; + } + + /* Get ototal */ + + ototal = att_estimate_defense(A_PARA, off, &olist, def, a_spy); + if (att_abort(A_PARA, off, def)) { + pr("Air-assault aborted\n"); + return RET_OK; + } + + /* Get the defense */ + + att_get_defense(&olist, def, &dlist, a_spy, ototal); + + /* Get defender support */ + + att_get_support(A_PARA, 0, 0, 0, 0, + &olist, off, &dlist, def, &osupport, &dsupport, + a_engineer); + + if (att_abort(A_PARA, off, def)) { + pr("Air-assault aborted\n"); + return RET_OK; + } + /* + * Death, carnage, and destruction. + */ + + att_fight(A_PARA,off,&olist,osupport,def,&dlist,dsupport); + + return RET_OK; +} diff --git a/src/lib/commands/path.c b/src/lib/commands/path.c new file mode 100644 index 00000000..ccd2f80d --- /dev/null +++ b/src/lib/commands/path.c @@ -0,0 +1,128 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * path.c: Show empire distribution paths + * + * Known contributors to this file: + * David Muir Sharnoff, 1986 + * (unknown rewrite), 1989 + */ + +#include "misc.h" +#include "player.h" +#include "var.h" +#include "xy.h" +#include "nsc.h" +#include "nat.h" +#include "file.h" +#include "sect.h" +#include "path.h" +#include "map.h" +#include "deity.h" +#include "commands.h" +#include "optlist.h" + +int +path(void) +{ + + struct nstr_sect ns; + struct natstr *natp; + struct range absrange; + struct range relrange; + struct sctstr sect, dsect; + coord cx, cy; + int i; + int y; + s_char *pp, *p, *BestDistPath(); + /* Note this is not re-entrant anyway, so we keep the buffers + around */ + static s_char *mapbuf = (s_char *)0; + static s_char **map = (s_char **)0; + double move_cost; + s_char buf[1024]; + + if (!(p = getstarg(player->argp[1], "from sector : ", buf)) || + !sarg_xy(p, &cx, &cy) || + !getsect(cx, cy, §)) + return RET_SYN; + if ((sect.sct_own != player->cnum) && !player->god){ + pr("Not yours\n"); + return RET_FAIL; + } + getsect(sect.sct_dist_x,sect.sct_dist_y,&dsect); + pp = BestDistPath(buf, §,&dsect,&move_cost,MOB_ROAD); + if (pp == (s_char *)0){ + pr("No path possible from %s to distribution sector %s\n", + xyas(sect.sct_x,sect.sct_y,player->cnum), + xyas(dsect.sct_x,dsect.sct_y,player->cnum)); + return RET_FAIL; + } + if (!mapbuf) + mapbuf = (s_char *)malloc((WORLD_Y*MAPWIDTH(3))*sizeof(s_char)); + if (!map) { + map = (s_char **)malloc(WORLD_Y * sizeof(s_char *)); + if (map && mapbuf) { + for (i = 0; i < WORLD_Y; i++) + map[i] = &mapbuf[MAPWIDTH(3) * i]; + } else if (map) { + free((s_char *)map); + map = (s_char **)0; + } + } + if (!mapbuf || !map) { + pr("Memory error, tell the deity.\n"); + logerror("malloc failed in path\n"); + return RET_FAIL; + } + pathrange(cx, cy, pp, 1, &absrange); + snxtsct_area(&ns, &absrange); + natp = getnatp(player->cnum); + xyrelrange(natp, &absrange, &relrange); + blankfill((s_char *)mapbuf, &ns.range, 3); + while (*pp && (i = chkdir(*pp, DIR_STOP, DIR_LAST)) >= 0) { + bcopy(routech[i][0], &map[deltay(cy, ns.range.ly)] + [deltax(cx, ns.range.lx)*2], 3); + cx += diroff[i][0]; + cy += diroff[i][1]; + ++pp; + } + border(&relrange, " ", " "); + while (nxtsct(&ns, §)) { + if (!player->owner) + continue; + map[ns.dy][ns.dx*2+1] = dchr[sect.sct_type].d_mnem; + } + for (y=ns.range.ly, i=0; i < ns.range.height; y++, i++) { + cy = yrel(natp, y); + pr("%4d %s %-4d\n", cy, map[i], cy); + if (y >= WORLD_Y) + y -= WORLD_Y; + } + border(&relrange, " ", " "); + return RET_OK; +} diff --git a/src/lib/commands/payo.c b/src/lib/commands/payo.c new file mode 100644 index 00000000..3c82204f --- /dev/null +++ b/src/lib/commands/payo.c @@ -0,0 +1,131 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * payo.c: Calculate trade ship payoffs + * + * Known contributors to this file: + * Thomas Ruschak, 1992 + */ + +#include "misc.h" +#include "player.h" +#include "var.h" +#include "xy.h" +#include "sect.h" +#include "ship.h" +#include "nat.h" +#include "nsc.h" +#include "deity.h" +#include "file.h" +#include "commands.h" +#include "optlist.h" + +int +payo(void) +{ + struct sctstr sect; + int nships; + struct nstr_item ni; + struct shpstr ship; + struct mchrstr *mp; + int dist; + float cash=0.0; + extern int trade_1_dist; /* less than this gets no money */ + extern int trade_2_dist; /* less than this gets trade_1 money */ + extern int trade_3_dist; /* less than this gets trade_2 money */ + extern float trade_1; /* return on trade_1 distance */ + extern float trade_2; /* return on trade_2 distance */ + extern float trade_3; /* return on trade_3 distance */ + extern float trade_ally_bonus; /* 20% bonus for trading with allies */ + + + if (!opt_TRADESHIPS) { + pr("Tradeships are not enabled.\n"); + return RET_FAIL; + } + if (!snxtitem(&ni, EF_SHIP, player->argp[1])) + return RET_SYN; + + nships = 0; + while (nxtitem(&ni, (s_char *)&ship)) { + if (!player->owner || ship.shp_own == 0) + continue; + if (ship.shp_type < 0 || ship.shp_type > shp_maxno) { + pr("bad ship type %d (#%d)\n", + ship.shp_type, ni.cur); + continue; + } + mp = &mchr[(int)ship.shp_type]; + + if (!(mp->m_flags & M_TRADE)) + continue; + + if (nships++ == 0) { + if (player->god) + pr("own "); + pr("shp# ship type orig x,y x,y dist $$\n"); + } + if (player->god) + pr("%3d ", ship.shp_own); + pr("%4d ", ni.cur); + pr("%-16.16s ", mchr[(int)ship.shp_type].m_name); + prxy("%4d,%-4d ", ship.shp_orig_x, + ship.shp_orig_y, player->cnum); + prxy("%4d,%-4d ", ship.shp_x, ship.shp_y, player->cnum); + + getsect(ship.shp_x,ship.shp_y,§); + + dist = mapdist(ship.shp_x, ship.shp_y, + ship.shp_orig_x, ship.shp_orig_y); + pr("%4d ", dist); + + if (dist < trade_1_dist) + cash = 0; + else if (dist < trade_2_dist) + cash = (1.0 + trade_1*((float)dist)); + else if (dist < trade_3_dist) + cash = (1.0 + trade_2*((float)dist)); + else + cash = (1.0 + trade_3*((float)dist)); + + cash *= mp->m_cost; + cash *= (((float)ship.shp_effic) / 100.0); + + if (sect.sct_own && (sect.sct_own != ship.shp_own)) + cash *= (1.0 + trade_ally_bonus); + pr("$%6.2f\n",cash); + } + if (nships == 0) { + if (player->argp[1]) + pr("%s: No ship(s)\n", player->argp[1]); + else + pr("%s: No ship(s)\n", ""); + return RET_FAIL; + }else + pr("%d ship%s\n", nships, splur(nships)); + return RET_OK; +} diff --git a/src/lib/commands/pboa.c b/src/lib/commands/pboa.c new file mode 100644 index 00000000..975c921a --- /dev/null +++ b/src/lib/commands/pboa.c @@ -0,0 +1,56 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * pboard.c: Capture an enemy plane + * + * Known contributors to this file: + * John Yockey, 2001 + */ + +#include "misc.h" +#include "file.h" +#include "sect.h" +#include "plane.h" + +int +pboa(void) +{ + struct sctstr sect; + struct nstr_item np; + struct plnstr plane; + + if (!snxtitem(&np, EF_PLANE, player->argp[1])) + return RET_SYN; + np.flags = 0; + while (nxtitem(&np, (s_char *)&plane)) { + getsect(plane.pln_x, plane.pln_y, §); + if (sect.sct_own != player->cnum) continue; + takeover_plane(&plane, player->cnum); + } + return RET_OK; +} + diff --git a/src/lib/commands/pdump.c b/src/lib/commands/pdump.c new file mode 100644 index 00000000..d87e6eea --- /dev/null +++ b/src/lib/commands/pdump.c @@ -0,0 +1,218 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * pdump.c: Dump plane information + * + * Known contributors to this file: + * John Yockey, 1997 + * Steve McClure, 1998 + */ + +#include "misc.h" +#include "player.h" +#include "var.h" +#include "xy.h" +#include "plane.h" +#include "nsc.h" +#include "nuke.h" +#include "file.h" +#include "nat.h" +#include "deity.h" +#include "optlist.h" +#include "commands.h" + +int +pdump(void) +{ + int nplanes; + struct nstr_item np; + struct plnstr plane; + int field[128]; + struct natstr *natp; + int n,i; + time_t now; + + if (!snxtitem(&np, EF_PLANE, player->argp[1])) + return RET_SYN; + prdate(); + + if (!player->argp[2]) { + for (n = 1; n <= 32; n++) field[n-1] = n; + field[n-1] = 0; + } else { + n = 2; + i = 0; + while (player->argp[n]) { + + if (!strcmp("type",player->argp[n])) { + field[i++] = 1; + } else if (!strcmp("x",player->argp[n])) { + field[i++] = 2; + } else if (!strcmp("y",player->argp[n])) { + field[i++] = 3; + } else if (!strcmp("wing",player->argp[n])) { + field[i++] = 4; + } else if (!strcmp("eff",player->argp[n])) { + field[i++] = 5; + } else if (!strcmp("mob",player->argp[n])) { + field[i++] = 6; + } else if (!strcmp("tech",player->argp[n])) { + field[i++] = 7; + } else if (!strcmp("att",player->argp[n])) { + field[i++] = 8; + } else if (!strcmp("def",player->argp[n])) { + field[i++] = 9; + } else if (!strcmp("acc",player->argp[n])) { + field[i++] = 10; + } else if (!strcmp("react",player->argp[n])) { + field[i++] = 11; + } else if (!strcmp("range",player->argp[n])) { + field[i++] = 12; + } else if (!strcmp("load",player->argp[n])) { + field[i++] = 13; + } else if (!strcmp("fuel",player->argp[n])) { + field[i++] = 14; + } else if (!strcmp("hard",player->argp[n])) { + field[i++] = 15; + } else if (!strcmp("ship",player->argp[n])) { + field[i++] = 16; + } else if (!strcmp("land",player->argp[n])) { + field[i++] = 17; + } else if (!strcmp("laun",player->argp[n])) { + field[i++] = 18; + } else if (!strcmp("orb",player->argp[n])) { + field[i++] = 19; + } else if (!strcmp("nuke",player->argp[n])) { + field[i++] = 20; + } else if (!strcmp("grd",player->argp[n])) { + field[i++] = 21; + } else { + pr("Unrecognized field %s\n",player->argp[n]); + } + if (n++ > 100) { + pr("Too many fields\n"); + return RET_FAIL; + } + } + field[i] = 0; + } + + if (player->god) + pr(" "); + time(&now); + pr("DUMP PLANES %d\n", now); + if (player->god) + pr("own "); + pr("id"); + n = 0; + while (field[n]) { + switch (field[n]) { + case 1: pr(" type"); break; + case 2: pr(" x"); break; + case 3: pr(" y"); break; + case 4: pr(" wing"); break; + case 5: pr(" eff"); break; + case 6: pr(" mob"); break; + case 7: pr(" tech"); break; + case 8: pr(" att"); break; + case 9: pr(" def"); break; + case 10: pr(" acc"); break; + case 11: pr(" react"); break; + case 12: pr(" range"); break; + case 13: pr(" load"); break; + case 14: pr(" fuel"); break; + case 15: pr(" hard"); break; + case 16: pr(" ship"); break; + case 17: pr(" land"); break; + case 18: pr(" laun"); break; + case 19: pr(" orb"); break; + case 20: pr(" nuke"); break; + case 21: pr(" grd"); break; + } + n++; + } + pr("\n"); + + nplanes = 0; + natp = getnatp(player->cnum); + while (nxtitem(&np, (s_char *)&plane)) { + if (!player->owner || plane.pln_own == 0) + continue; + nplanes++; + if (player->god) + pr("%3d ", plane.pln_own); + pr("%d", np.cur); + n = 0; + while (field[n]) { + switch (field[n++]) { + case 1: pr(" %0.4s", plchr[(int)plane.pln_type].pl_name); break; + case 2: pr(" %d", xrel(natp, plane.pln_x)); break; + case 3: pr(" %d", yrel(natp, plane.pln_y)); break; + case 4: if (plane.pln_wing == ' ') + pr(" ~"); + else + pr(" %c", plane.pln_wing); + break; + case 5: pr(" %d", plane.pln_effic); break; + case 6: pr(" %d", plane.pln_mobil); break; + case 7: pr(" %d", plane.pln_tech); break; + case 8: pr(" %d", plane.pln_att); break; + case 9: pr(" %d", plane.pln_def); break; + case 10: pr(" %d", plane.pln_acc); break; + case 11: pr(" %d", plane.pln_range); break; + case 12: pr(" %d", plane.pln_range_max); break; + case 13: pr(" %d", plane.pln_load); break; + case 14: pr(" %d", plane.pln_fuel); break; + case 15: pr(" %d", plane.pln_harden); break; + case 16: pr(" %d", plane.pln_ship); break; + case 17: pr(" %d", plane.pln_land); break; + case 18: if ((plchr[(int)plane.pln_type].pl_flags & (P_O|P_M)) == P_O) { + pr(" %c", (plane.pln_flags & PLN_LAUNCHED)?'Y':'N'); + } else pr (" N"); break; + case 19: if ((plchr[(int)plane.pln_type].pl_flags & (P_O|P_M)) == P_O) { + pr(" %c", opt_ORBIT?(plane.pln_flags & PLN_SYNCHRONOUS)?'Y':'N':'N'); + } else pr (" N"); break; + case 20: if (plane.pln_nuketype != -1) { + pr(" %0.5s", nchr[(int)plane.pln_nuketype].n_name); break; + } else pr(" N/A"); break; + + case 21: pr(" %c", plane.pln_flags & PLN_AIRBURST?'A':'G'); break; + } + } + pr("\n"); + } + if (nplanes == 0) { + if (player->argp[1]) + pr("%s: No plane(s)\n", player->argp[1]); + else + pr("%s: No plane(s)\n", ""); + return RET_FAIL; + }else + pr("%d plane%s\n", nplanes, splur(nplanes)); + + return RET_OK; +} diff --git a/src/lib/commands/plan.c b/src/lib/commands/plan.c new file mode 100644 index 00000000..729b6779 --- /dev/null +++ b/src/lib/commands/plan.c @@ -0,0 +1,108 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * plan.c: Do a plane report + * + * Known contributors to this file: + * Dave Pare, 1986 + * Steve McClure, 2000 + */ + +#include "misc.h" +#include "player.h" +#include "var.h" +#include "xy.h" +#include "plane.h" +#include "nsc.h" +#include "nuke.h" +#include "file.h" +#include "nat.h" +#include "deity.h" +#include "optlist.h" +#include "commands.h" + +int +plan(void) +{ + int nplanes; + struct nstr_item np; + struct plnstr plane; + + if (!snxtitem(&np, EF_PLANE, player->argp[1])) + return RET_SYN; + nplanes = 0; + while (nxtitem(&np, (s_char *)&plane)) { + if (!player->owner || plane.pln_own == 0) + continue; + if (nplanes++ == 0) { + if (player->god) + pr("own "); + pr(" # type x,y w eff mu def tech ran hard s/l L"); + if (opt_ORBIT) + pr("S"); + pr("B nuke\n"); + } + if (player->god) + pr("%3d ", plane.pln_own); + pr("%4d %-19.19s ", np.cur, plchr[(int)plane.pln_type].pl_name); + prxy("%4d,%-4d", plane.pln_x, plane.pln_y, player->cnum); + pr(" %c %3d%% %3d %3d %4d %3d %3d", + plane.pln_wing, plane.pln_effic, + plane.pln_mobil, + plane.pln_def, plane.pln_tech, + plane.pln_range, plane.pln_harden); + if (plane.pln_ship >= 0) + pr("%5dS", plane.pln_ship); + else + if (plane.pln_land >= 0) + pr("%5dL", plane.pln_land); + else + pr(" "); + if ((plchr[(int)plane.pln_type].pl_flags & (P_O|P_M)) == P_O) { + pr(" %c", (plane.pln_flags & PLN_LAUNCHED)?'Y':'N'); + pr("%c", + opt_ORBIT?(plane.pln_flags & PLN_SYNCHRONOUS)?'Y':'N':' '); + } else + pr(" "); + if (plane.pln_nuketype != -1) + pr("%c %-5.5s", + plane.pln_flags & PLN_AIRBURST?'A':'G', + nchr[(int)plane.pln_nuketype].n_name); + pr("\n"); + } + + if (nplanes == 0) { + if (player->argp[1]) + pr("%s: No plane(s)\n", player->argp[1]); + else + pr("%s: No plane(s)\n", ""); + return RET_FAIL; + }else + pr("%d plane%s\n", nplanes, splur(nplanes)); + + return RET_OK; +} diff --git a/src/lib/commands/play.c b/src/lib/commands/play.c new file mode 100644 index 00000000..b842ab97 --- /dev/null +++ b/src/lib/commands/play.c @@ -0,0 +1,129 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * play.c: Who is logged on? + * + * Known contributors to this file: + * Ken Stevens, 1995 + * Steve McClure, 1998 + */ + +#include "misc.h" +#include "player.h" +#include "file.h" +#include "nat.h" +#include "optlist.h" +#include "commands.h" + +static void play_header(void); +static int play_list(struct player *joe); + +int +play(void) +{ + struct player *joe; + int saw = 0; + int count = 0; + + for (joe = player_prev(0); joe; joe = player_prev(joe)) { + if (!count++) + play_header(); + saw += play_list(joe); + } + if (player->god || opt_BLITZ) + pr("%d player%s\n", count, splur(count)); + + return RET_OK; +} + +static void +play_header(void) +{ + prdate(); + pr("%9s %3s %-32s %5s %5s %-20s\n", + "", + "#", + "", + "time", + "idle", + "last command" + ); +} + +static int +play_list(struct player *joe) +{ + time_t now; + s_char *com; + struct natstr *natp; + struct natstr *us; + + if (joe->cnum >= MAXNOC || + !(natp = getnatp(joe->cnum))) + return 0; + + us = getnatp(player->cnum); + if (player->god) { + /* We are a god, we see everything */ + } else if (opt_BLITZ) { + /* It's a blitz, we see everything */ + } else if (joe->god) { + /* This country is a god, so we see it */ + } else if (us->nat_stat == VIS) { + /* We are a visitor country, we can't see squat, except deities */ + return 0; + } else if (joe->cnum != player->cnum) { + /* This isn't us. Can we see it? */ + if (natp->nat_stat == VIS) { + /* Yes, we can see visitors are logged on */ + } else if (getrel(natp, player->cnum) < ALLIED) { + /* This is a non-allied country, don't show it. */ + return 0; + } + } + + time(&now); + if (player->god) { + if (!joe->combuf || !*joe->combuf) + com = "NULL"; + else + com = joe->combuf; + } else + com = ""; + + + pr("%-9.9s %3d %32.32s %2d:%02d %4ds %-20.20s\n", + cname(joe->cnum), + joe->cnum, + (player->god || joe->cnum == player->cnum)?praddr(joe):(s_char *)"", + natp->nat_minused / 60, natp->nat_minused % 60, + now - joe->curup, + com + ); + return 1; +} + diff --git a/src/lib/commands/powe.c b/src/lib/commands/powe.c new file mode 100644 index 00000000..3be73665 --- /dev/null +++ b/src/lib/commands/powe.c @@ -0,0 +1,441 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * powe.c: Do a power report + * + * Known contributors to this file: + * Dave Pare + * Ken Stevens, 1995 + * Steve McClure, 1998-2000 + */ + +#ifdef Rel4 +#include +#endif /* Rel4 */ +#include "misc.h" +#include "player.h" +#include "var.h" +#include "sect.h" +#include "nat.h" +#include "ship.h" +#include "land.h" +#include "nuke.h" +#include "power.h" +#include "item.h" +#include "deity.h" +#include "plane.h" +#include "xy.h" +#include "nsc.h" +#include "file.h" +#include "optlist.h" +#include "commands.h" + + +#include + +struct powsort { + float powval; + natid cnum; +}; + +static int powcmp(struct powsort *p1, struct powsort *p2); +static void out5(double value, int round_val, int round_flag); +static void gen_power(void); +static void addtopow(register int *vec, register struct powstr *pow); + +int +powe(void) +{ + struct natstr *natp; + struct natstr *natp2; + int round_flag; + time_t pow_time; + struct nstr_item ni; + struct powstr pow; + int num; + int power_generated = 0; + int targets[MAXNOC]; + int use_targets = 0; + int got_targets = 0; + int no_numbers = 0; + s_char *p; + + bzero((s_char *)targets, sizeof(targets)); + natp = getnatp(player->cnum); + num = MAXNOC; + if (player->argp[1] && player->argp[1][0] == 'n') { + if (natp->nat_btu < 1) + pr("\n Insufficient BTUs, using the last report.\n\n"); + else { + gen_power(); + power_generated = 1; + if (player->argp[2] && (num = atoi(player->argp[2])) < 0) { + num = MAXNOC; + if (player->god) + no_numbers = 1; + else + return RET_SYN; + } + } + } else if (player->argp[1] && player->argp[1][0] == 'c') { + if (!player->argp[2]) + return RET_SYN; + if (strchr(player->argp[2], '/')) { + p = strtok(player->argp[2], "/"); + do { + got_targets |= set_target(p, targets); + } while (NULL != (p = strtok(0, "/"))); + } else { + got_targets |= set_target(player->argp[2], targets); + } + use_targets = 1; + } else if (player->argp[1] && (num = atoi(player->argp[1])) < 0) { + num = -(num); + if (num > MAXNOC || num < 0) + num = MAXNOC; + if (player->god) + no_numbers = 1; + else + return RET_SYN; + } + + if (use_targets && !got_targets) + return RET_FAIL; + + if (!power_generated) { + snxtitem_all(&ni, EF_POWER); + if (!nxtitem(&ni, (s_char *)&pow)) { + pr("Power for this game has not been built yet. Type 'power new' to build it.\n"); + return RET_FAIL; + } + } + pr(" - = [ Empire Power Report ] = -\n"); + pow_time = ef_mtime(EF_POWER); + pr(" as of %s\n sects eff civ", ctime(&pow_time)); + pr(" mil shell gun pet iron dust oil pln ship unit money\n"); + snxtitem_all(&ni, EF_POWER); + while ((nxtitem(&ni, (s_char *)&pow)) && num > 0) { + if (pow.p_nation == 0 || pow.p_power <= 0.0) + continue; + if (opt_HIDDEN) { + if (!player->god && pow.p_nation != player->cnum) + continue; + } + natp2 = getnatp(pow.p_nation); + if (natp2->nat_stat & STAT_GOD) + continue; + if (use_targets && !targets[pow.p_nation]) + continue; + if (pow.p_nation != player->cnum && player->cnum != 0) + round_flag = 1; + else + round_flag = 0; + num--; + pr("%9.9s", cname(pow.p_nation)); + out5(pow.p_sects, 5, round_flag); + if (pow.p_sects) pr("%4.0f%%", pow.p_effic / pow.p_sects); + else pr(" 0%%"); + out5(pow.p_civil, 50, round_flag); + out5(pow.p_milit, 50, round_flag); + out5(pow.p_shell, 25, round_flag); + out5(pow.p_guns, 5, round_flag); + out5(pow.p_petrol, 50, round_flag); + out5(pow.p_iron, 50, round_flag); + out5(pow.p_dust, 50, round_flag); + out5(pow.p_oil, 50, round_flag); + out5(pow.p_planes, 10, round_flag); + out5(pow.p_ships, 10, round_flag); + out5(pow.p_units, 10, round_flag); + out5(pow.p_money, 5000, round_flag); + pr("\n"); + if (player->god != 0 && !no_numbers) + pr("%9.2f\n", pow.p_power); + } + if (((player->god != 0) && opt_HIDDEN) || !opt_HIDDEN) { + pr(" ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----\n"); + getpower(0, &pow); + pr("worldwide"); + out5(pow.p_sects, 5, 1); + pr("%4.0f%%", pow.p_effic / (pow.p_sects + 0.1)); + out5(pow.p_civil, 50, 1); + out5(pow.p_milit, 50, 1); + out5(pow.p_shell, 25, 1); + out5(pow.p_guns, 5, 1); + out5(pow.p_petrol, 50, 1); + out5(pow.p_iron, 50, 1); + out5(pow.p_dust, 50, 1); + out5(pow.p_oil, 50, 1); + out5(pow.p_planes, 10, 1); + out5(pow.p_ships, 10, 1); + out5(pow.p_units, 10, 1); + out5(pow.p_money, 5000, 1); + pr("\n"); + } + return RET_OK; +} + +static void +out5(double value, int round_val, int round_flag) +{ + if (value > round_val && round_flag) + value = (int) (value / round_val + 0.5) * round_val; + if (value < -995000.) + pr("%4.0fM", value / 1e6); + else if (value < -9950.) + pr("%4.0fK", value / 1000.); + else if (value < -999.) + pr("%4.1fK", value / 1000.); + else if (value < 1000.) + pr("%4.0f ", value); + else if (value < 10000.) + pr("%4.1fK", value / 1000.); + else if (value < 1e6) + pr("%4.0fK", value / 1000.); + else if (value < 1e7) + pr("%4.1fM", value / 1e6); + else if (value >= 1e9) + pr("%4.0fG", value / 1e9); + else + pr("%4.0fM", value / 1e6); +} + +static void +gen_power(void) +{ + extern double powe_cost; + float *f_ptr; + float *f_pt2; + register struct powstr *pow; + register int i; + struct sctstr sect; + struct plnstr plane; + struct shpstr ship; + struct lndstr land; + struct powstr powbuf[MAXNOC]; + struct nstr_item ni; + struct nstr_sect ns; + int vec[I_MAX+1]; + struct powsort order[MAXNOC]; + struct natstr *natp; + float f; + + player->btused += powe_cost; + bzero((s_char *) powbuf, sizeof(powbuf)); + snxtsct_all(&ns); + while (nxtsct(&ns, §)) { + if (sect.sct_own == 0) + continue; + pow = &powbuf[sect.sct_own]; + pow->p_sects += 1.0; + pow->p_effic += sect.sct_effic; + getvec(VT_ITEM, vec, (s_char *)§, EF_SECTOR); + addtopow(vec, pow); + } + snxtitem_all(&ni, EF_LAND); + while (nxtitem(&ni, (s_char *)&land)) { + if (land.lnd_own == 0) + continue; + pow = &powbuf[land.lnd_own]; + getvec(VT_ITEM, vec, (s_char *)&land, EF_LAND); + addtopow(vec, pow); + if (opt_NEWPOWER == 0) { + pow->p_power += lchr[(int)land.lnd_type].l_lcm / 10.0; + pow->p_power += lchr[(int)land.lnd_type].l_hcm / 5.0; + } else { /* old power */ + f = ((float)(lchr[(int)land.lnd_type].l_lcm / 10.0)) * + ((float)land.lnd_effic)/100.0; + f += ((float)(lchr[(int)land.lnd_type].l_hcm / 10.0)) * + ((float)land.lnd_effic/100.0); + pow->p_power += f*2; + } /* end NEWPOWER */ + pow->p_units += 1.0; + } + snxtitem_all(&ni, EF_SHIP); + while (nxtitem(&ni, (s_char *)&ship)) { + if (ship.shp_own == 0) + continue; + pow = &powbuf[ship.shp_own]; + getvec(VT_ITEM, vec, (s_char *)&ship, EF_SHIP); + addtopow(vec, pow); + if (opt_NEWPOWER == 0) { + pow->p_power += mchr[(int)ship.shp_type].m_lcm / 10.0; + pow->p_power += mchr[(int)ship.shp_type].m_hcm / 5.0; + } else { /* old power formula */ + f = ((float)(mchr[(int)ship.shp_type].m_lcm / 10.0)) * + ((float)ship.shp_effic)/100.0; + f += ((float)(mchr[(int)ship.shp_type].m_hcm / 10.0)) * + ((float)ship.shp_effic/100.0); + pow->p_power += f*2; + } /* end NEWPOWER */ + pow->p_ships += 1.0; + } + snxtitem_all(&ni, EF_PLANE); + while (nxtitem(&ni, (s_char *)&plane)) { + if (plane.pln_own == 0) + continue; + pow = &powbuf[plane.pln_own]; + pow->p_planes += 1.0; + if (opt_NEWPOWER == 0) + pow->p_power += plane.pln_effic / 100.0; + else { /* old POWER */ + natp=getnatp(plane.pln_own); + pow->p_power += 20 * (plane.pln_effic / 100.0) * + (natp->nat_level[NAT_TLEV]/500.0); + } /* end old POWER */ + } + for (i=1; NULL != (natp = getnatp(i)); i++) { + pow = &powbuf[i]; + pow->p_nation = i; + if ((natp->nat_stat & STAT_INUSE) == 0 || + (natp->nat_stat & STAT_NORM) == 0) { + pow->p_power = 0.; + continue; + } + if (opt_NEWPOWER && (natp->nat_stat & STAT_GOD)) { + pow->p_power = 0.; + continue; + } + pow->p_money = natp->nat_money; + pow->p_power += pow->p_money / 100.; + + pow->p_power += pow->p_petrol / (opt_NEWPOWER ? 500.0 : 50.0); + + if (opt_NEWPOWER == 0) { + pow->p_power += (pow->p_civil + pow->p_milit + + pow->p_shell) / 10.; + pow->p_power += (pow->p_iron + pow->p_dust + + pow->p_effic + pow->p_oil) / 10.; + pow->p_power += (pow->p_guns + pow->p_effic) / 3.; + pow->p_power += pow->p_ships; + pow->p_power += pow->p_sects * 3.0; + pow->p_power += pow->p_planes * 5.0; + } else { /* new POWER format */ + pow->p_power += (pow->p_civil + pow->p_milit)/10.0; + pow->p_power += (pow->p_shell)/12.5; + pow->p_power += (pow->p_iron)/100.0; + pow->p_power += (pow->p_dust/5 + + pow->p_oil/10 + + pow->p_bars); + pow->p_power += (pow->p_guns) / 2.5; + if (pow->p_sects > 0) + pow->p_power += (pow->p_sects * + ((pow->p_effic/pow->p_sects)/ + 100.0)) * 10.0; + if (natp->nat_level[NAT_TLEV] > 0.0) + pow->p_power = pow->p_power * + (((float)natp->nat_level[NAT_TLEV])/ + 500.0); + else + pow->p_power = pow->p_power * (1.0/500.0); + } /* end new POWER */ + /* ack. add this vec to the "world power" element */ + f_pt2 = &(powbuf[0].p_sects); + f_ptr = &(pow->p_sects); + while (f_ptr <= &(pow->p_power)) { + *f_pt2 += *f_ptr; + f_pt2++; + f_ptr++; + } + } + for (i=1; i < MAXNOC; i++) { + struct natstr *np; + int maxpop; + float f = 1.0; + + if (opt_RES_POP) { + np = getnatp(i); + maxpop = max_pop(np->nat_level[NAT_RLEV], 0); + f = 1.0 + (((float)maxpop)/10000.0); + } + powbuf[i].p_power *= f; + order[i].powval = powbuf[i].p_power; + order[i].cnum = i; + } + qsort((s_char *)&order[1], MAXNOC-1, sizeof(*order), (qsort_func_t)powcmp); + putpower(0, &powbuf[0]); + for (i=1; ipowval > p2->powval) + return -1; + if (p1->powval < p2->powval) + return 1; + return 0; +} + +static void +addtopow(register int *vec, register struct powstr *pow) +{ + pow->p_civil += vec[I_CIVIL]; + pow->p_milit += vec[I_MILIT]; + pow->p_shell += vec[I_SHELL]; + pow->p_guns += vec[I_GUN]; + pow->p_petrol += vec[I_PETROL]; + pow->p_iron += vec[I_IRON]; + pow->p_dust += vec[I_DUST]; + pow->p_food += vec[I_FOOD]; + pow->p_oil += vec[I_OIL]; + pow->p_bars += vec[I_BAR]; + pow->p_power += vec[I_LCM] / 10.0; + pow->p_power += vec[I_HCM] / 5.0; +} + +int +set_target(s_char *p, int *targets) +{ + int target; + struct natstr *natp; + + if (!p) + return 0; + + if (isdigit(*p)) + target = atoi(p); + else + target = cnumb(p); + + if (target > 0 && target < MAXNOC && (natp = getnatp(target))) { + if (natp->nat_stat & STAT_GOD) { + pr("Country #%d is a deity country\n", target); + } else if (!(natp->nat_stat & STAT_INUSE)) { + pr("Country #%d is not in use\n", target); + } else if (!(natp->nat_stat & STAT_NORM)) { + pr("Country #%d is not a normal country\n", target); + } else { + targets[target] = 1; + return 1; + } + } else + pr("Bad country: \'%s\'\n", p); + + return 0; +} diff --git a/src/lib/commands/prod.c b/src/lib/commands/prod.c new file mode 100644 index 00000000..6c66f187 --- /dev/null +++ b/src/lib/commands/prod.c @@ -0,0 +1,428 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * prod.c: Calculate production levels + * + * Known contributors to this file: + * David Muir Sharnoff, 1987 + * Steve McClure, 1997-2000 + */ + +#include "misc.h" +#include "player.h" +#include "var.h" +#include "xy.h" +#include "nsc.h" +#include "sect.h" +#include "product.h" +#include "nat.h" +#include "item.h" +#include "file.h" +#include "optlist.h" +#include "commands.h" + +int +count_pop(register int n) +{ + register int i; + register int pop = 0; + struct sctstr *sp; + int vec[I_MAX+1]; + + for (i = 0; NULL != (sp = getsectid(i)); i++) { + if (sp->sct_own != n) + continue; + if (sp->sct_oldown != n) + continue; + if (getvec(VT_ITEM, vec, (s_char *)sp, EF_SECTOR) <= 0) + continue; + pop += vec[I_CIVIL]; + } + return pop; +} + +int +prod(void) +{ + extern double obrate, uwbrate; + extern int etu_per_update; + struct natstr *natp; + struct sctstr sect; + struct nstr_sect nstr; + struct pchrstr *pp; + double effic; + double maxr; /* floating version of max */ + double prodeff; + double real; /* floating pt version of act */ + double work; + int totpop; + int act; /* actual production */ + int cost; + int i; + int max; /* production w/infinate materials */ + double maxtake; + int nsect; + double take; + double mtake; + int there; + int totcomp; /* sum of component amounts */ + int used; /* production w/infinite workforce */ + int wforce; + int it; + u_short *amount; /* amount for component pointer */ + u_char *comp; /* component pointer */ + u_char *endcomp; + u_char vtype; + s_char *resource; + int c; + s_char maxc[3][10]; + s_char use[3][10]; + int items[I_MAX+1]; + int vec[I_MAX+1], lcms, hcms; + int civs=0; + int uws=0; + int bwork; + int twork; + int type; + int eff; + int maxpop; + u_char otype; + + if (!snxtsct(&nstr, player->argp[1])) + return RET_SYN; + player->simulation = 1; + prdate(); + nsect = 0; + while (nxtsct(&nstr, §)) { + if (!player->owner) + continue; + getvec(VT_ITEM, items, (s_char *)§, EF_SECTOR); + + civs = min(9999, (int) ((obrate * (double) etu_per_update + 1.0) + * (double) items[I_CIVIL])); + uws = min(9999, (int) ((uwbrate * (double) etu_per_update + 1.0) + * (double) items[I_UW])); + if (opt_RES_POP) { + natp = getnatp(sect.sct_own); + maxpop = max_pop((float)natp->nat_level[NAT_RLEV], §); + civs = min(civs, maxpop); + uws = min(uws, maxpop); + } else { /* now RES_POP */ + civs = min(999,civs); + uws = min(999,uws); + } /* end RES_POP */ + + /* This isn't quite right, since research might rise/fall */ + /* during the update, but it's the best we can really do */ + wforce = (int)(((double)civs * (double)sect.sct_work) + / 100.0 + (double)uws + (double)items[I_MILIT] * 2.0 / 5.0); + work = (double)etu_per_update * (double)wforce / 100.0; + bwork = (int)((double)work / 2.0); + + if (sect.sct_off) + continue; + type = sect.sct_type; + eff = sect.sct_effic; + if(sect.sct_newtype != type) { + twork = (eff+3)/4; + if(twork > bwork) { + twork = bwork; + } + bwork -= twork; + eff -= twork*4; + otype = type; + if(eff <= 0) { + type = sect.sct_newtype; + eff = 0; + } + if (opt_BIG_CITY) { + if (!eff && dchr[otype].d_pkg == UPKG && + dchr[type].d_pkg != UPKG) { + if (opt_RES_POP) { + natp = getnatp(sect.sct_own); + civs = min(civs, max_pop(natp->nat_level[NAT_RLEV],0)); + uws = min(uws, max_pop(natp->nat_level[NAT_RLEV], 0)); + } else { + civs = min(9999,civs); + uws = min(9999,uws); + } + wforce = (int)((civs * sect.sct_work) / 100.0 + uws + items[I_MILIT] * 2 / 5.0); + work = etu_per_update * wforce / 100.0; + bwork = min((int)(work/2), bwork); + } + } + twork = 100 - eff; + if(twork > bwork) { + twork = bwork; + } + getvec(VT_ITEM, vec, (s_char *)§, EF_SECTOR); + if (dchr[type].d_lcms>0){ + lcms = vec[I_LCM]; + lcms /= dchr[type].d_lcms; + if (twork > lcms) + twork = lcms; + } + if (dchr[type].d_hcms>0){ + hcms = vec[I_HCM]; + hcms /= dchr[type].d_hcms; + if (twork > hcms) + twork = hcms; + } + bwork -= twork; + eff += twork; + } else if (eff < 100) { + twork = 100 - eff; + if (twork > bwork) { + twork = bwork; + } + bwork -= twork; + eff += twork; + } + work = work/2 + bwork; + if (eff < 60 || (type != SCT_ENLIST && eff < 61)) + continue; + + effic = eff/100.0; + if (effic > 1.0) + effic = 1.0; + + if (dchr[type].d_prd == 0 && type != SCT_ENLIST) + continue; + totcomp = 0; + pp = &pchr[dchr[type].d_prd]; + vtype = pp->p_type; + natp = getnatp(sect.sct_own); + /* + * sect effic (inc improvements) + */ + if (type == SCT_ENLIST && sect.sct_own != sect.sct_oldown) + continue; + if (type == SCT_ENLIST) + goto is_enlist; + if (pp->p_nrndx != 0) { + totcomp++; + resource = ((s_char *) §) + pp->p_nrndx; + effic = (*resource * effic) / 100.0; + if (pp->p_nrdep > 0) { + maxtake = (*resource * 100.0) / pp->p_nrdep; + if (effic > maxtake) + effic = maxtake; + } + } + /* + * production effic. + */ + if (pp->p_nlndx >= 0) { + prodeff = natp->nat_level[pp->p_nlndx] - pp->p_nlmin; + if (prodeff < 0.0) { + prodeff = 0.0; + } + prodeff = prodeff / (prodeff + pp->p_nllag); + } else { + prodeff = 1.0; + } + used = 999; + comp = pp->p_vtype; + endcomp = pp->p_vtype + pp->p_nv; + amount = pp->p_vamt; + while (comp < endcomp) { + if (*amount == 0) + totcomp++; + else { + used = min(used, (int)(getvar((int)*comp, (s_char *)§, + EF_SECTOR) / *amount)); + totcomp += *amount; + } + ++comp; + ++amount; + } + if (totcomp == 0) + continue; + /* + * is production limited by resources or + * workforce? + */ + max = (int) (work * effic / (double) totcomp) + 0.5; + act = min(used, max); + /* + * some things are easier to make.. food, + * pet, etc. + */ + act = (int) (((double)pp->p_effic * 0.01 * (double)act) + 0.5); + max = (int) (((double)pp->p_effic * 0.01 * (double)max) + 0.5); + + real = (double)act * (double)prodeff; + maxr = (double)max * (double)prodeff; + + if (vtype != 0) { + if (real < 0.0) + real = 0.0; + /* production backlog? */ + if ((there = getvar((int)vtype, (s_char *)§, EF_SECTOR)) >= 9999) { + there = 9999; + } + act = min(act, (9999 - there)); + max = min(max, (9999 - there)); + } + + if (prodeff != 0) { + take = real / prodeff; + mtake = maxr / prodeff; + } else + mtake = take = 0.0; + + if (take > 999.0) + take = 999.0; + if (mtake > 999.0) + mtake = 999.0; + + take = (double)take / ((double)pp->p_effic * 0.01); + mtake = (double)mtake / ((double)pp->p_effic * 0.01); + + cost = (int)(take * (double)pp->p_cost); + if (opt_TECH_POP) { + if (pp->p_level == NAT_TLEV) { + totpop = count_pop(sect.sct_own); + if (totpop > 50000) + cost = (int)((double)cost * (double)totpop / 50000.0); + } + } + + comp = pp->p_vtype; + amount = pp->p_vamt; + i = 0; + while (comp < endcomp) { + it = unitem((int) *comp); + if (it > 0 && it <= I_MAX && ichr[it].i_name != 0) + c = ichr[it].i_name[0]; + else + c = ' '; + (void) sprintf(use[i], " %3d%c", (int)((take * (double)(*amount)) + 0.5), c); + (void) sprintf(maxc[i], " %3d%c", (int)((mtake * (double)(*amount)) + 0.5), c); + ++comp; + ++amount; + ++i; + } + while (i < 3) { + strcpy(use[i], " "); + strcpy(maxc[i], " "); + ++i; + } + + is_enlist: + + if (nsect++ == 0) { + pr("PRODUCTION SIMULATION\n"); + pr(" sect des eff wkfc will make- p.e. cost use1 use2 use3 max1 max2 max3 max\n"); + } + + prxy("%4d,%-4d", nstr.x, nstr.y, player->cnum); + pr(" %c", dchr[type].d_mnem); + pr(" %3.0f%%", effic * 100.0); + + pr(" %4d", wforce); + if (vtype != 0) { + pr(" %4d", (int)(real + 0.5)); + } else if (type != SCT_ENLIST) { + switch (pp->p_level) { + case NAT_TLEV: + case NAT_RLEV: + pr(" %1.2f", real); + break; + case NAT_ELEV: + case NAT_HLEV: + pr(" %4.0f", real); + break; + default: + pr("ERROR"); + break; + } + } else { + int maxmil; + int enlisted; + int civs; + + civs = min(999, (int) ((obrate * (double) etu_per_update + 1.0) + * (double) items[I_CIVIL])); + natp = getnatp(sect.sct_own); + maxpop = max_pop((float)natp->nat_level[NAT_RLEV], §); + civs = min(civs, maxpop); + /* This isn't quite right, since research might + rise/fall during the update, but it's the best + we can really do */ + enlisted = 0; + maxmil = (civs / 2) - items[I_MILIT]; + if (maxmil > 0) { + enlisted = (etu_per_update * (10 + items[I_MILIT]) * 0.05); + if (enlisted > maxmil) + enlisted = maxmil; + } + if (enlisted < 0) + enlisted = 0; + if (natp->nat_priorities[type] == 0){ + maxmil = 0; + } + pr(" %4d mil 1.00 $%-5d%3dc", + enlisted, enlisted * 3, enlisted); + pr(" %3dc %4d\n", + enlisted, maxmil, maxmil); + continue; + } + + pr(" %-5.5s", pp->p_sname); + prodeff = prodeff * (double)pp->p_effic * 0.01; + pr(" %.2f", prodeff); + pr(" $%-4d", cost); + for (i = 0; i < 3; i++) { + pr(use[i]); + } + pr(" "); + for (i = 0; i < 3; i++) { + pr(maxc[i]); + } + if (natp->nat_priorities[type] == 0){ + max = 0; + maxr = 0; + } + if (vtype != 0 || pp->p_level == NAT_ELEV + || pp->p_level == NAT_HLEV) + pr(" %4d\n", min(999,(int)(max * prodeff + 0.05))); + else + pr(" %1.2f\n", maxr); + } + player->simulation = 0; + if (nsect == 0) { + if (player->argp[1]) + pr("%s: No sector(s)\n", player->argp[1]); + else + pr("%s: No sector(s)\n", ""); + return RET_FAIL; + } else + pr("%d sector%s\n", nsect, splur(nsect)); + return RET_OK; +} + diff --git a/src/lib/commands/pstat.c b/src/lib/commands/pstat.c new file mode 100644 index 00000000..5e581c14 --- /dev/null +++ b/src/lib/commands/pstat.c @@ -0,0 +1,97 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * pstat.c: Show the stats of your planes + * + * Known contributors to this file: + * Steve McClure, 1996 + */ + +#include "misc.h" +#include "player.h" +#include "var.h" +#include "xy.h" +#include "plane.h" +#include "nsc.h" +#include "nuke.h" +#include "file.h" +#include "nat.h" +#include "deity.h" +#include "optlist.h" +#include "commands.h" + +int +pstat(void) +{ + int nplanes; + struct nstr_item np; + struct plnstr plane; + + if (!snxtitem(&np, EF_PLANE, player->argp[1])) + return RET_SYN; + nplanes = 0; + while (nxtitem(&np, (s_char *)&plane)) { + if (!player->owner || plane.pln_own == 0) + continue; + if (plane.pln_type < 0 || plane.pln_type > pln_maxno) { + pr("bad plane type %d (#%d)\n", + plane.pln_type, np.cur); + continue; + } + if (nplanes++ == 0) { +pr("pln# %22.22s x,y eff tech att def acc ran load fuel\n", "plane-type"); + } + pr("%4d %-22.22s ", + plane.pln_uid, + plchr[(int)plane.pln_type].pl_name); + prxy("%4d,%-4d", + plane.pln_x, + plane.pln_y, + player->cnum); + pr(" %3d%% %4d %3d %3d %3d %3d %4d %4d", + plane.pln_effic, + plane.pln_tech, + plane.pln_att, + plane.pln_def, + plane.pln_acc, + plane.pln_range_max, + plane.pln_load, + plane.pln_fuel); + pr("\n"); + } + + if (nplanes == 0) { + if (player->argp[1]) + pr("%s: No plane(s)\n", player->argp[1]); + else + pr("%s: No plane(s)\n", ""); + return RET_FAIL; + }else + pr("%d plane%s\n", nplanes, splur(nplanes)); + + return RET_OK; +} diff --git a/src/lib/commands/rada.c b/src/lib/commands/rada.c new file mode 100644 index 00000000..4cadf25b --- /dev/null +++ b/src/lib/commands/rada.c @@ -0,0 +1,150 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * rada.c: Do radar from a ship/unit/sector + * + * Known contributors to this file: + * + */ + +#include +#include "misc.h" +#include "player.h" +#include "xy.h" +#include "var.h" +#include "ship.h" +#include "land.h" +#include "sect.h" +#include "nsc.h" +#include "nat.h" +#include "file.h" +#include "commands.h" +#include "optlist.h" + +int +rada(void) +{ + s_char *cp; + int type; + double tf; + double tech; + struct nstr_item ni; + struct nstr_sect ns; + struct shpstr ship; + struct lndstr land; + struct sctstr sect; + int from_unit; + s_char buf[1024]; + + from_unit = (**player->argp == 'l'); + + if (!from_unit) + cp = getstarg(player->argp[1], "Radar from (ship # or sector(s)) : ", buf); + else + cp = getstarg(player->argp[1], "Radar from (unit # or sector(s)) : ", buf); + if (cp == 0) + return RET_SYN; + type = sarg_type(cp); + if (type == NS_AREA) { + if (!snxtsct(&ns, cp)) + return RET_SYN; + tech = tfact(player->cnum, 8.0); + if (tech > ((double)WORLD_Y/4.0)) + tech = ((double)WORLD_Y/4.0); + if (tech > ((double)WORLD_X/8.0)) + tech = ((double)WORLD_X/8.0); + while (nxtsct(&ns, §)) { + if (sect.sct_type != SCT_RADAR) + continue; + if (!player->owner) + continue; + radmap(sect.sct_x, sect.sct_y, (int)sect.sct_effic, + (int) (tech * 2.0), 0.0); + } + } else if (type == NS_LIST || type == NS_GROUP) { + if (!from_unit){ + /* assumes a NS_LIST return is a shipno */ + if (!snxtitem(&ni, EF_SHIP, cp)) { + pr("Specify at least one ship\n"); + return RET_SYN; + } + while (nxtitem(&ni, (s_char *)&ship)) { + if (!player->owner) + continue; + if (mchr[(int)ship.shp_type].m_flags & M_SONAR) + tf = techfact(ship.shp_tech, 1.0); + else + tf = 0.0; + pr("%s at ", prship(&ship)); + tech = techfact(ship.shp_tech, + (double) mchr[(int)ship.shp_type].m_vrnge); + if (tech > ((double)WORLD_Y/2.0)) + tech = ((double)WORLD_Y/2.0); + if (tech > ((double)WORLD_X/4.0)) + tech = ((double)WORLD_X/4.0); + radmap(ship.shp_x, ship.shp_y, ship.shp_effic, + (int) tech, tf); + } + }else{ + /* from a land unit */ + if (!snxtitem(&ni, EF_LAND, cp)) { + pr("Specify at least one unit\n"); + return RET_SYN; + } + while (nxtitem(&ni, (s_char *)&land)) { + if (!player->owner) + continue; + if (!(lchr[(int)land.lnd_type].l_flags & L_RADAR)){ + pr("%s can't use radar!\n", + prland(&land)); + continue; + } + if (land.lnd_ship >= 0){ + pr("Units on ships can't use radar!\n"); + continue; + } + tf = 0.0; + pr("%s at ", prland(&land)); + tech = techfact(land.lnd_tech, + (double) land.lnd_spy); + if (tech > ((double)WORLD_Y/2.0)) + tech = ((double)WORLD_Y/2.0); + if (tech > ((double)WORLD_X/4.0)) + tech = ((double)WORLD_X/4.0); + radmap(land.lnd_x, land.lnd_y, land.lnd_effic, + (int) tech, tf); + } + } + } else { + if (!from_unit) + pr("Must use a ship or sector specifier\n"); + else + pr("Must use a unit or sector specifier\n"); + return RET_SYN; + } + return RET_OK; +} diff --git a/src/lib/commands/rang.c b/src/lib/commands/rang.c new file mode 100644 index 00000000..ef9d59d8 --- /dev/null +++ b/src/lib/commands/rang.c @@ -0,0 +1,108 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * rang.c: Edit range of plane/land unit + * + * Known contributors to this file: + * Jeff Bailey + */ + +#include "misc.h" +#include "player.h" +#include "var.h" +#include "xy.h" +#include "plane.h" +#include "land.h" +#include "nsc.h" +#include "file.h" +#include "nat.h" +#include "deity.h" +#include "commands.h" + +int +range(void) +{ + struct nstr_item np; + struct plnstr plane; + int i; + s_char *p; + s_char buf[1024]; + + if (!snxtitem(&np, EF_PLANE, player->argp[1])) + return RET_SYN; + while (nxtitem(&np, (s_char *)&plane)) { + if (!player->owner || plane.pln_own == 0) + continue; + p = getstarg(player->argp[2],"New range? ", buf); + if (!check_plane_ok(&plane)) + return RET_SYN; + if (!p || (i = atoi(p)) < 0) + continue; + plane.pln_range = (plane.pln_range_max < i) ? + plane.pln_range_max : i; + pr("Plane %d range changed to %d\n",plane.pln_uid, + plane.pln_range); + + putplane(plane.pln_uid,&plane); + } + + return RET_OK; +} + +int +lrange(void) +{ + struct nstr_item np; + struct lndstr land; + struct lchrstr *lcp; + int i; + s_char *p; + s_char prompt[128]; + s_char buf[128]; + + if (!snxtitem(&np, EF_LAND, player->argp[1])) + return RET_SYN; + while (nxtitem(&np, (s_char *)&land)) { + if (!player->owner || land.lnd_own == 0) + continue; + lcp = &lchr[(int)land.lnd_type]; + sprintf(prompt, "New range for %s? ", prland(&land)); + if ((p = getstarg(player->argp[2], prompt, buf)) == 0) + return RET_SYN; + if (!check_land_ok(&land)) + return RET_SYN; + if ((i = atoi(p)) < 0) + continue; + land.lnd_rad_max = (i < land.lnd_rad) ? + i : land.lnd_rad; + pr("%s reaction radius changed to %d\n", prland(&land), + land.lnd_rad_max); + putland(land.lnd_uid,&land); + } + + return RET_OK; +} diff --git a/src/lib/commands/rea.c b/src/lib/commands/rea.c new file mode 100644 index 00000000..d65b38e0 --- /dev/null +++ b/src/lib/commands/rea.c @@ -0,0 +1,243 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * rea.c: Read telegrams + * + * Known contributors to this file: + * Dave Pare + * Doug Hay, 1998 + * Steve McClure, 1998-2000 + */ + + +#ifdef aix +#define L_SET 0 +#endif /* aix */ + +#include "misc.h" +#include "player.h" +#include "nat.h" +#include "file.h" +#include "tel.h" +#include "deity.h" +#include "commands.h" + +#include +#include +#if !defined(_WIN32) +#include +#endif + +int +rea(void) +{ + extern s_char *telnames[]; + register s_char *p; + register s_char *mbox; + s_char mbox_buf[256]; /* Maximum path length */ + struct telstr tgm; + FILE *telfp; + int teles; + int size; + unsigned int nbytes; + s_char buf[4096]; + int lasttype; + int lastcnum; + time_t lastdate; + int header; + int filelen; + s_char kind[80]; + int n; + int num = player->cnum; + struct natstr *np = getnatp(player->cnum); + time_t now; + time_t then; + time_t delta; + int first = 1; + int readit; + + bzero(kind,80); + (void) time(&now); + + if (*player->argp[0] == 'w') { + sprintf(kind,"announcement"); + if (player->argp[1] && isdigit(*player->argp[1])) { + delta = days(atoi(player->argp[1])); + then = now - delta; + } else + then = np->nat_annotim; + mbox = annfil; + } else { + sprintf(kind,"telegram"); + if (player->god && player->argp[1] != 0) { + if ((n = natarg(player->argp[1], "")) < 0) + return RET_SYN; + num = n; + } + mbox = mailbox(mbox_buf, num); + clear_telegram_is_new(player->cnum); + } + +#if !defined(_WIN32) + if ((telfp = fopen(mbox, "r+")) == 0) { +#else + if ((telfp = fopen(mbox, "r+b")) == 0) { +#endif + logerror("telegram file %s", mbox); + return RET_FAIL; + } + teles = 0; + fseek(telfp, 0L, 0); + size = fsize(fileno(telfp)); +more: + lastdate = 0; + lastcnum = -1; + lasttype = -1; + while (fread((s_char *) &tgm, sizeof(tgm), 1, telfp) == 1) { + readit = 1; + if (tgm.tel_length < 0) { + logerror("bad telegram file header in %s", mbox); + break; + } + if (tgm.tel_type < 0 || tgm.tel_type > TEL_LAST) { + pr("Bad telegram header. Skipping telegram...\n"); + readit = 0; + goto skip; + } + if (*kind == 'a') { + if (!player->god && + (getrejects(tgm.tel_from, np) & REJ_ANNO)) { + readit = 0; + goto skip; + } + if (tgm.tel_date < then) { + readit = 0; + goto skip; + } + } + if (first && *kind == 'a') { + pr("\nAnnouncements since %s", ctime(&then)); + first = 0; + } + header = 0; + if (tgm.tel_type != lasttype || tgm.tel_from != lastcnum) + header++; + if (abs((int)(tgm.tel_date - (long)lastdate)) > TEL_SECONDS) + header++; + if (header) { + pr("\n> "); + lastcnum = tgm.tel_from; + lasttype = tgm.tel_type; + pr("%s ", telnames[(int)tgm.tel_type]); + if ((tgm.tel_type == TEL_NORM) || + (tgm.tel_type == TEL_ANNOUNCE)) { + pr("from %s, (#%d)", + cname(tgm.tel_from), + tgm.tel_from); + } + if (tgm.tel_type == TEL_BULLETIN){ + pr("from %s, (#%d)", cname(tgm.tel_from), tgm.tel_from); + } + pr(" dated %s", ctime(&tgm.tel_date)); + lastdate = tgm.tel_date; + } + teles++; + skip: + while (tgm.tel_length > 0) { + nbytes = tgm.tel_length; + if (nbytes > sizeof(buf)-1) + nbytes = sizeof(buf)-1; + (void) fread(buf, sizeof(s_char), nbytes, telfp); + buf[nbytes] = 0; + if (readit) + prnf(buf); + tgm.tel_length -= nbytes; + } + } + p=NULL; + if (teles > 0 && player->cnum == num) { /* } */ + pr("\n"); + if (teles == 1) { + if (chance(0.25)) + p = "Forget this one? "; + else + p = "Shall I burn it? "; + } else { + if (chance(0.25)) + p = "Into the shredder, boss? "; + else + p = "Can I throw away these old love letters? "; + } + if (player->god && *kind == 't') + p = getstarg(player->argp[2], p, buf); + else + p = getstarg(player->argp[1], p, buf); + if (p && *p == 'y') { + if ((filelen = fsize(fileno(telfp))) > size) { + pr("Wait a sec! A new %s has arrived...\n", kind); + /* force stdio to re-read tel file */ + (void) fflush(telfp); +#if !defined(_WIN32) + (void) fseek(telfp, (long)size, L_SET); +#else + (void) fseek(telfp, (long)size, SEEK_SET); +#endif + size = filelen; + (void) time(&now); + goto more; + } + if (*kind == 'a') { + np->nat_annotim = now; + putnat(np); + } else { + /* Here, we just re-open the file for "w" only, + and that will wipe the file clean automatically */ + (void)fclose(telfp); +#if !defined(_WIN32) + telfp = fopen((char *)mbox, "w"); +#else + telfp = fopen((char *)mbox, "wb"); +#endif + } + } + } + if (teles <= 0) { + if(player->cnum == num) + pr("No %ss for you at the moment...\n",kind); + else + pr("No %ss for %s at the moment...\n", kind, + cname(num)); + } + (void) fclose(telfp); + if (np->nat_flags & NF_INFORM) { + pr_inform(player, "\n"); + np->nat_tgms = 0; + putnat(np); + } + return RET_OK; +} + diff --git a/src/lib/commands/real.c b/src/lib/commands/real.c new file mode 100644 index 00000000..8e084e39 --- /dev/null +++ b/src/lib/commands/real.c @@ -0,0 +1,151 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * real.c: Show or set a realm + * + * Known contributors to this file: + * + */ + +#include "misc.h" +#include "player.h" +#include "nat.h" +#include "xy.h" +#include "file.h" +#include "nsc.h" +#include "commands.h" + +static void +list_realm(int curr, struct natstr *natp) +{ + struct boundstr *b; + struct range abs; + struct range rel; + + abs.width = 0; + abs.height = 0; + b = &natp->nat_b[curr]; + abs.lx = b->b_xl; + abs.hx = b->b_xh; + abs.ly = b->b_yl; + abs.hy = b->b_yh; + xyrelrange(natp, &abs, &rel); + pr("Realm #%d is %d:%d,%d:%d\n", curr, + rel.lx, rel.hx, rel.ly, rel.hy); + +} + +int +real(void) +{ + register struct boundstr *rp; + struct natstr *natp; + int curr; + int lastr; + struct range abs; + s_char *realmp = player->argp[1]; + + natp = getnatp(player->cnum); + if (!realmp) { + curr = 0; + lastr = MAXNOR - 1; + } else { + if (*realmp == '#') + ++realmp; + if (!isdigit(*realmp)) + return RET_SYN; + curr = lastr = atoi(realmp); + if (curr < 0 || curr >= MAXNOR) { + pr("Realm number must be in the range 0:%d\n", + MAXNOR-1); + return RET_SYN; + } + } + abs.width = 0; + abs.height = 0; + if (player->argp[2] == 0) { + while (curr <= lastr) { + list_realm(curr, natp); + curr++; + } + } else { + if (sarg_type(player->argp[2]) != NS_AREA) + return RET_SYN; + if (!sarg_area(player->argp[2], &abs)) + return RET_SYN; + rp = &natp->nat_b[curr]; + rp->b_xl = abs.lx; + rp->b_xh = abs.hx - 1; + rp->b_yl = abs.ly; + rp->b_yh = abs.hy - 1; + natp->nat_b[curr] = *rp; + list_realm(curr, natp); + putnat(natp); + } + return RET_OK; +} +/* +dreal() +{ + struct natstr *natp; + int curr; + int lastr; + struct range abs; + struct range rel; + struct boundstr *b; + int nat; + s_char *rp = player->argp[1]; + + lastr = MAXNOR - 1; + curr = 0; + if (rp == 0) { + nat = player->cnum; + } else { + nat = atoi(rp); + if (nat < 0) + return RET_SYN; + if (nat >= MAXNOC) + return RET_SYN; + } + pr("Realms for %s (#%d)\n",cname(nat),nat); + natp = getnatp(nat); + abs.width = 0; + abs.height = 0; + while (curr <= lastr) { + b = &natp->nat_b[curr]; + abs.lx = b->b_xl; + abs.hx = b->b_xh; + abs.ly = b->b_yl; + abs.hy = b->b_yh; + xyrelrange(natp, &abs, &rel); + pr("Realm #%d is %d:%d,%d:%d\n", curr, + rel.lx, rel.hx, rel.ly, rel.hy); + curr++; + } + return RET_OK; +} +*/ diff --git a/src/lib/commands/reco.c b/src/lib/commands/reco.c new file mode 100644 index 00000000..df6902a4 --- /dev/null +++ b/src/lib/commands/reco.c @@ -0,0 +1,145 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * reco.c: Fly a recon mission + * + * Known contributors to this file: + * Dave Pare, 1986 + */ + +#include "misc.h" +#include "player.h" +#include "var.h" +#include "sect.h" +#include "ship.h" +#include "item.h" +#include "plane.h" +#include "nuke.h" +#include "xy.h" +#include "nsc.h" +#include "news.h" +#include "file.h" +#include "nat.h" +#include "path.h" +#include "commands.h" + +int +reco(void) +{ + s_char *p; + int mission_flags; + int tech; + coord tx, ty; + coord ax, ay; + int ap_to_target; + s_char flightpath[MAX_PATH_LEN]; + int cno; + struct nstr_item ni_bomb; + struct nstr_item ni_esc; + coord x, y; + struct sctstr target; + struct emp_qelem bomb_list; + struct emp_qelem esc_list; + int wantflags; + struct sctstr ap_sect; + s_char buf[1024]; + + wantflags = 0; + if (!snxtitem(&ni_bomb, EF_PLANE, player->argp[1])) + return RET_SYN; + if (!snxtitem(&ni_esc, EF_PLANE, getstarg(player->argp[2], "escort(s)? ", buf))) + pr("No escorts...\n"); + if ((p = getstarg(player->argp[3], "assembly point? ", buf)) == 0 || *p == 0) + return RET_SYN; + if (!sarg_xy(p, &x, &y) || !getsect(x, y, &ap_sect)) + return RET_SYN; + if (ap_sect.sct_own && ap_sect.sct_own != player->cnum && + getrel(getnatp(ap_sect.sct_own), player->cnum) != ALLIED) { + pr("Assembly point not owned by you or an ally!\n"); + return RET_SYN; + } + ax = x; + ay = y; + if (getpath(flightpath, player->argp[4], ax, ay, 0, 0, + 0, P_FLYING) == 0 || *p == 0) + return RET_SYN; + tx = ax; + ty = ay; + (void) pathtoxy(flightpath, &tx, &ty, fcost); + pr("target is %s\n", xyas(tx, ty, player->cnum)); + getsect(tx, ty, &target); + cno = -1; + mission_flags = 0; + if (pln_onewaymission(&target, &cno, &wantflags) < 0) + return RET_SYN; + ap_to_target = strlen(flightpath); + if (*(flightpath+strlen(flightpath)-1) == 'h') + ap_to_target--; + pr("range to target is %d\n", ap_to_target); + /* + * select planes within range + */ + pln_sel(&ni_bomb, &bomb_list, &ap_sect, ap_to_target, + 1, wantflags, P_M|P_O); + if (QEMPTY(&bomb_list)) { + pr("No planes could be equipped for the mission.\n"); + return RET_FAIL; + } + wantflags |= P_F; + wantflags |= P_ESC; + pln_sel(&ni_esc, &esc_list, &ap_sect, ap_to_target, + 1, wantflags, P_M|P_O); + /* + * now arm and equip the bombers, transports, whatever. + */ + tech=0; + mission_flags |= P_X; /* stealth (shhh) */ + mission_flags |= P_H; /* gets turned off if not all choppers */ + mission_flags |= P_A; + mission_flags = pln_arm(&bomb_list, ap_to_target, 'r', 0, P_S|P_I, mission_flags,&tech); + if (QEMPTY(&bomb_list)) { + pr("No planes could be equipped for the mission.\n"); + return RET_FAIL; + } + mission_flags = pln_arm(&esc_list, ap_to_target, 'r', 0, P_F, mission_flags,&tech); + mission_flags |= PM_R; + + if (*player->argp[0] == 's') + mission_flags |= PM_S; + + ac_encounter(&bomb_list,&esc_list,ax,ay,flightpath,mission_flags,0,0,0); + if (QEMPTY(&bomb_list)) { + pr("No planes got through fighter defenses\n"); + } else { + getsect(tx, ty, &target); + pln_newlanding(&bomb_list, tx, ty, cno); + pln_newlanding(&esc_list, tx, ty, cno); + } + pln_put(&bomb_list); + pln_put(&esc_list); + return RET_OK; +} diff --git a/src/lib/commands/reje.c b/src/lib/commands/reje.c new file mode 100644 index 00000000..99934045 --- /dev/null +++ b/src/lib/commands/reje.c @@ -0,0 +1,116 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * reje.c: Refuse telegrams/annos/treaties/loans from countries + * + * Known contributors to this file: + * + */ + +#include "misc.h" +#include "player.h" +#include "nat.h" +#include "news.h" +#include "file.h" +#include "xy.h" +#include "nsc.h" +#include "commands.h" +#include "optlist.h" + +int +reje(void) +{ + register s_char *p; + int rel; + int do_undo; + struct natstr nat; + struct nstr_item ni; + s_char buf[1024]; + + if ((p = getstarg(player->argp[1], "reject or accept? ", buf)) == 0) + return RET_SYN; + switch (*p) { + case 'r': + do_undo = 1; + break; + case 'a': + do_undo = 0; + break; + default: + pr("That's not one of the choices!\n"); + return RET_SYN; + } + if ((p = getstarg(player->argp[2], "mail, treaties, loans, or announcements? ", buf)) == 0) + return RET_SYN; + switch (*p) { + case 'a': + rel = REJ_ANNO; + break; + case 'l': + rel = REJ_LOAN; + break; + case 'm': + rel = REJ_TELE; + break; + case 't': + rel = REJ_TREA; + break; + default: + pr("That's not one of the choices!\n"); + return RET_SYN; + } + if (!snxtitem(&ni, EF_NATION, player->argp[3])) + return RET_SYN; + while (nxtitem(&ni, (s_char *) &nat)) { +#if 0 + if ((nat.nat_stat & STAT_NORM) == 0) { + pr("You may not reject/accept stuff from %s\nbecause they are not a normal country.\n", nat.nat_cnam); + continue; + } +#endif + if (nat.nat_stat & STAT_GOD) { + pr("You may not reject/accept stuff from %s\nbecause they are a deity.\n", nat.nat_cnam); + continue; + } + if (opt_HIDDEN) { + if (!getcontact(getnatp(player->cnum), ni.cur)) + continue; + } + switch(rel){ + case REJ_ANNO: pr("%s annos from %s\n",(do_undo == 1 ? "Rejecting" : "Accepting"),nat.nat_cnam); + break; + case REJ_LOAN: pr("%s loans from %s\n",(do_undo == 1 ? "Rejecting" : "Accepting"),nat.nat_cnam); + break; + case REJ_TELE: pr("%s teles from %s\n",(do_undo == 1 ? "Rejecting" : "Accepting"),nat.nat_cnam); + break; + case REJ_TREA: pr("%s treaties from %s\n",(do_undo == 1 ? "Rejecting" : "Accepting"),nat.nat_cnam); + break; + } + setrej(player->cnum, (natid)ni.cur, do_undo, rel); + } + return RET_OK; +} diff --git a/src/lib/commands/rela.c b/src/lib/commands/rela.c new file mode 100644 index 00000000..94223c9e --- /dev/null +++ b/src/lib/commands/rela.c @@ -0,0 +1,102 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * rela.c: Show relations with other countries + * + * Known contributors to this file: + * + */ + +#include "misc.h" +#include "player.h" +#include "var.h" +#include "nat.h" +#include "sect.h" +#include "file.h" +#include "xy.h" +#include "commands.h" +#include "optlist.h" + +/* + * report relations with other countries. + * Optional argument reports relations from the + * viewpoint of another country + */ +int +rela(void) +{ + struct natstr *natp; + struct natstr *np; + natid cn; + natid as; + int n; + + if (player->argp[1] == 0) + as = player->cnum; + else { + if ((n = natarg(player->argp[1], "Which country? ")) < 0) { + pr("Bad country number\n"); + return RET_SYN; + } + as = (natid) n; + } + if ((natp = getnatp(as)) == 0) { + pr("Bad country number %d\n", player->cnum); + return RET_SYN; + } + pr("\t%s Diplomatic Relations Report\t", cname(as)); + prdate(); + if (opt_SLOW_WAR) { + pr("\n Formal Relations %5s theirs\n", + player->cnum == as ? "yours" : "his"); + } else { + pr("\n Formal Relations %5s theirs\n", + player->cnum == as ? "yours" : "his"); + } + for (cn=1; cn < MAXNOC; cn++) { + if ((np = getnatp(cn)) == 0) + break; + if (cn == as) + continue; + if ((np->nat_stat & STAT_NORM) == 0 && + (np->nat_stat & STAT_SANCT) == 0) + continue; + if (opt_HIDDEN) { + if (!player->god && !getcontact(natp, cn)) + continue; + if (!player->god && !getcontact(getnatp(player->cnum), cn)) + continue; + } + pr("%3d) %-20.20s ", cn, cname(cn)); + if (opt_SLOW_WAR) { + pr("%-10s %s\n", relatename(natp, cn), relatename(np, as)); + } else { + pr("%-9s %s\n", relatename(natp, cn), relatename(np, as)); + } + } + return RET_OK; +} diff --git a/src/lib/commands/repa.c b/src/lib/commands/repa.c new file mode 100644 index 00000000..ddf2c127 --- /dev/null +++ b/src/lib/commands/repa.c @@ -0,0 +1,146 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * repa.c: repay loan from a country + * + * Known contributors to this file: + * + */ + +#include +#include "misc.h" +#include "player.h" +#include "nat.h" +#include "loan.h" +#include "news.h" +#include "file.h" +#include "commands.h" +#include "optlist.h" + +int +repa(void) +{ + struct lonstr loan; + struct natstr *natp; + struct natstr *loaner; + int loan_num; + long payment; + long owe; + long due; + long last_payment; + long normaltime; + long doubletime; + double rate_per_sec,amt; + s_char *cp; + time_t now; + s_char buf[1024]; + + if (!opt_LOANS) { + pr("Loans are not enabled.\n"); + return RET_FAIL; + } + natp = getnatp(player->cnum); + cp = getstarg(player->argp[1], "Repay loan #? ", buf); + if (cp == 0) + return RET_SYN; + loan_num = atoi(cp); + if (loan_num < 0) + return RET_SYN; + if (!getloan(loan_num, &loan) || loan.l_lonee != player->cnum + || loan.l_status != LS_SIGNED) { + pr("You don't owe anything on that loan.\n"); + return RET_FAIL; + } + (void) time(&now); + due = loan.l_duedate; + last_payment = loan.l_lastpay; + if (now < due) { + normaltime = now - last_payment; + doubletime = 0; + } + if (last_payment < due && due < now) { + normaltime = due - last_payment; + doubletime = now - due; + } + if (due < last_payment) { + normaltime = 0; + doubletime = now - last_payment; + } + rate_per_sec = loan.l_irate / + ((double) loan.l_ldur * SECS_PER_DAY * 100.0); + + owe = (long) (loan.l_amtdue * + ((double) normaltime * rate_per_sec + 1.0 + + (double) doubletime * rate_per_sec * 2.0) + 0.5); + amt = ((double) normaltime * rate_per_sec + 1.0 + + (double) doubletime * rate_per_sec * 2.0); + if (((1 << 30) / amt) < loan.l_amtdue) + owe = (1 << 30); + else + owe = (long) (loan.l_amtdue * + ((double) normaltime * rate_per_sec + 1.0 + + (double) doubletime * rate_per_sec * 2.0) + 0.5); + if ((cp = getstarg(player->argp[2], "amount? ", buf)) == 0) + return RET_SYN; + if (!check_loan_ok(&loan)) + return RET_FAIL; + payment = atoi(cp); + if (payment <= 0) + return RET_SYN; + if (payment > owe) { + pr("You don't owe that much.\n"); + return RET_FAIL; + } + if (natp->nat_money < payment) { + pr("You only have $%d.\n", natp->nat_money); + return RET_FAIL; + } + player->dolcost += payment; + loaner = getnatp(loan.l_loner); + loaner->nat_money += payment; + putnat(loaner); + (void) time(&loan.l_lastpay); + if (owe <= payment) { + wu(0, loan.l_loner, "Country #%d paid off loan #%d with $%d\n", + player->cnum, loan_num, payment); + nreport(player->cnum, N_REPAY_LOAN, loan.l_loner, 1); + loan.l_status = LS_FREE; + loan.l_ldur = 0; + pr("Congratulations, you've paid off the loan!\n"); + } else { + wu(0, loan.l_loner, + "Country #%d paid $%.2f on loan %d\n", player->cnum, + (double) payment, loan_num); + loan.l_amtdue = owe - payment; + loan.l_amtpaid += payment; + } + if (!putloan(loan_num, &loan)) { + pr("Can't save loan; get help!\n"); + return RET_SYS; + } + return RET_OK; +} diff --git a/src/lib/commands/repo.c b/src/lib/commands/repo.c new file mode 100644 index 00000000..f577565b --- /dev/null +++ b/src/lib/commands/repo.c @@ -0,0 +1,256 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * repo.c: Report on various levels (tech, research) of other nations + * + * Known contributors to this file: + * Keith Muller, 1983 + * Dave Pare, 1986 (rewrite) + * Steve McClure, 2000 + */ + +#include "misc.h" +#include "player.h" +#include "var.h" +#include "sect.h" +#include "nat.h" +#include "deity.h" +#include "file.h" +#include "xy.h" +#include "nsc.h" +#include +#include +#include "commands.h" +#include "optlist.h" + +struct stats { + double res; + double tech; + double edu; + double hap; + int stat; +}; + +static void printdiff(int mystat, double ours, struct natstr *natp, int what); +static void repo_header(void); +static void repo_list(struct stats *stat, natid cn, struct natstr *natp); + +static int check(s_char *buf, double theirs, double min, double max, int shift, int what, int tolerance); + +int +repo(void) +{ + struct natstr *natp; + struct stats mystat; + struct natstr nat; + struct nstr_item ni; + int first; + + if (!snxtitem(&ni, EF_NATION, player->argp[1])) + return RET_SYN; + prdate(); + natp = getnatp(player->cnum); + bzero((s_char *)&mystat, sizeof(struct stats)); + mystat.stat = natp->nat_stat; + if (mystat.stat & STAT_NORM) { + mystat.res = natp->nat_level[NAT_RLEV]; + mystat.tech = natp->nat_level[NAT_TLEV]; + mystat.edu = natp->nat_level[NAT_ELEV]; + mystat.hap = natp->nat_level[NAT_HLEV]; + } + if (opt_HIDDEN) { + repo_header(); + first = 0; + } else { + first = 1; + } + while (nxtitem(&ni, (s_char *) &nat)) { + if (!(nat.nat_stat & STAT_INUSE)) + continue; + if (opt_HIDDEN) { + if (!player->god && + !getcontact(getnatp(player->cnum), ni.cur)) + continue; + } + if (first) { + repo_header(); + first = 0; + } + repo_list(&mystat, (natid)ni.cur, &nat); + } + return RET_OK; +} + +static void +repo_header(void) +{ + pr(" # name tech research education happiness "); + if (player->god) + pr("capital\n"); + else { + if (opt_HIDDEN) + pr("\n"); + else + pr(" status\n"); + } +} + +static void +repo_list(struct stats *stat, natid cn, struct natstr *natp) +{ + struct sctstr cap; + + if (player->god) { + pr(" %-3d %-14.14s ", cn, natp->nat_cnam); + pr(" %7.2f %7.2f %7.2f %7.2f", + natp->nat_level[NAT_TLEV], + natp->nat_level[NAT_RLEV], + natp->nat_level[NAT_ELEV], + natp->nat_level[NAT_HLEV]); + prxy(" %4d,%-4d\n", natp->nat_xcap, natp->nat_ycap, + player->cnum); + return; + } + switch (natp->nat_stat & (STAT_NORM|STAT_GOD|STAT_NEW|STAT_SANCT)) { + case STAT_NORM: + case (STAT_NORM|STAT_SANCT): + pr(" %-3d %-14.14s ", cn, natp->nat_cnam); + printdiff(stat->stat, stat->tech, natp, NAT_TLEV); + printdiff(stat->stat, stat->res, natp, NAT_RLEV); + printdiff(stat->stat, stat->edu, natp, NAT_ELEV); + printdiff(stat->stat, stat->hap, natp, NAT_HLEV); + getsect(natp->nat_xcap, natp->nat_ycap, &cap); + if (opt_HIDDEN) { + pr("\n"); + } else { + if ((cap.sct_own != cn) || + (cap.sct_type != SCT_CAPIT && + cap.sct_type != SCT_MOUNT) || + (natp->nat_flags & NF_SACKED)) + pr("In flux\n"); + else if (natp->nat_money <= 0) + pr("Broke\n"); + else + pr("Active\n"); + } + break; + case STAT_SANCT: + break; + case STAT_NEW: + case 0: + break; + case STAT_SANCT|STAT_NORM|STAT_GOD: + case STAT_NORM|STAT_GOD: + case STAT_GOD: + break; + default: + pr("???? ???? ???? ????\n"); + break; + } +} + +static void +printdiff(int mystat, double ours, struct natstr *natp, int what) +{ + double theirs; + int shift; + int tolerance; + s_char buf[128]; + + if (natp->nat_cnum == player->cnum) { + pr(" %7.2f ", ours); + return; + } + if (ours && mystat & STAT_NORM && + natp->nat_stat &STAT_NORM) { + theirs = natp->nat_level[what]; + if ((shift = min((int)theirs, (int)ours) - 100) > 0) { + ours -= shift; + theirs -= shift; + } else + shift = 0; + switch (what) { + case NAT_TLEV: + tolerance = 20; break; + case NAT_RLEV: + tolerance = 10; break; + default: + tolerance = 5; + } + if (tolerance > 2 * ours) + tolerance = (int)(2 * ours); + if (check(buf, theirs, 2 * ours, -1.0, shift, what, tolerance)); + else if (check(buf, theirs, 1.5*ours, 2.0*ours, shift, what, tolerance)); + else if (check(buf, theirs, 1.2*ours, 1.5*ours, shift, what, tolerance)); + else if (check(buf, theirs, 1.1*ours, 1.2*ours, shift, what, tolerance)); + else if (check(buf, theirs, ours/1.1, 1.1*ours, shift, what, tolerance)); + else if (check(buf, theirs, ours/1.2, ours/1.1, shift, what, tolerance)); + else if (check(buf, theirs, ours/1.5, ours/1.2, shift, what, tolerance)); + else if (check(buf, theirs, ours/2.0, ours/1.5, shift, what, tolerance)); + else if (check(buf, theirs, -1.0, ours/2.0, shift, what, tolerance)); + else sprintf(buf, " n/a"); + } else + sprintf(buf, " n/a"); + + pr("%-11s ", buf); +} + +static int +check(s_char *buf, double theirs, double min, double max, int shift, int what, int tolerance) +{ + double shove; + + if (min < 0) { + if (theirs <= max) { + if (max < tolerance) + max = tolerance; + sprintf(buf, " 0 - %d", (int)max + shift); + return 1; + } + } else if (max < 0) { + if (theirs >= min) { + sprintf(buf, " >= %d", (int)min + shift); + return 1; + } + } else if (theirs >= min && theirs <= max) { + if (max - min < tolerance) { + shove = (tolerance - (max - min)) / 2; + if (min + shift - shove >= 0) { + min -= shove; + max += shove; + } else { + min = 0; + max = tolerance; + } + } + sprintf(buf, "%4d - %d", (int)min + shift, (int)max + shift); + return 1; + } + + return 0; +} + diff --git a/src/lib/commands/rese.c b/src/lib/commands/rese.c new file mode 100644 index 00000000..69f3df37 --- /dev/null +++ b/src/lib/commands/rese.c @@ -0,0 +1,150 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * rese.c: Reset (lower) commodity prices + * + * Known contributors to this file: + * Jeff Bailey + * Pat Loney, 1992 + * Steve McClure, 1996 + */ + +#include "misc.h" +#include "xy.h" +#include "file.h" +#include "var.h" +#include "sect.h" +#include "item.h" +#include "nsc.h" +#include "nat.h" +#include "land.h" +#include "nuke.h" +#include "plane.h" +#include "ship.h" +#include "trade.h" +#include /* bailey@math-cs.kent.edu */ +#include "commodity.h" +#include "player.h" +#include "commands.h" +#include "optlist.h" + +int +rese(void) +{ + struct comstr comm; + struct sctstr sect; + struct ichrstr *ix; + int number_set; + int m; + char *p; + float price; + time_t now; + s_char buf[1024]; + + if (!opt_MARKET) { + pr("The market is disabled.\n"); + return RET_FAIL; + } + check_market(); + check_trade(); + if ((p = getstarg(player->argp[1], "Which lot : ",buf)) == 0 || *p == 0) + return RET_SYN; + number_set = atoi(p); + getcomm(number_set, &comm); + if (comm.com_owner != player->cnum && !player->god) { + pr("That's not your lot.\n"); + return RET_OK; + } + if (comm.com_maxbidder != player->cnum && !player->god) { + pr("Some one already has a bid out on that\n"); + return RET_OK; + } + if ((p = getstarg(player->argp[2], "New (lower) price: ",buf)) == 0 || *p == 0) + return RET_SYN; + if (!check_comm_ok(&comm)) + return RET_FAIL; + price = (float)atof(p); + if (price <= 0) { + getsect(comm.sell_x, comm.sell_y, §); + if (!player->owner && !player->god) { + pr("The destination sector must be one of yours\n"); + return RET_OK; + } + if (player->god) { + if ((p = getstring("Really destroy that lot? ", buf)) == 0) + return RET_FAIL; + if (!check_comm_ok(&comm)) + return RET_FAIL; + if (*p == 'Y' || *p == 'y') { + comm.com_owner = 0; + putcomm(number_set, &comm); + pr("Goods destroyed.\n"); + return RET_OK; + } + return RET_FAIL; + } + if (sect.sct_type != SCT_HARBR && sect.sct_type != SCT_WAREH) { + pr("That sector is not available for receiving goods.\n"); + return RET_OK; + } + if (sect.sct_effic < 60) { + pr("The destination sector must be at least 60%% efficient.\n"); + return RET_OK; + } + ix = whichitem(comm.com_type); + sect.sct_x = comm.sell_x; + sect.sct_y = comm.sell_y; + m = getvar(ix->i_vtype, (char *)§, EF_SECTOR); + m = m + comm.com_amount; + if (m > 9999) + m = 9999; + putvar(ix->i_vtype, m, (char *)§, EF_SECTOR); + putsect(§); + comm.com_owner = 0; + putcomm(number_set, &comm); + pr("The goods have been returned to your trading post\n"); + return RET_OK; + } + if (price >= comm.com_price) { + pr("You can only lower the price.\n"); + return RET_OK; + } + if (price < 0){ + pr("New price must be greater than or equal to zero.\n"); + return RET_OK; + } + comm.com_price = price; + (void) time(&now); + comm.com_markettime = now; + if((int)price < comm.com_maxprice) + comm.com_maxprice = (int) price; + if(!putcomm(number_set, &comm)){ + pr("Problems with the commodities file, Call the Deity\n"); + return RET_OK; + } + return RET_OK; +} diff --git a/src/lib/commands/reso.c b/src/lib/commands/reso.c new file mode 100644 index 00000000..48ec3685 --- /dev/null +++ b/src/lib/commands/reso.c @@ -0,0 +1,106 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * reso.c: Display natural resources + * + * Known contributors to this file: + * Dave Pare, 1989 + */ + +#include "misc.h" +#include "player.h" +#include "var.h" +#include "xy.h" +#include "sect.h" +#include "nsc.h" +#include "nat.h" +#include "deity.h" +#include "path.h" +#include "file.h" +#include "commands.h" + +static void reso_hdr(void); + +int +reso(void) +{ + struct sctstr sect; + int nsect; + struct nstr_sect nstr; + + if (!snxtsct(&nstr, player->argp[1])) + return RET_SYN; + prdate(); + nsect = 0; + while (nxtsct(&nstr, §)) { + if (!player->owner) + continue; + if (nsect++ == 0) + reso_hdr(); + if (player->god) + pr("%3d ", sect.sct_own); + prxy("%4d,%-4d", nstr.x, nstr.y, player->cnum); + pr(" %c", dchr[sect.sct_type].d_mnem); + if (sect.sct_newtype != sect.sct_type) + pr("%c", dchr[sect.sct_newtype].d_mnem); + else + pr(" "); + pr("%4d%%", sect.sct_effic); + pr(" %4d", sect.sct_min); + pr("%5d", sect.sct_gmin); + pr("%5d", sect.sct_fertil); + pr("%4d", sect.sct_oil); + pr("%5d", sect.sct_uran); +/* pr("%5d", sect.sct_elev);*/ + if (!player->god && sect.sct_terr) + pr("%4d", sect.sct_terr); + pr("\n"); + } + if (nsect == 0) { + if (player->argp[1]) + pr("%s: No sector(s)\n", player->argp[1]); + else + pr("%s: No sector(s)\n", ""); + return RET_FAIL; + }else + pr("%d sector%s\n", nsect, splur(nsect)); + return 0; +} + +static void +reso_hdr(void) +{ + if (player->god) + pr(" "); + pr("RESOURCE\n"); + if (player->god) + pr("own "); + pr(" sect eff min gold fert oil uran "); + if (!player->god) + pr("ter"); + pr("\n"); +} diff --git a/src/lib/commands/retr.c b/src/lib/commands/retr.c new file mode 100644 index 00000000..8754192b --- /dev/null +++ b/src/lib/commands/retr.c @@ -0,0 +1,301 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * retr.c: Set retreat conditionals for ships + * + * Known contributors to this file: + * Ken Stevens, 1995 + * Steve McClure, 2000 + */ + +#include "options.h" +#include "misc.h" +#include "player.h" +#include "var.h" +#include "xy.h" +#include "sect.h" +#include "retreat.h" +#include "ship.h" +#include "land.h" +#include "nat.h" +#include "nsc.h" +#include "deity.h" +#include "file.h" +#include "path.h" +#include "commands.h" + +int +retr(void) +{ + s_char *pq, *fl; + int nships; + struct nstr_item ni; + struct shpstr ship; + int isfleet=0, rflags=(-2),zero; + unsigned int x; + s_char buf1[1024]; + s_char buf2[1024]; + + if (!snxtitem(&ni, EF_SHIP, player->argp[1])) + return RET_SYN; + nships = 0; + if (player->argp[1] != (s_char *)0) + if (isalpha(player->argp[1][0])) + isfleet=1; + if (player->argp[2] != (s_char *)0) + pq = getstarg(player->argp[2], "Retreat path? ", buf1); + else + pq = (s_char *)0; + + if (pq != (s_char *)0){ + fl = getstarg(player->argp[3], "Retreat conditions [i|t|s|h|b|d|u|c]? ", buf2); + if (!fl) + return RET_SYN; + rflags=0|isfleet; + + for(x=0;xowner || ship.shp_own == 0) + continue; + if (ship.shp_type < 0 || ship.shp_type > shp_maxno) { + pr("bad ship type %d (#%d)\n", + ship.shp_type, ni.cur); + continue; + } + if (zero) + bzero(ship.shp_rpath,RET_LEN); + + if (pq != (s_char *)0){ + bzero(ship.shp_rpath,RET_LEN); + bcopy(pq,ship.shp_rpath,strlen(pq)); + putship(ship.shp_uid,&ship); + } + if (rflags >= 0){ + ship.shp_rflags = rflags; + putship(ship.shp_uid,&ship); + } + if (nships++ == 0) { + if (player->god) + pr("own "); + pr("shp# ship type x,y fl path as flt? flags\n"); + } + if (player->god) + pr("%3d ", ship.shp_own); + pr("%4d ", ni.cur); + pr("%-16.16s ", mchr[(int)ship.shp_type].m_name); + prxy("%4d,%-4d ", ship.shp_x, ship.shp_y, player->cnum); + pr("%1c", ship.shp_fleet); + pr(" %-11s", ship.shp_rpath); + if (ship.shp_rflags & RET_GROUP) + pr("Yes "); + else + pr(" "); + if (ship.shp_rflags & RET_INJURED) + pr("I"); + if (ship.shp_rflags & RET_TORPED) + pr("T"); + if (ship.shp_rflags & RET_SONARED) + pr("S"); + if (ship.shp_rflags & RET_HELPLESS) + pr("H"); + if (ship.shp_rflags & RET_BOMBED) + pr("B"); + if (ship.shp_rflags & RET_DCHRGED) + pr("D"); + if (ship.shp_rflags & RET_BOARDED) + pr("U"); + pr("\n"); + } + if (nships == 0) { + if (player->argp[1]) + pr("%s: No ship(s)\n", player->argp[1]); + else + pr("%s: No ship(s)\n", ""); + return RET_FAIL; + }else + pr("%d ship%s\n", nships, splur(nships)); + return RET_OK; +} + +int +lretr(void) +{ + s_char *pq, *fl; + int nunits; + struct nstr_item ni; + struct lndstr land; + int isarmy=0, rflags=(-2),zero; + s_char buf1[1024]; + s_char buf2[1024]; + unsigned int x; + + if (!snxtitem(&ni, EF_LAND, player->argp[1])) + return RET_SYN; + nunits = 0; + if (player->argp[1] != (s_char *)0) + if (isalpha(player->argp[1][0])) + isarmy=1; + if (player->argp[2] != (s_char *)0) + pq = getstarg(player->argp[2], "Retreat path? ", buf1); + else + pq = (s_char *)0; + if (pq != (s_char *)0){ + fl = getstarg(player->argp[3], "Retreat conditions [i|h|b|c]? ", buf2); + if (!fl) + return RET_SYN; + rflags=0|isarmy; + + for(x=0;xowner || land.lnd_own == 0) + continue; + if (land.lnd_type < 0 || land.lnd_type > lnd_maxno) { + pr("bad unit type %d (#%d)\n", + land.lnd_type, ni.cur); + continue; + } + if (zero) + bzero(land.lnd_rpath,RET_LEN); + + if (pq != (s_char *)0){ + bzero(land.lnd_rpath,RET_LEN); + bcopy(pq,land.lnd_rpath,strlen(pq)); + putland(land.lnd_uid,&land); + } + if (rflags >= 0){ + land.lnd_rflags = rflags; + putland(land.lnd_uid,&land); + } + + if (nunits++ == 0) { + if (player->god) + pr("own "); + pr("lnd# unit type x,y ar path as army? flags\n"); + } + if (player->god) + pr("%3d ", land.lnd_own); + pr("%4d ", ni.cur); + pr("%-16.16s ", lchr[(int)land.lnd_type].l_name); + prxy("%4d,%-4d ", land.lnd_x, land.lnd_y, player->cnum); + pr("%1c", land.lnd_army); + pr(" %-11s", land.lnd_rpath); + if (land.lnd_rflags & RET_GROUP) + pr("Yes "); + else + pr(" "); + if (land.lnd_rflags & RET_INJURED) + pr("I"); + if (land.lnd_rflags & RET_TORPED) + pr("T"); + if (land.lnd_rflags & RET_SONARED) + pr("S"); + if (land.lnd_rflags & RET_HELPLESS) + pr("H"); + if (land.lnd_rflags & RET_BOMBED) + pr("B"); + if (land.lnd_rflags & RET_DCHRGED) + pr("D"); + if (land.lnd_rflags & RET_BOARDED) + pr("U"); + pr("\n"); + } + if (nunits == 0) { + if (player->argp[1]) + pr("%s: No unit(s)\n", player->argp[1]); + else + pr("%s: No unit(s)\n", ""); + return RET_FAIL; + } + pr("%d unit%s\n", nunits, splur(nunits)); + return RET_OK; +} diff --git a/src/lib/commands/rout.c b/src/lib/commands/rout.c new file mode 100644 index 00000000..43fd42e5 --- /dev/null +++ b/src/lib/commands/rout.c @@ -0,0 +1,141 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * rout.c: Show empire deliver routes + * + * Known contributors to this file: + * + */ + +#include "misc.h" +#include "player.h" +#include "var.h" +#include "xy.h" +#include "nat.h" +#include "nsc.h" +#include "sect.h" +#include "item.h" +#include "path.h" +#include "file.h" +#include "map.h" +#include "commands.h" +#include "optlist.h" + +int +rout(void) +{ + struct ichrstr *ip; + struct nstr_sect ns; + struct natstr *natp; + struct sctstr sect; + struct nscstr cond[NS_NCOND]; + int ncond; + struct range relrange; + int row; + int y; + int ry; + int i_del; + int dir; + s_char *p; + s_char what[64]; + s_char *str; + s_char buf1[1024]; + /* Note this is not re-entrant anyway, so we keep the buffers + around */ + static s_char *mapbuf = (s_char *)0; + static s_char **map = (s_char **)0; + static s_char *buf = (s_char *)0; + int i; + + if ((ip = whatitem(player->argp[1], "What item? ")) == 0) + return RET_SYN; + i_del = V_DEL(ip-ichr); + if(player->argp[2] == (s_char *) 0) { + if ((str = getstring("(sects)? ", buf1)) == 0) + return RET_SYN; + } else { + str = player->argp[2]; + } + if(*str == '*') { + sprintf(what, "%d:%d,%d:%d", + -WORLD_X/2, WORLD_X/2-1, + -WORLD_Y/2, WORLD_Y/2-1); + if (!snxtsct(&ns, what)) + return RET_FAIL; + } else if (!snxtsct(&ns, str)) + return RET_FAIL; + if (!mapbuf) + mapbuf = (s_char *)malloc((WORLD_Y*MAPWIDTH(3))*sizeof(s_char)); + if (!map) { + map = (s_char **)malloc(WORLD_Y * sizeof(s_char *)); + if (map && mapbuf) { + for (i = 0; i < WORLD_Y; i++) + map[i] = &mapbuf[MAPWIDTH(3) * i]; + } else if (map) { + free((s_char *)map); + map = (s_char **)0; + } + } + if (!buf) + buf = (s_char *)malloc((MAPWIDTH(3) + 12) * sizeof(s_char)); + if (!mapbuf || !map || !buf) { + pr("Memory error, tell the deity.\n"); + logerror("malloc failed in rout\n"); + return RET_FAIL; + } + ncond = ns.ncond; + bcopy((s_char *)ns.cond, (s_char *)cond, sizeof(struct nscstr) * ncond); + ns.ncond = 0; + + natp = getnatp(player->cnum); + xyrelrange(natp, &ns.range, &relrange); + bzero((s_char *)mapbuf,((WORLD_Y * MAPWIDTH(3)) * sizeof(s_char))); + blankfill((s_char *)mapbuf, &ns.range, 3); + border(&relrange, " ", " "); + + while (nxtsct(&ns, §)) { + if (!player->owner) + continue; + p = &map[ns.dy][ns.dx*2]; + if ((dir = getvar(i_del, (s_char *)§, EF_SECTOR) & 0x7) && + nstr_exec(cond, ncond, (s_char *)§, EF_SECTOR)) + bcopy(routech[dir][0], p, 3); + p[1] = dchr[sect.sct_type].d_mnem; + } + for (row = 0, y = ns.range.ly; row < ns.range.height; y++,row++) { + ry = yrel(natp, y); + bzero(buf,(MAPWIDTH(3) + 10) * sizeof(s_char)); + sprintf(buf,"%4d ",ry); + bcopy(map[row],buf+5,ns.range.width*2+1); + sprintf(buf+5+ns.range.width*2+1," %-4d\n",ry); + pr("%s", buf); + if (y >= WORLD_Y) + y -= WORLD_Y; + } + border(&relrange, " ", " "); + return RET_OK; +} diff --git a/src/lib/commands/sabo.c b/src/lib/commands/sabo.c new file mode 100644 index 00000000..950f0ba6 --- /dev/null +++ b/src/lib/commands/sabo.c @@ -0,0 +1,130 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * sabo.c: Spy terrorist bombing + * + * Known contributors to this file: + * John Yockey, 2001 + */ + +/* +#include +#include "player.h" +#include "sect.h" +#include "news.h" +#include "xy.h" +#include "nat.h" +#include "path.h" +#include "deity.h" +#include "map.h" +#include "commands.h" +*/ + +#include "misc.h" +#include "var.h" +#include "land.h" +#include "nsc.h" +#include "file.h" + +int +sabo(void) +{ + struct nstr_item ni; + struct lndstr land; + struct sctstr sect; + double odds; + int vec[I_MAX+1]; + int dam; + + if (!snxtitem(&ni, EF_LAND, player->argp[1])) + return RET_SYN; + + while (nxtitem(&ni, (s_char *)&land)) { + if (!player->owner) continue; + if (!(lchr[(int)land.lnd_type].l_flags & L_SPY)) { + pr("%s is not a spy.\n", prland(&land)); + continue; + } + if (land.lnd_ship >= 0) { + pr("%s is on ship %d.\n", prland(&land), + land.lnd_ship); + continue; + } + if (land.lnd_land >= 0) { + pr("%s is on unit %d.\n", prland(&land), + land.lnd_land); + continue; + } + if (!getsect(land.lnd_x, land.lnd_y, §)) continue; + getvec(VT_ITEM, vec, (s_char *)&land, EF_LAND); + if (vec[I_SHELL] == 0) { + pr("%s has no shells.\n", prland(&land)); + continue; + } + putvar(V_SHELL, vec[I_SHELL] - 1, (s_char *)&land, EF_LAND); + + odds = (100 - land.lnd_effic) / 100.0 + .10; + if (chance(odds)) { + wu(0, sect.sct_own, + "%s spy shot in %s during sabotage attempt.\n", + cname(player->cnum), + xyas(sect.sct_x, sect.sct_y, sect.sct_own)); + pr("%s was shot and killed.\n", prland(&land)); + land.lnd_effic = 0; + putland(land.lnd_uid, &land); + continue; + } + + land.lnd_own = 0; + putland(land.lnd_uid, &land); + + getvec(VT_ITEM, vec, (s_char *)§, EF_SECTOR); + dam = landgun(3*land.lnd_effic, 7); + if (vec[I_SHELL] > 20) + dam += seagun(land.lnd_effic, random() % (vec[I_SHELL] / 10)); + if (vec[I_PETROL] > 100) + dam += seagun(land.lnd_effic, random() % (vec[I_PETROL] / 50)); + + pr("Explosion in %s causes %d damage.\n", + xyas(land.lnd_x, land.lnd_y, land.lnd_own), dam); + if (sect.sct_own) { + wu(0, sect.sct_own, + "Sabotage in sector %s caused %d damage.\n", + xyas(sect.sct_x, sect.sct_y, sect.sct_own), dam); + } + sectdamage(§, dam, 0); + putsect(§); + + land.lnd_own = player->cnum; + if (chance(odds)) { + pr("%s dies in explosion.\n", prland(&land)); + land.lnd_effic = 0; + } + putland(land.lnd_uid, &land); + } + return RET_OK; +} diff --git a/src/lib/commands/sail.c b/src/lib/commands/sail.c new file mode 100644 index 00000000..ad6ed7e9 --- /dev/null +++ b/src/lib/commands/sail.c @@ -0,0 +1,183 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * sail.c: Set sail path for leaders + * + * Known contributors to this file: + * Robert Forsman + */ + +#include +#include "misc.h" +#include "player.h" +#include "var.h" +#include "ship.h" +#include "path.h" +#include "xy.h" +#include "nsc.h" +#include "file.h" +#include "nat.h" +#include "deity.h" +#include "commands.h" +#include "optlist.h" + +static int +show_sail(struct nstr_item *nstr) +{ + register int count=0; + struct shpstr ship; + + while (nxtitem(nstr, (s_char *)&ship)) { + if (!player->owner || ship.shp_own==0) + continue; + if (ship.shp_type < 0 || ship.shp_type > shp_maxno) { + pr("bad ship type %d (#%d)\n", + ship.shp_type, nstr->cur); + continue; + } + if (count++==0) { + if (player->god) + pr("own "); + pr("shp# ship type x,y "); + pr("mobil mobquota follows path\n"); + } + if (player->god) + pr("%3d ",ship.shp_own); + pr("%4d ", ship.shp_uid); + pr("%-16.16s ", mchr[(int)ship.shp_type].m_name); + prxy("%4d,%-4d ", ship.shp_x, ship.shp_y, player->cnum); + pr("%3d ",ship.shp_mobil); + pr(" %3d ",ship.shp_mobquota); + pr(" %3d ",ship.shp_follow); + if (ship.shp_path[0]) { + pr(ship.shp_path); + } else if ((ship.shp_autonav & AN_AUTONAV)) { + pr("Has orders"); + } + pr("\n"); + if (opt_SHIPNAMES) { + if (ship.shp_name[0] != 0) { + if (player->god) + pr(" "); + pr(" %s\n",ship.shp_name); + } + } + } + if (count == 0) { + if (player->argp[1]) + pr("%s: No ship(s)\n", player->argp[1]); + else + pr("%s: No ship(s)\n", ""); + return RET_FAIL; + }else + pr("%d ship%s\n", count, splur(count)); + return RET_OK; +} + +static int +cmd_unsail_ship(struct nstr_item *nstr) +{ + struct shpstr ship; + int count = 0; + + while (nxtitem(nstr, (s_char *)&ship)) { + if (!player->owner || ship.shp_own==0) + continue; + if (ship.shp_type < 0 || ship.shp_type > shp_maxno) { + pr("bad ship type %d (#%d)\n", + ship.shp_type, nstr->cur); + continue; + } + if (ship.shp_path[0]) { + pr("Ship #%d unsailed\n",ship.shp_uid); + count++; + ship.shp_path[0] = 0; + putship(ship.shp_uid, &ship); + } + } + return RET_OK; +} + +static int +cmd_sail_ship(struct nstr_item *nstr) +{ + s_char *cp; + struct shpstr ship; + char navpath[MAX_PATH_LEN]; + + while (!player->aborted && nxtitem(nstr, (s_char *)&ship)) { + if (!player->owner || ship.shp_own==0) + continue; + if (ship.shp_type < 0 || ship.shp_type > shp_maxno) { + pr("bad ship type %d (#%d)\n", + ship.shp_type, nstr->cur); + continue; + } + if ((ship.shp_autonav & AN_AUTONAV) && + !(ship.shp_autonav & AN_STANDBY)) { + pr("Ship #%d has other orders!\n", + ship.shp_uid); + continue; + } + + pr("Ship #%d at %s\n", ship.shp_uid, + xyas(ship.shp_x,ship.shp_y,ship.shp_own)); + cp = getpath(navpath, player->argp[2], + ship.shp_x, ship.shp_y, 0, 0, 0, P_SAILING); + if (!check_ship_ok(&ship)) + continue; + if (!player->aborted) { + bzero(ship.shp_path, sizeof(ship.shp_path)); + strncpy(ship.shp_path, cp, sizeof(ship.shp_path)-2); + ship.shp_mission = 0; + putship(ship.shp_uid, &ship); + } + } + return RET_OK; +} + +int +sail(void) +{ + s_char *cp; + struct nstr_item nstr; + + if (!opt_SAIL) { + pr("The SAIL option is not enabled, so this command is not valid.\n"); + return RET_FAIL; + } + if (!snxtitem(&nstr, EF_SHIP, player->argp[1])) + return RET_SYN; + cp = player->argp[2]; + if ( (*player->argp[0]=='q')/*qsail command*/ || (cp && *cp=='q') ) { + return(show_sail(&nstr)); + } else if ( *player->argp[0]=='u' /*unsail command*/ || (cp && *cp=='-')) { + return(cmd_unsail_ship(&nstr)); + } else + return(cmd_sail_ship(&nstr)); +} + diff --git a/src/lib/commands/sate.c b/src/lib/commands/sate.c new file mode 100644 index 00000000..a2896073 --- /dev/null +++ b/src/lib/commands/sate.c @@ -0,0 +1,109 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * sate.c: Do satellite maps/reports. + * + * Known contributors to this file: + * Edward M. Rynes Esq, 1988 + * Ken Stevens, 1995 + * Steve McClure, 1998-2000 + */ + +#include "misc.h" +#include "player.h" +#include "var.h" +#include "xy.h" +#include "plane.h" +#include "sect.h" +#include "nsc.h" +#include "file.h" +#include "nat.h" +#include "commands.h" + +int +sate(void) +{ + extern int plane_mob_max; + double tech; + int pln_uid; + struct plnstr plane; + int type = EF_BAD; + + if (!player->argp[1] || + !*player->argp[1] || + !isdigit(*player->argp[1]) || + (pln_uid = atoi(player->argp[1])) < 0) + return RET_SYN; + + if (!getplane(pln_uid, &plane)) { + pr("No such plane\n"); + return RET_FAIL; + } + + if (plane.pln_own != player->cnum && !player->god) { + pr("You don't own plane #%d\n", pln_uid); + return RET_FAIL; + } + + if (!(plane.pln_flags & PLN_LAUNCHED)) { + pr("%s isn't in orbit\n", + prplane(&plane)); + return RET_FAIL; + } + if (plane.pln_mobil < plane_mob_max) { + pr("%s doesn't have enough mobility (needs %d)\n", + prplane(&plane), + plane_mob_max); + return RET_FAIL; + } + if (player->argp[2]) { + switch (*player->argp[2]) { + case 'l': + type = EF_LAND; + break; + case 's': + if (*(player->argp[2] + 1) == 'e') + type = EF_SECTOR; + else + type = EF_SHIP; + break; + default: + return RET_SYN; + } + } + + if (plchr[(int)plane.pln_type].pl_flags & P_S) + pr("Satellite Spy Report:\n"); + else + pr("Satellite Map Report:\n"); + pr("%s at ", prplane(&plane)); + tech = techfact(plane.pln_tech, 20.0); + satmap(plane.pln_x, plane.pln_y, plane.pln_effic, + (int)tech, plchr[(int)plane.pln_type].pl_flags, type); + + return RET_OK; +} diff --git a/src/lib/commands/scra.c b/src/lib/commands/scra.c new file mode 100644 index 00000000..03497266 --- /dev/null +++ b/src/lib/commands/scra.c @@ -0,0 +1,341 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * scra.c: Scrap ships, planes or land units + * + * Known contributors to this file: + * Steve McClure, 2000 + * + */ + +#include "misc.h" +#include "player.h" +#include "var.h" +#include "xy.h" +#include "sect.h" +#include "ship.h" +#include "plane.h" +#include "land.h" +#include "nat.h" +#include "nsc.h" +#include "deity.h" +#include "file.h" +#include "commands.h" +#include "optlist.h" + +union item_u { + struct shpstr ship; + struct plnstr plane; + struct lndstr land; +}; + +int +scra(void) +{ + struct nstr_item ni; + union item_u item; + int vec[I_MAX+1]; + int itemvec[I_MAX+1]; + int type; + struct sctstr sect; + struct mchrstr *mp; + struct plchrstr *pp; + struct lchrstr *lp; + s_char *p; + int i; + struct nstr_item ni2; + struct plnstr plane; + struct lndstr land; + struct sctstr sect2; + s_char prompt[128]; + s_char buf[1024]; + float eff; + + if (!(p = getstarg(player->argp[1], "Ship, land, or plane? ", buf))) + return RET_SYN; + switch (*p) { + case 's': + type = EF_SHIP; break; + case 'p': + type = EF_PLANE; break; + case 'l': + type = EF_LAND; break; + default: + pr("Ships, land units, or planes only! (s, l, p)\n"); + return RET_SYN; + } + sprintf(prompt, "%s(s)? ", ef_nameof(type)); + if ((p = getstarg(player->argp[2], prompt, buf)) == 0) + return RET_SYN; + if (!snxtitem(&ni, type, p)) + return RET_SYN; + if (p && (isalpha(*p) || (*p == '*') || (*p == '~') || issector(p) + || islist(p))){ + s_char y_or_n[80], bbuf[80]; + + bzero(y_or_n, 80); + if (type == EF_SHIP) { + if (*p == '*') + sprintf(bbuf,"all ships"); + else if (*p == '~') + sprintf(bbuf,"all unassigned ships"); + else if (issector(p)) + sprintf(bbuf,"all ships in %s",p); + else if (isalpha(*p)) + sprintf(bbuf,"fleet %c",*p); + else + sprintf(bbuf,"ships %s",p); + } else if (type == EF_LAND) { + if (*p == '*') + sprintf(bbuf,"all land units"); + else if (*p == '~') + sprintf(bbuf,"all unassigned land units"); + else if (issector(p)) + sprintf(bbuf,"all units in %s",p); + else if (isalpha(*p)) + sprintf(bbuf,"army %c",*p); + else + sprintf(bbuf,"units %s",p); + } else { + if (*p == '*') + sprintf(bbuf,"all planes"); + else if (*p == '~') + sprintf(bbuf,"all unassigned planes"); + else if (issector(p)) + sprintf(bbuf,"all planes in %s",p); + else if (isalpha(*p)) + sprintf(bbuf,"wing %c",*p); + else + sprintf(bbuf,"planes %s",p); + } + + sprintf(y_or_n,"Really scrap %s [n]? ", bbuf); + if (!confirm(y_or_n)) + return RET_FAIL; + } + while (nxtitem(&ni, (s_char *)&item)) { + if (!player->owner) + continue; + + if (opt_MARKET) { + if (ontradingblock(type, (int *)&item.ship)) { + pr("You cannot scrap an item on the trading block!\n"); + continue; + } + } + + if (type == EF_SHIP) { + getsect(item.ship.shp_x, item.ship.shp_y, §); + if (sect.sct_type != SCT_HARBR) + continue; + if (sect.sct_effic < 60 || sect.sct_own != player->cnum) + continue; + } else if (type == EF_LAND) { + if (item.land.lnd_ship >= 0) { + pr("%s is on a ship, and cannot be scrapped!\n", prland(&item.land)); + continue; + } + getsect(item.land.lnd_x, item.land.lnd_y, §); + } else { + getsect(item.plane.pln_x, item.plane.pln_y, §); + if (sect.sct_type != SCT_AIRPT) + continue; + if (sect.sct_effic < 60 || + (sect.sct_own != player->cnum && + getrel(getnatp(sect.sct_own),player->cnum) < FRIENDLY)) + continue; + } + getvec(VT_ITEM, vec, (s_char *)§, EF_SECTOR); + if (type == EF_SHIP) { + eff = ((float)item.ship.shp_effic/100.0); + mp = &mchr[(int)item.ship.shp_type]; + if (opt_TRADESHIPS) { + if (mp->m_flags & M_TRADE) { + pr("WARNING: You only collect money from trade ships if you \"scuttle\" them!\n"); + sprintf(prompt, "Are you really sure that you want to scrap %s (n)? ", prship(&item.ship)); + if (!confirm(prompt)) { + pr("%s not scrapped\n", prship(&item.ship)); + continue; + } + } + } + pr("%s", prship(&item.ship)); + getvec(VT_ITEM, itemvec, (s_char *)&item.ship, EF_SHIP); + for (i = 1; i <= I_MAX; i++) { + vec[i] += itemvec[i]; + } + vec[I_LCM] += mp->m_lcm * 2 / 3 * eff; + vec[I_HCM] += mp->m_hcm * 2 / 3 * eff; + getsect(item.ship.shp_x,item.ship.shp_y,§2); + snxtitem_all(&ni2, EF_PLANE); + while (nxtitem(&ni2, (s_char *)&plane)){ + if (plane.pln_own == 0) + continue; + if (plane.pln_ship == item.ship.shp_uid){ + wu(0 ,plane.pln_own, + "Plane %d transferred off ship %d to %s\n", + ni2.cur, item.ship.shp_uid, + xyas(plane.pln_x, plane.pln_y,player->cnum)); + plane.pln_ship = -1; + if(sect2.sct_own != plane.pln_own) { + wu(0, plane.pln_own, + "%s given to %s\n", prplane(&plane), + cname(sect2.sct_own)); + wu(0, sect2.sct_own, + "%s given to you by %s\n", prplane(&plane), + cname(player->cnum)); + } + makelost(EF_PLANE, plane.pln_own, plane.pln_uid, + plane.pln_x, plane.pln_y); + plane.pln_own = sect2.sct_own; + makenotlost(EF_PLANE, plane.pln_own, plane.pln_uid, + plane.pln_x, plane.pln_y); + putplane(plane.pln_uid, (s_char *)&plane); + } + } + snxtitem_all(&ni2, EF_LAND); + while (nxtitem(&ni2, (s_char *)&land)){ + if (land.lnd_own == 0) + continue; + if (land.lnd_ship == item.ship.shp_uid){ + wu(0, land.lnd_own, + "Land unit %d transferred off ship %d to %s\n", + ni2.cur, item.ship.shp_uid, + xyas(land.lnd_x, land.lnd_y,player->cnum)); + land.lnd_ship = -1; + if(sect2.sct_own != land.lnd_own){ + wu(0, land.lnd_own, + "%s given to %s\n", prland(&land), + cname(sect2.sct_own)); + wu(0, sect2.sct_own, + "%s given to you by %s\n", prland(&land), + cname(player->cnum)); + } + makelost(EF_LAND, land.lnd_own, land.lnd_uid, + land.lnd_x, land.lnd_y); + land.lnd_own = sect2.sct_own; + makenotlost(EF_LAND, land.lnd_own, land.lnd_uid, + land.lnd_x, land.lnd_y); + putland(land.lnd_uid, (s_char *)&land); + } + } + makelost(EF_SHIP, item.ship.shp_own, item.ship.shp_uid, + item.ship.shp_x, item.ship.shp_y); + item.ship.shp_own = 0; + putship(item.ship.shp_uid, (s_char *)&item.ship); + } else if (type == EF_LAND) { + eff = ((float)item.land.lnd_effic/100.0); + lp = &lchr[(int)item.land.lnd_type]; + pr("%s", prland(&item.land)); + getvec(VT_ITEM, itemvec, (s_char *)&item.land, EF_LAND); + for (i = 1; i <= I_MAX; i++) { + vec[i] += itemvec[i]; + } +/* Military, guns and shells are not required to build land units */ +/* vec[I_MILIT] += total_mil(&item.land);*/ +/* vec[I_GUN] += lp->l_gun * 2 / 3 * eff;*/ +/* vec[I_SHELL] += lp->l_shell * 2 / 3 * eff;*/ + vec[I_LCM] += lp->l_lcm * 2 / 3 * eff; + vec[I_HCM] += lp->l_hcm * 2 / 3 * eff; + getsect(item.land.lnd_x,item.land.lnd_y,§2); + + snxtitem_all(&ni2, EF_LAND); + while (nxtitem(&ni2, (s_char *)&land)){ + if (land.lnd_own == 0) + continue; + if (land.lnd_land == item.land.lnd_uid){ + wu(0, land.lnd_own, + "Land unit %d transferred off land unit %d to %s\n", + land.lnd_uid, item.land.lnd_uid, + xyas(land.lnd_x, land.lnd_y,player->cnum)); + land.lnd_land = -1; + if (sect2.sct_own != land.lnd_own) { + wu(0, land.lnd_own, + "%s given to %s\n", prland(&land), + cname(sect2.sct_own)); + wu(0, sect2.sct_own, + "%s given to you by %s\n", prland(&land), + cname(player->cnum)); + } + makelost(EF_LAND, land.lnd_own, land.lnd_uid, + land.lnd_x, land.lnd_y); + land.lnd_own = sect2.sct_own; + makenotlost(EF_LAND, land.lnd_own, land.lnd_uid, + land.lnd_x, land.lnd_y); + putland(land.lnd_uid, (s_char *)&land); + } + } + + snxtitem_all(&ni2, EF_PLANE); + while (nxtitem(&ni2, (s_char *)&plane)) { + if (plane.pln_own == 0) + continue; + if (plane.pln_land == item.land.lnd_uid){ + wu(0, plane.pln_own, + "Plane %d transferred off land unit %d to %s\n", + ni2.cur, item.land.lnd_uid, + xyas(plane.pln_x, plane.pln_y,player->cnum)); + plane.pln_land = -1; + if(sect2.sct_own != plane.pln_own) { + wu(0, plane.pln_own, + "%s given to %s\n", prplane(&plane), + cname(sect2.sct_own)); + wu(0, sect2.sct_own, + "%s given to you by %s\n", prplane(&plane), + cname(player->cnum)); + } + makelost(EF_PLANE, plane.pln_own, plane.pln_uid, + plane.pln_x, plane.pln_y); + plane.pln_own = sect2.sct_own; + makenotlost(EF_PLANE, plane.pln_own, plane.pln_uid, + plane.pln_x, plane.pln_y); + putplane(plane.pln_uid, (s_char *)&plane); + } + } + makelost(EF_LAND, item.land.lnd_own, item.land.lnd_uid, + item.land.lnd_x, item.land.lnd_y); + item.land.lnd_own = 0; + putland(item.land.lnd_uid, (s_char *)&item.land); + } else { + eff = ((float)item.land.lnd_effic/100.0); + pp = &plchr[(int)item.plane.pln_type]; + pr("%s", prplane(&item.plane)); + vec[I_LCM] += pp->pl_lcm * 2 / 3 * eff; + vec[I_HCM] += pp->pl_hcm * 2 / 3 * eff; + vec[I_MILIT] += pp->pl_crew; + makelost(EF_PLANE, item.plane.pln_own, item.plane.pln_uid, + item.plane.pln_x, item.plane.pln_y); + item.plane.pln_own = 0; + putplane(item.plane.pln_uid, (s_char *)&item.plane); + } + pr(" scrapped in %s\n", + xyas(sect.sct_x, sect.sct_y, player->cnum)); + putvec(VT_ITEM, vec, (s_char *)§, EF_SECTOR); + putsect(§); + } + return RET_OK; +} diff --git a/src/lib/commands/scut.c b/src/lib/commands/scut.c new file mode 100644 index 00000000..70875c34 --- /dev/null +++ b/src/lib/commands/scut.c @@ -0,0 +1,364 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * scut.c: Scuttle ships, planes or land units + * + * Known contributors to this file: + * + */ + +#include "misc.h" +#include "player.h" +#include "sect.h" +#include "news.h" +#include "var.h" +#include "xy.h" +#include "ship.h" +#include "land.h" +#include "plane.h" +#include "nat.h" +#include "nsc.h" +#include "deity.h" +#include "file.h" +#include "commands.h" +#include "optlist.h" + +union item_u { + struct shpstr ship; + struct plnstr plane; + struct lndstr land; +}; + +int +scuttle_tradeship(struct shpstr *sp, int interactive) +{ + extern int trade_1_dist; /* less than this gets no money */ + extern int trade_2_dist; /* less than this gets trade_1 money */ + extern int trade_3_dist; /* less than this gets trade_2 money */ + extern float trade_1; /* return on trade_1 distance */ + extern float trade_2; /* return on trade_2 distance */ + extern float trade_3; /* return on trade_3 distance */ + extern float trade_ally_bonus; /* 20% bonus for trading with allies */ + extern float trade_ally_cut; /* 10% bonus for ally you trade with */ + float cash = 0; + float ally_cash = 0; + int dist; + struct sctstr sect; + struct mchrstr *mp; + struct natstr *np; + s_char buf[512]; + struct natstr *natp; + + mp = &mchr[(int)sp->shp_type]; + getsect(sp->shp_x,sp->shp_y,§); + if (sect.sct_own && sect.sct_type == SCT_HARBR) { + dist = mapdist(sp->shp_x, sp->shp_y, + sp->shp_orig_x, + sp->shp_orig_y); + if (interactive) + pr("%s has gone %d sects\n", prship(sp), dist); + else + wu(0, sp->shp_own, "%s has gone %d sects\n", prship(sp), + dist); + if (dist < trade_1_dist) + cash = 0; + else if (dist < trade_2_dist) + cash = (1.0 + trade_1*((float)dist)); + else if (dist < trade_3_dist) + cash = (1.0 + trade_2*((float)dist)); + else + cash = (1.0 + trade_3*((float)dist)); + cash *= mp->m_cost; + cash *= (((float)sp->shp_effic) / 100.0); + + if (sect.sct_own != sp->shp_own) { + cash *= (1.0 + trade_ally_bonus); + ally_cash = cash * trade_ally_cut; + } + } + + if (!interactive && cash) { + natp = getnatp(sp->shp_own); + natp->nat_money += cash; + putnat(natp); + wu(0, sp->shp_own, "You just made $%d.\n", (int)cash); + } else if (!cash && !interactive) { + wu(0, sp->shp_own, "Unfortunately, you make $0 on this trade.\n"); + } else if (cash && interactive) { + player->dolcost -= cash; + } else if (interactive) { + pr("You won't get any money if you scuttle in %s!", + xyas(sp->shp_x, sp->shp_y, player->cnum)); + sprintf(buf, "Are you sure you want to scuttle %s? ", + prship(sp)); + return confirm(buf); + } + + if (ally_cash) { + np = getnatp(sect.sct_own); + np->nat_money += ally_cash; + putnat(np); + wu(0,sect.sct_own, + "Trade with %s nets you $%d at %s\n", + cname(sp->shp_own), + (int)ally_cash, + xyas(sect.sct_x, sect.sct_y, sect.sct_own)); + if (sp->shp_own != sp->shp_orig_own) + nreport(sp->shp_own, + N_PIRATE_TRADE, sp->shp_orig_own, 1); + else + nreport(sp->shp_own, N_TRADE, sect.sct_own, 1); + } else if (sp->shp_own != sp->shp_orig_own) + nreport(sp->shp_own, N_PIRATE_KEEP, sp->shp_orig_own, 1); + + return 1; +} + +int +scut(void) +{ + struct nstr_item ni; + union item_u item; + int type; + struct mchrstr *mp; + struct plchrstr *pp; + struct lchrstr *lp; + s_char *p; + s_char prompt[128]; + s_char buf[1024]; + + if (!(p = getstarg(player->argp[1], "Ship, land, or plane? ", buf))) + return RET_SYN; + switch (*p) { + case 's': + type = EF_SHIP; break; + case 'p': + type = EF_PLANE; break; + case 'l': + type = EF_LAND; break; + default: + pr("Ships, land units, or planes only! (s, l, p)\n"); + return RET_SYN; + } + sprintf(prompt, "%s(s)? ", ef_nameof(type)); + if ((p = getstarg(player->argp[2], prompt, buf)) == 0) + return RET_SYN; + if (!snxtitem(&ni, type, p)) + return RET_SYN; + if (p && (isalpha(*p) || (*p == '*') || (*p == '~') || issector(p) + || islist(p))){ + s_char y_or_n[80], bbuf[80]; + + if (type == EF_SHIP) { + if (*p == '*') + sprintf(bbuf,"all ships"); + else if (*p == '~') + sprintf(bbuf,"all unassigned ships"); + else if (issector(p)) + sprintf(bbuf,"all ships in %s",p); + else if (isalpha(*p)) + sprintf(bbuf,"fleet %c",*p); + else + sprintf(bbuf,"ships %s",p); + } else if (type == EF_LAND) { + if (*p == '*') + sprintf(bbuf,"all land units"); + else if (*p == '~') + sprintf(bbuf,"all unassigned land units"); + else if (issector(p)) + sprintf(bbuf,"all units in %s",p); + else if (isalpha(*p)) + sprintf(bbuf,"army %c",*p); + else + sprintf(bbuf,"units %s",p); + } else { + if (*p == '*') + sprintf(bbuf,"all planes"); + else if (*p == '~') + sprintf(bbuf,"all unassigned planes"); + else if (issector(p)) + sprintf(bbuf,"all planes in %s",p); + else if (isalpha(*p)) + sprintf(bbuf,"wing %c",*p); + else + sprintf(bbuf,"planes %s",p); + } + sprintf(y_or_n,"Really scuttle %s? ", bbuf); + if (!confirm(y_or_n)) + return RET_FAIL; + } + while (nxtitem(&ni, (s_char *)&item)) { + if (!player->owner) + continue; + if (opt_MARKET) { + if (ontradingblock(type, (int *)&item.ship)) { + pr("You cannot scuttle an item on the trading block!\n"); + continue; + } + } + + if (type == EF_SHIP) { + mp = &mchr[(int)item.ship.shp_type]; + if (opt_TRADESHIPS) { + if (mp->m_flags & M_TRADE) + if (!scuttle_tradeship(&item.ship, 1)) + continue; + } + pr("%s", prship(&item.ship)); + scuttle_ship(&item.ship); + } else if (type == EF_LAND) { + if (item.land.lnd_ship >= 0) { + pr("%s is on a ship, and cannot be scuttled!\n", + prland(&item.land)); + continue; + } + lp = &lchr[(int)item.land.lnd_type]; + pr("%s", prland(&item.land)); + scuttle_land(&item.land); + } else { + pp = &plchr[(int)item.plane.pln_type]; + pr("%s", prplane(&item.plane)); + if (item.plane.pln_ship >= 0){ + struct shpstr ship; + + getship(item.plane.pln_ship,&ship); + take_plane_off_ship(&item.plane,&ship); + } + makelost(EF_PLANE, item.plane.pln_own, item.plane.pln_uid, item.plane.pln_x, item.plane.pln_y); + item.plane.pln_own = 0; + putplane(item.plane.pln_uid, (s_char *)&item.plane); + } + pr(" scuttled in %s\n", + xyas(item.ship.shp_x, item.ship.shp_y , player->cnum)); + } + + return RET_OK; +} + +void +scuttle_ship(struct shpstr *sp) +{ + struct nstr_item ni; + struct sctstr sect; + struct plnstr plane; + struct lndstr land; + + getsect(sp->shp_x, sp->shp_y, §); + snxtitem_all(&ni, EF_PLANE); + while (nxtitem(&ni, (s_char *)&plane)) { + if (plane.pln_own == 0) + continue; + if (plane.pln_ship == sp->shp_uid) { + plane.pln_ship = -1; + if (sect.sct_own != sp->shp_own) { + wu(0, plane.pln_own, "Plane %d scuttled in %s\n", + plane.pln_uid, + xyas(plane.pln_x, plane.pln_y, plane.pln_own)); + makelost(EF_PLANE, plane.pln_own, plane.pln_uid, plane.pln_x, plane.pln_y); + plane.pln_own = 0; + } else { + wu(0, plane.pln_own, + "Plane %d transferred off ship %d to %s\n", + plane.pln_uid, sp->shp_uid, + xyas(plane.pln_x, plane.pln_y,plane.pln_own)); + } + putplane(plane.pln_uid, (s_char *)&plane); + } + } + snxtitem_all(&ni, EF_LAND); + while (nxtitem(&ni, (s_char *)&land)) { + if (land.lnd_own == 0) + continue; + if (land.lnd_ship == sp->shp_uid) { + land.lnd_ship = -1; + if (sect.sct_own == sp->shp_own) { + wu(0, land.lnd_own, + "Land unit %d transferred off ship %d to %s\n", + land.lnd_uid, sp->shp_uid, + xyas(land.lnd_x, land.lnd_y, land.lnd_own)); + putland(land.lnd_uid, (s_char *)&land); + } else + scuttle_land(&land); + } + } + makelost(EF_SHIP, sp->shp_own, sp->shp_uid, sp->shp_x, sp->shp_y); + sp->shp_own = 0; + putship(sp->shp_uid, sp); +} + +void +scuttle_land(struct lndstr *lp) +{ + struct nstr_item ni; + struct sctstr sect; + struct plnstr plane; + struct lndstr land; + + getsect(lp->lnd_x, lp->lnd_y, §); + snxtitem_all(&ni, EF_PLANE); + while (nxtitem(&ni, (s_char *)&plane)) { + if (plane.pln_own == 0) + continue; + if (plane.pln_land == lp->lnd_uid) { + plane.pln_land = -1; + if (sect.sct_own != lp->lnd_own) { + wu(0, plane.pln_own, "Plane %d scuttled in %s\n", + plane.pln_uid, + xyas(plane.pln_x, plane.pln_y, plane.pln_own)); + makelost(EF_PLANE, plane.pln_own, plane.pln_uid, plane.pln_x, plane.pln_y); + plane.pln_own = 0; + } else { + wu(0, plane.pln_own, + "Plane %d transferred off unit %d to %s\n", + plane.pln_uid, lp->lnd_uid, + xyas(plane.pln_x, plane.pln_y,plane.pln_own)); + } + putplane(plane.pln_uid, (s_char *)&plane); + } + } + snxtitem_all(&ni, EF_LAND); + while (nxtitem(&ni, (s_char *)&land)) { + if (land.lnd_own == 0) + continue; + if (land.lnd_land == lp->lnd_uid) { + land.lnd_land = -1; + if (sect.sct_own == lp->lnd_own) { + wu(0, land.lnd_own, + "Land unit %d transferred off unit %d to %s\n", + land.lnd_uid, lp->lnd_uid, + xyas(land.lnd_x, land.lnd_y, land.lnd_own)); + putland(land.lnd_uid, (s_char *)&land); + } else + scuttle_land(&land); + } + } + makelost(EF_LAND, lp->lnd_own, lp->lnd_uid, lp->lnd_x, lp->lnd_y); + lp->lnd_own = 0; + putland(lp->lnd_uid, lp); +} + + diff --git a/src/lib/commands/sdump.c b/src/lib/commands/sdump.c new file mode 100644 index 00000000..6b91c90d --- /dev/null +++ b/src/lib/commands/sdump.c @@ -0,0 +1,274 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * sdump.c: Dump ship information + * + * Known contributors to this file: + * John Yockey, 1997 + * Steve McClure, 1998 + */ + +#include "misc.h" +#include "player.h" +#include "var.h" +#include "xy.h" +#include "sect.h" +#include "ship.h" +#include "nat.h" +#include "nsc.h" +#include "deity.h" +#include "file.h" +#include "optlist.h" +#include "commands.h" + +int +sdump(void) +{ + int nships; + struct nstr_item ni; + struct shpstr ship; + int vec[I_MAX+1]; + int field[128]; + struct natstr *np; + int n,i; + time_t now; + + if (!snxtitem(&ni, EF_SHIP, player->argp[1])) + return RET_SYN; + prdate(); + + if (!player->argp[2]) { + for (n = 1; n <= 34; n++) field[n-1] = n; + field[n-1] = 0; + } else { + n = 2; + i = 0; + while (player->argp[n]) { + if (!strcmp("type",player->argp[n])) { + field[i++] = 1; + } else if (!strcmp("x",player->argp[n])) { + field[i++] = 2; + } else if (!strcmp("y",player->argp[n])) { + field[i++] = 3; + } else if (!strcmp("flt",player->argp[n])) { + field[i++] = 4; + } else if (!strcmp("eff",player->argp[n])) { + field[i++] = 5; + } else if (!strcmp("civ",player->argp[n])) { + field[i++] = 6; + } else if (!strcmp("mil",player->argp[n])) { + field[i++] = 7; + } else if (!strcmp("uw",player->argp[n])) { + field[i++] = 8; + } else if (!strcmp("food",player->argp[n])) { + field[i++] = 9; + } else if (!strcmp("pln",player->argp[n])) { + field[i++] = 10; + } else if (!strcmp("he",player->argp[n])) { + field[i++] = 11; + } else if (!strcmp("xl",player->argp[n])) { + field[i++] = 12; + } else if (!strcmp("land",player->argp[n])) { + field[i++] = 13; + } else if (!strcmp("mob",player->argp[n])) { + field[i++] = 14; + } else if (!strcmp("fuel",player->argp[n])) { + field[i++] = 15; + } else if (!strcmp("tech",player->argp[n])) { + field[i++] = 16; + } else if (!strcmp("shell",player->argp[n])) { + field[i++] = 17; + } else if (!strcmp("gun",player->argp[n])) { + field[i++] = 18; + } else if (!strcmp("petrol",player->argp[n])) { + field[i++] = 19; + } else if (!strcmp("iron",player->argp[n])) { + field[i++] = 20; + } else if (!strcmp("dust",player->argp[n])) { + field[i++] = 21; + } else if (!strcmp("bar",player->argp[n])) { + field[i++] = 22; + } else if (!strcmp("oil",player->argp[n])) { + field[i++] = 23; + } else if (!strcmp("lcm",player->argp[n])) { + field[i++] = 24; + } else if (!strcmp("hcm",player->argp[n])) { + field[i++] = 25; + } else if (!strcmp("rad",player->argp[n])) { + field[i++] = 26; + } else if (!strcmp("def",player->argp[n])) { + field[i++] = 27; + } else if (!strcmp("spd",player->argp[n])) { + field[i++] = 28; + } else if (!strcmp("vis",player->argp[n])) { + field[i++] = 29; + } else if (!strcmp("rng",player->argp[n])) { + field[i++] = 30; + } else if (!strcmp("fir",player->argp[n])) { + field[i++] = 31; + } else if (!strcmp("origx", player->argp[n])) { + field[i++] = 32; + } else if (!strcmp("origy", player->argp[n])) { + field[i++] = 33; + } else if (!strcmp("name",player->argp[n])) { + field[i++] = 34; + } else { + pr("Unrecognized field %s\n",player->argp[n]); + } + if (n++ > 100) { + pr("Too many fields\n"); + return RET_FAIL; + } + } + field[i] = 0; + } + + if (player->god) + pr(" "); + time(&now); + pr("DUMP SHIPS %d\n", now); + if (player->god) + pr("own "); + pr("id"); + n = 0; + while (field[n]) { + switch (field[n]) { + case 1: pr(" type"); break; + case 2: pr(" x"); break; + case 3: pr(" y"); break; + case 4: pr(" flt"); break; + case 5: pr(" eff"); break; + case 6: pr(" civ"); break; + case 7: pr(" mil"); break; + case 8: pr(" uw"); break; + case 9: pr(" food"); break; + case 10: pr(" pln"); break; + case 11: pr(" he"); break; + case 12: pr(" xl"); break; + case 13: pr(" land"); break; + case 14: pr(" mob"); break; + case 15: pr(" fuel"); break; + case 16: pr(" tech"); break; + case 17: pr(" shell"); break; + case 18: pr(" gun"); break; + case 19: pr(" petrol"); break; + case 20: pr(" iron"); break; + case 21: pr(" dust"); break; + case 22: pr(" bar"); break; + case 23: pr(" oil"); break; + case 24: pr(" lcm"); break; + case 25: pr(" hcm"); break; + case 26: pr(" rad"); break; + case 27: pr(" def"); break; + case 28: pr(" spd"); break; + case 29: pr(" vis"); break; + case 30: pr(" rng"); break; + case 31: pr(" fir"); break; + case 32: pr(" origx"); break; + case 33: pr(" origy"); break; + case 34: pr(" name"); break; + } + n++; + } + pr("\n"); + + nships = 0; + np = getnatp(player->cnum); + while (nxtitem(&ni, (s_char *)&ship)) { + if (!player->owner || ship.shp_own == 0) + continue; + if (ship.shp_type < 0 || ship.shp_type > shp_maxno) { + pr("bad ship type %d (#%d)\n", + ship.shp_type, ni.cur); + continue; + } + count_planes(&ship); + count_units(&ship); + nships++; + if (player->god) + pr("%3d ", ship.shp_own); + pr("%d", ni.cur); + n = 0; + getvec(VT_ITEM, vec, (s_char *)&ship, EF_SHIP); + while (field[n]) { + switch (field[n++]) { + case 1: pr(" %0.4s", mchr[(int)ship.shp_type].m_name); break; + case 2: pr(" %d", xrel(np, ship.shp_x)); break; + case 3: pr(" %d", yrel(np, ship.shp_y)); break; + case 4: if (ship.shp_fleet == ' ') + pr(" ~"); + else + pr(" %c", ship.shp_fleet); + break; + case 5: pr(" %d", ship.shp_effic); break; + case 6: pr(" %d", vec[I_CIVIL]); break; + case 7: pr(" %d", vec[I_MILIT]); break; + case 8: pr(" %d", vec[I_UW]); break; + case 9: pr(" %d", vec[I_FOOD]); break; + case 10: pr(" %d", ship.shp_nplane); break; + case 11: pr(" %d",ship.shp_nchoppers); break; + case 12: pr(" %d",ship.shp_nxlight); break; + case 13: pr(" %d", ship.shp_nland); break; + case 14: pr(" %d", ship.shp_mobil); break; + case 15: if (opt_FUEL) + pr(" %d",ship.shp_fuel); + else + pr(" 0"); + break; + case 16: pr(" %d", ship.shp_tech); break; + case 17: pr(" %d", vec[I_SHELL]); break; + case 18: pr(" %d", vec[I_GUN]); break; + case 19: pr(" %d", vec[I_PETROL]); break; + case 20: pr(" %d", vec[I_IRON]); break; + case 21: pr(" %d", vec[I_DUST]); break; + case 22: pr(" %d", vec[I_BAR]); break; + case 23: pr(" %d", vec[I_OIL]); break; + case 24: pr(" %d", vec[I_LCM]); break; + case 25: pr(" %d", vec[I_HCM]); break; + case 26: pr(" %d", vec[I_RAD]); break; + case 27: pr(" %d", ship.shp_armor); break; + case 28: pr(" %d", ship.shp_speed); break; + case 29: pr(" %d", ship.shp_visib); break; + case 30: pr(" %d", ship.shp_frnge); break; + case 31: pr(" %d", ship.shp_glim); break; + case 32: pr(" %d", xrel(np, ship.shp_orig_x)); break; + case 33: pr(" %d", yrel(np, ship.shp_orig_y)); break; + case 34: pr(" %c%s%c", '"', ship.shp_name, '"'); break; + } + } + pr("\n"); + } + if (nships == 0) { + if (player->argp[1]) + pr("%s: No ship(s)\n", player->argp[1]); + else + pr("%s: No ship(s)\n", ""); + return RET_FAIL; + }else + pr("%d ship%s\n", nships, splur(nships)); + return RET_OK; +} diff --git a/src/lib/commands/sect.c b/src/lib/commands/sect.c new file mode 100644 index 00000000..c946d1e5 --- /dev/null +++ b/src/lib/commands/sect.c @@ -0,0 +1,138 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * sect.c: Show sectors in map-like format with conditionals. + * + * Known contributors to this file: + * Dave Pare, 1986 + */ + +#include "misc.h" +#include "player.h" +#include "var.h" +#include "xy.h" +#include "sect.h" +#include "nsc.h" +#include "com.h" +#include "nat.h" +#include "file.h" +#include "map.h" +#include "deity.h" +#include "commands.h" +#include "optlist.h" + +int +sct(void) +{ + struct nstr_sect ns; + struct sctstr sect; + struct nscstr cond[NS_NCOND]; + struct range range; + struct natstr *np; + int ncond; + int nsect; + s_char *ptr; + coord y, yval; + int i; + s_char what[64]; + s_char *str; + s_char buf[1024]; + /* Note this is not re-entrant anyway, so we keep the buffers + around */ + static s_char *mapbuf = (s_char *)0; + static s_char **map = (s_char **)0; + + nsect = 0; + if(player->argp[1] == (s_char *) 0) { + if ((str = getstring("(sects)? ", buf)) == 0) + return RET_SYN; + } + else { + str = player->argp[1]; + } + + if(*str == '*') { + sprintf(what, "%d:%d,%d:%d", + -WORLD_X/2, WORLD_X/2-1, + -WORLD_Y/2, WORLD_Y/2-1); + if (!snxtsct(&ns, what)) + return RET_FAIL; + } + else + if (!snxtsct(&ns, str)) + return RET_SYN; + if (!mapbuf) + mapbuf = (s_char *)malloc((WORLD_Y*MAPWIDTH(1))*sizeof(s_char)); + if (!map) { + map = (s_char **)malloc(WORLD_Y * sizeof(s_char *)); + if (map && mapbuf) { + for (i = 0; i < WORLD_Y; i++) + map[i] = &mapbuf[MAPWIDTH(1) * i]; + } else if (map) { + free((s_char *)map); + map = (s_char **)0; + } + } + if (!mapbuf || !map) { + pr("Memory error, tell the deity.\n"); + logerror("malloc failed in sect\n"); + return RET_FAIL; + } + np = getnatp(player->cnum); + ncond = ns.ncond; + bcopy((s_char *)ns.cond, (s_char *)cond, sizeof(*cond) * ncond); + ns.ncond = 0; + xyrelrange(getnatp(player->cnum), &ns.range, &range); + border(&range, " ", ""); + blankfill((s_char *)mapbuf, &ns.range, 1); + while (nxtsct(&ns, §)) { + if (!player->owner) + continue; + ptr = &map[ns.dy][ns.dx]; + *ptr = dchr[sect.sct_type].d_mnem; + if (nstr_exec(cond, ncond, (s_char *)§, EF_SECTOR)) { + ++nsect; + *ptr |= 0x80; + } + } + for (i=0,y=ns.range.ly; i < ns.range.height; y++,i++) { + yval = yrel(np, y); + pr("%3d %s %-3d\n", yval, map[i], yval); + if (y >= WORLD_Y) + y -= WORLD_Y; + } + border(&range, " ", ""); + if (nsect == 0) { + if (player->argp[1]) + pr("%s: No sector(s)\n", player->argp[1]); + else + pr("%s: No sector(s)\n", ""); + return RET_FAIL; + }else + pr("%d sector%s\n", nsect, splur(nsect)); + return RET_OK; +} diff --git a/src/lib/commands/sell.c b/src/lib/commands/sell.c new file mode 100644 index 00000000..da126345 --- /dev/null +++ b/src/lib/commands/sell.c @@ -0,0 +1,203 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * sell.c: Sell commodities to other nations. + * + * Known contributors to this file: + * Dave Pare, 1986 + * Jeff Bailey + * Pat Loney, 1992 + * Steve McClure, 1996 + */ + +#include "misc.h" +#include "xy.h" +#include "file.h" +#include "var.h" +#include "sect.h" +#include "item.h" +#include "nsc.h" +#include "nat.h" +#include "nuke.h" +#include "plane.h" +#include "ship.h" +#include /* bailey@math-cs.kent.edu */ +#include "commodity.h" +#include "land.h" +#include "trade.h" +#include "player.h" +#include "commands.h" +#include "optlist.h" +/*#define EF_COMM 10*/ + +/* + * format: sell + * where NUMBER represents either the number to reach + * or, if negative, the abs number to try and get from + * each sector. + */ +int +sell(void) +{ + struct sctstr sect; + struct ichrstr *ip; + struct comstr comm; + int number_set; + int number_sub; + int totalcom; + int amt; + int com; + char *p; + float price; + char cc; + time_t now; + int ii = 0; + coord x, y; + s_char buf[1024]; + + if (!opt_MARKET) { + pr("The market is disabled.\n"); + return RET_FAIL; + } + check_market(); + check_trade(); + if ((ip = whatitem(player->argp[1], "Commodity you want to sell: ")) == 0) + return RET_SYN; + if (ip->i_sell == 0) { + pr("You can't sell %s\n", ip->i_name); + return RET_FAIL; + } + if (!(p = getstarg(player->argp[2], "Sector to sell from: ",buf))) + return RET_SYN; + if (!sarg_xy(p, &x, &y)) + return RET_SYN; + if (!getsect(x, y, §)) + pr("Could not access that sector.\n"); + if ((sect.sct_type != SCT_HARBR && sect.sct_type != SCT_WAREH) || + !player->owner) { + pr("That sector cannot sell goods.\n"); + return RET_FAIL; + } + if(sect.sct_effic < 60){ + pr("Sectors need to be >= 60%% efficient to sell goods.\n"); + return RET_FAIL; + } + if (sect.sct_mobil <= 0) { + pr("Sectors need at least 1 mobility to sell goods.\n"); + return RET_FAIL; + } + number_set = 0; + number_sub = 0; + if ((p = getstarg(player->argp[3], "Amount: ",buf)) == 0 || *p == 0) + return RET_SYN; + if (!check_sect_ok(§)) + return RET_FAIL; + number_set = atoi(p); + if ((p = getstarg(player->argp[4], "Price per unit: ", buf)) == 0 || + *p == 0) + return RET_SYN; + if (!check_sect_ok(§)) + return RET_FAIL; + price = atof(p); + if (price <= 0.0) { + pr("No sale.\n"); + return RET_FAIL; + } + if (price > 1000.0) /* Inf can cause overflow */ + price = 1000.0; /* bailey@math-cs.kent.edu */ + totalcom = 0; + /* + * military control necessary to sell + * goodies in occupied territory. + */ + if (sect.sct_oldown != player->cnum) { + int tot_mil=0; + struct nstr_item ni; + struct lndstr land; + + snxtitem_xy(&ni, EF_LAND, sect.sct_x, sect.sct_y); + while (nxtitem(&ni, (s_char *)&land)){ + if (land.lnd_own == player->cnum) + tot_mil += total_mil(&land); + } + if (((tot_mil+(getvar(V_MILIT, (char *)§, EF_SECTOR))) * 10) + < getvar(V_CIVIL, (char *)§, EF_SECTOR)) { + pr("Military control required to sell goods.\n"); + return RET_FAIL; + } + } + if (((amt = getvar(ip->i_vtype, (char *)§,EF_SECTOR))) == 0) { + pr("You don't have any %s to sell there.\n", ip->i_name); + return RET_FAIL; + } + if (number_set > 0) + com = min(number_set, amt); + else if (number_set < 0) + com = amt + number_set; + else + com = 0; + if (com <= 0) + return RET_SYN; + totalcom += com; + amt -= com; + pr("Sold %d %s at %s (%d left)\n", com, ip->i_name, + xyas(sect.sct_x, sect.sct_y, player->cnum), amt); + putvar(ip->i_vtype, amt, (char *)§, EF_SECTOR); + cc = ip->i_mnem; + putsect(§); + if (totalcom > 0) { + for (ii = 0; getcomm(ii, &comm); ii++) { + if (comm.com_owner == 0) + break; + } + if (getcomm(ii, &comm) == 0) + ef_extend(EF_COMM, 1); + (void) time(&now); + comm.com_type = ip->i_mnem; + comm.com_owner = player->cnum; + comm.com_price = price; + comm.com_maxbidder = player->cnum; + comm.com_maxprice = price; + comm.com_markettime = now; + comm.com_amount = totalcom; + comm.com_x = 0; + comm.com_y = 0; + comm.sell_x = sect.sct_x; + comm.sell_y = sect.sct_y; + comm.com_uid = ii; + if(!putcomm(ii, &comm)) { + pr("Problems with the commodities file, call the Deity\n"); + return RET_FAIL; + } + } else { + pr("No eligible %s for sale\n", ip->i_name); + return RET_FAIL; + } + return RET_OK; +} + + diff --git a/src/lib/commands/set.c b/src/lib/commands/set.c new file mode 100644 index 00000000..17af3794 --- /dev/null +++ b/src/lib/commands/set.c @@ -0,0 +1,186 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * set.c: Place units/ships/planes/nukes up for sale. + * + * Known contributors to this file: + * Dave Pare, 1986 + * Pat Loney, 1992 + * Steve McClure, 1996 + */ + +#include "misc.h" +#include "var.h" +#include "sect.h" +#include "ship.h" +#include "land.h" +#include "nuke.h" +#include "plane.h" +#include "xy.h" +#include "nsc.h" +#include "nat.h" +#include "trade.h" +#include "file.h" +#include "player.h" +#include "commands.h" +#include "optlist.h" + +/* + * format: set + */ +int +set(void) +{ + char *p; + int type; + int price; + char prompt[80]; + struct trdstr trade; + struct nstr_item ni; + struct nstr_item ni_trade; + union trdgenstr item; + union trdgenstr check; + struct sctstr sect; + int freeslot; + int foundslot; + int id; + time_t now; + s_char buf[1024]; + + if (!opt_MARKET) { + pr("The market is disabled.\n"); + return RET_FAIL; + } + check_market(); + check_trade(); + + if ((p = getstarg(player->argp[1], "Item type? ", buf)) == 0) + return RET_SYN; + if ((type = ef_byname(p)) < 0) { + pr("%s: not an item type\n", p); + return RET_SYN; + } + if (type == EF_SECTOR) + type = EF_SHIP; + if (type == EF_NEWS) + type = EF_NUKE; + if (type == EF_LOAN) + type = EF_LAND; + if (!snxtitem(&ni, type, player->argp[2])) + return RET_SYN; + while (nxtitem(&ni, (char *)&item)) { + if (!player->owner && !player->god) + continue; + getsect(item.gen.trg_x, item.gen.trg_y, §); + /* + * military control necessary to sell + * goodies in occupied territory. + */ + if (sect.sct_oldown != player->cnum && !player->god) { + int tot_mil=0; + struct nstr_item ni; + struct lndstr land; + snxtitem_xy(&ni, EF_LAND, sect.sct_x, sect.sct_y); + while (nxtitem(&ni, (s_char *)&land)){ + if (land.lnd_own == player->cnum) + tot_mil += total_mil(&land); + } + if (tot_mil+(getvar(V_MILIT, (char *)§, EF_SECTOR)) * 10 + < getvar(V_CIVIL, (char *)§, EF_SECTOR)) { + pr("Military control required to sell goods.\n"); + return RET_FAIL; + } + } + trade.trd_type = type; + sprintf(prompt, "%s #%d; Price? ", + trade_nameof(&trade, &item), ni.cur); + memcpy(&check, &item, sizeof(union trdgenstr)); + if ((p = getstarg(player->argp[3], prompt, buf))==0) + break; + if (memcmp(&check, &item, sizeof(union trdgenstr))) { + pr("That item has changed!\n"); + return RET_FAIL; + } + if ((price = atoi(p)) < 0) + continue; + if (!ef_lock(EF_TRADE)) { + logerror("can't lock trade file"); + return RET_SYS; + } + foundslot = -1; + freeslot = -1; + snxtitem_all(&ni_trade, EF_TRADE); + while (nxtitem(&ni_trade, (char *)&trade)) { + if (trade.trd_unitid < 0) + freeslot = ni_trade.cur; + if (trade.trd_unitid == ni.cur && + trade.trd_type == type) { + foundslot = ni_trade.cur; + break; + } + } + if (price == 0 && foundslot >= 0) { + pr("%s #%d (lot #%d) removed from trading\n", + trade_nameof(&trade, &item), + ni.cur, foundslot); + trade.trd_type = 0; + trade.trd_owner = 0; + trade.trd_unitid = -1; + trade.trd_price = 0; + (void) time(&now); + trade.trd_markettime = now; + trade.trd_maxbidder = player->cnum; + trade.trd_maxprice = 0; + puttrade(ni_trade.cur, &trade); + } else if (price > 0) { + trade.trd_x = item.gen.trg_x; + trade.trd_y = item.gen.trg_x; + trade.trd_type = type; + trade.trd_owner = player->cnum; + trade.trd_unitid = ni.cur; + trade.trd_price = price; + (void) time(&now); + trade.trd_markettime = now; + trade.trd_maxbidder = player->cnum; + trade.trd_maxprice = price; + if (foundslot >= 0) + id = foundslot; + else if (freeslot >= 0) + id = freeslot; + else { + ef_extend(EF_TRADE, 1); + id = ni_trade.cur; + } + puttrade(id, &trade); + pr("%s #%d (lot #%d) price %s to $%d\n", + trade_nameof(&trade, &item), ni.cur, + id, foundslot >= 0 ? "reset" : "set", price); + } + ef_unlock(EF_TRADE); + } + return RET_OK; +} diff --git a/src/lib/commands/setres.c b/src/lib/commands/setres.c new file mode 100644 index 00000000..9ece4d00 --- /dev/null +++ b/src/lib/commands/setres.c @@ -0,0 +1,169 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * setres.c: Set resources of a sector + * + * Known contributors to this file: + * David Muir Sharnoff + * Karl Hagen + * Steve McClure, 1998 + */ + +#include +#include +#include "misc.h" +#include "player.h" +#include "var.h" +#include "xy.h" +#include "sect.h" +#include "nat.h" +#include "news.h" +#include "nsc.h" +#include "item.h" +#include "file.h" +#include "commands.h" +#include "optlist.h" + +/* + * format: setres resource + */ +int +setres(void) +{ + struct sctstr sect; + s_char *what; + int amt; + s_char *p; + struct nstr_sect nstr; + s_char buf[1024]; + + if ((what = getstarg(player->argp[1], + "Set What (iron, gold, oil, uranium, fertility)? ", buf)) == 0) + return RET_SYN; + switch (what[0]) { + case 'i': + if (!snxtsct(&nstr, player->argp[2])) + return RET_SYN; + while (nxtsct(&nstr,§) > 0) { + if( !(p = getstarg(player->argp[3], "What value : ", buf)) || + (*p == '\0')) + return RET_SYN; + amt = atoi(p); + if (amt > 100) + amt = 100; + if (amt < 0) + amt = 0; + if (sect.sct_own != 0) + resnoise(§,1,"Iron ore content", + (int) sect.sct_min, amt); + sect.sct_min = (u_char) amt; + putsect(§); + } + break; + case 'g': + if (!snxtsct(&nstr, player->argp[2])) + return RET_SYN; + while (nxtsct(&nstr,§) > 0) { + if( !(p = getstarg(player->argp[3], "What value : ", buf)) || + (*p == '\0')) + return RET_SYN; + amt = atoi(p); + if (amt > 100) + amt = 100; + if (amt < 0) + amt = 0; + if (sect.sct_own != 0) + resnoise(§,1,"Gold content", + (int) sect.sct_gmin, amt); + sect.sct_gmin = (u_char) amt; + putsect(§); + } + break; + case 'o': + if (!snxtsct(&nstr, player->argp[2])) + return RET_SYN; + while (nxtsct(&nstr,§) > 0) { + if( !(p = getstarg(player->argp[3], "What value : ", buf)) || + (*p == '\0')) + return RET_SYN; + amt = atoi(p); + if (amt > 100) + amt = 100; + if (amt < 0) + amt = 0; + if (sect.sct_own != 0) + resnoise(§,1,"Oil content", + (int) sect.sct_oil, amt); + sect.sct_oil = (u_char) amt; + putsect(§); + } + break; + case 'f': + if (!snxtsct(&nstr, player->argp[2])) + return RET_SYN; + while (nxtsct(&nstr,§) > 0) { + if( !(p = getstarg(player->argp[3], "What value : ", buf)) || + (*p == '\0')) + return RET_SYN; + amt = atoi(p); + if (amt > 100) + amt = 100; + if (amt < 0) + amt = 0; + if (sect.sct_own != 0) + resnoise(§,1,"Fertility content", + (int) sect.sct_fertil, amt); + sect.sct_fertil = (u_char) amt; + putsect(§); + } + break; + case 'u': + if (!snxtsct(&nstr, player->argp[2])) + return RET_SYN; + while (nxtsct(&nstr,§) > 0) { + if( !(p = getstarg(player->argp[3], "What value : ", buf)) || + (*p == '\0')) + return RET_SYN; + amt = atoi(p); + if (amt > 100) + amt = 100; + if (amt < 0) + amt = 0; + if (sect.sct_own != 0) + resnoise(§,1,"Uranium content", + (int) sect.sct_uran, amt); + sect.sct_uran = (u_char) amt; + putsect(§); + } + break; + default: + pr("huh?\n"); + return RET_SYN; + } + return RET_OK; +} + diff --git a/src/lib/commands/setsect.c b/src/lib/commands/setsect.c new file mode 100644 index 00000000..076ac34c --- /dev/null +++ b/src/lib/commands/setsect.c @@ -0,0 +1,388 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * setsect.c: Give resources to a country + * + * Known contributors to this file: + * David Muir Sharnoff + * Steve McClure, 1998 + */ + +#include +#include +#include "misc.h" +#include "player.h" +#include "var.h" +#include "xy.h" +#include "sect.h" +#include "nat.h" +#include "news.h" +#include "nsc.h" +#include "item.h" +#include "file.h" +#include "commands.h" +#include "optlist.h" + + +/* + * format: setres thing <#> + */ +int +setsector(void) +{ + struct sctstr sect; + s_char *what; + int amt,current; + s_char *p; + struct nstr_sect nstr; + s_char buf[1024]; + s_char char0, char1; + + if ((what = getstarg(player->argp[1], + "Give What (iron, gold, oil, uranium, fertility, owner, eff., Mob., Work, Avail., oldown, mines)? ", buf)) == 0) + return RET_SYN; + char0 = what[0]; + char1 = what[1]; + + switch (char0) { + case 'i': + if (!snxtsct(&nstr, player->argp[2])) + return RET_SYN; + while (nxtsct(&nstr,§) > 0) { + if( !(p = getstarg(player->argp[3], "What value : ", buf)) || + (*p == '\0')) + return RET_SYN; + amt = atoi(p); + current = sect.sct_min; + current += amt; + if (current < 0) + current = 0; + if (current > 100) + current = 100; + if (sect.sct_own != 0) + resnoise(§,1,"Iron ore content", + (int) sect.sct_min, current); + sect.sct_min = (u_char) current; + putsect(§); + } + break; + case 'g': + if (!snxtsct(&nstr, player->argp[2])) + return RET_SYN; + while (nxtsct(&nstr,§) > 0) { + if( !(p = getstarg(player->argp[3], "What value : ", buf)) || + (*p == '\0')) + return RET_SYN; + amt = atoi(p); + current = sect.sct_gmin; + current += amt; + if (current < 0) + current = 0; + if (current > 100) + current = 100; + if (sect.sct_own != 0) + resnoise(§,1,"Gold content", + (int) sect.sct_gmin, current); + sect.sct_gmin = (u_char) current; + putsect(§); + } + break; + case 'o': + switch(char1) { + case 'i': + if (!snxtsct(&nstr, player->argp[2])) + return RET_SYN; + while (nxtsct(&nstr,§) > 0) { + if( !(p = getstarg(player->argp[3], "What value : ", buf)) || + (*p == '\0')) + return RET_SYN; + amt = atoi(p); + current = sect.sct_oil; + current += amt; + if (current < 0) + current = 0; + if (current > 100) + current = 100; + if (sect.sct_own != 0) + resnoise(§,1,"Oil content", + (int) sect.sct_oil, current); + sect.sct_oil = (u_char) current; + putsect(§); + } + break; + case 'w': + if (!snxtsct(&nstr, player->argp[2])) + return RET_SYN; + while (nxtsct(&nstr,§) > 0) { + if( !(p = getstarg(player->argp[3], "What value : ", buf)) || + (*p == '\0')) + return RET_SYN; + amt = atoi(p); + if ((amt < 0) || (amt > MAXNOC-1)) + return RET_SYN; + pr("Owner of %s changed from %s (#%d) to %s (#%d).\n", + xyas(sect.sct_x, sect.sct_y, player->cnum), + cname(sect.sct_own), + sect.sct_own, cname(amt), amt); + if (sect.sct_own) { + wu(player->cnum, sect.sct_own, + "Sector %s lost to deity intervention\n", + xyas(sect.sct_x, sect.sct_y, + sect.sct_own)); + } + if (amt) + wu(player->cnum, amt, + "Sector %s gained from deity intervention\n", + xyas(sect.sct_x, sect.sct_y, + amt)); + makelost(EF_SECTOR, sect.sct_own, 0, sect.sct_x, sect.sct_y); + makenotlost(EF_SECTOR, amt, 0, sect.sct_x, sect.sct_y); + + sect.sct_own = (natid) amt; + putsect(§); + } + break; + case 'l': + if (!snxtsct(&nstr, player->argp[2])) + return RET_SYN; + while (nxtsct(&nstr,§) > 0) { + if( !(p = getstarg(player->argp[3], "What value : ", buf)) || + (*p == '\0')) + return RET_SYN; + amt = atoi(p); + if ((amt < 0) || (amt > MAXNOC-1)) + return RET_SYN; + pr("Old owner of %s changed from %s (#%d) to %s (#%d).\n", + xyas(sect.sct_x, sect.sct_y, player->cnum), + cname(sect.sct_oldown), + sect.sct_oldown, cname(amt), amt); + sect.sct_oldown = (natid) amt; + putsect(§); + } + break; + default: + pr("huh?\n"); + return RET_SYN; + } + break; + case 'e': + if (!snxtsct(&nstr, player->argp[2])) + return RET_SYN; + while (nxtsct(&nstr,§) > 0) { + if( !(p = getstarg(player->argp[3], "What value : ", buf)) || + (*p == '\0')) + return RET_SYN; + amt = atoi(p); + current = sect.sct_effic; + current += amt; + if (current < 0) + current = 0; + if (current > 100) + current = 100; + pr("Efficiency in %s changed to %d.\n", + xyas(sect.sct_x, sect.sct_y, player->cnum), + current); + sect.sct_effic = (u_char) current; + putsect(§); + } + break; + case 'm': + switch(char1) { + case 'i': + if (!snxtsct(&nstr, player->argp[2])) + return RET_SYN; + while (nxtsct(&nstr,§) > 0) { + int mines; + + if(!(p = getstarg(player->argp[3], "What value : ", buf)) || + (*p == '\0')) + return RET_SYN; + amt = atoi(p); + mines=getvar(V_MINE, (s_char *)§,EF_SECTOR); + current = mines; + current += amt; + if (current < 0) + current = 0; + if (sect.sct_own != 0) + resnoise(§,1,"Mines", + (int) mines, current); + putvar(V_MINE,current,(s_char *)§, + EF_SECTOR); + putsect(§); + } + break; + case 'o': + if (!snxtsct(&nstr, player->argp[2])) + return RET_SYN; + while (nxtsct(&nstr,§) > 0) { + if(!(p = getstarg(player->argp[3],"What value : ",buf)) || + (*p == '\0')) + return RET_SYN; + amt = atoi(p); + current = sect.sct_mobil; + current += amt; + if (current < -127) + current = -127; + if (current > 127) + current = 127; + pr("Mobility in %s changed to %d.\n", + xyas(sect.sct_x, sect.sct_y, player->cnum), + current); + sect.sct_mobil = (short) current; + putsect(§); + } + break; + default: + pr("huh?\n"); + return RET_SYN; + } + break; + case 'a': + if (!snxtsct(&nstr, player->argp[2])) + return RET_SYN; + while (nxtsct(&nstr,§) > 0) { + if( !(p = getstarg(player->argp[3], "What value : ", buf)) || + (*p == '\0')) + return RET_SYN; + amt = atoi(p); + current = sect.sct_avail; + current += amt; + if (current < 0) + current = 0; + if (current > 9999) + current = 9999; + pr("Available in %s changed to %d.\n", + xyas(sect.sct_x, sect.sct_y, player->cnum), + current); + sect.sct_avail = (short) current; + putsect(§); + } + break; + case 'w': + if (!snxtsct(&nstr, player->argp[2])) + return RET_SYN; + while (nxtsct(&nstr,§) > 0) { + if( !(p = getstarg(player->argp[3], "What value : ", buf)) || + (*p == '\0')) + return RET_SYN; + amt = atoi(p); + current = sect.sct_work; + current += amt; + if (current < 0) + current = 0; + if (current > 100) + current = 100; + pr("Work in %s changed to %d.\n", + xyas(sect.sct_x, sect.sct_y, player->cnum), + current); + sect.sct_work = (u_char) current; + putsect(§); + } + break; + case 'f': + if (!snxtsct(&nstr, player->argp[2])) + return RET_SYN; + while (nxtsct(&nstr,§) > 0) { + if( !(p = getstarg(player->argp[3], "What value : ", buf)) || + (*p == '\0')) + return RET_SYN; + amt = atoi(p); + current = sect.sct_fertil; + current += amt; + if (current < 0) + current = 0; + if (current > 120) + current = 120; + if (sect.sct_own != 0) + resnoise(§,1,"Fertility content", + (int) sect.sct_fertil, current); + sect.sct_fertil = (u_char) current; + putsect(§); + } + break; + case 'u': + if (!snxtsct(&nstr, player->argp[2])) + return RET_SYN; + while (nxtsct(&nstr,§) > 0) { + if( !(p = getstarg(player->argp[3], "What value : ", buf)) || + (*p == '\0')) + return RET_SYN; + amt = atoi(p); + current = sect.sct_uran; + current += amt; + if (current < 0) + current = 0; + if (current > 100) + current = 100; + if (sect.sct_own != 0) + resnoise(§,1,"Uranium content", + (int) sect.sct_uran, current); + sect.sct_uran = (u_char) current; + putsect(§); + } + break; + default: + pr("huh?\n"); + return RET_SYN; + } + return RET_OK; +} + +static void +resbenefit(natid who, int good) +{ + if (!opt_GODNEWS) + return; + + if (good) { + if (who) + nreport(player->cnum, N_AIDS, who, 1); + } else { + if (who) + nreport(player->cnum, N_HURTS, who, 1); + } +} + +extern void +resnoise(struct sctstr *sptr, int public_amt, s_char *name, int old, int new) +{ + s_char p[100]; + + pr("%s of %s changed from %d to %d%%\n", + name, xyas(sptr->sct_x, sptr->sct_y, player->cnum), old, new); + if (public_amt) + (void) sprintf(p, "changed from %d to %d", old, new); + else + (void) sprintf(p, "%s", oldsct_own) + wu(0, sptr->sct_own, + "%s in %s was %s by an act of %s\n", + name, xyas(sptr->sct_x, sptr->sct_y, sptr->sct_own), + p, cname(player->cnum)); + resbenefit(sptr->sct_own, (old < new)); +} + diff --git a/src/lib/commands/shar.c b/src/lib/commands/shar.c new file mode 100644 index 00000000..49d41b13 --- /dev/null +++ b/src/lib/commands/shar.c @@ -0,0 +1,80 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * shar.c: share a bmap with a friend + * + * Known contributors to this file: + * Ken Stevens, 1995 + */ + +#include "misc.h" +#include "nsc.h" +#include "nat.h" +#include "player.h" +#include "file.h" +#include "commands.h" + +int +shar(void) +{ + int to; + struct nstr_sect ns; + s_char des = 0; + int n; + + if (!player->argp[1] || + !*player->argp[1] || + (to = natarg(player->argp[1], "Share bmap with which country? ")) < 0) + return RET_SYN; + + if (getrel(getnatp(to), player->cnum) < FRIENDLY) { + pr("%s does not have friendly relations towards you\n", + cname(to)); + return RET_FAIL; + } + + if (!snxtsct(&ns, player->argp[2])) + return RET_SYN; + + if (player->argp[3] && *player->argp[3]) { + if (typematch(player->argp[3], EF_SECTOR) < 0) + return RET_SYN; + else + des = *player->argp[3]; + } + + if (!bmaps_intersect(player->cnum, to)) { + pr("Your bmap does not intersect %s's bmap.\n", cname(to)); + return RET_FAIL; + } + + n = share_bmap(player->cnum, to, &ns, des, cname(player->cnum)); + pr("%d designations transmitted\n", n); + + return RET_OK; +} + diff --git a/src/lib/commands/shark.c b/src/lib/commands/shark.c new file mode 100644 index 00000000..80749b33 --- /dev/null +++ b/src/lib/commands/shark.c @@ -0,0 +1,131 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * shark.c: Transfer a loan by buying it out + * + * Known contributors to this file: + * Pat Loney, 1992 + * Steve McClure, 1996-2000 + */ + +#include +#include "misc.h" +#include "var.h" +#include "file.h" +#include "sect.h" +#include "item.h" +#include "loan.h" +#include "news.h" +#include "nat.h" +#include "xy.h" +#include "player.h" +#include "commands.h" +#include "optlist.h" + +int +shark(void) +{ + register int arg; + time_t now; + char *p; + struct lonstr loan; + struct natstr *natp; + struct natstr *oldie; + long due; + long last; + long rdur; + long xdur; + double rate; + double owed; + long payment; + s_char buf[1024]; + + if (!opt_LOANS) { + pr("Loans are not enabled.\n"); + return RET_FAIL; + } + p = getstarg(player->argp[1], "Transfer which loan #: ", buf); + if (p == 0) + return RET_SYN; + if (*p == 0) + return RET_SYN; + arg = atoi(p); + if (arg < 0) + return RET_SYN; + /* Check if it's a valid loan to shark. That means, is it a valid loan, + not owed to this player, with a valid duration and it's been signed. */ + if (!getloan(arg,&loan) || (loan.l_loner == player->cnum) || + (loan.l_ldur == 0) || (loan.l_status != LS_SIGNED)) { + pr("Invalid loan\n"); + return RET_FAIL; + } + /* If we got here, we check to see if it's been defaulted on. */ + (void) time(&now); + due = loan.l_duedate; + if (now <= due) { + pr("There has been no default on loan %d\n", arg); + return RET_FAIL; + } + last = loan.l_lastpay; + if (last < due && due < now) { + rdur = due - last; + xdur = now - due; + } else if (due < last) { + rdur = 0; + xdur = now - last; + } + rate = loan.l_irate / (loan.l_ldur * 8.64e6); + + owed = ((rdur * rate) + (xdur * rate * 2.0) + 1.0); + if (((1 << 30) / owed) < loan.l_amtdue) + owed = (1 << 30); + else + owed *= loan.l_amtdue; + pr("That loan is worth $%.2f.\n", owed); + natp = getnatp(player->cnum); + payment = owed * (1.0 + loan.l_irate / 100.0); + if (payment > natp->nat_money - 100.0){ + pr("You do not have enough to cover that loan\n"); + return RET_FAIL; + }else{ + wu(0, loan.l_lonee, + "%s bought loan #%d. You now owe him!\n", + cname(player->cnum), + arg); + wu(0, loan.l_loner, + "%s bought loan #%d out from under you for %d\n", + cname(player->cnum), arg, payment); + pr("You now own loan #%d. Go break some legs.\n", arg); + } +/* NAT_DELTA(natp->nat_money, loan.l_loner, payment);*/ + oldie = getnatp(loan.l_loner); + oldie->nat_money += payment; + player->dolcost += payment; + loan.l_loner = player->cnum; + putloan(arg, &loan); + return RET_OK; +} diff --git a/src/lib/commands/shi.c b/src/lib/commands/shi.c new file mode 100644 index 00000000..63f76c30 --- /dev/null +++ b/src/lib/commands/shi.c @@ -0,0 +1,121 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * shi.c: Show a list of your ships + * + * Known contributors to this file: + * Steve McClure, 2000 + * + */ + +#include "misc.h" +#include "player.h" +#include "var.h" +#include "xy.h" +#include "sect.h" +#include "ship.h" +#include "nat.h" +#include "nsc.h" +#include "deity.h" +#include "file.h" +#include "optlist.h" +#include "commands.h" + +int +shi(void) +{ + int nships; + struct nstr_item ni; + struct shpstr ship; + int vec[I_MAX+1]; + + if (!snxtitem(&ni, EF_SHIP, player->argp[1])) + return RET_SYN; + + nships = 0; + while (nxtitem(&ni, (s_char *)&ship)) { + if (!player->owner || ship.shp_own == 0) + continue; + if (ship.shp_type < 0 || ship.shp_type > shp_maxno) { + pr("bad ship type %d (#%d)\n", + ship.shp_type, ni.cur); + continue; + } + count_planes(&ship); + count_units(&ship); + if (nships++ == 0) { + if (player->god) + pr("own "); +pr("shp# ship type x,y fl eff civ mil uw fd pn"); + pr(" he"); + pr(" xl"); + pr(" ln"); + pr(" mob"); + if (opt_FUEL) + pr(" fuel"); + pr(" tech\n"); + } + if (player->god) + pr("%3d ", ship.shp_own); + pr("%4d ", ni.cur); + pr("%-16.16s ", mchr[(int)ship.shp_type].m_name); + prxy("%4d,%-4d ", ship.shp_x, ship.shp_y, player->cnum); + pr("%1c", ship.shp_fleet); + pr("%4d%%", ship.shp_effic); + + getvec(VT_ITEM, vec, (s_char *)&ship, EF_SHIP); + pr("%4d", vec[I_CIVIL]); + pr("%4d", vec[I_MILIT]); + pr("%4d", vec[I_UW]); + pr("%4d", vec[I_FOOD]); + + pr("%3d", ship.shp_nplane); + pr("%3d",ship.shp_nchoppers); + pr("%3d",ship.shp_nxlight); + pr("%3d", ship.shp_nland); + pr("%4d", ship.shp_mobil); + if (opt_FUEL) + pr("%5d",ship.shp_fuel); + pr("%5d\n", ship.shp_tech); + if (opt_SHIPNAMES) { + if (ship.shp_name[0] != 0) { + if (player->god) + pr(" "); + pr(" %s\n",ship.shp_name); + } + } + } + if (nships == 0) { + if (player->argp[1]) + pr("%s: No ship(s)\n", player->argp[1]); + else + pr("%s: No ship(s)\n", ""); + return RET_FAIL; + }else + pr("%d ship%s\n", nships, splur(nships)); + return RET_OK; +} diff --git a/src/lib/commands/shoo.c b/src/lib/commands/shoo.c new file mode 100644 index 00000000..10ef4079 --- /dev/null +++ b/src/lib/commands/shoo.c @@ -0,0 +1,136 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * shoo.c: Shoot some conquered populace or pigeons. + * + * Known contributors to this file: + * Dave Pare, 1986 + */ + +#include "misc.h" +#include "player.h" +#include "xy.h" +#include "var.h" +#include "sect.h" +#include "news.h" +#include "item.h" +#include "path.h" +#include "nat.h" +#include "file.h" +#include "nsc.h" +#include "land.h" +#include "commands.h" + +int +shoo(void) +{ + struct sctstr sect; + struct nstr_sect nstr; + struct nstr_item ni; + int nshot; + int mob_cost; + double m; + int item; + struct ichrstr *ip; + struct lndstr land; + int targets; + s_char *p; + int vec[I_MAX+1], mil, nsec; + s_char prompt[128]; + s_char buf[128]; + + ip = whatitem(player->argp[1], "Shoot what "); + if (ip == 0 || (ip->i_vtype != V_CIVIL && ip->i_vtype != V_UW)) + return RET_SYN; + item = ip - ichr; + if (!snxtsct(&nstr, player->argp[2])) + return RET_SYN; + sprintf(prompt, "number of %s to shoot (max 999)? ", ip->i_name); + p = getstarg(player->argp[3], prompt, buf); + if (p == 0 || (targets = atoi(p)) <= 0) + return RET_SYN; + if (targets > 999) + targets = 999; + while (nxtsct(&nstr, §)) { + if (!player->owner) + continue; + if (getvec(VT_ITEM, vec, (s_char *) §, EF_SECTOR) <= 0) + continue; + mil = vec[I_MILIT]; + nsec = 0; + snxtitem_xy(&ni, EF_LAND, sect.sct_x, sect.sct_y); + while (nxtitem(&ni, (s_char *)&land)){ + mil += total_mil(&land); + + if (lchr[(int)land.lnd_type].l_flags & L_SECURITY){ + mil += total_mil(&land); + nsec++; + } + } + + if (vec[item] == 0 || vec[I_CIVIL] > mil * 10) + continue; + nshot = vec[item] > targets ? targets : vec[item]; + m = ((double)nshot + 4.0) / 5.0; + + if (m > sect.sct_mobil) { + nshot = sect.sct_mobil * 5; + m = sect.sct_mobil; + } + /* + * Each security unit lowers the cost of + * shooting a person by 10%. However, you + * can't go lower than 50% of normal cost + */ + if (nsec > 5) + nsec=5; + m = ((float)m * (1.0-((float)nsec * 0.1))); + if (nshot <= 0) + continue; + if (m < 0) + m = 0; + if (m > sect.sct_mobil) + m = sect.sct_mobil; + mob_cost = roundavg(m); + sect.sct_mobil -= (u_char)mob_cost; + vec[item] -= nshot; + pr("BANG!! (thump) %d %s shot in %s!\n", + nshot, ip->i_name, + xyas(sect.sct_x, sect.sct_y,player->cnum)); + if (chance(nshot / 100.0)) + nreport(player->cnum, N_SHOOT_CIV, sect.sct_oldown, 1); + if (vec[item] <= 0 && ip->i_vtype == V_CIVIL && + (sect.sct_own != sect.sct_oldown)) { + sect.sct_oldown = sect.sct_own; + pr(" %s is now completely yours\n", + xyas(sect.sct_x, sect.sct_y,player->cnum)); + } + putvar(ip->i_vtype, vec[item], (s_char *)§, EF_SECTOR); + putsect(§); + } + return RET_OK; +} diff --git a/src/lib/commands/show.c b/src/lib/commands/show.c new file mode 100644 index 00000000..ed0ea562 --- /dev/null +++ b/src/lib/commands/show.c @@ -0,0 +1,123 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * show.c: Give info on empire objects, planes, boats, nukes, etc. + * + * Known contributors to this file: + * Julian Onions, 1988 + * Steve McClure, 1997 + */ + +#include "misc.h" +#include "player.h" +#include "nat.h" +#include "file.h" +#include "deity.h" +#include "optlist.h" +#include "subs.h" +#include "commands.h" + +int +show(void) +{ + s_char *p; + void (*cfunc)(int); + void (*sfunc)(int); + void (*bfunc)(int); + struct natstr *natp; + int tlev; + s_char buf[1024]; + extern float drnuke_const; + int rlev; + + if (!(p = getstarg(player->argp[1], "Describe what (plane, nuke, bridge, ship, sect, land unit, tower)? ", buf)) || !*p) + return RET_SYN; + + natp = getnatp (player->cnum); + rlev = (int) (1.25 * natp->nat_level[NAT_RLEV]); + + if (!player->argp[3]) { + tlev = (int) (1.25 * natp->nat_level[NAT_TLEV]); + if (player->god) + tlev = 1000; + } else { + tlev = (int)atoi(player->argp[3]); + if (tlev > (int)(1.25 * natp->nat_level[NAT_TLEV]) && !player->god) + tlev = (int) (1.25 * natp->nat_level[NAT_TLEV]); + } + if (player->god) + rlev = 1000; + pr("Printing for tech level '%d'\n", tlev); + switch (*p) { + case 'b': + show_bridge(99999); + return RET_OK; + case 't': + show_tower(99999); + return RET_OK; + case 'n': + if (opt_DRNUKE) + tlev = ((rlev/drnuke_const) > tlev ? tlev : + (rlev/drnuke_const)); + bfunc = show_nuke_build; + cfunc = show_nuke_capab; + sfunc = show_nuke_stats; + break; + case 'l': + bfunc = show_land_build; + sfunc = show_land_stats; + cfunc = show_land_capab; + break; + case 'p': + bfunc = show_plane_build; + sfunc = show_plane_stats; + cfunc = show_plane_capab; + break; + case 's': + if (*(p+1) == 'e'){ + bfunc = show_sect_build; + sfunc = show_sect_stats; + cfunc = show_sect_capab; + }else{ + bfunc = show_ship_build; + sfunc = show_ship_stats; + cfunc = show_ship_capab; + } + break; + default: + return RET_SYN; + } + if (!(p = getstarg(player->argp[2], "Build, stats, or capability data (b,s,c)? ", buf)) || !*p) + return RET_SYN; + if (*p == 'B' || *p == 'b') + (*bfunc) (tlev); + else if (*p == 'C' || *p == 'c') + (*cfunc) (tlev); + else if (*p == 'S' || *p == 's') + (*sfunc) (tlev); + return RET_OK; +} diff --git a/src/lib/commands/shut.c b/src/lib/commands/shut.c new file mode 100644 index 00000000..0e696e28 --- /dev/null +++ b/src/lib/commands/shut.c @@ -0,0 +1,100 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * shut.c: Shut down the server with a warning. + * + * Known contributors to this file: + * Ken Stevens, 1995 + */ + +#include +#include "misc.h" +#include "player.h" +#include "empthread.h" +#include "nat.h" +#include "file.h" +#include "commands.h" + +extern void shutdown_sequence(); + +int +shut(void) +{ + extern int update_pending; + extern int shutdown_pending; + int shutdown_minutes; + int shutdown_was_pending; + s_char buf[100]; + s_char newbuf[100]; + struct natstr *us; + s_char *p; + + if (update_pending) { + pr("Update is pending\n"); + return RET_FAIL; + } + shutdown_minutes = onearg(player->argp[1], "Time until shutdown in minutes (0 to abort shutdown sequence)? "); + if (shutdown_minutes < 0) + return RET_SYN; + if (!updates_disabled()) + if (!(p=getstarg(player->argp[3],"Disable update [y]? ",buf))|| + *p != 'n') + disa(); + + shutdown_was_pending = shutdown_pending; + shutdown_pending = shutdown_minutes + !!shutdown_minutes; + buf[0] = '\0'; + if (shutdown_was_pending) { + if (shutdown_minutes) { + sprintf(buf, "The shutdown time has been changed to %d minutes", shutdown_minutes); + } else { + sprintf(buf, "The server shutdown has been cancelled"); + } + } else if (shutdown_minutes) { + pr("Shutdown sequence begun.\n"); + logerror("Shutdown sequence begun"); + empth_create(PP_SHUTDOWN, shutdown_sequence, (50*1024), + 0, "shutdownSeq", + "Counts down server shutdown", 0); + } + us = getnatp(player->cnum); + if (buf[0]) { + sprintf(newbuf, ": %s!", buf); + sendmessage(us, 0, newbuf, 1); + pr("%s.\n", buf); + logerror(buf); + } + if (shutdown_minutes) { + sprintf(buf, "The server will shut down in %d minutes", shutdown_minutes); + sprintf(newbuf, ": %s!", buf); + sendmessage(us, 0, newbuf, 1); + pr("%s.\n", buf); + logerror(buf); + } + return RET_OK; +} + diff --git a/src/lib/commands/sinf.c b/src/lib/commands/sinf.c new file mode 100644 index 00000000..f98a4a30 --- /dev/null +++ b/src/lib/commands/sinf.c @@ -0,0 +1,97 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * sinf.c: Do an infrastructure report + * + * Known contributors to this file: + * Steve McClure, 1996 + */ + +#include "misc.h" +#include "player.h" +#include "var.h" +#include "xy.h" +#include "sect.h" +#include "nsc.h" +#include "nat.h" +#include "deity.h" +#include "path.h" +#include "file.h" +#include "commands.h" + +int +sinfra(void) +{ + struct sctstr sect; + int nsect; + struct nstr_sect nstr; + double sector_mcost(); + double sector_strength(struct sctstr *); + + if (!snxtsct(&nstr, player->argp[1])) + return RET_SYN; + prdate(); + nsect = 0; + while (nxtsct(&nstr, §)) { + if (!player->owner) + continue; + if (nsect++ == 0) { + if (player->god) + pr(" "); + pr(" road rail defense\n"); + if (player->god) + pr("own "); + pr(" sect eff eff mcost eff mcost eff fact\n"); + } + if (player->god) + pr("%3d ", sect.sct_own); + prxy("%4d,%-4d", nstr.x, nstr.y, player->cnum); + pr(" %c", dchr[sect.sct_type].d_mnem); + if (sect.sct_newtype != sect.sct_type) + pr("%c", dchr[sect.sct_newtype].d_mnem); + else + pr(" "); + pr("%4d%% ", sect.sct_effic); + pr("%4d%% ", sect.sct_road); + pr("%4.3f ", sector_mcost(§, MOB_ROAD)); + pr("%4d%% ", sect.sct_rail); + pr("%4.3f ", sector_mcost(§, MOB_RAIL)); + pr("%4d%% ", sect.sct_defense); + pr("%5.2f\n", sector_strength(§)); + } + if (nsect == 0) { + if (player->argp[1]) + pr("%s: No sector(s)\n", player->argp[1]); + else + pr("%s: No sector(s)\n", ""); + return RET_FAIL; + }else + pr("%d sector%s\n", nsect, splur(nsect)); + return 0; +} + + diff --git a/src/lib/commands/skyw.c b/src/lib/commands/skyw.c new file mode 100644 index 00000000..56868799 --- /dev/null +++ b/src/lib/commands/skyw.c @@ -0,0 +1,176 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * skyw.c: Look at satellites in the sky. + * + * Known contributors to this file: + * Ken Stevens, 1995 + */ + +#include "misc.h" +#include "player.h" +#include "var.h" +#include "sect.h" +#include "plane.h" +#include "nat.h" +#include "xy.h" +#include "nsc.h" +#include "file.h" +#include "commands.h" +#include "optlist.h" + +#define TSIZE 200 + +struct sky { + struct sky *s_next; + int s_spotted; + struct plnstr s_sat; +}; + +static int showsat(struct sky **skypp, int x, int y); + +/* + * format: skywatch [] + */ +int +skyw(void) +{ + struct sctstr sect; + struct nstr_sect nstr; + struct sky *skyp; + struct sky *list[TSIZE]; + int i, k, j, n; + int vrange, see; + int x, y; + int mink, minj, maxk, maxj; + int nsat = 0; + float tech; + struct nstr_item ni; + + if (snxtsct(&nstr, player->argp[1]) == 0) + return RET_SYN; + for (i = 0; i < TSIZE; i++) + list[i] = 0; + skyp = (struct sky *)malloc(sizeof(*skyp)); + snxtitem_all(&ni, EF_PLANE); + while (nxtitem(&ni, (s_char *) &skyp->s_sat)) { + if (!skyp->s_sat.pln_own) + continue; + if (!(skyp->s_sat.pln_flags & PLN_LAUNCHED)) + continue; + getsect(skyp->s_sat.pln_x, skyp->s_sat.pln_y, §); + n = scthash(skyp->s_sat.pln_x, skyp->s_sat.pln_y, TSIZE); + skyp->s_spotted = 0; + skyp->s_next = list[n]; + list[n] = skyp; + skyp = (struct sky *)malloc(sizeof(*skyp)); + nsat++; + } + /* get that last one! */ + free((s_char *)skyp); + pr("- = [ Skywatch report for %s ] = -\n", cname(player->cnum)); + pr(" %18s%20s %s\n","Country", "Satellite", "Location"); + tech = tfact(player->cnum, 1.0); + while (nxtsct(&nstr, §) && nsat) { + if (sect.sct_own != player->cnum) + continue; + see = sect.sct_type == SCT_RADAR ? 14 : 4; + vrange = (int) (sect.sct_effic / 100.0 * see * tech); + if (vrange < 1) + vrange = 1; + maxk = vrange; + maxj = vrange * 2; + vrange *= vrange; + mink = -maxk; + minj = -maxj; + for (j = minj; j <= maxj && nsat; j++) { + x = xnorm(sect.sct_x + j); + for (k = mink; k <= maxk && nsat; k++) { + if ((j + k) & 01) + continue; + /* quick range check to save time... */ + if (vrange < (j * j + 3 * k * k) / 4) + continue; + y = ynorm(sect.sct_y + k); + n = scthash(x, y, TSIZE); + if (list[n] == 0) + continue; + nsat -= showsat(&list[n], x, y); + } + } + } + /* free up the sky structs calloc'ed above */ + for (i = 0; i < TSIZE; i++) { + while (NULL != (skyp = list[i])) { + list[i] = skyp->s_next; + free((s_char *)skyp); + } + } + return RET_OK; +} + +static int +showsat(struct sky **skypp, int x, int y) +{ + register struct sky *skyp; + register struct sky *todelete = 0; + register struct sky **prev; + register struct plchrstr *pcp; + s_char *name; + int nsat = 0; + + prev = 0; + skyp = *skypp; + prev = skypp; + do { + /* we delete it, we free it. */ + if (todelete) { + free((s_char *)todelete); + todelete = 0; + } + if (skyp->s_sat.pln_x != x || skyp->s_sat.pln_y != y) { + prev = &(*prev)->s_next; + continue; + } + pcp = &plchr[(int)skyp->s_sat.pln_type]; + name = pcp->pl_name; + pr(" %12.12s (#%d) %20s %s\n", + cname(skyp->s_sat.pln_own), skyp->s_sat.pln_own, + name, xyas(x, y, player->cnum)); + if (opt_HIDDEN) { + /* FOUND_COAST should probably be changed to FOUND_SKY -KHS */ + setcont(player->cnum, skyp->s_sat.pln_own, FOUND_COAST); + } + *prev = skyp->s_next; + todelete = skyp; + nsat++; + } while (NULL != (skyp = skyp->s_next)); + /* check that last one! */ + if (todelete) + free((s_char *)todelete); + return (nsat); +} diff --git a/src/lib/commands/sona.c b/src/lib/commands/sona.c new file mode 100644 index 00000000..a4468cd7 --- /dev/null +++ b/src/lib/commands/sona.c @@ -0,0 +1,402 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * sona.c: Sonar from a sub (or other sonar-equipped ship) + * + * Known contributors to this file: + * Jim Griffith, 1989 + * Ken Stevens, 1995 + */ + +#include "misc.h" +#include "player.h" +#include "var.h" +#include "xy.h" +#include "sect.h" +#include "nsc.h" +#include "retreat.h" +#include "ship.h" +#include "nat.h" +#include "path.h" +#include "file.h" +#include "queue.h" +#include "plane.h" +#include +#include +#include "commands.h" +#include "optlist.h" + +int +sona(void) +{ + struct nstr_item ni, nit; + struct sctstr sect; + struct shpstr ship; + struct shpstr targ; + struct natstr *natp; + struct mchrstr *mcp; + struct mchrstr *tmcp; + struct nstr_sect ns; + int range; + int pingrange; + int srange; + int vrange; + int dist; + int x,y; + int cx,cy; + int mines; + int changed = 0; + int row; + /* Where these are used are non-re-entrant, so we keep 'em around */ + static s_char **rad = (s_char **)0; + static s_char *radbuf = (s_char *)0; + static s_char **vis = (s_char **)0; + static s_char *visbuf = (s_char *)0; + + if (!snxtitem(&ni, EF_SHIP, player->argp[1])) + return RET_SYN; + if (!radbuf) + radbuf = (s_char *)malloc((WORLD_Y*(WORLD_X+1)) * sizeof(s_char)); + if (!visbuf) + visbuf = (s_char *)malloc((WORLD_Y*(WORLD_X+1)) * sizeof(s_char)); + if (!rad) { + rad = (s_char **)malloc(WORLD_Y * sizeof(s_char *)); + if (rad && radbuf) { + for (x = 0; x < WORLD_Y; x++) { + rad[x] = &radbuf[(WORLD_X + 1) * x]; + } + } else if (rad) { + free((s_char *)rad); + rad = (s_char **)0; + } + } + if (!vis) { + vis = (s_char **)malloc(WORLD_Y * sizeof(s_char *)); + if (vis && visbuf) { + for (x = 0; x < WORLD_Y; x++) { + vis[x] = &visbuf[(WORLD_X + 1) * x]; + } + } else if (vis) { + free((s_char *)vis); + vis = (s_char **)0; + } + } + if (!radbuf || !visbuf || !rad || !vis) { + pr("Memory error, tell the deity.\n"); + logerror("malloc failed in sona\n"); + return RET_FAIL; + } + while (nxtitem(&ni, (s_char *)&ship)) { + if (!player->owner) + continue; + mcp = &mchr[(int)ship.shp_type]; + if (!(mcp->m_flags & M_SONAR)) + continue; + getsect(ship.shp_x, ship.shp_y, §); + if (sect.sct_type != SCT_WATER) + continue; + range = (int) techfact(ship.shp_tech, + (double) mcp->m_vrnge); + srange = min(7, 7 * range * ship.shp_effic / 200); + pr("%s at %s efficiency %d%%, max range %d\n", + prship(&ship), + xyas(ship.shp_x, ship.shp_y, player->cnum), + ship.shp_effic, + srange); + snxtsct_dist(&ns,ship.shp_x,ship.shp_y,srange); + blankfill((s_char *)radbuf, &ns.range, 1); + while(nxtsct(&ns,§)){ + if (player->owner || sect.sct_type == SCT_WATER) + rad[ns.dy][ns.dx] = dchr[sect.sct_type].d_mnem; + else { + rad[ns.dy][ns.dx] = '?'; + } + } + snxtsct_dist(&ns,ship.shp_x,ship.shp_y,srange); + cx = deltax(ship.shp_x, ns.range.lx); + cy = deltay(ship.shp_y, ns.range.ly); + while(nxtsct(&ns,§)) { + if (!line_of_sight(rad, cx, cy, ns.dx, ns.dy)) { + rad[ns.dy][ns.dx] = ' '; + continue; + } + if (ship.shp_tech >= 310 && + sect.sct_type == SCT_WATER) { + mines=getvar(V_MINE,(s_char *)§,EF_SECTOR); + if (mines) { + pr("Sonar detects %d mines in %s!\n", + mines, + xyas(sect.sct_x,sect.sct_y,player->cnum)); + rad[ns.dy][ns.dx] = 'X'; + } + } + changed |= map_set(player->cnum, sect.sct_x, sect.sct_y, + rad[ns.dy][ns.dx], 0); + + } + bzero((s_char *)visbuf, (WORLD_Y * (WORLD_X + 1))); + snxtitem_dist(&nit, EF_SHIP, ship.shp_x, ship.shp_y, range); + while (nxtitem(&nit, (caddr_t)&targ)) { + + if (targ.shp_own == player->cnum || targ.shp_own == 0) + continue; + tmcp = &mchr[(int)targ.shp_type]; + pingrange = min(7, max(targ.shp_visib,10)*range/10); + vrange = pingrange * ship.shp_effic / 200; + dist = mapdist(targ.shp_x, targ.shp_y, + ship.shp_x, ship.shp_y); + pingrange = (max(pingrange, 2) * targ.shp_effic)/100; + if (dist > pingrange) + continue; + if (tmcp->m_flags & M_SONAR && targ.shp_own) { + natp = getnatp(targ.shp_own); + if (natp->nat_flags & NF_SONAR) + wu(0, targ.shp_own, + "Sonar ping from %s detected by %s!\n", + + xyas(ship.shp_x, ship.shp_y, + targ.shp_own), + prship(&targ)); + if (targ.shp_rflags & RET_SONARED){ + retreat_ship(&targ, 's'); + putship(targ.shp_uid,&targ); + } + } + if (dist > vrange) + continue; + x = deltx(&ns.range,(int)targ.shp_x); + y = delty(&ns.range,(int)targ.shp_y); + if (rad[y][x] != dchr[SCT_WATER].d_mnem && + rad[y][x] != 'X') + continue; + if (tmcp->m_flags & M_SUB && + getrel(getnatp(targ.shp_own), player->cnum) < FRIENDLY) { + if (mcp->m_vrnge + targ.shp_visib < 8) + pr("Sonar detects sub #%d @ %s\n", + targ.shp_uid, + xyas(targ.shp_x, targ.shp_y, player->cnum)); + else if (mcp->m_vrnge + targ.shp_visib < 10) + pr("Sonar detects %s @ %s\n", + prship(&targ), + xyas(targ.shp_x, targ.shp_y, player->cnum)); + else + pr("Sonar detects %s %s @ %s\n", cname(targ.shp_own), + prship(&targ), + xyas(targ.shp_x, targ.shp_y, player->cnum)); + } else + pr("Sonar detects %s %s @ %s\n", cname(targ.shp_own), + prship(&targ), + xyas(targ.shp_x, targ.shp_y, player->cnum)); + + if (targ.shp_visib > vis[y][x]) { + vis[y][x] = targ.shp_visib; + /* &~0x20 makes it a cap letter */ + rad[y][x] = (*mchr[(int)targ.shp_type].m_name) & ~0x20; + } + } + if (!player->argp[2]) { + rad[cy][cx] = '0'; + for (row=0; row < ns.range.height; row++) + if (!blankrow(rad[row])) + pr("%s\n", rad[row]); + } + pr("\n"); + + } + if (changed) + writemap(player->cnum); + return RET_OK; +} + +void +plane_sona(struct emp_qelem *plane_list, int x, int y, struct shiplook *head) +{ + struct plnstr *pp; + struct plchrstr *pcp; + struct mchrstr *tmcp; + struct shpstr *targ,s; + struct natstr *natp; + struct emp_qelem *qp; + struct emp_qelem *next; + struct plist *ip; + struct sctstr sect; + int found=0; + int range,i; + int pingrange; + int vrange; + int dist; + + getsect(x,y,§); + if ((sect.sct_type != SCT_WATER) && (sect.sct_type != SCT_HARBR)) + return; + for (qp = plane_list->q_forw; qp != plane_list; qp = next) { + next = qp->q_forw; + ip = (struct plist *) qp; + pp = &ip->plane; + pcp = ip->pcp; + if (!(pcp->pl_flags & P_A)) /* if it isn't an ASW plane */ + continue; + range = (int) techfact(pp->pln_tech, (double) ((100-pp->pln_acc)/10)); +/* + for (i=0; targ = getshipp(i); i++) { +*/ + for (i=0; getship(i,&s) ; i++) { + targ = &s; + if (targ->shp_own == pp->pln_own || targ->shp_own == 0) + continue; +/* + if (have_looked(targ->shp_uid,head)) + continue; +*/ + if (have_found(targ->shp_uid,head)) + continue; + set_have_looked(targ->shp_uid,head); + tmcp = &mchr[(int)targ->shp_type]; + if (!(tmcp->m_flags & M_SUB)) + continue; + if (roll(100) > pln_identchance(pp, shp_hardtarget(targ), EF_SHIP)) + continue; + pingrange = max(targ->shp_visib, 10) * range / 10; + vrange = ((float)pingrange) * ((float)pp->pln_effic / 200.0); + dist = mapdist(targ->shp_x, targ->shp_y, x, y); + pingrange = (max(pingrange, 2) * targ->shp_effic); + pingrange = roundavg(pingrange/100.0); + if (dist > pingrange) + continue; + if (tmcp->m_flags & M_SONAR && targ->shp_own) { + natp = getnatp(targ->shp_own); + if (natp->nat_flags & NF_SONAR) + wu(0, targ->shp_own, + "Sonar ping from %s detected by %s!\n", + xyas(x, y, targ->shp_own), + prship(targ)); + } + if ((dist > vrange)) + continue; + set_have_found(targ->shp_uid,head); + if (!found){ + mpr(pp->pln_own, + "\nSonar contact in %s\n",xyas(x,y,pp->pln_own)); + found=1; + } + if (getrel(getnatp(targ->shp_own), pp->pln_own) < FRIENDLY && + roll(100) > pln_identchance(pp, shp_hardtarget(targ), EF_SHIP)) + if (roll(100) > pln_identchance(pp, shp_hardtarget(targ), EF_SHIP)) + mpr(pp->pln_own, + "sub #%d %s\n", + targ->shp_uid, + xyas(targ->shp_x, targ->shp_y, pp->pln_own)); + else + mpr(pp->pln_own, + "%s %s\n", + prship(targ), + xyas(targ->shp_x, targ->shp_y, pp->pln_own)); + else + mpr(pp->pln_own, + "%s %s @ %s\n", cname(targ->shp_own), + prship(targ), + xyas(targ->shp_x, targ->shp_y, pp->pln_own)); + } + } +} + +/* + * line_of_sight() - is there a "straight" all water path from (x,y) to (tx,ty) + * Ken & Irina Stevens, 1995 + */ + +#define DOT(ax,ay,bx,by) ((ax)*(bx) + (ay)*(by)) +#define LEN(x,y) ((x)*(x) + (y)*(y)) +#define DIST(ax,ay,bx,by) LEN(bx - ax, by -ay) + +int +line_of_sight(s_char **rad, int ax, int ay, int bx, int by) +{ + int dx = bx - ax; + int dy = by - ay; + int dlen = LEN(dx, dy); + int n; + int cx = 0; + int cy = 0; + int tx, ty; /* test point */ + double cd_dist = dlen; /* closest distance from c to vector d */ + double md_dist; /* minimum distance from t to vector d */ + double td_dist; /* distance from t to vector d */ + double td_proj; /* the projection of t onto vector d */ + int closest; /* index of closest */ + int blocked = 0; + struct sctstr *sectp; + + while (cd_dist) { + if (blocked) + return 0; + md_dist = 100; /* will always be <= 2 */ + closest = -1; + for (n = 1; n <= 6; ++n) { /* Directions */ + tx = cx + diroff[n][0]; + ty = cy + diroff[n][1]; + if (DIST(tx,ty,dx,dy) >= cd_dist) + continue; + td_proj = (double)DOT(tx,ty,dx,dy) / dlen; + td_dist = DIST(tx,ty,td_proj*dx,td_proj*dy); + if (td_dist < md_dist) { + md_dist = td_dist; + closest = n; + } + } + if (closest < 0) /* not possible */ + return 0; + cx = cx + diroff[closest][0]; + cy = cy + diroff[closest][1]; + if (rad) { + blocked = (rad[ay+cy][ax+cx] != dchr[SCT_WATER].d_mnem); + } else { + sectp = getsectp((ax + cx), (ay + cy)); + if (sectp) { + if (sectp->sct_type == SCT_WATER || + sectp->sct_type == SCT_BSPAN) { + blocked = 0; + } else { + blocked = 1; + } + } + } + cd_dist = DIST(cx,cy,dx,dy); + } + return 1; +} + +int +blankrow(s_char *s) +{ + while (*s) { + if (*s != ' ') + return 0; + ++s; + } + return 1; +} diff --git a/src/lib/commands/spy.c b/src/lib/commands/spy.c new file mode 100644 index 00000000..1a59cdb8 --- /dev/null +++ b/src/lib/commands/spy.c @@ -0,0 +1,361 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * spy.c: Spy on your neighbors + * + * Known contributors to this file: + * Dave Pare, 1986 + * Steve McClure, 1998-2000 + */ + +#include "misc.h" +#include "player.h" +#include "var.h" +#include "sect.h" +#include "item.h" +#include "nat.h" +#include "xy.h" +#include "nsc.h" +#include "nuke.h" +#include "news.h" +#include "deity.h" +#include "path.h" +#include "file.h" +#include "land.h" +#include "commands.h" +#include "optlist.h" + +/* + * format: spy + * + */ +static void spyline(struct sctstr *sp); +static void insert(coord *table, int *len, coord x, coord y); +static int check(coord *table, int *len, coord x, coord y); + +int +spy(void) +{ + int caught; + natid own; + int relat; + coord x, y; + coord nx, ny; + int military; + int savemil; + int btucost; + int i; + coord *table; /* sectors already seen */ + int t_len = 0; + int vec[I_MAX+1]; + int dvec[I_MAX+1]; + int nrecon; + int nunits; + struct nstr_sect nstr; + struct nstr_item ni; + struct natstr *natp; + struct sctstr from; + struct sctstr dsect; + struct lndstr land; + int changed = 0; + int nsects; + + /* + * first arg should be the range of sectors + */ + if (!snxtsct(&nstr, player->argp[1])) + return RET_SYN; + nsects = (nstr.range.width+1) * nstr.range.height / 2; + btucost = (nsects / 40) + 1; + natp = getnatp(player->cnum); + if (natp->nat_btu < btucost) { + pr("You don't have the BTU's for spying on that scale!\n"); + return RET_FAIL; + } + /* + * set up all the goodies we need later + * 6 = neighbors, 2 = x,y + */ + table = (coord *) malloc((nsects + 1) * 6 * 2 * sizeof(coord)); + bzero((s_char *)table, (nsects + 1) * 6 * 2 * sizeof(coord)); + pr("SPY report\n"); + prdate(); +pr(" old sct rd rl def\n"); +pr(" sect de own own eff eff eff eff civ mil shl gun pet food bars lnd pln\n"); + while (nxtsct(&nstr, &from)) { + if (!player->owner && !player->god) + continue; + getvec(VT_ITEM, vec, (s_char *) &from, EF_SECTOR); + nrecon=0; + nunits=0; + snxtitem_xy(&ni, EF_LAND, from.sct_x, from.sct_y); + while (nxtitem(&ni, (s_char *)&land)){ + nunits++; + if (lchr[(int)land.lnd_type].l_flags & L_RECON) + nrecon++; + } + if ((military = vec[I_MILIT]) == 0 && (nunits == 0)) + continue; + x = from.sct_x; + y = from.sct_y; + /* Print out the units/planes in this sector */ + prunits(x, y); + prplanes(x, y); + savemil = military; + /* + * check the neighboring sectors. + */ + for (i = 1; i <= 6; i++) { + if ((military == 0) && (nunits == 0)) + break; + nx = x + diroff[i][0]; + ny = y + diroff[i][1]; + /* + * if we've already seen the + * sector, don't bother checking it + * out. + */ + if (check(table, &t_len, nx, ny)) { + continue; + } + getsect(nx, ny, &dsect); + getvec(VT_ITEM, dvec, (s_char *) &dsect, EF_SECTOR); + if (player->owner || (dsect.sct_type == SCT_WATER) || + (!dvec[I_MILIT] && !dvec[I_CIVIL] && + (num_units(nx, ny) == 0))) { + /* mark sector as seen */ + insert(table, &t_len, nx, ny); + continue; + } + /* catch spy N/200 chance, N = # military */ + caught = chance((double) dvec[I_MILIT] / 200.0); + own = dsect.sct_own; + /* determine spyee relations with spyer */ + relat = getrel(getnatp(own), player->cnum); + if (relat == NEUTRAL && caught) { + /* neutral spy-ee */ + pr("Spy deported from %s\n", + xyas(nx, ny, player->cnum)); + if(own != 0) + wu(0, own, "%s (#%d) spy deported from %s\n", + cname(player->cnum), player->cnum, + xyas(nx, ny, own)); + } else if (relat < NEUTRAL && caught) { + /* at-war with spy-ee */ + pr("BANG!! A spy was shot in %s\n", + xyas(nx, ny, player->cnum)); + military--; + if(own != 0) + wu(0, own, "%s (#%d) spy caught in %s\n", + cname(player->cnum), player->cnum, + xyas(nx, ny, own)); + nreport(player->cnum, N_SPY_SHOT, own, 1); + } else { + insert(table, &t_len, nx, ny); + spyline(&dsect); + changed += map_set(player->cnum, dsect.sct_x, + dsect.sct_y, + dchr[dsect.sct_type].d_mnem, 0); + prunits(dsect.sct_x,dsect.sct_y); + prplanes(dsect.sct_x,dsect.sct_y); + if (opt_HIDDEN) { + setcont(player->cnum, own, FOUND_SPY); + } + } + /* + * If you have a recon unit, it'll + * see the sector anyway... + */ + if (nrecon && caught){ + insert(table, &t_len, nx, ny); + spyline(&dsect); + changed += map_set(player->cnum, dsect.sct_x, + dsect.sct_y, + dchr[dsect.sct_type].d_mnem, 0); + prunits(dsect.sct_x, dsect.sct_y); + prplanes(dsect.sct_x,dsect.sct_y); + } + } + /* subtract any military if necessary */ + if ((savemil != military) && (savemil > 0)){ + if ((military < 0) || (military > savemil)) + military = 0; + vec[I_MILIT] = military; + putvec (VT_ITEM, vec, (s_char *) &from, EF_SECTOR); + putsect(&from); + } + } + if (changed) + writemap(player->cnum); + player->btused += btucost; + free((s_char *)table); + return RET_OK; +} + + +/* + * just a big printf. + */ +static void +spyline(struct sctstr *sp) +{ + int vec[I_MAX+1]; + + getvec(VT_ITEM, vec, (s_char *) sp, EF_SECTOR); + prxy("%4d,%-4d",sp->sct_x, sp->sct_y, player->cnum); + pr(" %c%c %3d %3d %3d %3d %3d %3d %4d %4d %4d %3d %4d %4d %4d %3d %3d\n", + dchr[sp->sct_type].d_mnem, + (sp->sct_newtype == sp->sct_type)?' ':dchr[sp->sct_newtype].d_mnem, + sp->sct_own, + sp->sct_oldown, + roundintby((int)sp->sct_effic, 10), + roundintby((int)sp->sct_road, 10), + roundintby((int)sp->sct_rail, 10), + roundintby((int)sp->sct_defense, 10), + roundintby(vec[I_CIVIL], 10), roundintby(vec[I_MILIT], 10), + roundintby(vec[I_SHELL], 10), roundintby(vec[I_GUN], 10), + roundintby(vec[I_PETROL], 10), roundintby(vec[I_FOOD], 10), + roundintby(vec[I_BAR], 10), count_sect_units(sp), count_sect_planes(sp)); +} + + +/* + * insert a key into the table. + */ +static void +insert(coord *table, int *len, coord x, coord y) +{ + if (!check(table, len, x, y)) { + table[(*len)++] = x; + table[(*len)++] = y; + } +} +/* + * see if a key is in the bitmask table + */ +static int +check(coord *table, int *len, coord x, coord y) +{ + int i; + + for (i = 0; i < *len; i += 2) + if (table[i] == x && table[i + 1] == y) + return 1; + return 0; +} + +int +num_units(int x, int y) +{ + struct lndstr land; + struct nstr_item ni; + int n=0; + + snxtitem_xy(&ni, EF_LAND, x, y); + while (nxtitem(&ni, (s_char *)&land)) { + if ((land.lnd_own == player->cnum) || (land.lnd_own == 0)) + continue; + if (land.lnd_ship >= 0 || land.lnd_land >= 0) + continue; + n++; + } + + return n; +} + +void +prunits(int x, int y) +{ + struct lndstr land; + struct nstr_item ni; + s_char report[128]; + double odds; + + snxtitem_xy(&ni, EF_LAND, x, y); + while (nxtitem(&ni, (s_char *)&land)) { + if (land.lnd_own == player->cnum || land.lnd_own == 0) + continue; + if (land.lnd_ship >= 0 || land.lnd_land >= 0) + continue; + /* Don't always see spies */ + if (lchr[(int)land.lnd_type].l_flags & L_SPY) { + odds = (double)(100 - land.lnd_effic) + 0.10; + if (!(chance(odds))) + continue; + } + if ((land.lnd_own != player->cnum) && land.lnd_own) { + int rel; + s_char *format; + + rel = getrel(getnatp(player->cnum),land.lnd_own); + if (rel == ALLIED) + format = "Allied (%s) unit in %s: "; + else if (rel == FRIENDLY || rel == NEUTRAL) + format = "Neutral (%s) unit in %s: "; + else + format = "Enemy (%s) unit in %s: "; + sprintf(report, format, cname(land.lnd_own), + xyas(land.lnd_x, land.lnd_y,player->cnum)); + intelligence_report(player->cnum, &land, 3, report); + } + } +} + +void +prplanes(int x, int y) +{ + struct plnstr plane; + struct nstr_item ni; + s_char report[128]; + + snxtitem_xy(&ni, EF_PLANE, x, y); + while (nxtitem(&ni, (s_char *)&plane)) { + if (plane.pln_own == player->cnum || plane.pln_own == 0) + continue; + if (plane.pln_ship >= 0 || plane.pln_land >= 0) + continue; + if (plane.pln_flags & PLN_LAUNCHED) + continue; + if ((plane.pln_own != player->cnum) && plane.pln_own) { + int rel; + s_char *format; + + rel = getrel(getnatp(player->cnum),plane.pln_own); + if (rel == ALLIED) + format = "Allied (%s) plane in %s: %s\n"; + else if (rel == FRIENDLY || rel == NEUTRAL) + format = "Neutral (%s) plane in %s: %s\n"; + else + format = "Enemy (%s) plane in %s: %s\n"; + sprintf(report, format, cname(plane.pln_own), + xyas(plane.pln_x, plane.pln_y,player->cnum), + prplane(&plane)); + pr(report); + } + } +} + diff --git a/src/lib/commands/sstat.c b/src/lib/commands/sstat.c new file mode 100644 index 00000000..e3949ca1 --- /dev/null +++ b/src/lib/commands/sstat.c @@ -0,0 +1,98 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * sstat.c: Show the stats of your ships + * + * Known contributors to this file: + * Steve McClure, 1996 + */ + +#include "misc.h" +#include "player.h" +#include "var.h" +#include "xy.h" +#include "sect.h" +#include "ship.h" +#include "nat.h" +#include "nsc.h" +#include "deity.h" +#include "file.h" +#include "optlist.h" +#include "commands.h" + +int +sstat(void) +{ + int nships; + struct nstr_item ni; + struct shpstr ship; + + if (!snxtitem(&ni, EF_SHIP, player->argp[1])) + return RET_SYN; + + nships = 0; + while (nxtitem(&ni, (s_char *)&ship)) { + if (!player->owner || ship.shp_own == 0) + continue; + if (ship.shp_type < 0 || ship.shp_type > shp_maxno) { + pr("bad ship type %d (#%d)\n", + ship.shp_type, ni.cur); + continue; + } + count_planes(&ship); + count_units(&ship); + + if (nships++ == 0) { +pr("shp# %22.22s x,y eff tech def spd vis rng fir\n", "ship-type"); + } + pr("%4d %-22.22s ", + ship.shp_uid, + mchr[(int)ship.shp_type].m_name); + prxy("%4d,%-4d", + ship.shp_x, + ship.shp_y, + player->cnum); + pr(" %3d%% %4d %3d %3d %3d %3d %3d", + ship.shp_effic, + ship.shp_tech, + ship.shp_armor, + ship.shp_speed, + ship.shp_visib, + ship.shp_frnge, + ship.shp_glim); + pr("\n"); + } + if (nships == 0) { + if (player->argp[1]) + pr("%s: No ship(s)\n", player->argp[1]); + else + pr("%s: No ship(s)\n", ""); + return RET_FAIL; + }else + pr("%d ship%s\n", nships, splur(nships)); + return RET_OK; +} diff --git a/src/lib/commands/star.c b/src/lib/commands/star.c new file mode 100644 index 00000000..21f46489 --- /dev/null +++ b/src/lib/commands/star.c @@ -0,0 +1,102 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * star.c: Start a sector producing + * + * Known contributors to this file: + * Thomas Ruschak, 1992 + * Steve McClure, 1998 + */ + +#include "misc.h" +#include "player.h" +#include "var.h" +#include "xy.h" +#include "sect.h" +#include "nsc.h" +#include "nat.h" +#include "deity.h" +#include "path.h" +#include "file.h" +#include "product.h" +#include "commands.h" + +static void start_hdr(void); + +int +start(void) +{ + struct sctstr sect; + int nsect; + struct nstr_sect nstr; + + if (!snxtsct(&nstr, player->argp[1])) + return RET_SYN; + prdate(); + nsect = 0; + while (nxtsct(&nstr, §)) { + if (!player->owner) + continue; + if (nsect++ == 0) + start_hdr(); + if (player->god) + pr("%3d ", sect.sct_own); + prxy("%4d,%-4d", nstr.x, nstr.y, player->cnum); + pr(" %c", dchr[sect.sct_type].d_mnem); + if (sect.sct_newtype != sect.sct_type) + pr("%c", dchr[sect.sct_newtype].d_mnem); + else + pr(" "); + pr("%4d%%", sect.sct_effic); + + pr(" will be updated normally.\n"); + if (sect.sct_off != 0) { + sect.sct_off = 0; + putsect(§); + } + } + if (nsect == 0) { + if (player->argp[1]) + pr("%s: No sector(s)\n", player->argp[1]); + else + pr("%s: No sector(s)\n", ""); + return RET_FAIL; + }else + pr("%d sector%s\n", nsect, splur(nsect)); + return 0; +} + +static void +start_hdr(void) +{ + if (player->god) + pr(" "); + pr("PRODUCTION STARTING\n"); + if (player->god) + pr("own "); + pr(" sect eff\n"); +} diff --git a/src/lib/commands/stop.c b/src/lib/commands/stop.c new file mode 100644 index 00000000..4e47322f --- /dev/null +++ b/src/lib/commands/stop.c @@ -0,0 +1,102 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * stop.c: Stop a sector from producing + * + * Known contributors to this file: + * Thomas Ruschak, 1992 + * Steve McClure, 1998 + */ + +#include "misc.h" +#include "player.h" +#include "var.h" +#include "xy.h" +#include "sect.h" +#include "nsc.h" +#include "nat.h" +#include "deity.h" +#include "path.h" +#include "file.h" +#include "product.h" +#include "commands.h" + +static void stop_hdr(void); + +int +stop(void) +{ + struct sctstr sect; + int nsect; + struct nstr_sect nstr; + + if (!snxtsct(&nstr, player->argp[1])) + return RET_SYN; + prdate(); + nsect = 0; + while (nxtsct(&nstr, §)) { + if (!player->owner) + continue; + if (nsect++ == 0) + stop_hdr(); + if (player->god) + pr("%3d ", sect.sct_own); + prxy("%4d,%-4d", nstr.x, nstr.y, player->cnum); + pr(" %c", dchr[sect.sct_type].d_mnem); + if (sect.sct_newtype != sect.sct_type) + pr("%c", dchr[sect.sct_newtype].d_mnem); + else + pr(" "); + pr("%4d%%", sect.sct_effic); + + pr(" will not produce or gain efficiency.\n"); + if (sect.sct_off != 1) { + sect.sct_off = 1; + putsect(§); + } + } + if (nsect == 0) { + if (player->argp[1]) + pr("%s: No sector(s)\n", player->argp[1]); + else + pr("%s: No sector(s)\n", ""); + return RET_FAIL; + }else + pr("%d sector%s\n", nsect, splur(nsect)); + return 0; +} + +static void +stop_hdr(void) +{ + if (player->god) + pr(" "); + pr("PRODUCTION STOPPAGE\n"); + if (player->god) + pr("own "); + pr(" sect eff\n"); +} diff --git a/src/lib/commands/stre.c b/src/lib/commands/stre.c new file mode 100644 index 00000000..cf890157 --- /dev/null +++ b/src/lib/commands/stre.c @@ -0,0 +1,161 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * stre.c: Calculate military strengths of sectors + * + * Known contributors to this file: + * Ken Stevens, 1995 + */ + +#include +#include "misc.h" +#include "player.h" +#include "file.h" +#include "var.h" +#include "sect.h" +#include "path.h" +#include "news.h" +#include "treaty.h" +#include "nat.h" +#include "xy.h" +#include "land.h" +#include "nsc.h" +#include "mission.h" +#include "ship.h" +#include "combat.h" +#include "commands.h" + +static double units_in_sector(struct combat *def); +static void stre_hdr(void); + +int +stre(void) +{ + struct sctstr sect; + int nsect = 0; + struct nstr_sect nstr; + double dtotal, r_total, eff; + struct combat def[1]; + int dummy; + int mines; + + if (!snxtsct(&nstr, player->argp[1])) + return RET_SYN; + prdate(); + nsect = 0; + att_combat_init(def, EF_SECTOR); + while (nxtsct(&nstr, §)) { + if (!player->owner) + continue; + if (nsect++ == 0) + stre_hdr(); + if (player->god) + pr("%3d ", sect.sct_own); + prxy("%4d,%-4d", nstr.x, nstr.y, player->cnum); + pr(" %c", dchr[sect.sct_type].d_mnem); + pr("%4d%%", sect.sct_effic); + def->x = nstr.x; + def->y = nstr.y; + def->set = 0; + att_get_combat(def, 1); + if (def->mil) + pr("%5d", def->mil); + else + pr("%5s", ""); + dtotal = units_in_sector(def); + if (dtotal > 0) + pr("%7d", (int)dtotal); + else + pr("%7s", ""); + + r_total = att_reacting_units(def, 0, 0, &dummy, 9999999); + def->own = 0; + eff = att_combat_eff(def); + if (sect.sct_own == sect.sct_oldown) { + mines = getvar(V_MINE, (s_char *)§, EF_SECTOR); + if (mines > 0) + pr("%7d", mines); + else + pr("%7s", ""); + eff *= (1.0 + min(mines,20) * 0.02); + } else { + pr("%7s", "?"); + } + pr("%6.2f", eff); + pr("%9d", (int)((dtotal + def->mil) * eff)); + if (r_total > 0) + pr(" %9d", (int)(r_total * eff)); + else + pr(" %9s", ""); + pr("%9d\n", (int)((dtotal + def->mil + r_total) * eff)); + } + if (!nsect) { + if (player->argp[1]) + pr("%s: No sector(s)\n", player->argp[1]); + else + pr("%s: No sector(s)\n", ""); + return RET_FAIL; + } else + pr("%d sector%s\n", nsect, splur(nsect)); + return 0; +} + +static double +units_in_sector(struct combat *def) +{ + double d_unit; + double dtotal = 0.0; + struct nstr_item ni; + struct lndstr land; + + snxtitem_xy(&ni,EF_LAND,def->x, def->y); + while(nxtitem(&ni,(s_char *)&land)){ + if (land.lnd_own == 0) + continue; + if (land.lnd_own != def->own) + continue; + if (land.lnd_ship >= 0) + continue; + d_unit = defense_val(&land); + if (!has_supply(&land)) + d_unit /= 2.0; + dtotal += d_unit; + } + return dtotal; +} + +static void +stre_hdr(void) +{ + if (player->god) + pr(" "); + pr("DEFENSE STRENGTH land sect sector reacting total\n"); + if (player->god) + pr("own "); + pr(" sect eff mil units mines mult defense units defense\n"); +} + diff --git a/src/lib/commands/strv.c b/src/lib/commands/strv.c new file mode 100644 index 00000000..75e3b2df --- /dev/null +++ b/src/lib/commands/strv.c @@ -0,0 +1,271 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * star.c: Do a starvation report + * + * Known contributors to this file: + * + */ + +#include "misc.h" +#include "player.h" +#include "var.h" +#include "xy.h" +#include "sect.h" +#include "nsc.h" +#include "nat.h" +#include "deity.h" +#include "path.h" +#include "file.h" +#include +#include "item.h" +#include "ship.h" +#include "optlist.h" +#include "land.h" +#include "commands.h" + +extern int etu_per_update; +static void starv_sects(s_char *range); +static void starv_ships(s_char *range); +static void starv_units(s_char *range); +static void sect_hdr(void); +static void ship_hdr(void); +static void unit_hdr(void); + +int +starve(void) +{ + struct nstr_sect nstr; + int do_sects = 0; + int do_ships = 0; + int do_units = 0; + s_char range[1024]; + + if (opt_NOFOOD) { /* no food - no work! */ + pr("No food is required in this game\n"); + return RET_OK; + } + + strcpy(range, "*"); + if (!player->argp[1]) { + do_sects = do_ships = do_units = 1; + } else if (*(player->argp[1]) == 's') { + do_ships = 1; + if (player->argp[2]) + strcpy(range, player->argp[2]); + } else if (*(player->argp[1]) == 'l') { + do_units = 1; + if (player->argp[2]) + strcpy(range, player->argp[2]); + } else { + if (!snxtsct(&nstr, player->argp[1])) + return RET_SYN; + do_sects = 1; + strcpy(range, player->argp[1]); + } + player->simulation = 1; + prdate(); + if (do_sects) + starv_sects(range); + if (do_ships) + starv_ships(range); + if (do_units) + starv_units(range); + player->simulation = 0; + return RET_OK; +} + +static void +starv_sects(s_char *range) +{ + struct nstr_sect nstr; + struct sctstr sect; + int nsect = 0; + int vec[I_MAX+1], s, needed; + + if (!snxtsct(&nstr, range)) + return; + while (nxtsct(&nstr, §)) { + if (!player->owner) + continue; + if (sect.sct_type == SCT_SANCT) + continue; + + getvec(VT_ITEM, vec, (s_char *)§, EF_SECTOR); +/* This next 2 lines were added to overcompensate for the needy */ + if (vec[I_FOOD]) + vec[I_FOOD]--; + s = feed_people(vec, etu_per_update, &needed); + + if (s==0) + continue; + if (nsect++ == 0) + sect_hdr(); + if (player->god) + pr("%3d ", sect.sct_own); + prxy("%4d,%-4d", nstr.x, nstr.y, player->cnum); + pr(" %c", dchr[sect.sct_type].d_mnem); + pr(" %c", (sect.sct_own != sect.sct_oldown ? '*' : ' ')); + if (sect.sct_newtype != sect.sct_type) + pr("%c", dchr[sect.sct_newtype].d_mnem); + else + pr(" "); + pr("%4d%%", sect.sct_effic); + pr(" will starve %d people. %d more food needed\n",s, + needed); + } + if (nsect == 0) { + if (player->argp[1]) + pr("%s: No sector(s)\n", player->argp[1]); + else + pr("%s: No sector(s)\n", ""); + return; + }else + pr("%d sector%s\n", nsect, splur(nsect)); + return; +} + +static void +sect_hdr(void) +{ + if (player->god) + pr(" "); + pr("Starvation \n"); + if (player->god) + pr("own "); + pr(" sect eff "); + pr("\n"); +} + +static void +starv_ships(s_char *range) +{ + struct nstr_item ni; + struct shpstr ship; + int nship = 0; + int vec[I_MAX+1], s, needed; + + if (!snxtitem(&ni, EF_SHIP, range)) + return; + + while (nxtitem(&ni, (s_char *)&ship)) { + if (!player->owner || !ship.shp_own) + continue; + + getvec(VT_ITEM, vec, (s_char *)&ship, EF_SHIP); + s = feed_ship(&ship, vec, etu_per_update, &needed, 0); + + if (s==0) + continue; + if (nship++ == 0) + ship_hdr(); + if (player->god) + pr("%3d ", ship.shp_own); + pr("%5d ", ship.shp_uid); + pr("%-16.16s ", mchr[(int)ship.shp_type].m_name); + pr(" will starve %d people. %d more food needed\n",s, + needed); + } + if (nship == 0) { + if (range) + pr("%s: No ship(s)\n", range); + else + pr("%s: No ship(s)\n", ""); + return; + }else + pr("%d ship%s\n", nship, splur(nship)); + return; +} + +static void +ship_hdr(void) +{ + if (player->god) + pr(" "); + pr("Starvation \n"); + if (player->god) + pr("own "); + pr(" shp# ship type \n"); +} + +static void +starv_units(s_char *range) +{ + struct nstr_item ni; + struct lndstr land; + int nunit = 0; + int vec[I_MAX+1], s, needed; + + if (!snxtitem(&ni, EF_LAND, range)) + return; + + while (nxtitem(&ni, (s_char *)&land)) { + if (!player->owner || !land.lnd_own) + continue; + + getvec(VT_ITEM, vec, (s_char *)&land, EF_LAND); + s = feed_land(&land, vec, etu_per_update, &needed, 0); + + if (s==0) + continue; + if (nunit++ == 0) + unit_hdr(); + if (player->god) + pr("%3d ", land.lnd_own); + pr("%5d ", land.lnd_uid); + pr("%-16.16s ", lchr[(int)land.lnd_type].l_name); + pr(" will starve %d mil. %d more food needed\n",s, + needed); + } + if (nunit == 0) { + if (range) + pr("%s: No unit(s)\n", range); + else + pr("%s: No unit(s)\n", ""); + return; + }else + pr("%d unit%s\n", nunit, splur(nunit)); + return; +} + +static void +unit_hdr(void) +{ + if (player->god) + pr(" "); + pr("Starvation \n"); + if (player->god) + pr("own "); + pr(" lnd# unit type \n"); +} + + + + + + + diff --git a/src/lib/commands/supp.c b/src/lib/commands/supp.c new file mode 100644 index 00000000..a432f1ba --- /dev/null +++ b/src/lib/commands/supp.c @@ -0,0 +1,77 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * supp.c: supply land units + * + * Known contributors to this file: + * Ken Stevens, 1995 + */ + +#include "misc.h" +#include "player.h" +#include "var.h" +#include "xy.h" +#include "sect.h" +#include "land.h" +#include "nat.h" +#include "nsc.h" +#include "deity.h" +#include "file.h" +#include "commands.h" + +int +supp(void) +{ + int nunits; + struct nstr_item ni; + struct lndstr land; + + if (!snxtitem(&ni, EF_LAND, player->argp[1])) + return RET_SYN; + + nunits = 0; + while (nxtitem(&ni, (s_char *)&land)) { + if (!player->owner || land.lnd_own == 0) + continue; + nunits++; + resupply_all(&land); + putland(land.lnd_uid,&land); + if (has_supply(&land)) + pr("%s has supplies\n", prland(&land)); + else + pr("%s is out of supply\n", prland(&land)); + } + if (nunits == 0) { + if (player->argp[1]) + pr("%s: No unit(s)\n", player->argp[1]); + else + pr("%s: No unit(s)\n", ""); + return RET_FAIL; + }else + pr("%d unit%s\n", nunits, splur(nunits)); + return RET_OK; +} diff --git a/src/lib/commands/surv.c b/src/lib/commands/surv.c new file mode 100644 index 00000000..04472c81 --- /dev/null +++ b/src/lib/commands/surv.c @@ -0,0 +1,166 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * surv.c: Show sector survey + * + * Known contributors to this file: + * Dave Pare, 1986 + */ + +#include "misc.h" +#include "player.h" +#include "var.h" +#include "sect.h" +#include "xy.h" +#include "nsc.h" +#include "deity.h" +#include "file.h" +#include "nat.h" +#include "map.h" +#include "commands.h" +#include "optlist.h" + +static s_char code_char(long int coding, struct sctstr *sp); + +/* + * survey type ?cond + * + */ +int +surv(void) +{ + int nsect; + struct nstr_sect nstr; + int y; + long coding; + struct natstr *np; + struct sctstr sect; + struct range range; + s_char *ptr; + struct nscstr cond[NS_NCOND]; + int ncond; + int i; + s_char what[64]; + s_char buf[1024]; + s_char *str; + /* Note this is not re-entrant anyway, so we keep the buffers + around */ + static s_char *mapbuf = (s_char *)0; + static s_char **map = (s_char **)0; + + nsect = 0; + if ((ptr = getstarg(player->argp[1], "commodity or variable? ", buf)) == 0) + return RET_SYN; + if (encode(ptr, &coding, EF_SECTOR) < 0) + return RET_SYN; + if(player->argp[2] == (s_char *) 0) { + if ((str = getstring("(sects)? ", buf)) == 0) + return RET_SYN; + } else { + str = player->argp[2]; + } + if(*str == '*') { + sprintf(what, "%d:%d,%d:%d", + -WORLD_X/2, WORLD_X/2-1, + -WORLD_Y/2, WORLD_Y/2-1); + if (!snxtsct(&nstr, what)) + return RET_FAIL; + } + else + if (!snxtsct(&nstr, str)) + return RET_SYN; + if (!mapbuf) + mapbuf = (s_char *)malloc((WORLD_Y*MAPWIDTH(1))*sizeof(s_char)); + if (!map) { + map = (s_char **)malloc(WORLD_Y * sizeof(s_char *)); + if (map && mapbuf) { + for (i = 0; i < WORLD_Y; i++) + map[i] = &mapbuf[MAPWIDTH(1) * i]; + } else if (map) { + free((s_char *)map); + map = (s_char **)0; + } + } + if (!mapbuf || !map) { + pr("Memory error, tell the deity.\n"); + logerror("malloc failed in sect\n"); + return RET_FAIL; + } + ncond = nstr.ncond; + bcopy((s_char *)nstr.cond, (s_char *)cond, sizeof(struct nscstr) * ncond); + nstr.ncond = 0; + np = getnatp(player->cnum); + xyrelrange(np, &nstr.range, &range); + border(&range, " ", ""); + blankfill((s_char *)mapbuf, &nstr.range, 1); + while (nxtsct(&nstr, §)) { + if (!player->owner) + continue; + ptr = &map[nstr.dy][nstr.dx]; + if (nstr_exec(cond, ncond, (s_char *)§, EF_SECTOR)) { + ++nsect; + *ptr = 0x80 | code_char(coding, §); + } else { + *ptr = dchr[sect.sct_type].d_mnem; + } + } + for (y=nstr.range.ly, i=0; i < nstr.range.height; y++, i++) { + int yval; + + yval = yrel(np, y); + pr("%4d %s %4d\n", yval, map[i], yval); + if (y >= WORLD_Y) + y -= WORLD_Y; + } + border(&range, " ", ""); + if (nsect > 0) + pr("\n%d sector%s.\n", nsect, splur(nsect)); + return RET_OK; +} + +static +s_char +code_char(long int coding, struct sctstr *sp) +{ + int amt; + int n; + + if (!(coding & NSC_VAR)) + coding |= NSC_OFF; + amt = decode(player->cnum, coding, (s_char *) sp, EF_SECTOR); + n = 0; + if ((coding & NSC_CMASK) == NSC_VAR) { + if (amt != 0) + n = (amt / 100) + 1; + } else if (amt != 0) + n = (amt / 10) + 1; + if (n > 11) + n = 11; + if (n < 0) + n = 0; + return " 0123456789$"[n]; +} diff --git a/src/lib/commands/swap.c b/src/lib/commands/swap.c new file mode 100644 index 00000000..7aab1ee9 --- /dev/null +++ b/src/lib/commands/swap.c @@ -0,0 +1,111 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * swap.c: Swap two sectors on the map + * + * Known contributors to this file: + * Ken Stevens, 1995 + */ + +#include +#include +#include "misc.h" +#include "player.h" +#include "var.h" +#include "xy.h" +#include "sect.h" +#include "nat.h" +#include "news.h" +#include "nsc.h" +#include "item.h" +#include "file.h" +#include "commands.h" + + +/* + * Syntax: swap + */ +int +swaps(void) +{ + struct sctstr secta, sectb; + coord x,y; + s_char buf[1024]; + s_char *p; + + if (!(p = getstarg(player->argp[1], "First sector : ", buf)) || + !sarg_xy(p, §a.sct_x, §a.sct_y) || + !getsect(secta.sct_x, secta.sct_y, §a)) + return RET_SYN; + print_res(§a); + if (!(p = getstarg(player->argp[2], "Second sector : ", buf)) || + !sarg_xy(p, §b.sct_x, §b.sct_y) || + !getsect(sectb.sct_x, sectb.sct_y, §b)) + return RET_SYN; + print_res(§b); + if (!confirm("Are you sure these are the two sectors you wish to swap? ")) + return RET_FAIL; + /* save x and y from secta */ + x = secta.sct_x; + y = secta.sct_y; + /* change the location of secta to that of sectb */ + secta.sct_x = sectb.sct_x; + secta.sct_y = sectb.sct_y; + secta.sct_dist_x = sectb.sct_x; + secta.sct_dist_y = sectb.sct_y; + /* change the location of sectb to where secta was */ + sectb.sct_x = x; + sectb.sct_y = y; + sectb.sct_dist_x = x; + sectb.sct_dist_y = y; + putsect(§a); + putsect(§b); + pr("done\n"); + return RET_OK; +} + +void +print_res(struct sctstr *sp) +{ + pr("own sect eff min gold fert oil uran\n"); + + pr("%3d ", sp->sct_own); + + prxy("%4d,%-4d", sp->sct_x, sp->sct_y, player->cnum); + pr(" %c", dchr[sp->sct_type].d_mnem); + if (sp->sct_newtype != sp->sct_type) + pr("%c", dchr[sp->sct_newtype].d_mnem); + else + pr(" "); + pr("%4d%%", sp->sct_effic); + pr(" %4d", sp->sct_min); + pr("%5d", sp->sct_gmin); + pr("%5d", sp->sct_fertil); + pr("%4d", sp->sct_oil); + pr("%5d", sp->sct_uran); + pr("\n"); +} diff --git a/src/lib/commands/tele.c b/src/lib/commands/tele.c new file mode 100644 index 00000000..669e2b4a --- /dev/null +++ b/src/lib/commands/tele.c @@ -0,0 +1,135 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * tele.c: Send a telegram + * + * Known contributors to this file: + * Steve McClure, 2000 + * + */ + +#include "misc.h" +#include "player.h" +#include "nat.h" +#include "tel.h" +#include "news.h" +#include "deity.h" +#include "file.h" +#include "commands.h" +#include "optlist.h" + +int +tele(void) +{ + natid to; + struct natstr *natp; + int teltype; + s_char buf[MAXTELSIZE+1]; + int n; + + natp = getnatp(player->cnum); + if (*player->argp[0] == 'a') { + if (getele("everybody", buf) <= 0) { + pr("Announcement aborted\n"); + return RET_OK; + } + pr("\n"); + to = 0; + if (typed_wu(player->cnum, to, buf, TEL_ANNOUNCE) < 0) + logerror("tele: typed_wu failed to #%d", to); + } else if (*player->argp[0] == 'p') { + if (getele("your Gracious Deity", buf) <= 0) { + pr("Prayor aborted\n"); + return RET_OK; + } + pr("\n"); + if (typed_wu(player->cnum, 0, buf, TEL_NORM) < 0) + logerror("tele: typed_wu failed to #0"); + } else { + int kk; + + kk = 1; + while (player->argp[kk] != (s_char *)0){ + if ((n = natarg(player->argp[kk], "for which country? ")) < 0) { + if (opt_HIDDEN) { + if (n < -1) { + return RET_OK; + } else { + return RET_SYN; + } + } else { + return RET_SYN; + } + } + to = n; + + if (kk == 1){ + if (player->argp[2]){ + if(getele("multiple recipients",buf)<0){ + pr("Telegram aborted\n"); + return RET_OK; + } + }else{ + if (getele(cname(to), buf) < 0) { + pr("Telegram aborted\n"); + return RET_OK; + } + } + pr("\n"); + } + + natp = getnatp(to); + if (((natp->nat_stat & STAT_NORM) == 0) && + ((natp->nat_stat & STAT_SANCT) == 0)){ + pr("%s has no \"telegram priveleges\".\n", + cname(to)); + kk++; + continue; + } + if (!player->god && (getrejects(player->cnum,natp) & REJ_TELE)) { + pr("%s is rejecting your telegrams.\n", + cname(to)); + return RET_SYN; + } + teltype = /* player->god ? TEL_BULLETIN : */ TEL_NORM; + if (typed_wu(player->cnum, to, buf, teltype) < 0) { + logerror("tele: typed_wu failed to #%d", n); + return RET_FAIL; + } + + if (!player->god && + (natp->nat_stat & GOD) != GOD && + player->cnum != to) + nreport(player->cnum, N_SENT_TEL, to, 1); + if (opt_HIDDEN) { + setcont(to, player->cnum, FOUND_TELE); + } + kk++; + } + } + return RET_OK; +} diff --git a/src/lib/commands/tend.c b/src/lib/commands/tend.c new file mode 100644 index 00000000..db5cad06 --- /dev/null +++ b/src/lib/commands/tend.c @@ -0,0 +1,378 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * tend.c: Transfer goodies from one ship to another. + * + * Known contributors to this file: + * Dave Pare, 1986 + * Thomas Ruschak, 1992 + * Steve McClure, 2000 + */ + +#ifdef Rel4 +#include +#endif /* Rel4 */ +#include "misc.h" +#include "player.h" +#include "var.h" +#include "xy.h" +#include "file.h" +#include "ship.h" +#include "item.h" +#include "nsc.h" +#include "nat.h" +#include "land.h" +#include "plane.h" +#include "nuke.h" +#include "genitem.h" +#include "commands.h" + +static void expose_ship(struct shpstr *s1, struct shpstr *s2); +static int tend_land(struct shpstr *tenderp, s_char *units); + +int +tend(void) +{ + struct nstr_item targets; + struct nstr_item tenders; + struct shpstr tender; + struct shpstr target; + struct ichrstr *ip; + struct mchrstr *vbase; + int amt; + int retval; + int ontender; + int ontarget; + int maxtender; + int maxtarget; + int transfer; + int total; + int type; + s_char *p; + s_char prompt[512]; + s_char buf[1024]; + + if (!(p = getstarg(player->argp[1], + "Tend what commodity (or 'land')? ", buf)) || !*p) + return RET_SYN; + + if (!strncmp(p, "land", 4)) + type = EF_LAND; + else if (NULL != (ip = whatitem(p, (s_char *)0))) + type = EF_SECTOR; + else { + pr("Bad commodity.\n"); + return RET_SYN; + } + + if (!snxtitem(&tenders, EF_SHIP, getstarg(player->argp[2], "Tender(s)? ", buf))) + return RET_SYN; + + while (nxtitem(&tenders, (s_char *)&tender)) { + if (!player->owner) + continue; + if (type == EF_LAND) { + sprintf(prompt, "Land unit(s) to tend from %s? ", + prship(&tender)); + if (!(p = getstarg(player->argp[3], prompt, buf)) || !*p) + continue; + if (!check_ship_ok(&tender)) + return RET_SYN; + if (0 != (retval=tend_land(&tender, p))) + return retval; + continue; + } + sprintf(prompt, "Number of %s to tend from %s? ", + ip->i_name, prship(&tender)); + if (!(p = getstarg(player->argp[3], prompt, buf)) || !*p) + continue; + if (!check_ship_ok(&tender)) + return RET_SYN; + if (!(amt = atoi(p))) { + pr("Amount must be non-zero!\n"); + return RET_SYN; + } + ontender = getvar(ip->i_vtype, (s_char *)&tender, EF_SHIP); + if (ontender == 0 && amt > 0) { + pr("No %s on %s\n", ip->i_name, prship(&tender)); + return RET_FAIL; + } + vbase = &mchr[(int)tender.shp_type]; + maxtender = vl_find(ip->i_vtype, vbase->m_vtype, + vbase->m_vamt, (int)vbase->m_nv); + if (maxtender == 0) { + pr("A %s cannot hold any %s\n", + mchr[(int)tender.shp_type].m_name, + ip->i_name); + break; + } + if (!snxtitem(&targets, EF_SHIP, + getstarg(player->argp[4], "Ships to be tended? ", buf))) + break; + if (!check_ship_ok(&tender)) + return RET_SYN; + total = 0; + while (tend_nxtitem(&targets, (s_char *)&target)) { + if (!player->owner && + (getrel(getnatp(target.shp_own), + player->cnum) < FRIENDLY)) + continue; + if (target.shp_uid == tender.shp_uid) + continue; + if (tender.shp_x != target.shp_x || + tender.shp_y != target.shp_y) + continue; + ontarget = getvar(ip->i_vtype, + (s_char *)&target, EF_SHIP); + if (ontarget == 0 && amt < 0) { + pr("No %s on %s\n", + ip->i_name, prship(&target)); + continue; + } + vbase = &mchr[(int)target.shp_type]; + maxtarget = vl_find(ip->i_vtype, vbase->m_vtype, + vbase->m_vamt, (int)vbase->m_nv); + if (amt < 0) { + if (!player->owner) + amt=0; + + /* take from target and give to tender */ + transfer = min(ontarget, -amt); + transfer = min(maxtender - ontender, transfer); + if (transfer == 0) + continue; + putvar(ip->i_vtype, ontarget - transfer, + (s_char *)&target, EF_SHIP); + ontender += transfer; + total += transfer; + } else { + /* give to target from tender */ + transfer = min(ontender, amt); + transfer = min(transfer, maxtarget - ontarget); + if (transfer == 0) + continue; + putvar(ip->i_vtype, ontarget + transfer, + (s_char *)&target, EF_SHIP); + ontender -= transfer; + total += transfer; + } + expose_ship(&tender, &target); + putship(target.shp_uid, &target); + if (amt > 0 && ontender == 0) { + pr("%s out of %s\n", + prship(&tender), + ip->i_name); + break; + } + } + pr("%d total %s transferred %s %s\n", + total, ip->i_name, (amt > 0) ? "off of" : "to", + prship(&tender)); + putvar(ip->i_vtype, ontender, (s_char *)&tender, EF_SHIP); + tender.shp_mission = 0; + putship(tender.shp_uid, &tender); + } + return RET_OK; +} + +static void +expose_ship(struct shpstr *s1, struct shpstr *s2) +{ + if (getvar(V_PSTAGE, (s_char *)s1, EF_SHIP) == PLG_INFECT && + getvar(V_PSTAGE, (s_char *)s2, EF_SHIP) == PLG_HEALTHY) + putvar(V_PSTAGE, PLG_EXPOSED, (s_char *)s2, EF_SHIP); + if (getvar(V_PSTAGE, (s_char *)s2, EF_SHIP) == PLG_INFECT && + getvar(V_PSTAGE, (s_char *)s1, EF_SHIP) == PLG_HEALTHY) + putvar(V_PSTAGE, PLG_EXPOSED, (s_char *)s1, EF_SHIP); +} + +/* + * tend_nxtitem.c + * + * get next item from list. Stolen from nxtitem to make 1 itsy-bitsy change + * + * Dave Pare, 1989 + */ + +int +tend_nxtitem(struct nstr_item *np, caddr_t ptr) +{ + struct genitem *gp; + int selected; + + if (np->sel == NS_UNDEF) + return 0; + gp = (struct genitem *) ptr; + do { + if (np->sel == NS_LIST) { + np->index++; + if (np->index >= np->size) + return 0; + np->cur = np->list[np->index]; + } else { + np->cur++; + } + if (!np->read(np->type, np->cur, ptr)) { + /* if read fails, fatal */ + return 0; + } + selected = 1; + switch (np->sel) { + case NS_LIST: + /* The change is to take the player->owner check out here */ + break; + case NS_ALL: + /* XXX maybe combine NS_LIST and NS_ALL later */ + break; + case NS_DIST: + if (!xyinrange(gp->x, gp->y, &np->range)) { + selected = 0; + break; + } + np->curdist = mapdist((int)gp->x, (int)gp->y, + (int)np->cx, (int)np->cy); + if (np->curdist > np->dist) + selected = 0; + break; + case NS_AREA: + if (!xyinrange(gp->x, gp->y, &np->range)) + selected = 0; + if (gp->x == np->range.hx || gp->y == np->range.hy) + selected = 0; + break; + case NS_XY: + if (gp->x != np->cx || gp->y != np->cy) + selected = 0; + break; + case NS_GROUP: + if (np->group != gp->group) + selected = 0; + break; + default: + logerror("nxtitem: bad selector %d\n", np->sel); + return 0; + } + if (selected && np->ncond) { + /* nstr_exec is expensive, so we do it last */ + if (!nstr_exec(np->cond, np->ncond, ptr, np->type)) + selected = 0; + } + } while (!selected); + return 1; +} + +static int +tend_land(struct shpstr *tenderp, s_char *units) +{ + struct nstr_item lni; + struct nstr_item targets; + struct shpstr target; + struct lndstr land; + struct plnstr plane; + struct nstr_item pni; + s_char buf[1024]; + + if (!snxtitem(&lni, EF_LAND, units)) + return RET_SYN; + + while(nxtitem(&lni, (s_char *)&land)) { + if (!player->owner) + continue; + if (land.lnd_ship != tenderp->shp_uid) { + pr("%s is not on %s!\n", + prland(&land), prship(tenderp)); + continue; + } + if (!(lchr[(int)land.lnd_type].l_flags & L_ASSAULT)) { + pr("%s does not have \"assault\" capability and can't be tended\n", prland(&land)); + continue; + } + if (!snxtitem(&targets, EF_SHIP, + getstarg(player->argp[4], "Ship to be tended? ", buf))) + break; + if (!check_land_ok(&land)) + return RET_SYN; + while (tend_nxtitem(&targets, (s_char *)&target)) { + if (!player->owner && + (getrel(getnatp(target.shp_own), + player->cnum) < FRIENDLY)) + continue; + if (target.shp_uid == tenderp->shp_uid) + continue; + if (tenderp->shp_x != target.shp_x || + tenderp->shp_y != target.shp_y) + continue; + + /* Fit unit on ship */ + count_units(&target); + getship(target.shp_uid,&target); + + if (target.shp_nland >= mchr[(int)target.shp_type].m_nland) { + if (mchr[(int)target.shp_type].m_nland) + pr("%s doesn't have room for any more land units!\n",prship(&target)); + else + pr("%s doesn't carry land units!\n",prship(&target)); + continue; + } + pr("%s transferred from %s to %s\n", + prland(&land), prship(tenderp), prship(&target)); + sprintf(buf, "loaded on your %s at %s", + prship(&target),xyas(target.shp_x,target.shp_y, + target.shp_own)); + gift(target.shp_own,player->cnum,(s_char *)&land, + EF_LAND, buf); + makelost(EF_LAND, land.lnd_own, land.lnd_uid, land.lnd_x, land.lnd_y); + land.lnd_own = target.shp_own; + makenotlost(EF_LAND, land.lnd_own, land.lnd_uid, land.lnd_x, land.lnd_y); + land.lnd_ship = target.shp_uid; + land.lnd_harden = 0; + land.lnd_mission = 0; + target.shp_nland++; + putland(land.lnd_uid,&land); + expose_ship(tenderp, &target); + putship(target.shp_uid, &target); + count_units(tenderp); + putship(tenderp->shp_uid, tenderp); + snxtitem_xy(&pni,EF_PLANE,land.lnd_x,land.lnd_y); + while (nxtitem(&pni, (s_char *)&plane)) { + if (plane.pln_flags & PLN_LAUNCHED) + continue; + if (plane.pln_land != land.lnd_uid) + continue; + sprintf(buf, "loaded on %s", prship(&target)); + gift(target.shp_own,player->cnum,(s_char *)&plane, + EF_PLANE, buf); + makelost(EF_PLANE, plane.pln_own, plane.pln_uid, plane.pln_x, plane.pln_y); + plane.pln_own = target.shp_own; + makenotlost(EF_PLANE, plane.pln_own, plane.pln_uid, plane.pln_x, plane.pln_y); + plane.pln_mission = 0; + putplane(plane.pln_uid,&plane); + } + } + } + return 0; +} diff --git a/src/lib/commands/terr.c b/src/lib/commands/terr.c new file mode 100644 index 00000000..0510bd4c --- /dev/null +++ b/src/lib/commands/terr.c @@ -0,0 +1,100 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * terr.c: Designate territory of sectors + * + * Known contributors to this file: + * Edward M. Rynes Esq. + */ + +#include "misc.h" +#include "player.h" +#include "var.h" +#include "sect.h" +#include "xy.h" +#include "nsc.h" +#include "nat.h" +#include "file.h" +#include "commands.h" + +int +terr(void) +{ + struct sctstr sect; + s_char *p; + int terr_n; + int field; + struct nstr_sect nstr; + s_char prompt[128]; + s_char buf[1024]; + + if (!snxtsct(&nstr, player->argp[1])) + return RET_SYN; + if (player->argp[3] && isdigit(*(player->argp[3]))) { + field = atoi(player->argp[3]); + } else { + field = 0; + } + while (nxtsct(&nstr, §)) { + if (!player->owner) + continue; + sprintf(prompt, "%s %d%% %s territory? ", + xyas(nstr.x, nstr.y, player->cnum), + sect.sct_effic, dchr[sect.sct_type].d_name); + if ((p = getstarg(player->argp[2], prompt, buf)) == 0) + return RET_FAIL; + if (!check_sect_ok(§)) + return RET_FAIL; + if (*p == 0) + continue; + terr_n = atoi(p); + while (terr_n < 0 || terr_n > 99 || *p < '0' || *p > '9') { + pr("Enter a number between 0 and 99!\n"); + sprintf(prompt, "%s %d%% %s territory? ", + xyas(nstr.x, nstr.y, player->cnum), + sect.sct_effic, dchr[sect.sct_type].d_name); + if ((p = getstarg((s_char *)0, prompt, buf)) == 0) + return RET_FAIL; + if (!check_sect_ok(§)) + return RET_FAIL; + if (*p == 0) + break; + terr_n = atoi(p); + } + if (*p == 0) + continue; + switch (field) { + case 1: sect.sct_terr1 = terr_n; break; + case 2: sect.sct_terr2 = terr_n; break; + case 3: sect.sct_terr3 = terr_n; break; + default: sect.sct_terr = terr_n; + } + putsect(§); + } + return RET_OK; +} + diff --git a/src/lib/commands/thre.c b/src/lib/commands/thre.c new file mode 100644 index 00000000..d821291c --- /dev/null +++ b/src/lib/commands/thre.c @@ -0,0 +1,109 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * thre.c: Describe/set threshold for given commodity + * + * Known contributors to this file: + * Dave Pare, 1986 + * Steve McClure, 1998 + */ + +#include "misc.h" +#include "player.h" +#include "var.h" +#include "sect.h" +#include "xy.h" +#include "item.h" +#include "nsc.h" +#include "nat.h" +#include "file.h" +#include "commands.h" + +/* + * threshold + */ +int +thre(void) +{ + extern struct ichrstr *whatitem(); + struct sctstr sect; + struct nstr_sect nstr; + int val; + struct ichrstr *ip; + s_char *p; + int thresh; + int type; + s_char prompt[128]; + s_char buf[128]; + + if ((ip = whatitem(player->argp[1], "What commodity? ")) == 0) + return RET_SYN; + if (!snxtsct(&nstr, player->argp[2])) + return RET_SYN; + type = V_DIST(ip->i_vtype & (~VT_TYPE)); + if (player->argp[3] && *player->argp[3] && + (*player->argp[3] < '0' || *player->argp[3] > '9')) { + pr ("Threshold must be a number\n"); + return RET_SYN; + } + while (!player->aborted && nxtsct(&nstr, §)) { + if (!player->owner) + continue; + val = getvar(type, (s_char *)§, EF_SECTOR); + if (val > 0) + sprintf(prompt, "%s %s old threshold %d new? ", + xyas(nstr.x, nstr.y, player->cnum), + dchr[sect.sct_type].d_name, val); + else + sprintf(prompt, "%s %s threshold? ", + xyas(nstr.x, nstr.y, player->cnum), + dchr[sect.sct_type].d_name); + if ((p = getstarg(player->argp[3], prompt, buf)) == 0) + return RET_FAIL; + if (!check_sect_ok(§)) + return RET_FAIL; + if (*p == '\0' || *p == '-') + continue; + thresh = atoi(p); + if (thresh > 10000) + thresh = 10000; + if ((val > 0) && (val == thresh)) { + pr("%s threshold unchanged (left at %d)\n", + xyas(nstr.x, nstr.y, player->cnum), val); + continue; + } + if (val > 0 && (player->argp[3] != 0 && *player->argp[3] != 0)) + pr("%s old threshold %d\n", + xyas(nstr.x, nstr.y, player->cnum), + val); + if (putvar(type, thresh, (s_char *)§, EF_SECTOR) < 0) + pr("No room for threshold in %s\n", + xyas(nstr.x, nstr.y, player->cnum)); + putsect(§); + } + return RET_OK; +} diff --git a/src/lib/commands/togg.c b/src/lib/commands/togg.c new file mode 100644 index 00000000..ff4b6537 --- /dev/null +++ b/src/lib/commands/togg.c @@ -0,0 +1,110 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * togg.c: Set player flags + * + * Known contributors to this file: + * Ken Stevens, 1995 + * Steve McClure, 1996 + */ + +#include "misc.h" +#include "player.h" +#include "file.h" +#include "nat.h" +#include "commands.h" + +int +togg(void) +{ + int flag = 0; + int pos; + s_char *name; + struct natstr *np; + + np = getnatp(player->cnum); + if (player->argp[1]) { + switch (*player->argp[1]) { + case 'i': + name = "inform"; flag = NF_INFORM; break; + case 'f': + name = "flash"; flag = NF_FLASH; break; + case 'b': + name = "beep"; flag = NF_BEEP; break; + case 'c': + name = "coastwatch"; flag = NF_COASTWATCH; break; + case 's': + name = "sonar"; flag = NF_SONAR; break; + case 't': + name = "techlists"; flag = NF_TECHLISTS; break; + default: + return RET_SYN; + } + if (player->argp[2]) + if (!strcmp(player->argp[2], "on")) + pos = 1; + else if (!strcmp(player->argp[2], "off")) + pos = 0; + else + return RET_SYN; + else + pos = !(np->nat_flags & flag); + if (pos) + np->nat_flags |= flag; + else + np->nat_flags &= ~flag; + putnat(np); + pr("%s flag %s\n", name, pos?"on":"off"); + } else { + if (np->nat_flags & NF_INFORM) + pr("inform flag on\n"); + else + pr("inform flag off\n"); + if (np->nat_flags & NF_FLASH) + pr("flash flag on\n"); + else + pr("flash flag off\n"); + if (np->nat_flags & NF_BEEP) + pr("beep flag on\n"); + else + pr("beep flag off\n"); + if (np->nat_flags & NF_COASTWATCH) + pr("coastwatch flag on\n"); + else + pr("coastwatch flag off\n"); + if (np->nat_flags & NF_SONAR) + pr("sonar flag on\n"); + else + pr("sonar flag off\n"); + if (np->nat_flags & NF_TECHLISTS) + pr("techlists flag on\n"); + else + pr("techlists flag off\n"); + } + + return RET_OK; +} diff --git a/src/lib/commands/torp.c b/src/lib/commands/torp.c new file mode 100644 index 00000000..8ad43b53 --- /dev/null +++ b/src/lib/commands/torp.c @@ -0,0 +1,487 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * torp.c: Fire torpedoes at enemy ships + * + * Known contributors to this file: + * Dave Pare + * Thomas Ruschak, 1992 + * Ken Stevens, 1995 + * Steve McClure, 2000 + */ + +#include +#include "misc.h" +#include "player.h" +#include "var.h" +#include "ship.h" +#include "file.h" +#include "xy.h" +#include "nat.h" +#include "nsc.h" +#include "news.h" +#include "retreat.h" +#include "damage.h" +#include "commands.h" + +void anti_torp(int f, int ntorping, int vshipown); +void fire_dchrg(struct shpstr *sp, struct shpstr *targ, int range, int ntargets); + +s_char *prsub(struct shpstr *sp); + +int +torp(void) +{ + extern int torpedo_damage; + natid vshipown; + int range; + int dam; + int shells; + int subno; + int victno; + double erange; + double hitchance; + struct shpstr vship; + struct shpstr sub; + s_char *ptr; + double mobcost; + struct mchrstr *mcp; + struct nstr_item nbst; + s_char buf[1024]; + s_char *sav; + int ntorping=0; + s_char prompt[128]; + + if (!(sav = getstarg(player->argp[1], "From ship(s)? ", buf))) + return RET_SYN; + if (!snxtitem(&nbst, EF_SHIP, sav)) + return RET_SYN; + while (nxtitem(&nbst, (s_char *)&sub)){ + if (sub.shp_own != player->cnum) + continue; + if ((mchr[(int)sub.shp_type].m_flags & M_TORP) == 0) + continue; + shells = getvar(V_SHELL, (s_char *)&sub, EF_SHIP); + if (shells < 3) + shells += supply_commod(sub.shp_own,sub.shp_x,sub.shp_y,I_SHELL, + 3-shells); + if (getvar(V_GUN, (s_char *)&sub, EF_SHIP) == 0 || shells < 3) + continue; + if (getvar(V_MILIT, (s_char *)&sub, EF_SHIP) < 1) + continue; + if (sub.shp_effic < 60) + continue; + if (sub.shp_mobil <= 0) + continue; + ntorping++; + } + pr("%d ships are eligible to torp\n",ntorping); + snxtitem(&nbst, EF_SHIP, sav); + while (nxtitem(&nbst, (s_char *)&sub)) { + if (!sub.shp_own) + continue; + if (sub.shp_own != player->cnum) { + continue; + } + if ((mchr[(int)sub.shp_type].m_flags & M_TORP) == 0) { + pr("Ship # %d: A %s can't fire torpedoes!\n", sub.shp_uid, + mchr[(int)sub.shp_type].m_name); + continue; + } + shells = getvar(V_SHELL, (s_char *)&sub, EF_SHIP); + if (shells < 3) + shells += supply_commod(sub.shp_own,sub.shp_x,sub.shp_y +,I_SHELL, + 3-shells); + if (getvar(V_GUN, (s_char *)&sub, EF_SHIP) == 0 || shells < 3) { + pr("Ship #%d has insufficient armament\n",sub.shp_uid); + continue; + } + if (getvar(V_MILIT, (s_char *)&sub, EF_SHIP) < 1){ + pr("Ship #%d has insufficient crew\n",sub.shp_uid); + continue; + } + if (sub.shp_effic < 60) { + pr("Ship #%d torpedo tubes inoperative.\n",sub.shp_uid); + continue; + } + if (sub.shp_mobil <= 0) { + pr("Ship #%d has insufficient mobility\n",sub.shp_uid); + continue; + } + bzero(buf,80); + subno=sub.shp_uid; + sprintf(prompt, "Ship %d, target? ",sub.shp_uid); + if ((ptr = getstarg(player->argp[2],prompt, buf)) == 0) + return RET_SYN; + if (!check_ship_ok(&sub)) + return RET_FAIL; + if ((victno = atoi(ptr)) < 0) + return RET_SYN; + if (!getship(victno, &vship)) + return RET_FAIL; + if (!vship.shp_own) + return RET_FAIL; + vshipown=vship.shp_own; + if (victno == subno) { + pr("Shooting yourself, eh? How strange...\n"); + continue; + } + if (mchr[(int)vship.shp_type].m_flags & M_SUB) { + if (!(mchr[(int)sub.shp_type].m_flags & M_SUBT)){ + pr("You can't torpedo a submarine!\n"); + continue; + } + } + if ((mchr[(int)sub.shp_type].m_flags & M_SUB) == 0) + anti_torp(sub.shp_uid,ntorping,vshipown); + getship(sub.shp_uid,&sub); + if (sub.shp_own == 0){ + continue; + } + erange = ((double)sub.shp_effic/100.0) * + techfact(sub.shp_tech, ((double)sub.shp_frnge)); + erange = (double)roundrange(erange); + pr("Effective torpedo range is %.1f\n", erange); + shells -= 3; + putvar(V_SHELL, shells, (s_char *)&sub, EF_SHIP); + putship(sub.shp_uid,&sub); + mcp = &mchr[(int)sub.shp_type]; + mobcost = sub.shp_effic * 0.01 * sub.shp_speed; + mobcost = (480.0 / (mobcost + techfact(sub.shp_tech, mobcost))); + + /* Mob cost for a torp is equal to the cost of 1/2 sector of movement */ + mobcost /= 2.0; + sub.shp_mobil -= mobcost; + pr("Whooosh... "); + getship(victno, &vship); + vshipown = vship.shp_own; + range = mapdist(sub.shp_x, sub.shp_y, vship.shp_x, vship.shp_y); + hitchance = DTORP_HITCHANCE(range, sub.shp_visib); + if (range <= erange) { + pr("Hitchance = %d%%\n",(int)(hitchance*100)); + } + /* Now, can the torpedo even get there? */ + if (!line_of_sight((s_char **)0, sub.shp_x, sub.shp_y, + vship.shp_x, vship.shp_y)) { + pr("BOOM!... Torpedo slams into land before reaching target.\n"); + /* We only tell the victim if we were within range. */ + if (range <= erange) { + if (vshipown != 0) + wu(0, vshipown, "Torpedo sighted @ %s by %s\n", + xyas(sub.shp_x, sub.shp_y, vshipown), + prship(&vship)); + } + } else if (range > erange) { + pr("Out of range\n"); + } else if (hitchance >= 1.0 || chance(hitchance)) { + pr("BOOM!...\n"); + dam = TORP_DAMAGE(); + if(vshipown != 0) + wu(0, vshipown, "%s in %s torpedoed %s for %d damage.\n", prsub(&sub), + xyas(sub.shp_x, sub.shp_y, vshipown), + prship(&vship), dam); + if (vship.shp_rflags & RET_TORPED){ + retreat_ship(&vship, 't'); + shipdamage(&vship, dam); + }else + shipdamage(&vship, dam); + pr("Torpedo hit %s for %d damage.\n", + prship(&vship), + dam); + + if (vship.shp_effic < SHIP_MINEFF) + pr("%s sunk!\n", + prship(&vship)); + putship(vship.shp_uid, &vship); + if (mchr[(int)sub.shp_type].m_flags & M_SUB) + nreport(vshipown, N_TORP_SHIP, 0, 1); + else + nreport(vshipown, N_SHIP_TORP, player->cnum, 1); + } else { + pr("Missed\n"); + if (vshipown != 0) + wu(0, vshipown, "Torpedo sighted @ %s by %s\n", + xyas(sub.shp_x, sub.shp_y, vshipown), + prship(&vship)); + } + sub.shp_mission=0; + putship(sub.shp_uid, &sub); + if (mchr[(int)sub.shp_type].m_flags & M_SUB) + anti_torp(sub.shp_uid,ntorping,vshipown); + } + return RET_OK; +} + +void +anti_torp(int f, int ntorping, int vshipown) +{ + int range; + double erange; + struct shpstr sub; + struct shpstr dd; + int x; + + getship(f,&sub); + + if (sub.shp_own == vshipown) + return; + + if ((mchr[(int)sub.shp_type].m_flags & M_SUB) == 0) + pr("Starting our attack run...\n"); + + x=0; + while (getship(x++,&dd) && sub.shp_effic >= SHIP_MINEFF){ + if (dd.shp_own == 0) + continue; + if (dd.shp_own != vshipown) + continue; + if (dd.shp_effic < 60) + continue; + + if (!canshoot(&dd,&sub)) + continue; + + erange = techfact(dd.shp_tech, + ((double)dd.shp_frnge))/ 2.0; + + erange = (double)roundrange(erange); + + range = mapdist(sub.shp_x, sub.shp_y, dd.shp_x, dd.shp_y); + + if (range > erange) + continue; + + if (!line_of_sight((s_char **)0, sub.shp_x, sub.shp_y, + dd.shp_x, dd.shp_y)) + continue; + + if (cantorp(&dd,&sub)){ + /* Try torping.. if we can, maybe we can fire */ + if (!fire_torp(&dd,&sub,range,ntorping)) + if (candchrg(&dd,&sub)) + fire_dchrg(&dd,&sub,range,ntorping); + }else + fire_dchrg(&dd,&sub,range,ntorping); + } +} + +/* Can ship A shoot at ship B? */ +int +canshoot(struct shpstr *a, struct shpstr *b) +{ + /* Anyone can shoot a normal ship */ + if ((mchr[(int)b->shp_type].m_flags & M_SUB) == 0) + return 1; + + /* You can depth-charge a sub */ + if (mchr[(int)a->shp_type].m_flags & M_DCH) + return 1; + + /* If you have SUBT flag, you can torp a sub */ + if (mchr[(int)a->shp_type].m_flags & M_SUBT) + return 1; + + return 0; +} + +/* Can ship A torp ship B? */ +int +cantorp(struct shpstr *a, struct shpstr *b) +{ + if ((mchr[(int)a->shp_type].m_flags & M_TORP) == 0) + return 0; + + /* Anyone with TORP flag can torp a normal ship */ + if ((mchr[(int)b->shp_type].m_flags & M_SUB) == 0) + return 1; + + /* Ship b is a sub, so we need to have the SUBT flag */ + if (mchr[(int)a->shp_type].m_flags & M_SUBT) + return 1; + + return 0; +} + +/* Can ship A depth-charge (or fire guns at) ship B? */ +int +candchrg(struct shpstr *a, struct shpstr *b) +{ + if ((mchr[(int)b->shp_type].m_flags & M_SUB) == 0){ + if ((mchr[(int)a->shp_type].m_flags & M_SUB) == 0) + return 1; + + return 0; + } + + if ((mchr[(int)a->shp_type].m_flags & M_DCH) == 0) + return 0; + + return 1; +} + +void +fire_dchrg(struct shpstr *sp, struct shpstr *targ, int range, int ntargets) +{ + int dam; + int shells; + int gun; + double guneff; + + shells = getvar(V_SHELL, (s_char *)sp, EF_SHIP); + gun = getvar(V_GUN, (s_char *)sp, EF_SHIP); + gun = min(gun, sp->shp_glim); + gun = min(gun, getvar(V_MILIT, (s_char *)sp, EF_SHIP)/2); + + shells+=supply_commod(sp->shp_own,sp->shp_x,sp->shp_y,I_SHELL,(gun+1)/2-shells); + + gun = min(gun, shells*2); + if (gun == 0) return; + + /* ok, all set.. now, we shoot */ + shells -= ldround(((double)gun)/2.0,1); + putvar(V_SHELL, shells, (s_char *)sp, EF_SHIP); + putship(sp->shp_uid,sp); + + guneff = seagun(sp->shp_effic, gun); + dam = (int)guneff; + + if ((mchr[(int)targ->shp_type].m_flags & M_SUB) == 0){ + pr_beep(); + pr("Kaboom!!! Incoming shells!\n"); + if(sp->shp_own != 0) + wu(0, sp->shp_own, + "%s fired at %s\n", + prship(sp), + prship(targ)); + + if (ntargets > 2) + dam /= ((float)ntargets/2.0); + pr_beep(); + pr("BLAM! %d damage!\n", dam); + shipdamage(targ, dam); + putship(targ->shp_uid,targ); + }else{ + pr("\nCAPTAIN! !!Depth charges!!...\n"); + if(sp->shp_own != 0) + wu(0, sp->shp_own, + "%s depth charged %s\n", + prship(sp), prsub(targ)); + + if (ntargets>2) + dam /= ((float)ntargets/2.0); + + pr("click...WHAM! %d damage!\n", dam); + shipdamage(targ, dam); + putship(targ->shp_uid,targ); + } +} + +int +fire_torp(struct shpstr *sp, struct shpstr *targ, int range, int ntargets) +{ + extern int torpedo_damage; + int dam; + int shells; + double hitchance; + double mobcost; + struct mchrstr *mcp; + + shells = getvar(V_SHELL, (s_char *)sp, EF_SHIP); + + if (shells < 3) + shells += supply_commod(sp->shp_own,sp->shp_x,sp->shp_y,I_SHELL, + 3-shells); + + if (getvar(V_GUN, (s_char *)sp, EF_SHIP) == 0 || shells < 3) + return 0; + + if (getvar(V_MILIT, (s_char *)sp, EF_SHIP) < 1) + return 0; + + if (sp->shp_effic < 60) + return 0; + + if (sp->shp_mobil <= 0) + return 0; + + /* All set.. fire! */ + shells -= 3; + putvar(V_SHELL, shells, (s_char *)sp, EF_SHIP); + putship(sp->shp_uid,sp); + + mcp = &mchr[(int)sp->shp_type]; + mobcost = sp->shp_effic * 0.01 * sp->shp_speed; + mobcost = (480.0 / (mobcost + techfact(sp->shp_tech, mobcost))); + + /* Mob cost for a torp is equal to the cost of 1/2 sector of movement */ + mobcost /= 2.0; + sp->shp_mobil -= mobcost; + + hitchance = DTORP_HITCHANCE(range, sp->shp_visib); + + pr("Captain! Torpedoes sighted!\n"); + + if (chance(hitchance)) { + pr("BOOM!...\n"); + if(sp->shp_own != 0) + wu(0, sp->shp_own, "%s @ %s torpedoed %s\n", + prship(sp), + xyas(sp->shp_x, sp->shp_y, sp->shp_own), + prsub(targ)); + dam = TORP_DAMAGE(); + + if (ntargets>2) + dam /= ((float)ntargets/2.0); + + shipdamage(targ, dam); + putship(targ->shp_uid, targ); + + if (mchr[(int)sp->shp_type].m_flags & M_SUB) + nreport(targ->shp_own, N_TORP_SHIP, 0, 1); + else + nreport(targ->shp_own, N_SHIP_TORP, player->cnum, 1); + } else { + pr("Missed!\n"); + if(sp->shp_own != 0) + wu(0, sp->shp_own, + "%s missed %s with a torp at %s\n", + prship(sp), prsub(targ), + xyas(sp->shp_x, sp->shp_y, sp->shp_own)); + } + + return 1; +} + +s_char * +prsub(struct shpstr *sp) +{ + if (mchr[(int)sp->shp_type].m_flags & M_SUB) + return "sub"; + else + return prship(sp); +} diff --git a/src/lib/commands/trad.c b/src/lib/commands/trad.c new file mode 100644 index 00000000..92049330 --- /dev/null +++ b/src/lib/commands/trad.c @@ -0,0 +1,601 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * trad.c: Buy units/ships/planes/nukes from other nations. + * + * Known contributors to this file: + * Dave Pare, 1986 + * Pat Loney, 1992 + * Steve McClure, 1996-2000 + */ + +#include +#include "misc.h" +#include "var.h" +#include "sect.h" +#include "nat.h" +#include "news.h" +#include "item.h" +#include "ship.h" +#include "nuke.h" +#include "land.h" +#include "plane.h" +#include "trade.h" +#include "deity.h" +#include "xy.h" +#include "nsc.h" +#include "file.h" +#include "player.h" +#include "commodity.h" +#include "loan.h" +#include "commands.h" +#include "optlist.h" + +extern int sect_mob_neg_factor; +extern int etu_per_update; +extern int TRADE_DELAY; + +/* + * format: trade + */ +int +trad(void) +{ + struct sctstr sect; + struct natstr *natp; + struct comstr comt; + int lotno; + float price; + coord sx, sy; + int n; + char *p; + struct nstr_item ni; + struct trdstr trade; + struct trdstr tmpt; + union trdgenstr tg; + int plflags; + extern double tradetax; + extern double buytax; + double canspend; + time_t now; + int bid; + double tleft; + double tally; + int q; + s_char buf[1024]; + + + if (!opt_MARKET) { + pr("The market is disabled.\n"); + return RET_FAIL; + } + /* First, we execute all trades, so that we can only buy what is available. */ + check_market(); + check_trade(); + + pr("\n Empire Trade Report\n "); + prdate(); + n = 0; + pr(" lot high bid by time left owner description\n"); + pr(" --- -------- -- --------- ----- -------------------------\n"); + + snxtitem_all(&ni, EF_TRADE); + while (nxtitem(&ni, (char *)&trade)) { + if (trade.trd_unitid < 0) + continue; + if (!trade_getitem(&trade, &tg)) { + continue; + }; + /* fix up database if things get weird */ + /*if (trade.trd_owner != tg.gen.trg_own) { + trade.trd_unitid = -1; + (void) puttrade(ni.cur, &trade); + continue; + }*/ + pr(" %3d ", ni.cur); + (void) time(&now); + tleft = TRADE_DELAY/3600.0 - (now - trade.trd_markettime) / 3600.0; + if (tleft < 0.0) tleft = 0.0; + pr("$%7d %2d %5.2f hrs ",trade.trd_maxprice, + trade.trd_maxbidder, tleft); + (void) trade_desc(&trade, &tg); /* XXX */ + pr("\n"); + if (trade.trd_owner == player->cnum && !player->god) + pr(" (your own lot)\n"); + n++; + } + if (n == 0) { + pr("Nothing to buy at the moment...\n"); + return RET_OK; + } + if ((p = getstring("Which lot to buy: ", buf)) == 0 || *p == 0) + return RET_OK; + if (isdigit(*p) == 0) + return RET_OK; + lotno = atoi(p); + if (lotno < 0 || lotno >= ni.cur) { + pr("Bad lot number\n"); + return RET_OK; + } + if (!gettrade(lotno, &trade)) { + pr("No such lot number\n"); + return RET_OK; + } + if (trade.trd_unitid < 0) { + pr("Invalid lot number.\n"); + return RET_OK; + } + if (!trade_getitem(&trade, &tg)) { + pr("Can't find trade #%d!\n", trade.trd_unitid); + trade.trd_unitid = -1; + if (!puttrade(lotno, &trade)) { + pr("Couldn't save after getitem failed; get help!\n"); + return RET_SYS; + } + return RET_OK; + } + switch (trade.trd_type) { + case EF_NUKE: + /* + if (!getsect(tg.gen.trg_x, tg.gen.trg_y, §)) { + return RET_FAIL; + } + trade.trd_owner = sect.sct_own; + break; + */ + case EF_PLANE: + case EF_SHIP: + case EF_LAND: + break; + default: + pr("Bad unit type on lot number %d\n", lotno); + return RET_FAIL; + } + if (trade.trd_owner == player->cnum) { + pr("You can't buy from yourself!\n"); + return RET_OK; + } + price = trade.trd_maxprice; + natp = getnatp(player->cnum); + if (natp->nat_money < price) { + pr("You don't have %.2f to spend!\n", price); + return RET_OK; + } + tally = 0.0; + for (q = 0; gettrade(q, &tmpt); q++) { + if (tmpt.trd_maxbidder == player->cnum && + tmpt.trd_unitid >= 0 && + tmpt.trd_owner != player->cnum) { + tally += tmpt.trd_maxprice * tradetax; + } + } + for (q = 0; getcomm(q, &comt); q++) { + if (comt.com_maxbidder == player->cnum && + comt.com_owner != 0 && + comt.com_owner != player->cnum) { + tally += (comt.com_maxprice * comt.com_amount) * buytax; + } + } + canspend = natp->nat_money - tally; + /* + * Find the destination sector for the plane before the trade + * is actually made. Must be owned (except for satellites) and + * must be a 60% airfield (except for VTOL planes). + */ + if (((trade.trd_type == EF_PLANE) || (trade.trd_type == EF_NUKE)) + && ((trade.trd_type == EF_NUKE) || + !(tg.pln.pln_flags & PLN_LAUNCHED))) { + plflags = plchr[(int)tg.pln.pln_type].pl_flags; + while (1) { + p = getstring("Destination sector: ", buf); + if (!trade_check_ok(lotno, &trade, &tg)) + return RET_FAIL; + if (p == 0) { + return RET_FAIL; + } + if (!sarg_xy(p, &sx, &sy) || + !getsect(sx, sy, §)) { + pr("Bad sector designation; try again!\n"); + continue; + } + if (!player->owner && !(plflags & P_O)) { + pr("You don't own that sector; try again!\n"); + continue; + } + if (!(plflags & (P_V | P_O))) { + if (!player->god && (sect.sct_type != SCT_AIRPT)) { + pr( + "Destination sector is not an airfield!\n"); + continue; + } + if (!player->god && (sect.sct_effic < 60)) { + pr( + "That airport still under construction!\n"); + continue; + } + } + break; + } + } + if (trade.trd_type == EF_LAND){ + while (1) { + p = getstring("Destination sector: ", buf); + if (!trade_check_ok(lotno, &trade, &tg)) + return RET_FAIL; + if (p == 0) { + return RET_FAIL; + } + if (!sarg_xy(p, &sx, &sy) || + !getsect(sx, sy, §)) { + pr("Bad sector designation; try again!\n"); + continue; + } + if (!player->owner) { + pr("You don't own that sector; try again!\n"); + continue; + } + if (!player->god && (sect.sct_type != SCT_HEADQ)) { + pr("Destination sector is not a headquarters!\n"); + continue; + } + if (!player->god && (sect.sct_effic < 60)) { + pr("That headquarters still under construction!\n"); + continue; + } + break; + } + } + + pr("WARNING! This market issues credit. If you make more\n"); + pr(" bids than your treasury can cover at the time of sale,\n"); + pr(" you can potentially go into financial ruin, and see no\n"); + pr(" gains. You have been warned.\n\n"); + + if((p = getstring("How much do you bid: ", buf)) == 0 || *p == 0) + return RET_OK; + if (!trade_check_ok(lotno, &trade, &tg)) + return RET_FAIL; + bid = atoi(p); + if (bid < price) + bid = price; + if (bid > canspend) { + pr("You don't have %.2f to spend!\n", price); + return RET_OK; + } + if (bid > trade.trd_maxprice) { + /* Add five minutes to the time if less than 5 minutes left. */ + time(&now); + if (((TRADE_DELAY - (now - trade.trd_markettime)) < 300) && + trade.trd_maxbidder != player->cnum) + trade.trd_markettime += 300; + trade.trd_maxprice = bid; + trade.trd_maxbidder = player->cnum; + trade.trd_x = sx; + trade.trd_y = sy; + pr("Your bid on lot #%d is being considered.\n",lotno); + if (!puttrade(lotno, &trade)) + pr("Problems with the trade file. Get help\n"); + } else + pr("Your bid wasn't high enough (you need to bid more than someone else.)\n"); + + check_trade(); + + return RET_OK; +} + +int +check_trade(void) +{ + int n; + int j; + extern double tradetax; + struct nstr_item ni; + struct plnstr plane; + struct lndstr land; + struct natstr *natp; + struct trdstr trade; + union trdgenstr tg; + time_t now; + double subleft; + double monleft; + double tleft; + float price; + int saveid; + struct lonstr loan; + long outstanding; /* Outstanding debt */ + long couval; /* Value of country's goods */ + int foundloan; + +/* logerror("Checking the trades.\n");*/ + for (n = 0; gettrade(n, &trade); n++) { + if (trade.trd_unitid < 0) + continue; + if (!trade_getitem(&trade, &tg)) + continue; + if (tg.gen.trg_own == 0) { + trade.trd_unitid = -1; + puttrade(n, &trade); + continue; + } + if (tg.gen.trg_own != trade.trd_owner) { + logerror("SOmething weird, tg.gen.trg_own != trade.trd_owner!\n"); + trade.trd_unitid = -1; + puttrade(n, &trade); + continue; + } + + if (trade.trd_owner == trade.trd_maxbidder) + continue; + + (void) time(&now); + tleft = TRADE_DELAY / 3600.0 - (now - trade.trd_markettime) / 3600.0; + if (tleft < 0.0) + tleft = 0.0; + if (tleft > 0.0) + continue; + + saveid = trade.trd_unitid; + trade.trd_unitid = -1; + if (!puttrade(n, &trade)) { + logerror("Couldn't save trade after purchase; get help!\n"); + continue; + } + + monleft = 0; + price = trade.trd_maxprice; + natp = getnatp(trade.trd_maxbidder); + if (natp->nat_money <= 0) + monleft = price; + if (natp->nat_money < price && natp->nat_money > 0) { + monleft = price - (natp->nat_money - 1); + natp->nat_money = 1; + price = price - monleft; + } else if (natp->nat_money > 0) { + monleft = 0; + natp->nat_money -= price; + } + + subleft = monleft; + + if (opt_LOANS) { + /* Try to make a loan for the rest from the owner. */ + if (monleft > 0 && natp->nat_money > 0) { + if ((float)((float)price / (float)(price + monleft)) < 0.1) { + wu(0, trade.trd_maxbidder, "You need at least 10 percent down to purchase something on credit.\n"); + } else { + couval = get_couval(trade.trd_maxbidder); + outstanding = get_outstand(trade.trd_maxbidder); + couval = couval - outstanding; + if (couval > monleft) { + /* Make the loan */ + foundloan = 0; + for (j = 0; getloan(j, &loan); j++) { + if (loan.l_status != LS_FREE) + continue; + foundloan = 1; + break; + } + if (!foundloan) + ef_extend(EF_LOAN, 1); + loan.l_status = LS_SIGNED; + loan.l_loner = trade.trd_owner; + loan.l_lonee = trade.trd_maxbidder; + loan.l_irate = 25; + loan.l_ldur = 4; + loan.l_amtpaid = 0; + loan.l_amtdue = monleft; + time(&loan.l_lastpay); + loan.l_duedate = (loan.l_ldur * SECS_PER_DAY) + loan.l_lastpay; + loan.l_uid = j; + if (!putloan(j, &loan)) + logerror("Error writing to the loan file.\n"); + else + monleft = 0; + nreport(trade.trd_maxbidder,N_FIN_TROUBLE, trade.trd_owner, 1); + wu(0, trade.trd_maxbidder, "You just took loan #%d for $%.2f to cover the cost of your purchase.\n", j, (float)loan.l_amtdue); + wu(0, trade.trd_owner, "You just extended loan #%d to %s to help with the purchase cost.\n", j, cname(trade.trd_maxbidder)); + } else { + nreport(trade.trd_maxbidder,N_CREDIT_JUNK, trade.trd_owner, 1); + wu(0, trade.trd_maxbidder, "You don't have enough credit to get a loan.\n"); + wu(0, trade.trd_owner, "You just turned down a loan to %s.\n", cname(trade.trd_maxbidder)); + } + } + } + } + if (monleft > 0) { + nreport(trade.trd_maxbidder, N_WELCH_DEAL, trade.trd_owner, 1); + wu(0, trade.trd_owner, "%s tried to buy a %s #%d from you for $%.2f\n", + cname(trade.trd_maxbidder), trade_nameof(&trade, &tg), + saveid, (float)(price * tradetax)); + wu(0, trade.trd_owner, " but couldn't afford it.\n"); + wu(0, trade.trd_owner, " Your item was taken off the market.\n"); + wu(0, trade.trd_maxbidder, + "You tried to buy %s #%d from %s for $%.2f\n", + trade_nameof(&trade, &tg), saveid, cname(trade.trd_owner), + (float)(price * tradetax)); + wu(0, trade.trd_maxbidder, "but couldn't afford it.\n"); + continue; + } + +/* If we get this far, the sale will go through. */ +/* Only pay tax on the part you actually get cash for. As a break, + we don't tax the part you have to give a loan on. */ + + putnat(natp); + natp = getnatp(trade.trd_owner); + /* Make sure we subtract the extra amount */ + natp->nat_money += (roundavg(price * tradetax) - subleft); + putnat(natp); + switch (trade.trd_type) { + case EF_NUKE: + tg.nuk.nuk_x = trade.trd_x; + tg.nuk.nuk_y = trade.trd_y; + makelost(EF_NUKE, tg.nuk.nuk_own, tg.nuk.nuk_uid, tg.nuk.nuk_x, tg.nuk.nuk_y); + tg.nuk.nuk_own = trade.trd_maxbidder; + makenotlost(EF_NUKE, tg.nuk.nuk_own, tg.nuk.nuk_uid, tg.nuk.nuk_x, tg.nuk.nuk_y); + break; + case EF_PLANE: + if ((tg.pln.pln_flags & PLN_LAUNCHED) == 0) { + tg.pln.pln_x = trade.trd_x; + tg.pln.pln_y = trade.trd_y; + } + makelost(EF_PLANE, tg.pln.pln_own, tg.pln.pln_uid, tg.pln.pln_x, tg.pln.pln_y); + tg.pln.pln_own = trade.trd_maxbidder; + makenotlost(EF_PLANE, tg.pln.pln_own, tg.pln.pln_uid, tg.pln.pln_x, tg.pln.pln_y); + tg.pln.pln_wing = ' '; + /* no cheap version of fly */ + if (opt_MOB_ACCESS) { + tg.pln.pln_mobil = -(etu_per_update / sect_mob_neg_factor); + } else { + tg.pln.pln_mobil = 0; + } + tg.pln.pln_mission = 0; + tg.pln.pln_harden = 0; + time(&tg.pln.pln_access); + tg.pln.pln_ship = -1; + tg.pln.pln_land = -1; + break; + case EF_SHIP: + takeover_ship(&tg.shp, trade.trd_maxbidder, 0); + break; + case EF_LAND: + tg.lnd.lnd_x = trade.trd_x; + tg.lnd.lnd_y = trade.trd_y; + if (tg.lnd.lnd_ship >= 0){ + struct shpstr ship; + getship(tg.lnd.lnd_ship, &ship); + ship.shp_nland--; + putship(ship.shp_uid,&ship); + } + makelost(EF_LAND, tg.lnd.lnd_own, tg.lnd.lnd_uid, tg.lnd.lnd_x, tg.lnd.lnd_y); + tg.lnd.lnd_own = trade.trd_maxbidder; + makenotlost(EF_LAND, tg.lnd.lnd_own, tg.lnd.lnd_uid, tg.lnd.lnd_x, tg.lnd.lnd_y); + tg.lnd.lnd_army = ' '; + /* no cheap version of fly */ + if (opt_MOB_ACCESS) { + tg.lnd.lnd_mobil = -(etu_per_update / sect_mob_neg_factor); + } else { + tg.lnd.lnd_mobil = 0; + } + tg.lnd.lnd_harden = 0; + time(&tg.lnd.lnd_access); + tg.lnd.lnd_mission = 0; + /* Drop any land units this unit was carrying */ + snxtitem_xy(&ni, EF_LAND, tg.lnd.lnd_x, tg.lnd.lnd_y); + while (nxtitem(&ni, (s_char *)&land)) { + if (land.lnd_land != tg.lnd.lnd_uid) + continue; + land.lnd_land = -1; + wu(0, land.lnd_own, "unit #%d dropped in %s\n", + land.lnd_uid, + xyas(land.lnd_x, land.lnd_y, land.lnd_own)); + putland(land.lnd_uid, &land); + } + /* Drop any planes this unit was carrying */ + snxtitem_xy(&ni, EF_PLANE, tg.lnd.lnd_x, tg.lnd.lnd_y); + while (nxtitem(&ni, (s_char *)&plane)) { + if (plane.pln_flags & PLN_LAUNCHED) + continue; + if (plane.pln_land != land.lnd_uid) + continue; + plane.pln_land = -1; + wu(0, plane.pln_own, "plane #%d dropped in %s\n", + plane.pln_uid, + xyas(plane.pln_x, plane.pln_y, plane.pln_own)); + putplane(plane.pln_uid, &plane); + } + tg.lnd.lnd_ship = -1; + tg.lnd.lnd_land = -1; + break; + default: + logerror("Bad trade type %d in trade\n", trade.trd_type); + break; + } + if (!ef_write(trade.trd_type, saveid, (char *)&tg)) { + logerror("Couldn't write unit to disk; seek help.\n"); + continue; + } + nreport(trade.trd_owner, N_MAKE_SALE, trade.trd_maxbidder, 1); + wu(0, trade.trd_owner, "%s bought a %s #%d from you for $%.2f\n", + cname(trade.trd_maxbidder), trade_nameof(&trade, &tg), + saveid, (float)(price * tradetax)); + wu(0, trade.trd_maxbidder, + "The bidding is over & you bought %s #%d from %s for $%.2f\n", + trade_nameof(&trade, &tg), saveid, cname(trade.trd_owner), + (float)price); + } +/* logerror("Done checking the trades.\n");*/ + return RET_OK; +} + +int +ontradingblock(int type, int *ptr) + /* Generic pointer */ +{ + struct trdstr trade; + union trdgenstr tg; + int n; + + for (n = 0; gettrade(n, &trade); n++) { + if (trade.trd_unitid < 0) + continue; + if (!trade_getitem(&trade, &tg)) + continue; + if (trade.trd_type != type) + continue; + if (tg.gen.trg_uid == ((struct genstr *)ptr)->trg_uid) + return 1; + } + return 0; +} + +void +trdswitchown(int type, int *ptr, int newown) + /* Generic pointer */ +{ + struct trdstr trade; + union trdgenstr tg; + int n; + + for (n = 0; gettrade(n, &trade); n++) { + if (trade.trd_unitid < 0) + continue; + if (!trade_getitem(&trade, &tg)) + continue; + if (trade.trd_type != type) + continue; + if (tg.gen.trg_uid != ((struct genstr *)ptr)->trg_uid) + continue; + if (trade.trd_owner == trade.trd_maxbidder) + trade.trd_maxbidder = newown; + trade.trd_owner = newown; + if (newown == 0) + trade.trd_unitid = -1; + puttrade(n, &trade); + return; + } +} diff --git a/src/lib/commands/tran.c b/src/lib/commands/tran.c new file mode 100644 index 00000000..8baaa09d --- /dev/null +++ b/src/lib/commands/tran.c @@ -0,0 +1,344 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * tran.c: Transport nuclear devices and planes + * + * Known contributors to this file: + * Steve McClure, 2000 + * + */ + +#ifdef Rel4 +#include +#endif /* Rel4 */ +#include "misc.h" +#include "player.h" +#include "var.h" +#include "sect.h" +#include "nuke.h" +#include "xy.h" +#include "nsc.h" +#include "plane.h" +#include "ship.h" +#include "file.h" +#include "nat.h" +#include "land.h" +#include "commands.h" + +#include + +static int tran_map(s_char *what, coord curx, coord cury, s_char *arg); +static int tran_nuke(void); +static int tran_plane(void); + +int +tran(void) +{ + s_char *what; + s_char buf[1024]; + + what = getstarg(player->argp[1], "transport what (nuke or plane): ", buf); + if (what == 0) + return RET_SYN; + if (*what == 'n') + return tran_nuke(); + else if (*what == 'p') + return tran_plane(); + return RET_SYN; +} + +/* + * Kinda silly; only moves the first nuke. + * Maybe nukes should be made into commodities? + */ +static int +tran_nuke(void) +{ + struct nchrstr *ncp; + int len; + coord x, y; + coord dstx, dsty; + int found; + s_char *p; + int i; + int nuketype; + int moving; + struct nukstr nuke; + struct sctstr sect; + struct sctstr endsect; + int mcost, dam; + struct nstr_item nstr; + s_char buf[1024]; + + if (!(p = getstarg(player->argp[2], "from sector : ", buf))) + return RET_SYN; + if (!sarg_xy(p, &x, &y)) + return RET_SYN; + if (!getsect(x, y, §) || !player->owner) { + pr("Not yours\n"); + return RET_FAIL; + } +#if 0 + if (!snxtitem_xy(&nstr,EF_NUKE,sect.sct_x,sect.sct_y)) { + pr("There are no nukes in %s\n", + xyas(sect.sct_x, sect.sct_y, player->cnum)); + return RET_FAIL; + } +#else + snxtitem_xy(&nstr,EF_NUKE,sect.sct_x,sect.sct_y); +#endif + found = 0; + while (nxtitem(&nstr, (caddr_t)&nuke)) { + if (player->owner) { + found = 1; + break; + } + } + if (!found) { + pr("There are no nukes in %s\n", + xyas(sect.sct_x, sect.sct_y, player->cnum)); + return RET_FAIL; + } + if (!(p = getstarg(player->argp[3], "warhead type : ", buf))) + return RET_SYN; + if (!check_sect_ok(§)) + return RET_FAIL; + len = strlen(p); + for (i=0, ncp = nchr; in_name, p, len) == 0) + break; + } + if (i >= N_MAXNUKE) { + pr("No such nuke type!\n"); + return RET_SYN; + } + nuketype = i; + if (!nuke.nuk_types[nuketype]) { + pr("No %s nukes in %s\n", + ncp->n_name, + xyas(sect.sct_x, sect.sct_y, player->cnum)); + return RET_FAIL; + } + p = getstarg(player->argp[4], "number of warheads : ", buf); + if (!check_sect_ok(§)) + return RET_FAIL; + if (p == 0 || *p == 0 || (moving = atoi(p)) < 0) + return RET_FAIL; + if (moving > nuke.nuk_types[nuketype]) { + moving = nuke.nuk_types[nuketype]; + if (moving) + pr("only moving %d\n", moving); + else + return RET_FAIL; + } + /* + * military control necessary to move + * goodies in occupied territory. + */ + if (sect.sct_oldown != player->cnum){ + int tot_mil=0; + struct nstr_item ni; + struct lndstr land; + snxtitem_xy(&ni, EF_LAND, sect.sct_x, sect.sct_y); + while (nxtitem(&ni, (s_char *)&land)){ + if (land.lnd_own == player->cnum) + tot_mil += total_mil(&land); + } + if ((getvar(V_MILIT, (s_char *)§, EF_SECTOR)+tot_mil) * 10 + < getvar(V_CIVIL, (s_char *)§, EF_SECTOR)) { + pr("Military control required to move goods.\n"); + return RET_FAIL; + } + } + dam = 0; + mcost = move_ground((s_char *)&nuke, §, &endsect, + (double)sect.sct_mobil, + (double) ncp->n_weight * moving, + player->argp[5], tran_map, 0, &dam); + + if (mcost < 0) + return 0; + + if (mcost > 0) + pr("Total movement cost = %d\n",mcost); + else + pr("No mobility used\n"); + + dstx = endsect.sct_x; + dsty = endsect.sct_y; + /* + * decrement mobility from src sector + */ + getsect(nuke.nuk_x, nuke.nuk_y, §); + sect.sct_mobil -= mcost; + if (sect.sct_mobil < 0) + sect.sct_mobil = 0; + putsect(§); + /* + * update old nuke + */ + if (!getnuke(nuke.nuk_uid, &nuke)) { + pr("Could not find that stockpile again.\n"); + return RET_FAIL; + } + if (nuke.nuk_types[nuketype] < moving || nuke.nuk_own != player->cnum) { + pr("Stockpile changed!\n"); + return RET_FAIL; + } + nuk_delete(&nuke, nuketype, moving); + nuk_add(dstx, dsty, nuketype, moving); + return RET_OK; +} + +static int +tran_plane(void) +{ + int srcx, srcy; + int dstx, dsty; + int mcost; + int weight, count; + int first; + int type, dam; + struct nstr_item nstr; + struct plnstr plane; + struct sctstr sect; + struct sctstr endsect; + + first = 1; + weight = 0; + count = 0; + if (!snxtitem(&nstr, EF_PLANE, player->argp[2])) + return RET_SYN; + /* + * First do some sanity checks: make sure that they are all in the, + * same sector, not on ships, owned, etc. + * No one could seriously want to move planes in parallel from + * several sectors! + */ + while (nxtitem(&nstr, (s_char *)&plane)) { + if (!player->owner) + continue; + type = plane.pln_type; + if (plane.pln_ship >= 0) { + pr("%s is at sea and can't be transported\n", + prplane(&plane)); + return RET_FAIL; + } else if (plane.pln_harden != 0) { + pr("%s has been hardened and can't be transported\n", + prplane(&plane)); + return RET_FAIL; + } else if ((plane.pln_flags & PLN_LAUNCHED) && + (plchr[type].pl_flags & P_O)) { + pr("%s is in space and can't be transported\n", + prplane(&plane)); + return RET_FAIL; + } + if (first == 1) { + srcx = plane.pln_x; + srcy = plane.pln_y; + first = 0; + } else { + if (plane.pln_x != srcx || plane.pln_y != srcy) { + pr("All planes must be in the same sector.\n"); + return RET_FAIL; + } + } + weight += plchr[type].pl_lcm + (plchr[type].pl_hcm * 2); + ++count; + } + if (first == 1) { + /* no planes */ + return RET_FAIL; + } + getsect(srcx, srcy, §); + /* + * military control necessary to move + * goodies in occupied territory. + */ + if (sect.sct_oldown != player->cnum){ + int tot_mil=0; + struct nstr_item ni; + struct lndstr land; + snxtitem_xy(&ni, EF_LAND, sect.sct_x, sect.sct_y); + while (nxtitem(&ni, (s_char *)&land)) + tot_mil += total_mil(&land); + if ((getvar(V_MILIT, (s_char *)§, EF_SECTOR)+tot_mil) * 10 + < getvar(V_CIVIL, (s_char *)§, EF_SECTOR)) { + pr("Military control required to move goods.\n"); + return RET_FAIL; + } + } + dam = 1; + mcost = move_ground((s_char *)&plane, §, &endsect, + (double)sect.sct_mobil, (double)weight, + player->argp[3], tran_map, 0, &dam); + dam /= count; + if (mcost < 0) + return 0; + + dstx = endsect.sct_x; + dsty = endsect.sct_y; + snxtitem_rewind(&nstr); + while (nxtitem(&nstr, (s_char *)&plane)) { + if (!player->owner) + continue; + if (dam) { + planedamage(&plane,dam); + pr("\t%s takes %d\n", + prplane(&plane), + dam); + } + plane.pln_x = dstx; + plane.pln_y = dsty; + plane.pln_mission = 0; + putplane(plane.pln_uid, &plane); + } + if (mcost > 0) + pr("Total movement cost = %d\n",mcost); + else + pr("No mobility used\n"); + sect.sct_mobil -= mcost; + if (sect.sct_mobil < 0) + sect.sct_mobil = 0; + putsect(§); + return RET_OK; +} + +/* + * Pretty tacky, but it works. + * If more commands start doing this, then + * rewrite map to do the right thing. + */ +/* I think this is no longer used, check subs/move.c:move_ground() */ +/*ARGSUSED*/ +static int +tran_map(s_char *what, coord curx, coord cury, s_char *arg) +{ + player->argp[1] = arg; + player->condarg = 0; + return map(); +} diff --git a/src/lib/commands/trea.c b/src/lib/commands/trea.c new file mode 100644 index 00000000..3d45b876 --- /dev/null +++ b/src/lib/commands/trea.c @@ -0,0 +1,63 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * trea.c: Look at current treaties. + * + * Known contributors to this file: + * + */ + +#include "misc.h" +#include "player.h" +#include "xy.h" +#include "nsc.h" +#include "nat.h" +#include "treaty.h" +#include "file.h" +#include "commands.h" + +int +trea(void) +{ + struct trtstr treaty; + struct nstr_item nstr; + int ntreaty; + + if (!snxtitem(&nstr, EF_TREATY, player->argp[1])) + return RET_SYN; + pr("\t... %s Treaty Report ...\n", cname(player->cnum)); + ntreaty = 0; + while (nxtitem(&nstr, (s_char *)&treaty)) { + if (distrea(nstr.cur, &treaty) > 0) + ntreaty++; + } + if (!ntreaty) + pr("No treaties found.\n"); + else + pr("%d treat%s\n", ntreaty, iesplur(ntreaty)); + return RET_OK; +} diff --git a/src/lib/commands/turn.c b/src/lib/commands/turn.c new file mode 100644 index 00000000..90fc698e --- /dev/null +++ b/src/lib/commands/turn.c @@ -0,0 +1,89 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * turn.c: Turn the game on, off, or set the login message. + * + * Known contributors to this file: + * + */ + +#include "misc.h" +#include "player.h" +#include "tel.h" +#include "commands.h" + +#include + +int +turn(void) +{ + extern s_char *upfil; + extern s_char *downfil; + int fd; + struct telstr tgm; + register s_char *p; + s_char buf[MAXTELSIZE]; + + p = getstarg(player->argp[1], "on, off or message? ", buf); + if (!p) + return RET_SYN; + if (strcmp(p, "off") == 0) { + (void) unlink(upfil); +#if !defined(_WIN32) + fd = open(downfil, O_RDWR|O_CREAT|O_TRUNC, 0660); +#else + fd = open(downfil, O_RDWR|O_CREAT|O_TRUNC|O_BINARY, 0660); +#endif + pr("off "); + } else if (strcmp(p, "on") == 0) { + (void) unlink(downfil); +#if !defined(_WIN32) + fd = open(upfil, O_RDWR|O_CREAT|O_TRUNC, 0660); +#else + fd = open(upfil, O_RDWR|O_CREAT|O_TRUNC|O_BINARY, 0660); +#endif + pr("on "); + } else { +#if !defined(_WIN32) + fd = open(upfil, O_RDWR|O_CREAT|O_TRUNC, 0660); +#else + fd = open(upfil, O_RDWR|O_CREAT|O_TRUNC|O_BINARY, 0660); +#endif + pr("motd "); + } + (void) time(&tgm.tel_date); + if ((tgm.tel_length = getele("The World", buf)) <= 0) { + pr("Ignored\n"); + close(fd); + return RET_SYN; + } + (void) write(fd, (s_char *)&tgm, sizeof (tgm)); + (void) write(fd, buf, tgm.tel_length); + (void) close(fd); + pr("\n"); + return RET_OK; +} diff --git a/src/lib/commands/upda.c b/src/lib/commands/upda.c new file mode 100644 index 00000000..a381af8b --- /dev/null +++ b/src/lib/commands/upda.c @@ -0,0 +1,187 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * upda.c: Give the time of the next update + * + * Known contributors to this file: + * + */ + +#include +#include +#include "misc.h" +#include "player.h" +#include "commands.h" +#include "optlist.h" + +#include "keyword.h" +#include "wantupd.h" + +/* + * Tell what the update policy is, and when the next update + * is likely to be. + */ +int +upda(void) +{ + FILE *fp; + struct mob_acc_globals timestamps; + extern int updating_mob; + extern int update_window; + extern s_char *timestampfil; + + if (opt_MOB_ACCESS) { +#if !defined(_WIN32) + if ((fp = fopen(timestampfil, "r")) == NULL) { +#else + if ((fp = fopen(timestampfil, "rb")) == NULL) { +#endif + logerror("Unable to open timestamp file."); + } else { + rewind(fp); + fread(×tamps, sizeof(timestamps), 1, fp); + fclose(fp); + if (updating_mob) + pr("Mobility updating is enabled.\n\n"); + else { + pr("Mobility updating will come back on around %s", + ctime(×tamps.starttime)); + pr("game time, within 3 minutes, depending on when the server checks.\n\n"); + } + } + } + if (opt_UPDATESCHED) { + time_t now, next, delta; + extern int update_time; + extern int update_policy; + extern int update_demandpolicy; + extern int update_wantmin; + extern int blitz_time; + extern s_char *update_times; + extern s_char *update_demandtimes; + extern s_char *game_days; + extern s_char *game_hours; + + if (updates_disabled()) + pr("UPDATES ARE DISABLED!\n"); + + (void) time(&now); + switch (update_policy) { + case UDP_NORMAL: + next_update_time(&now, &next, &delta); + pr("\nUpdates occur at times specified by the ETU rates.\n\n"); + pr("The next update is at %19.19s.\n", ctime(&next)); + break; + case UDP_TIMES: + next_update_time(&now, &next, &delta); + pr("\nUpdates occur at scheduled times.\n\n"); + pr("The next update is at %19.19s.\n", ctime(&next)); + break; + case UDP_BLITZ: + next_update_time(&now, &next, &delta); + pr("\nBlitz Updates occur every %d minutes. \n\n", + blitz_time); + pr("The next update is at %19.19s.\n",ctime(&next)); + break; + case UDP_NOREG: + pr("There are no regularly scheduled updates.\n"); + break; + default: + pr("Update policy is inconsistent.\n"); + } + pr("The current time is %19.19s.\n\n", ctime(&now)); + + if (update_window) { + now = update_time - update_window; + next_update_time(&now, &next, &delta); + pr("The next update window starts at %19.19s.\n",ctime(&next)); + next += update_window; + pr("The next update window stops at %19.19s.\n",ctime(&next)); + } + if (opt_DEMANDUPDATE) { + if (update_demandpolicy != UDDEM_DISABLE) { + switch (update_demandpolicy) { + case UDDEM_TMCHECK: + next_update_check_time(&now, &next, &delta); + pr("Demand updates occur at update CHECK times.\n"); + pr("The next update check is at %19.19s.\n", + ctime(&next)); + break; + case UDDEM_COMSET: + pr("Demand updates occur right after the demand is set.\n"); + break; + default: + pr("Update demand policy is inconsistent.\n"); + } + } + } + + if ((update_policy == UDP_TIMES) || + ((update_demandpolicy == UDDEM_TMCHECK) && + opt_DEMANDUPDATE)) { + if (*update_times != 0) + pr("The update schedule is: %s\n", update_times); + } + if (opt_DEMANDUPDATE) { + if (update_demandpolicy != UDDEM_DISABLE) { + if (*update_demandtimes != 0) + pr("Demand updates are allowed during: %s\n", update_demandtimes); + if (update_wantmin == 0) { + pr("Demand updates are disabled by a mininum of 0\n"); + } else { + pr("Demand updates require %d country(s) to want one.\n",update_wantmin); + } + } + } + if (*game_days != 0) pr("Game days are: %s\n", game_days); + if (*game_hours != 0) pr("Game hours are: %s\n", game_hours); + + return(0); + } else { + extern int s_p_etu; + extern int etu_per_update; + extern int adj_update; + time_t now; + time_t upd_time; + time_t next_update; + int secs_per_update; + int delta; + + (void) time(&now); + upd_time = now + adj_update; + secs_per_update = etu_per_update * s_p_etu; + delta = secs_per_update - (upd_time % secs_per_update); + next_update = now + delta; + pr("The next update is at %19.19s.\n",ctime(&next_update)); + pr("The current time is %19.19s.\n",ctime(&now)); + if (update_window) { + pr("Update times are variable, update window is +/- %d minutes %d seconds.\n", + update_window / 60, update_window % 60); + } + return 0; + } +} diff --git a/src/lib/commands/upgr.c b/src/lib/commands/upgr.c new file mode 100644 index 00000000..98bc4c47 --- /dev/null +++ b/src/lib/commands/upgr.c @@ -0,0 +1,386 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * upgr.c: Upgrade tech of ships/planes/units + * + * Known contributors to this file: + * Dave Pare, 1986 + * Steve McClure, 1996-2000 + */ + +#include "misc.h" +#include "player.h" +#include "xy.h" +#include "var.h" +#include "ship.h" +#include "land.h" +#include "plane.h" +#include "sect.h" +#include "nat.h" +#include "nsc.h" +#include "file.h" +#include "commands.h" + +int +upgr(void) +{ + s_char *p; + s_char buf[1024]; + + if (!(p = getstarg(player->argp[1], "Ship, land, or plane? ", buf))) + return RET_SYN; + switch (*p) { + case 's': + case 'S': + return supgr(); + case 'p': + case 'P': + return pupgr(); + case 'l': + case 'L': + return lupgr(); + default: + pr("Ships, land units or planes only!\n"); + return RET_SYN; + } + return RET_OK; +} + +int +lupgr(void) +{ + struct sctstr sect; + struct natstr *natp; + struct nstr_item ni; + struct lndstr land; + struct lchrstr *lp; + int n; + int tlev; + int w_p_eff; + int points; + int rel; + int techdiff; + long cash; + + if (!snxtitem(&ni, EF_LAND, player->argp[2])) + return RET_SYN; + ni.flags &= ~(EFF_OWNER); + natp = getnatp(player->cnum); + cash = natp->nat_money; + tlev = (int) natp->nat_level[NAT_TLEV]; + n = 0; + while (nxtitem(&ni, (s_char *) &land)) { + if (land.lnd_own == 0) + continue; + getsect(land.lnd_x, land.lnd_y, §); + if (sect.sct_own != player->cnum) + continue; + if (sect.sct_type != SCT_HEADQ || sect.sct_effic < 60) + continue; + rel=getrel(getnatp(land.lnd_own),sect.sct_own); + if ((rel < FRIENDLY) && (sect.sct_own != land.lnd_own)){ + pr("You are not on friendly terms with the owner of unit %d!\n", + land.lnd_uid); + continue; + } + n++; + lp = &lchr[(int)land.lnd_type]; + w_p_eff = ((lp->l_lcm / 2) + lp->l_hcm); + points = sect.sct_avail * 100 / w_p_eff; + if (points < 20) { + pr("Not enough available work in %s to upgrade a %s\n", + xyas(sect.sct_x, sect.sct_y, player->cnum), + lp->l_name); + pr(" (%d available work required)\n", + 1 + (w_p_eff * 20)/100); + continue; + } + if (land.lnd_effic < 60) { + pr("%s is too damaged to upgrade!\n", prland(&land)); + continue; + } + if (land.lnd_tech >= tlev) { + pr("%s tech: %d, yours is only %d\n", prland(&land), + land.lnd_tech, tlev); + continue; + } + if (lp->l_cost * .15 + player->dolcost > cash) { + pr("You don't have enough money to upgrade %s!\n", + prland(&land)); + continue; + } + + sect.sct_avail = (sect.sct_avail * 100 - w_p_eff * 20) / 100; + land.lnd_effic -= 35; + + land.lnd_tech = tlev; + techdiff = (int)(tlev - lp->l_tech); + + land.lnd_harden = 0; + land.lnd_mission = 0; + + land.lnd_att = (float)LND_ATTDEF(lp->l_att, techdiff); + land.lnd_def = (float)LND_ATTDEF(lp->l_def, techdiff); + land.lnd_vul = (int)LND_VUL(lp->l_vul, techdiff); + land.lnd_spd = (int)LND_SPD(lp->l_spd, techdiff); + land.lnd_vis = (int)LND_VIS(lp->l_vis, techdiff); + land.lnd_spy = (int)LND_SPY(lp->l_spy, techdiff); + land.lnd_rad = (int)LND_RAD(lp->l_rad, techdiff); + land.lnd_frg = (int)LND_FRG(lp->l_frg, techdiff); + land.lnd_acc = (int)LND_ACC(lp->l_acc, techdiff); + land.lnd_dam = (int)LND_DAM(lp->l_dam, techdiff); + land.lnd_ammo = (int)LND_AMM(lp->l_ammo, lp->l_dam, techdiff); + land.lnd_aaf = (int)LND_AAF(lp->l_aaf, techdiff); + land.lnd_fuelc = (int)LND_FC(lp->l_fuelc, techdiff); + land.lnd_fuelu = (int)LND_FU(lp->l_fuelu, techdiff); + land.lnd_maxlight = (int)LND_XPL(lp->l_nxlight, techdiff); + land.lnd_maxland = (int)LND_MXL(lp->l_mxland, techdiff); + + time(&land.lnd_access); + + putland(land.lnd_uid, &land); + putsect(§); + player->dolcost += (double) lp->l_cost * .15; + pr("%s upgraded to tech %d, at a cost of %d\n", prland(&land), + land.lnd_tech, + (int)(lp->l_cost * .15)); + if (land.lnd_own != player->cnum) + wu(0,land.lnd_own,"%s upgraded by %s to tech %d, at a cost of %d\n", prland(&land), + cname(player->cnum), + land.lnd_tech, (int)(lp->l_cost * .15)); + } + if (n == 0) { + pr("No land units\n"); + return RET_SYN; + } + return RET_OK; +} + +int +supgr(void) +{ + struct sctstr sect; + struct natstr *natp; + struct nstr_item ni; + struct shpstr ship; + struct mchrstr *mp; + int n; + int tlev; + int w_p_eff; + int points; + int rel; + int techdiff; + long cash; + + if (!snxtitem(&ni, EF_SHIP, player->argp[2])) + return RET_SYN; + ni.flags &= ~(EFF_OWNER); + natp = getnatp(player->cnum); + cash = natp->nat_money; + tlev = (int) natp->nat_level[NAT_TLEV]; + n = 0; + while (nxtitem(&ni, (s_char *) &ship)) { + if (ship.shp_own == 0) + continue; + getsect(ship.shp_x, ship.shp_y, §); + if (sect.sct_own != player->cnum) + continue; + if (sect.sct_type != SCT_HARBR || sect.sct_effic < 60) + continue; + rel=getrel(getnatp(ship.shp_own),sect.sct_own); + if ((rel < FRIENDLY) && (sect.sct_own != ship.shp_own)){ + pr("You are not on friendly terms with the owner of ship %d!\n", + ship.shp_uid); + continue; + } + n++; + mp = &mchr[(int)ship.shp_type]; + w_p_eff = ((mp->m_lcm / 2) + mp->m_hcm); + points = sect.sct_avail * 100 / w_p_eff; + if (points < 20) { + pr("Not enough available work in %s to upgrade a %s\n", + xyas(sect.sct_x, sect.sct_y, player->cnum), + mp->m_name); + pr(" (%d available work required)\n", + 1 + (w_p_eff * 20)/100); + continue; + } + if (ship.shp_effic < 60) { + pr("%s is too damaged to upgrade!\n", prship(&ship)); + continue; + } + if (ship.shp_tech >= tlev) { + pr("%s tech: %d, yours is only %d\n", prship(&ship), + ship.shp_tech, tlev); + continue; + } + if (mp->m_cost * .15 + player->dolcost > cash) { + pr("You don't have enough money to upgrade %s!\n", + prship(&ship)); + continue; + } + + sect.sct_avail = (sect.sct_avail * 100 - w_p_eff * 20) / 100; + ship.shp_effic -= 35; + ship.shp_tech = tlev; + + techdiff = (int)(tlev - mp->m_tech); + ship.shp_armor = (short)SHP_DEF(mp->m_armor, techdiff); + ship.shp_speed = (short)SHP_SPD(mp->m_speed, techdiff); + ship.shp_visib = (short)SHP_VIS(mp->m_visib, techdiff); + ship.shp_frnge = (short)SHP_RNG(mp->m_frnge, techdiff); + ship.shp_glim = (short)SHP_FIR(mp->m_glim, techdiff); + + ship.shp_mission = 0; + time(&ship.shp_access); + + putship(ship.shp_uid, &ship); + putsect(§); + player->dolcost += (double) mp->m_cost * .15; + pr("%s upgraded to tech %d, at a cost of %d\n", prship(&ship), + ship.shp_tech, + (int)(mp->m_cost * .15)); + if (ship.shp_own != player->cnum) + wu(0,ship.shp_own,"%s upgraded by %s to tech %d, at a cost of %d\n", prship(&ship), + cname(player->cnum), + ship.shp_tech, (int)(mp->m_cost * .15)); + } + if (n == 0) { + pr("No ships\n"); + return RET_SYN; + } + return RET_OK; +} + +int +pupgr(void) +{ + struct sctstr sect; + struct natstr *natp; + struct nstr_item ni; + struct plnstr plane; + struct plchrstr *pp; + int n; + int tlev; + int w_p_eff; + int points; + int rel; + int techdiff; + long cash; + + if (!snxtitem(&ni, EF_PLANE, player->argp[2])) + return RET_SYN; + ni.flags &= ~(EFF_OWNER); + natp = getnatp(player->cnum); + cash = natp->nat_money; + tlev = (int) natp->nat_level[NAT_TLEV]; + n = 0; + while (nxtitem(&ni, (s_char *) &plane)) { + if (plane.pln_own == 0) + continue; + getsect(plane.pln_x, plane.pln_y, §); + if (sect.sct_own != player->cnum) + continue; + if (sect.sct_type != SCT_AIRPT || sect.sct_effic < 60) + continue; + rel=getrel(getnatp(plane.pln_own),sect.sct_own); + if ((rel < FRIENDLY) && (sect.sct_own != plane.pln_own)){ + pr("You are not on friendly terms with the owner of plane %d!\n", + plane.pln_uid); + continue; + } + n++; + pp = &plchr[(int)plane.pln_type]; + w_p_eff = ((pp->pl_lcm / 2) + pp->pl_hcm); + points = sect.sct_avail * 100 / w_p_eff; + if (points < 20) { + pr("Not enough available work in %s to upgrade a %s\n", + xyas(sect.sct_x, sect.sct_y, player->cnum), + pp->pl_name); + pr(" (%d available work required)\n", + 1 + (w_p_eff * 20)/100); + continue; + } + if (plane.pln_effic < 60) { + pr("%s is too damaged to upgrade!\n", prplane(&plane)); + continue; + } + if (plane.pln_tech >= tlev) { + pr("%s tech: %d, yours is only %d\n", prplane(&plane), + plane.pln_tech, tlev); + continue; + } + if (pp->pl_cost * .15 + player->dolcost > cash) { + pr("You don't have enough money to upgrade %s!\n", + prplane(&plane)); + continue; + } + if (plane.pln_flags & PLN_LAUNCHED) { + pr("Plane %s is in orbit!\n", prplane(&plane)); + continue; + } + + sect.sct_avail = (sect.sct_avail * 100 - w_p_eff * 20) / 100; + plane.pln_effic -= 35; + + plane.pln_tech = tlev; + techdiff = (int)(tlev - pp->pl_tech); + + plane.pln_mission = 0; + plane.pln_opx = 0; + plane.pln_opy = 0; + plane.pln_radius = 0; + plane.pln_harden = 0; + plane.pln_mission = 0; + + plane.pln_att = PLN_ATTDEF(pp->pl_att, techdiff); + plane.pln_def = PLN_ATTDEF(pp->pl_def, techdiff); + plane.pln_acc = PLN_ACC(pp->pl_acc, techdiff); + plane.pln_range = PLN_RAN(pp->pl_range, techdiff); + plane.pln_range_max = plane.pln_range; + plane.pln_load = PLN_LOAD(pp->pl_load, techdiff); + + time(&plane.pln_access); + + putplane(plane.pln_uid, &plane); + putsect(§); + player->dolcost += (double) pp->pl_cost * .15; + pr("%s upgraded to tech %d, at a cost of %d\n", prplane(&plane), + plane.pln_tech, + (int)(pp->pl_cost * .15)); + if (plane.pln_own != player->cnum) + wu(0,plane.pln_own,"%s upgraded by %s to tech %d, at a cost of %d\n", prplane(&plane), + cname(player->cnum), + plane.pln_tech, (int)(pp->pl_cost * .15)); + } + if (n == 0) { + pr("No planes.\n"); + return RET_SYN; + } + return RET_OK; +} + diff --git a/src/lib/commands/vers.c b/src/lib/commands/vers.c new file mode 100644 index 00000000..04645b9a --- /dev/null +++ b/src/lib/commands/vers.c @@ -0,0 +1,258 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * vers.c: Print out the Empire version + * + * Known contributors to this file: + * Dave Pare + * Jeff Bailey + * Thomas Ruschak + * Ken Stevens + * Steve McClure + */ + +#include +#include +#include "gamesdef.h" +#include "misc.h" +#include "player.h" +#include "deity.h" +#include "nat.h" +#include "version.h" +#include "ship.h" +#include "optlist.h" +#include "commands.h" + +extern float drnuke_const; + +int +vers(void) +{ + extern int s_p_etu; + extern int etu_per_update; + extern int m_m_p_d; + extern int players_at_00; + extern float btu_build_rate; + extern double fgrate, fcrate; + extern double eatrate, babyeat; + extern double obrate, uwbrate; + extern double bankint; + extern double hap_cons, edu_cons; + extern double money_civ, money_uw, money_mil, money_res; + extern float hap_avg, edu_avg, ally_factor; + extern float level_age_rate; +/* extern float easy_tech, hard_tech, tech_log_base; */ + extern float easy_tech, tech_log_base; + extern int land_mob_max; + extern int land_grow_scale; + extern float land_mob_scale; + extern int sect_mob_max; + extern float sect_mob_scale; + extern int ship_mob_max; + extern float ship_mob_scale; + extern int ship_grow_scale; + extern int plane_mob_max; + extern float plane_mob_scale; + extern int plane_grow_scale; + extern int War_Cost; + extern float fire_range_factor; + extern int trade_1_dist; /* less than this gets no money */ + extern int trade_2_dist; /* less than this gets trade_1 money */ + extern int trade_3_dist; /* less than this gets trade_2 money */ + extern float trade_1; /* return on trade_1 distance */ + extern float trade_2; /* return on trade_2 distance */ + extern float trade_3; /* return on trade_3 distance */ + extern float trade_ally_bonus; /* 20% bonus for trading with allies */ + extern float trade_ally_cut; /* 10% bonus for ally you trade with */ + extern double tradetax; + extern double buytax; + struct option_list *op; + + time_t now; + int j; + + (void) time(&now); + pr("Empire %d.%d.%d\n(KSU distribution %2.2f, Chainsaw version %2.2f, Wolfpack version %2.2f)\n\n", + EMP_VERS_MAJOR, EMP_VERS_MINOR, EMP_VERS_PATCH, + (float)KSU_DIST, (float)CHAINSAW_DIST, (float)WOLFPACK_DIST); + pr("The following parameters have been set for this game:\n"); + pr("World size is %d by %d.\n", WORLD_X, WORLD_Y); + pr("There can be up to %d countries.\n", MAXNOC); + pr("By default, countries use %s coordinate system.\n", + (players_at_00) ? "the deity's" : "their own"); + pr("\n"); + pr("An Empire time unit is %d second%s long.\n", + s_p_etu, s_p_etu != 1 ? "s" : ""); + pr("Use the 'update' command to find out the time of the next update.\n"); + pr("The current time is %19.19s.\n",ctime(&now)); + pr("An update consists of %d empire time units.\n", + etu_per_update); + pr("Each country is allowed to be logged in %d minutes a day.\n", + m_m_p_d); + pr("It takes %.2f civilians to produce a BTU in one time unit.\n", + (1.0/(btu_build_rate*100.0))); + pr("\n"); + + pr("A non-aggi, 100 fertility sector can grow %.2f food per etu.\n", + 100.0 * fgrate); + pr("1000 civilians will harvest %.1f food per etu.\n", + 1000.0*fcrate); + pr("1000 civilians will give birth to %.1f babies per etu.\n", + 1000.0*obrate); + pr("1000 uncompensated workers will give birth to %.1f babies.\n", + 1000.0*uwbrate); + pr("In one time unit, 1000 people eat %.1f units of food.\n", + 1000.0*eatrate); + pr("1000 babies eat %.1f units of food becoming adults.\n", + 1000.0*babyeat); + if (opt_NOFOOD) + pr("No food is needed!!\n"); + + pr("\n"); + + pr("Banks pay $%.2f in interest per 1000 gold bars per etu.\n", + bankint*1000.0); + pr("1000 civilians generate $%.2f, uncompensated workers $%.2f each time unit.\n", 1000.0*money_civ, 1000.0*money_uw); + pr("1000 active military cost $%.2f, reserves cost $%.2f.\n", + -money_mil*1000.0, -money_res*1000.0); + if (opt_SLOW_WAR) + pr("Declaring war will cost you $%i\n\n", War_Cost); + pr("Happiness p.e. requires 1 happy stroller per %d civ.\n", + (int) hap_cons / etu_per_update); + pr("Education p.e. requires 1 class of graduates per %d civ.\n", + (int) edu_cons / etu_per_update); + pr("Happiness is averaged over %d time units.\n", (int)hap_avg); + pr("Education is averaged over %d time units.\n", (int)edu_avg); + if (opt_ALL_BLEED == 0) + pr( + "The technology/research boost you get from your allies is %.2f%%.\n", + 100.0/ally_factor); + else /* ! ALL_BLEED */ + pr( + "The technology/research boost you get from the world is %.2f%%.\n", + 100.0/ally_factor); + + pr("Nation levels (tech etc.) decline 1%% every %d time units.\n", + (int)(level_age_rate)); + + pr("Tech Buildup is "); +/* if (tech_log_base <= 1.0 && hard_tech == 0.0) { */ + if (tech_log_base <= 1.0 ) { + pr("not limited\n"); + } + if (tech_log_base > 1.0) { + pr("limited to logarithmic growth (base %.2f)", + tech_log_base); + if (easy_tech == 0.0) + pr(".\n"); + else + pr(" after %0.2f.\n", easy_tech); + } /*else { + pr("limited to asymptotic growth towards %.2f", + hard_tech + easy_tech); + if (easy_tech == 0.00) + pr(".\n"); + else + pr("after %.2f\n",easy_tech); + } */ + + pr("\n"); + pr("\t\t\t\tSectors\tShips\tPlanes\tUnits\n"); + pr("Maximum mobility\t\t%d\t%d\t%d\t%d\n", sect_mob_max, + ship_mob_max, plane_mob_max, land_mob_max); + pr("Max mob gain per update\t\t%d\t%d\t%d\t%d\n", + (int)(sect_mob_scale*(float)etu_per_update), + (int)(ship_mob_scale*(float)etu_per_update), + (int)(plane_mob_scale*(float)etu_per_update), + (int)(land_mob_scale*(float)etu_per_update)); + pr("Max eff gain per update\t\t--\t%d\t%d\t%d\n", + min(ship_grow_scale*etu_per_update,100), + min(plane_grow_scale*etu_per_update,100), + min(land_grow_scale*etu_per_update,100)); + pr("\n"); + pr("Ships on autonavigation may use %i cargo holds per ship.\n",TMAX); + if (opt_TRADESHIPS) { + pr("Trade-ships that go at least %d sectors get a return of %.1f%% per sector.\n", + trade_1_dist, (float)(trade_1 * 100.0)); + pr("Trade-ships that go at least %d sectors get a return of %.1f%% per sector.\n", + trade_2_dist, (float)(trade_2 * 100.0)); + pr("Trade-ships that go at least %d sectors get a return of %.1f%% per sector.\n", + trade_3_dist, (float)(trade_3 * 100.0)); + pr("Cashing in trade-ships with an ally nets you a %.1f%% bonus.\n", + trade_ally_bonus * 100.0); + pr("Cashing in trade-ships with an ally nets your ally a %.1f%% bonus.\n\n", + trade_ally_cut * 100.0); + } + if (opt_MARKET) { + pr("The tax you pay on selling things on the trading block is %.1f%%\n", + (1.00-tradetax) * 100.0); + pr("The tax you pay on buying commodities on the market is %.1f%%\n\n", + (buytax - 1.00) * 100.0); + } + + if (opt_NONUKES) + pr("Nukes are disabled.\n"); + else if(opt_DRNUKE) { /* NUKES && DRNUKE enabled */ + pr("In order to build a nuke, you need %1.2f times the tech level in research\n", + drnuke_const); + pr("\tExample: In order to build a 300 tech nuke, you need %d research\n\n", + (int)(300.0*drnuke_const)); + } + + pr("Fire ranges are scaled by %.2f\n", fire_range_factor); + + pr("\nOptions enabled in this game:\n "); + for (j = 0, op = Options; op -> opt_key; op++) { + if (*op -> opt_valuep == 0) + continue; + + j += strlen (op -> opt_key) + 2; + if (j > 70) { + pr ("\n "); + j = strlen (op -> opt_key) + 2; + } + pr ("%s%s", op -> opt_key, op[1].opt_key == NULL ? "": ", "); + } + pr("\n\nOptions disabled in this game:\n "); + for (j = 0, op = Options; op -> opt_key; op++) { + if (!(*op -> opt_valuep == 0)) + continue; + + j += strlen (op -> opt_key) + 2; + if (j > 70) { + pr ("\n "); + j = strlen (op -> opt_key) + 2; + } + pr ("%s%s", op -> opt_key, op[1].opt_key == NULL ? "": ", "); + } + pr("\n\n\"info Options\" for a detailed list of options and descriptions"); + pr("\n\n"); + pr("The person to annoy if something goes wrong is:\n\t%s\n\t(%s).\n", + privname, privlog); + pr("You can get your own copy of the source %s\n", GET_SOURCE); + return RET_OK; +} diff --git a/src/lib/commands/wai.c b/src/lib/commands/wai.c new file mode 100644 index 00000000..913b8a55 --- /dev/null +++ b/src/lib/commands/wai.c @@ -0,0 +1,60 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * wai.c: Wait for telegrams and announcements + * + * Known contributors to this file: + * + */ + +#include "misc.h" +#include "player.h" +#include "nat.h" +#include "file.h" +#include "empio.h" +#include "commands.h" + +int +wai(void) +{ + struct natstr *np; + + np = getnatp(player->cnum); + io_output(player->iop, IO_WAIT); + if (np->nat_ann == 0 && np->nat_tgms == 0) { + player->waiting++; + io_input(player->iop, IO_WAIT); + player->waiting--; + } + if (player->aborted || io_eof(player->iop)) + return RET_OK; + if (np->nat_ann != 0) + player->argp[0] = "wire"; + if (np->nat_tgms != 0) + player->argp[0] = "read"; + return rea(); +} diff --git a/src/lib/commands/wing.c b/src/lib/commands/wing.c new file mode 100644 index 00000000..f30165b0 --- /dev/null +++ b/src/lib/commands/wing.c @@ -0,0 +1,77 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * wing.c: Add planes to a wing + * + * Known contributors to this file: + * + */ + +#include +#include "misc.h" +#include "player.h" +#include "var.h" +#include "plane.h" +#include "xy.h" +#include "nsc.h" +#include "nat.h" +#include "file.h" +#include "commands.h" + +int +wing(void) +{ + + struct plnstr plane; + register int count; + s_char *cp; + s_char c; + struct nstr_item nstr; + s_char buf[1024]; + + if (!(cp = getstarg(player->argp[1], "wing? ", buf))) + return RET_SYN; + c = *cp; + if (!isalpha(c) && c != '~') { + pr("Specify wing, (1 alpha char or '~')\n"); + return RET_SYN; + } + if (c == '~') + c = ' '; + if (!snxtitem(&nstr, EF_PLANE, player->argp[2])) + return RET_SYN; + for (count = 0; nxtitem(&nstr, (s_char *)&plane); count++) { + if (plane.pln_own != player->cnum) { + count--; + continue; + } + plane.pln_wing = c; + putplane(plane.pln_uid, &plane); + } + pr("%d plane%s added to wing `%c'\n", count, splur(count), c); + return RET_OK; +} diff --git a/src/lib/commands/wipe.c b/src/lib/commands/wipe.c new file mode 100644 index 00000000..d5828361 --- /dev/null +++ b/src/lib/commands/wipe.c @@ -0,0 +1,64 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * wipe.c: Clear all existing distribution thresholds + * + * Known contributors to this file: + * Jim Griffith, 1989 + */ + +#include "misc.h" +#include "player.h" +#include "var.h" +#include "xy.h" +#include "sect.h" +#include "nsc.h" +#include "nat.h" +#include "item.h" +#include "file.h" +#include "commands.h" + +int +wipe(void) +{ + struct sctstr sect; + struct nstr_sect nstr; + int vec[I_MAX+1]; + + if (!snxtsct(&nstr, player->argp[1])) + return RET_SYN; + bzero((s_char *)vec, sizeof(vec)); + while (nxtsct(&nstr, §)) { + if (!player->owner) + continue; + putvec(VT_DIST, vec, (s_char *)§, EF_SECTOR); + pr("Distribution thresholds wiped from %s\n", + xyas(nstr.x, nstr.y, player->cnum)); + putsect(§); + } + return RET_OK; +} diff --git a/src/lib/commands/work.c b/src/lib/commands/work.c new file mode 100644 index 00000000..89212fc1 --- /dev/null +++ b/src/lib/commands/work.c @@ -0,0 +1,190 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * work.c: Implementation of the work command + * + * Known contributors to this file: + * + */ + +#include "misc.h" +#include "player.h" +#include "var.h" +#include "xy.h" +#include "sect.h" +#include "land.h" +#include "nat.h" +#include "nsc.h" +#include "deity.h" +#include "file.h" +#include "optlist.h" +#include "commands.h" + +int +work(void) +{ + int nunits; + struct nstr_item ni; + struct sctstr sect; + struct lndstr land; + int work_amt, eff_amt, w; + s_char *p; + extern int land_mob_max; + coord donex = 0, doney = 1; + s_char buf[1024]; + + if (!snxtitem(&ni, EF_LAND, player->argp[1])) + return RET_SYN; + p = getstarg(player->argp[2], "Amount: ", buf); + if (p == 0 || *p == 0) + return RET_SYN; + work_amt = atoi(p); + if ((work_amt<0) || (work_amt > land_mob_max)){ + pr("Mobility used must be from 0 to %d\n",land_mob_max); + return RET_FAIL; + } + nunits = 0; + while (nxtitem(&ni, (s_char *)&land)) { + if (!player->owner || land.lnd_own == 0) + continue; + if (land.lnd_type < 0 || land.lnd_type > lnd_maxno) { + pr("bad unit type %d (#%d)\n", + land.lnd_type, ni.cur); + continue; + } + if (!(lchr[(int)land.lnd_type].l_flags & L_ENGINEER)) + continue; + if (land.lnd_mobil <= 0){ + pr("%s has no mobility!\n", + prland(&land)); + continue; + } + getsect(land.lnd_x,land.lnd_y,§); + if (sect.sct_effic >= 100 + && sect.sct_type == sect.sct_newtype) { + if (sect.sct_x != donex || sect.sct_y != doney) + pr("%s is %d%% efficient\n", + xyas(sect.sct_x, sect.sct_y, player->cnum), + sect.sct_effic); + /* not perfect, but it'll do -KHS */ + donex = sect.sct_x; + doney = sect.sct_y; + continue; + } + eff_amt= min(land.lnd_mobil,work_amt); + w = ldround(((double)eff_amt * land.lnd_effic/600.0),1); + if (w < 1) { + pr("%s doesn't work enough to change efficiency (try increasing amount)\n", + prland(&land)); + continue; + } + nunits++; + eff_amt = ((6 * buildeff(§, w, &player->dolcost)) / + (land.lnd_effic / 100.0)); + land.lnd_mission = 0; + land.lnd_mobil -= eff_amt; + pr("%s %s efficiency at %s to %d\n", + prland(&land), + sect.sct_type == sect.sct_newtype ? "raised" : "lowered", + xyas(land.lnd_x,land.lnd_y,player->cnum), + (int)sect.sct_effic); + putland(land.lnd_uid,&land); + putsect(§); + } + if (nunits == 0) { + if (player->argp[1]) + pr("%s: No unit(s)\n", player->argp[1]); + else + pr("%s: No unit(s)\n", ""); + return RET_FAIL; + }else + pr("%d unit%s\n", nunits, splur(nunits)); + return RET_OK; +} + +int +buildeff(struct sctstr *sp, int work, double *money) +{ + int vec[I_MAX+1]; + register int work_cost; + int n, hcms, lcms; + int effdone = 0; + + getvec(VT_ITEM, vec, (s_char *)sp, EF_SECTOR); + + work_cost = 0; + if (sp->sct_type != sp->sct_newtype) { + /* + * Tear down existing sector. + * Easier to destroy than to build. + */ + work_cost = (sp->sct_effic + 3) / 4; + if (work_cost > work) + work_cost = work; + n = sp->sct_effic - work_cost * 4; + if (n <= 0) { + n = 0; + sp->sct_type = sp->sct_newtype; + } + sp->sct_effic = n; + if (!opt_DEFENSE_INFRA) + sp->sct_defense = sp->sct_effic; + work -= work_cost; + *money += work_cost; + effdone += work_cost; + } + if (sp->sct_type == sp->sct_newtype) { + work_cost = 100 - sp->sct_effic; + if (work_cost > work) + work_cost = work; + + if (dchr[sp->sct_type].d_lcms>0){ + lcms = vec[I_LCM]; + lcms /= dchr[sp->sct_type].d_lcms; + if (work_cost > lcms) + work_cost = lcms; + } + if (dchr[sp->sct_type].d_hcms>0){ + hcms = vec[I_HCM]; + hcms /= dchr[sp->sct_type].d_hcms; + if (work_cost > hcms) + work_cost = hcms; + } + + sp->sct_effic += work_cost; + *money += work_cost*dchr[sp->sct_type].d_build; + + if ((dchr[sp->sct_type].d_lcms>0) || + (dchr[sp->sct_type].d_hcms>0)){ + vec[I_LCM] -= work_cost * dchr[sp->sct_type].d_lcms; + vec[I_HCM] -= work_cost * dchr[sp->sct_type].d_hcms; + } + effdone += work_cost; + } + putvec(VT_ITEM, vec, (s_char *)sp, EF_SECTOR); + return effdone; +} diff --git a/src/lib/commands/zdon.c b/src/lib/commands/zdon.c new file mode 100644 index 00000000..27af2a9d --- /dev/null +++ b/src/lib/commands/zdon.c @@ -0,0 +1,145 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * zdon.c: Update right now + * + * Known contributors to this file: + * Doug Hay, 1990 + */ + +/* + * Syntax: + * Normal player: zdone [Y|N|C] + * Deity : zdone [country_num [Y|N|C]] + * + * Where: + * Y = Yes, wants an update. + * N = No, change status to not wanting an update. + * C = Check (the default), check how many want an update. + * + * Sets/Unsets a nation flag. + * + * Only considers NORMAL, active countries. No Deities or sanctuaries. + * + * After the change, send a message to the "tm" for it to check + * if an update should occur. + */ + +#include +#include "misc.h" +#include "player.h" +#include "nat.h" +#include "file.h" +#include "deity.h" +#include "empthread.h" +#include "commands.h" +#include "optlist.h" + +int +zdon(void) +{ + extern empth_sem_t *update_sem; + natid whichcnum; + struct natstr *natp; + register s_char *p; + + int update; + int checking; + int wantupd; + int totpop; + int totwant; + int dowant; + s_char buf[1024]; + + if (!opt_DEMANDUPDATE) { + pr("Demand updates are not enabled.\n"); + return RET_FAIL; + } + whichcnum = player->cnum; + p = NULL; + if (player->god) { + /* Deity syntax "country what" */ + whichcnum = onearg(player->argp[1], "Which country no.? "); + if ((whichcnum > 0) && (getnatp(whichcnum))) + p = getstarg(player->argp[2], "Want update? [Yes|No|Check] ", buf); + } else { + p = getstarg(player->argp[1], "Want update? [Yes|No|Check] ", buf); + } + if (player->aborted) + return RET_FAIL; + + if (!p) { + /* Default response is checking only */ + checking = 1; + } else { + checking = 0; + if (*p == 'n' || *p == 'N') { + wantupd = 0; + } else if (*p == 'y' || *p == 'Y') { + wantupd = 1; + } else { + /* Default response is checking only */ + checking = 1; + } + } + + if (!checking) { + if (!(natp = getnatp(whichcnum))) { + pr("Unable to find country. %d\n", whichcnum); + pr("Notify the Deity.\n"); + return RET_FAIL; + } + if (wantupd) { + update = natp->nat_update | WUPD_WANT; + natp->nat_missed = 0; + pr("You (%d) now want an update.\n", + whichcnum); + } else { + update = natp->nat_update & ~WUPD_WANT; + pr("You (%d) now DON'T want an update.\n", + whichcnum); + } + natp->nat_update = update; + putnat(natp); + } + + dowant = demand_update_want(&totwant, &totpop, whichcnum); + if (checking) { + if (dowant) { + pr("You want an update.\n"); + } else + pr("You DON'T want an update, yet.\n"); + } + + pr("%d of a total of %d lunatics want an update.\n", totwant, totpop); + + if (!checking && wantupd && demandupdatecheck()) { + pr("Here goes...\n"); + empth_sem_signal(update_sem); + } + return RET_OK; +} diff --git a/src/lib/common/Makefile b/src/lib/common/Makefile new file mode 100644 index 00000000..785b9f0f --- /dev/null +++ b/src/lib/common/Makefile @@ -0,0 +1,67 @@ +# +# Empire - A multi-player, client/server Internet based war game. +# Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, +# Ken Stevens, Steve McClure +# +# 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 2 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, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# --- +# +# See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the +# related information and legal notices. It is expected that any future +# projects/authors will amend these files as needed. +# +# Makefile - Wolfpack, 1996 + +# Note that these could have been listed 1 per line, but I chose to just +# stick them all together this way to shorten the file. + +include ../../../build.conf +include ../../make.src +include ../../make.defs + +LIB = $(SRCDIR)/lib/libcommon.a +NTLIB = $(SRCDIR)\lib\libcommon.lib + +OBJS = bestpath.o bridgefall.o check.o damage.o file.o fsize.o getvar.o \ + hap_fact.o hours.o keyword.o land.o log.o mailbox.o maps.o move.o \ + nat.o nstr_subs.o path.o res_pop.o sectdamage.o snxtit_subs.o \ + snxtsct_subs.o stmtch.o tfact.o type.o vlist.o wantupd.o xy.o + +NTOBJS = bestpath.obj bridgefall.obj check.obj damage.obj file.obj fsize.obj \ + getvar.obj hap_fact.obj hours.obj keyword.obj land.obj log.obj \ + mailbox.obj maps.obj move.obj nat.obj nstr_subs.obj path.obj res_pop.obj \ + sectdamage.obj snxtit_subs.obj snxtsct_subs.obj stmtch.obj tfact.obj \ + type.obj vlist.obj wantupd.obj xy.obj + +all: $(LIB) + +nt: $(NTLIB) + +$(NTLIB): $(NTOBJS) + -del /q $@ + lib /OUT:$@ /DEBUGTYPE:CV $(NTOBJS) + +$(LIB): $(OBJS) + rm -f $(LIB) + ar cq $(LIB) $(OBJS) + $(RANLIB) $(LIB) + +clean: + -(rm -f $(OBJS)) + -(del /q $(NTOBJS)) + +include ../../make.rules +include Makedepend diff --git a/src/lib/common/bestpath.c b/src/lib/common/bestpath.c new file mode 100644 index 00000000..9d4b039a --- /dev/null +++ b/src/lib/common/bestpath.c @@ -0,0 +1,322 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * bestpath.c: Find the best path between sectors + * + * Known contributors to this file: + * Steve McClure, 1998-2000 + */ + +/* + * IMPORTANT: These routines are very selectively used in the server. + * + * "bestpath" is now obsolete (and removed) + * "bestownedpath" is only used to determine paths for ships and planes. + * + * Callers should not be calling these directly anymore. They should use + * the "BestShipPath", "BestAirPath", "BestLandPath" and "BestDistPath" + * functions. Note that those last two use the A* algorithms to find + * information. + */ + +#include "gamesdef.h" +#include "misc.h" +#include "xy.h" +#include "var.h" +#include "sect.h" +#include "file.h" +#include "nat.h" +#include "common.h" +#include "optlist.h" + +static int owned_and_navigable(s_char * , int , int , s_char * , int ); + +#define MAXROUTE 100 /* return '?' if path longer than this */ +#define valid(x,y) (((x^y)&1)==0) + +/* ________________________________________________________________ +** +** bestpath(x1,y1,x2,y2,(s_char *)terrain); +** +** Calculate routing string to get from sector [x1,y1] to sector [x2,y2] +** via a specified type of terrain. +** +** Specify: +** +** x1,y1 starting coordinates +** +** x2,y2 destination coordinates +** +** terrain ptr to string showing the types of sectors that +** we're allowed to pass through: +** +** A null string enables routing through any kind of +** sector (useful for airplanes). +** +** A string that begins with an 'R' ensures that +** the source and destination sectors also match +** the specified type of terrain. +** +** A string that begins with a '~' (after the 'R', +** if necessary) specifies that we can pass through +** any kind of sector EXCEPT those in the remainder +** of the string. +** +** Examples: +** +** "R~.^" all sectors along route must be +** non-ocean, non-mountain +** +** "+" all sectors between start and end +** must be highway +** +** "h. " all sectors along route must be +** harbor, water, or unmapped +** +** 'bestpath' returns a pointer to a route string containing either: +** +** yugjbn - string of normal routing characters if route possible +** ? - if route is longer than MAXROUTE characters +** \0 - (null string) if no route possible +** h - if start and end points are the same sector +** ________________________________________________________________ +*/ + +s_char *dirchar = "juygbn"; +int dx[6] = { 2, 1,-1,-2,-1, 1 }; +int dy[6] = { 0,-1,-1, 0, 1, 1 }; +int tmp; + +/* + * Ok, note that here we malloc some buffers. BUT, we never + * free them. Why, you may ask? Because we want to allocate + * them based on world size which is now (or soon to be) dynamic, + * but we don't want to allocate each and every time, since that + * would be slow. And, since world size only changes at init + * time, we can do this safely. + * We also share these buffers between "bestpath" and "bestownedpath" + * since you can never be in both functions at the same time. If that + * did happen, we'd already be so broken that it won't matter. + */ +static unsigned int *mapbuf = (unsigned int *)0; +static unsigned int **mapindex = (unsigned int **)0; + +s_char *bestownedpath(s_char *bpath, + s_char *bigmap, + int x, + int y, + int ex, + int ey, + s_char *terrain, + int own) +{ + int i, j, tx, ty, markedsectors, restr2; + int minx, maxx, miny, maxy, scanx, scany; + unsigned int routelen; + + if (!mapbuf) + mapbuf = (unsigned int *)malloc((WORLD_X * WORLD_Y) * + sizeof(unsigned int)); + if (!mapbuf) + return ((s_char *)0); + if (!mapindex) { + mapindex = (unsigned int **)malloc(WORLD_X * sizeof(unsigned int *)); + if (mapindex) { + /* Setup the map pointers */ + for (i = 0; i < WORLD_X; i++) + mapindex[i] = &mapbuf[WORLD_Y * i]; + } + } + if (!mapindex) + return ((s_char *)0); + + bpath[0] = 0; + if (0 != (restr2 = (*terrain == 'R'))) + terrain++; + + x = XNORM(x); + y = YNORM(y); + ex = XNORM(ex); + ey = YNORM(ey); + + if (x == ex && y == ey) { + bpath[0] = 'h'; + bpath[1] = 0; + return ((s_char *)bpath); + } + + if (!valid(x,y) || !valid(ex,ey)) + return((s_char *)0); + + if (restr2 && (!owned_and_navigable(bigmap, x, y, terrain, own) || + !owned_and_navigable(bigmap, x, y, terrain, own))) + return ((s_char *)0); + + for (i = 0; i < WORLD_X; i++) + for (j = 0; j < WORLD_Y; j++) + mapindex[i][j] = 0xFFFF; /* clear the workspace */ + + routelen = 0; /* path length is now 0 */ + mapindex[x][y] = 0; /* mark starting spot */ + markedsectors = 1; /* source sector marked */ + minx = x - 2; /* set X scan bounds */ + maxx = x + 2; + miny = y - 1; /* set Y scan bounds */ + maxy = y + 1; + + do { + if (++routelen == MAXROUTE) { + bpath[0] = '?'; + bpath[1] = 0; + return ((s_char *)bpath); + } + markedsectors = 0; + for (scanx = minx; scanx <= maxx; scanx++) { + x = XNORM(scanx); + for (scany = miny; scany <= maxy; scany++) { + y = YNORM(scany); + if (valid(x,y)) { + if ((((mapindex[x][y]) & 0x1FFF) == (routelen - 1))) { + for (i = 0; i < 6; i++) { + tx = x + dx[i]; + ty = y + dy[i]; + tx = XNORM(tx); + ty = YNORM(ty); + if (mapindex[tx][ty] == 0xFFFF) { + if (owned_and_navigable(bigmap, tx, ty, terrain, own) || + (tx == ex && ty == ey && !restr2) ) { + mapindex[tx][ty] = ((i + 1) << 13) + routelen; + markedsectors++; + } + } + if (tx == ex && ty == ey) { + bpath[routelen] = 0; + while (routelen--) { + i = ((mapindex[tx][ty]) >> 13) - 1; + bpath[routelen] = dirchar[i]; + tx = tx - dx[i]; + ty = ty - dy[i]; + tx = XNORM(tx); + ty = YNORM(ty); + } + return((s_char *)bpath); + } + } + } + } + } + } + miny--; + maxy++; + minx -= 2; + maxx += 2; + } while (markedsectors); + + bpath[0] = 0; + return((s_char *)0); /* no route possible */ +} + +/* return TRUE if sector is passable */ +static int +owned_and_navigable(s_char *map, int x, int y, s_char *terrain, int own) +{ + s_char c; + s_char *t; + s_char mapspot; /* What this spot on the bmap is */ + int negate; + struct sctstr *sect; + int rel; + + /* No terrain to check? Everything is navigable! (this + probably means we are flying) */ + if (!(*terrain)) + return (1); + + /* Are we checking this map? */ + if (map) { + /* Do we know what this sector is? If not, we assume it's ok, + since otherwise we'll never venture anywhere */ + mapspot = map[sctoff(x, y)]; + if (mapspot == ' ' || mapspot == 0) + return (1); + + /* Now, is it marked with a 'x' or 'X'? If so, avoid it! */ + if (mapspot == 'x' || mapspot == 'X') + return (0); + } else { + /* We don't know what it is since we have no map, so return ok! */ + return (1); + } + + /* Now, check this bmap entry to see if it is one of the + terrain types. */ + t = terrain; + if (*t == '~') { + negate = 1; + t++; + } else + negate = 0; + + while (*t) { + if (*t == mapspot) + break; + t++; + } + if (negate && *t) { + /* We found it, so we say it's bad since we are negating */ + return (0); + } else if (!negate && !*t) { + /* We didn't find it, so we say it's bad since we aren't negating */ + return (0); + } + + /* According to our bmap, this sector is ok so far. */ + + /* Ok, we made it this far. Now get the sector */ + sect = getsectp(x, y); + c = dchr[sect->sct_type].d_mnem; + /* Ok, now, check the owner if needed */ + if (own >= 0) { + if (sect->sct_own != own) { + rel = getrel(getnatp(sect->sct_own), own); + /* We can't sail through deity sectors, but we can sail + through any ocean */ + if (rel < FRIENDLY && sect->sct_type != SCT_WATER) + return (0); + } + } + /* Ok, now, check these two sector types */ + /* check for bad harbors. */ + if (c == 'h' && sect->sct_effic < 2) + return (0); + /* check for bad bridges */ + if (c == '=' && sect->sct_effic < 60) + return (0); + /* Woo-hoo, it's ok! */ + return (1); +} + diff --git a/src/lib/common/bridgefall.c b/src/lib/common/bridgefall.c new file mode 100644 index 00000000..f9c16511 --- /dev/null +++ b/src/lib/common/bridgefall.c @@ -0,0 +1,167 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * bridgefall.c: Knock a bridge down + * + * Known contributors to this file: + * Steve McClure, 1998 + */ + +#include "misc.h" +#include "var.h" +#include "sect.h" +#include "path.h" +#include "file.h" +#include "xy.h" +#include "plane.h" +#include "land.h" +#include "nsc.h" +#include "common.h" +#include "subs.h" +#include "lost.h" +#include "optlist.h" + +void +bridgefall(struct sctstr *sp, struct emp_qelem *list) +{ + register int i; + register int j; + struct sctstr sect; + struct sctstr bh_sect; + int nx; + int ny; + int nnx; + int nny; + + for (i = 1; i <= 6; i++) { + nx = sp->sct_x + diroff[i][0]; + ny = sp->sct_y + diroff[i][1]; + getsect(nx, ny, §); + if (sect.sct_type != SCT_BSPAN) + continue; + for (j = 1; j <= 6; j++) { + nnx = nx + diroff[j][0]; + nny = ny + diroff[j][1]; + if (nnx == sp->sct_x && nny == sp->sct_y) + continue; + getsect(nnx, nny, &bh_sect); + if (bh_sect.sct_type == SCT_BHEAD && + bh_sect.sct_newtype == SCT_BHEAD) + break; + if (bh_sect.sct_type == SCT_BTOWER) + break; + /* With EASY_BRIDGES, it just has to be next to any + land */ + if (opt_EASY_BRIDGES) { + if (bh_sect.sct_type != SCT_WATER && + bh_sect.sct_type != SCT_BSPAN) + break; + } + } + if (j > 6) { + knockdown(§, list); + putsect(§); + } + } +} + +/* Knock down a bridge span. Note that this does NOT write the + * sector out to the database, it's up to the caller to do that. */ +void +knockdown(struct sctstr *sp, struct emp_qelem *list) +{ + struct lndstr land; + struct plnstr plane; + struct nstr_item ni; + int mines; + struct natstr *np; + + if (sp->sct_type == SCT_BTOWER) + mpr(sp->sct_own, "Crumble... SCREEEECH! Splash! Bridge tower falls at %s!\n", + xyas(sp->sct_x, sp->sct_y, sp->sct_own)); + else + mpr(sp->sct_own, "Crumble... SCREEEECH! Splash! Bridge falls at %s!\n", + xyas(sp->sct_x, sp->sct_y, sp->sct_own)); + sp->sct_type = SCT_WATER; + sp->sct_newtype = SCT_WATER; + makelost(EF_SECTOR, sp->sct_own, 0, sp->sct_x, sp->sct_y); + sp->sct_own = 0; + sp->sct_oldown = 0; + sp->sct_mobil = 0; + sp->sct_effic = 0; + + /* Sink all the units */ + snxtitem_xy(&ni,EF_LAND,sp->sct_x,sp->sct_y); + while (nxtitem(&ni, (s_char *)&land)){ + if (land.lnd_own == 0) + continue; + if(land.lnd_x != sp->sct_x || land.lnd_y != sp->sct_y) + continue; + if (land.lnd_ship >= 0) + continue; + np = getnatp(land.lnd_own); + if (np->nat_flags & NF_BEEP) + mpr(land.lnd_own, "\07"); + mpr(land.lnd_own, " AARGH! %s tumbles to its doom!\n", prland(&land)); + makelost(EF_LAND, land.lnd_own, land.lnd_uid, land.lnd_x, land.lnd_y); + land.lnd_own = 0; + land.lnd_effic = 0; + putland(land.lnd_uid, &land); + } + /* Sink all the planes */ + snxtitem_xy(&ni,EF_PLANE,sp->sct_x,sp->sct_y); + while (nxtitem(&ni, (s_char *)&plane)){ + if (plane.pln_own == 0) + continue; + if(plane.pln_x != sp->sct_x || plane.pln_y != sp->sct_y) + continue; + if (plane.pln_flags & PLN_LAUNCHED) + continue; + if (plane.pln_ship >= 0) + continue; + /* Is this plane flying in this list? */ + if (ac_isflying(&plane, list)) + continue; + np = getnatp(plane.pln_own); + if (np->nat_flags & NF_BEEP) + mpr(plane.pln_own, "\07"); + mpr(plane.pln_own, " AARGH! %s tumbles to its doom!\n", prplane(&plane)); + makelost(EF_PLANE, plane.pln_own, plane.pln_uid, plane.pln_x, plane.pln_y); + plane.pln_own = 0; + plane.pln_effic = 0; + putplane(plane.pln_uid, &plane); + } + /* + * save only the mines; zero the rest of the + * commodities. + */ + mines = getvar(V_MINE, (caddr_t)sp, EF_SECTOR); + sp->sct_nv = 0; + if (mines > 0) + (void) putvar(V_MINE, mines, (caddr_t)sp, EF_SECTOR); +} + diff --git a/src/lib/common/check.c b/src/lib/common/check.c new file mode 100644 index 00000000..9e7a6402 --- /dev/null +++ b/src/lib/common/check.c @@ -0,0 +1,165 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * check.c: Check a sector, plane, land unit, ship or nuke + * + * Known contributors to this file: + * Steve McClure, 1998 + */ + +#include "misc.h" +#include "player.h" +#include "xy.h" +#include "file.h" +#include "var.h" +#include "sect.h" +#include "ship.h" +#include "plane.h" +#include "nuke.h" +#include "land.h" +#include "item.h" +#include "nsc.h" +#include "nat.h" +#include "commodity.h" +#include "loan.h" +#include "optlist.h" +#include "commands.h" +#include "trade.h" + +/* Note that timestamps make things tricky. And, we don't + * really care about the timestamp, we just care about the rest + * of the structure. So, we make a copy, and zero the timestamps + * in both copies, and then compare. */ + +int +check_sect_ok(struct sctstr *sectp) +{ + struct sctstr chksect; + struct sctstr tsect; + + getsect(sectp->sct_x, sectp->sct_y, &chksect); + memcpy(&tsect, sectp, sizeof(struct sctstr)); + tsect.sct_timestamp = chksect.sct_timestamp = 0; + if (memcmp(&tsect, &chksect, sizeof(struct sctstr))) { + pr("Sector %s has changed!\n", + xyas(sectp->sct_x, sectp->sct_y, player->cnum)); + return 0; + } + return 1; +} + +int +check_ship_ok(struct shpstr *shipp) +{ + struct shpstr chkship; + struct shpstr tship; + + getship(shipp->shp_uid, &chkship); + memcpy(&tship, shipp, sizeof(struct shpstr)); + tship.shp_timestamp = chkship.shp_timestamp = 0; + if (memcmp(&tship, &chkship, sizeof(struct shpstr))) { + pr("Ship #%d has changed!\n", shipp->shp_uid); + return 0; + } + return 1; +} + +int +check_plane_ok(struct plnstr *planep) +{ + struct plnstr chkplane; + struct plnstr tplane; + + getplane(planep->pln_uid, &chkplane); + memcpy(&tplane, planep, sizeof(struct plnstr)); + tplane.pln_timestamp = chkplane.pln_timestamp = 0; + if (memcmp(&tplane, &chkplane, sizeof(struct plnstr))) { + pr("Plane #%d has changed!\n", planep->pln_uid); + return 0; + } + return 1; +} + +int +check_land_ok(struct lndstr *landp) +{ + struct lndstr chkland; + struct lndstr tland; + + getland(landp->lnd_uid, &chkland); + memcpy(&tland, landp, sizeof(struct lndstr)); + tland.lnd_timestamp = chkland.lnd_timestamp = 0; + if (memcmp(&tland, &chkland, sizeof(struct lndstr))) { + pr("Land unit #%d has changed!\n", landp->lnd_uid); + return 0; + } + return 1; +} + +int +check_nuke_ok(struct nukstr *nukep) +{ + struct nukstr chknuke; + struct nukstr tnuke; + + getnuke(nukep->nuk_uid, &chknuke); + memcpy(&tnuke, nukep, sizeof(struct nukstr)); + tnuke.nuk_timestamp = chknuke.nuk_timestamp = 0; + if (memcmp(&tnuke, &chknuke, sizeof(struct nukstr))) { + pr("Nuclear stockpile %d has changed!\n", nukep->nuk_uid); + return 0; + } + return 1; +} + +int +check_loan_ok(struct lonstr *loanp) +{ + struct lonstr chkloan; + + getloan(loanp->l_uid, &chkloan); + if (memcmp(loanp, &chkloan, sizeof(struct lonstr))) { + pr("Loan %d has changed!\n", loanp->l_uid); + return 0; + } + return 1; +} + +int +check_comm_ok(struct comstr *commp) +{ + struct comstr chkcomm; + + getcomm(commp->com_uid, &chkcomm); + if (memcmp(commp, &chkcomm, sizeof(struct comstr))) { + pr("Commodity %d has changed!\n", commp->com_uid); + return 0; + } + return 1; +} + + diff --git a/src/lib/common/damage.c b/src/lib/common/damage.c new file mode 100644 index 00000000..0705f9e2 --- /dev/null +++ b/src/lib/common/damage.c @@ -0,0 +1,199 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * damage.c: Damage stuff. + * + * Known contributors to this file: + * Dave Pare, 1989 + * Steve McClure, 1997 + */ + +#include "misc.h" +#include "var.h" +#include "sect.h" +#include "ship.h" +#include "land.h" +#include "plane.h" +#include "nuke.h" +#include "xy.h" +#include "nsc.h" +#include +#include "file.h" +#include "optlist.h" +#include "damage.h" +#include "common.h" +#include "gen.h" +#include "subs.h" + +void +ship_damage(struct shpstr *sp, int dam) +{ + + if (dam <= 0) + return; + if (dam > 100) + dam = 100; + + mpr(sp->shp_own, "\t%s takes %d\n", prship(sp), dam); + + sp->shp_effic = damage((int)sp->shp_effic, dam); + if (sp->shp_mobil > 0) + sp->shp_mobil = damage((int)sp->shp_mobil, dam); + if (opt_FUEL && sp->shp_fuel) + sp->shp_fuel = damage((int)sp->shp_fuel, dam); + sp->shp_nv = vl_damage(dam, sp->shp_vtype, sp->shp_vamt, + (int) sp->shp_nv); +} + +void +shipdamage(struct shpstr *sp, int dam) +{ + ship_damage(sp, (int)( dam/(1.0 + sp->shp_armor / 100.0))); +} + +void +land_damage(struct lndstr *lp, int dam) +{ + if (dam <= 0) + return; + if (dam > 100) + dam = 100; + + mpr(lp->lnd_own, "\t%s takes %d\n", prland(lp), dam); + if (lchr[(int)lp->lnd_type].l_flags & L_SPY) { + /* Spies die! */ + lp->lnd_effic = 0; + } else { + lp->lnd_effic = damage((int)lp->lnd_effic, dam); + if (lp->lnd_mobil > 0) + lp->lnd_mobil = damage((int)lp->lnd_mobil, dam); + if (opt_FUEL && lp->lnd_fuel) + lp->lnd_fuel = damage((int)lp->lnd_fuel, dam); + lp->lnd_nv = vl_damage(dam, lp->lnd_vtype, lp->lnd_vamt, + (int) lp->lnd_nv); + } +} + +void +landdamage(struct lndstr *lp, int dam) +{ + double damage_factor, m; + extern int land_mob_max; + + m = (double)land_mob_max; + + /* fortification reduces damage */ + damage_factor = m / (m+((double)lp->lnd_harden)); + if (damage_factor == 0.0) + damage_factor = 1.0; + + /* vulnerable units take more damage */ + damage_factor *= lp->lnd_vul / 100.0; + + land_damage(lp, ldround(damage_factor * dam,1)); +} + +void +planedamage(struct plnstr *pp, int dam) +{ + if (dam <= 0) + return; + if (dam > 100) + dam = 100; + + mpr(pp->pln_own, "\t%s takes %d\n", prplane(pp), dam); + pp->pln_effic = damage((int)pp->pln_effic, dam); + if (pp->pln_mobil > 0) + pp->pln_mobil = damage((int)pp->pln_mobil, dam); +} + +/* + * nukedamage() actually just calculates damage + * rather than inflicting it. + */ +int +nukedamage(struct nchrstr *ncp, int range, int airburst) +{ + int dam; + int rad; + + rad = ncp->n_blast; + if (airburst) + rad = (int) (rad * 1.5); + if (rad < range) + return 0; + if (airburst) { + /* larger area, less center damage */ + dam = (int) ((ncp->n_dam * 0.75) - (range * 20)); + } else { + /* smaller area, more center damage */ + dam = (int) (ncp->n_dam / (range + 1.0)); + } + if (dam < 5) + dam = 0; + return dam; +} + +int +damage(register int amt, int pct) +{ + register int tmp; + register int lost; + + if (amt <= 0) + return 0; + tmp = amt * pct; + lost = tmp / 100; + if ((random() % 100) < (tmp % 100)) + lost++; + return amt - lost; +} + +/* asymptotic damage to commodities, efficiency, and sectors */ +int +effdamage(register int amt, int dam) +{ + return damage(amt, PERCENT_DAMAGE(dam)); +} + +int +commdamage(register int amt, int dam, int vtype) +{ + extern double people_damage; + int lost; + + if (vtype == V_BAR && opt_SUPER_BARS) + return amt; + + lost = amt - effdamage(amt, dam); + + if (vtype == V_MILIT || + vtype == V_CIVIL || + vtype == V_UW) + lost = ldround(people_damage * lost, 1); + return amt - lost; +} diff --git a/src/lib/common/file.c b/src/lib/common/file.c new file mode 100644 index 00000000..1b24ac41 --- /dev/null +++ b/src/lib/common/file.c @@ -0,0 +1,494 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * file.c: Misc. operations on files + * + * Known contributors to this file: + * Dave Pare, 1989 + * Steve McClure, 2000 + */ + +#ifdef Rel4 +#include +#endif /* Rel4 */ +#include +#include +#include +#if !defined(_WIN32) +#include +#endif +#include "misc.h" +#include "xy.h" +#include "nsc.h" +#include "file.h" +#include "match.h" +#include "struct.h" +#include "common.h" +#include "gen.h" + +#ifdef Rel4 +#include +#endif + +static void fillcache(struct empfile *ep, int start); + +int +ef_open(int type, int mode, int how) +{ + register struct empfile *ep; + static int block; + int size; + +#if defined(_WIN32) + mode |= _O_BINARY; +#endif + if (ef_check(type) < 0) + return 0; + ep = &empfile[type]; + if ((ep->fd = open(ep->file, mode, 0660)) < 0) { + logerror("%s: open failed", ep->file); + return 0; + } + if (block == 0) + block = blksize(ep->fd); + ep->baseid = 0; + ep->cids = 0; + ep->mode = mode; + ep->flags |= how; + ep->fids = fsize(ep->fd) / ep->size; + if (ep->flags & EFF_MEM) + ep->csize = ep->fids; + else + ep->csize = block / ep->size; + size = ep->csize * ep->size; + ep->cache = (s_char *)malloc(size); + if ((ep->cache == 0) && (size !=0)) { + logerror("ef_open: %s malloc(%d) failed\n", ep->file, size); + return 0; + } + if (ep->flags & EFF_MEM) { + if (read(ep->fd, ep->cache, size) != size) { + logerror("ef_open: read(%s) failed\n", ep->file); + return 0; + } + ep->cids = size / ep->size; + } + return 1; +} + +int +ef_close(int type) +{ + register struct empfile *ep; + int r; + + if (ef_check(type) < 0) + return 0; + ep = &empfile[type]; + if (ep->cache == 0) { + /* no cache implies never opened */ + return 0; + } + ef_flush(type); + ep->flags &= ~EFF_MEM; + free(ep->cache); + ep->cache = 0; + if ((r = close(ep->fd)) < 0) { + logerror("ef_close: %s close(%d) -> %d", + ep->name, ep->fd, r); + } + return 1; +} + +int +ef_flush(int type) +{ + register struct empfile *ep; + int size; + int r; + + if (ef_check(type) < 0) + return 0; + ep = &empfile[type]; + if (ep->cache == 0) { + /* no cache implies never opened */ + return 0; + } + size = ep->csize * ep->size; + if (ep->mode > 0 && (ep->flags & EFF_MEM)) { + if ((r = lseek(ep->fd, 0L, 0)) < 0) { + logerror("ef_flush: %s cache lseek(%d, 0L, 0) -> %d", + ep->name, ep->fd, r); + return 0; + } + if (write(ep->fd, ep->cache, size) != size) { + logerror("ef_flush: %s cache write(%d, %x, %d) -> %d", + ep->name, ep->fd, ep->cache, ep->size, r); + return 0; + } + } + /*ef_zapcache(type);*/ + return 1; +} + +s_char * +ef_ptr(int type, int id) +{ + register struct empfile *ep; + + if (ef_check(type) < 0) + return 0; + ep = &empfile[type]; + if (id < 0 || id >= ep->fids) + return 0; + if ((ep->flags & EFF_MEM) == 0) { + logerror("ef_ptr: (%s) only valid for EFF_MEM entries", + ep->file); + return 0; + } + return (s_char *) (ep->cache + ep->size * id); +} + +/* + * buffered read. Tries to read a large number of items. + * This system won't work if item size is > sizeof buffer area. + */ +int +ef_read(int type, int id, caddr_t ptr) +{ + register struct empfile *ep; + caddr_t from; + + if (ef_check(type) < 0) + return 0; + ep = &empfile[type]; + if (id < 0) + return 0; + if (ep->flags & EFF_MEM) { + if (id >= ep->fids) + return 0; + from = ep->cache + (id * ep->size); + } else { + if (id >= ep->fids) { + ep->fids = fsize(ep->fd) / ep->size; + if (id >= ep->fids) + return 0; + } + if (ep->baseid + ep->cids <= id || ep->baseid > id) + fillcache(ep, id); + from = ep->cache + (id - ep->baseid) * ep->size; + } + bcopy(from, ptr, ep->size); + + if (ep->postread) + ep->postread(id, ptr); + return 1; +} + +static void +fillcache(struct empfile *ep, int start) +{ + int n; + + ep->baseid = start; + lseek(ep->fd, start * ep->size, 0); + n = read(ep->fd, ep->cache, ep->csize * ep->size); + ep->cids = n / ep->size; +} + +#ifdef notdef +/* + * no-buffered read + * zaps read cache + */ +int +ef_nbread(int type, int id, caddr_t ptr) +{ + register struct empfile *ep; + int r; + + if (ef_check(type) < 0) + return 0; + ep = &empfile[type]; + if (id < 0) + return 0; + if (id >= ep->fids) { + ep->fids = fsize(ep->fd) / ep->size; + if (id >= ep->fids) + return 0; + } + if ((r = lseek(ep->fd, id * ep->size, 0)) < 0) { + logerror("ef_nbread: %s #%d lseek(%d, %d, 0) -> %d", + ep->name, id, ep->fd, id * ep->size, r); + return 0; + } + if ((r = read(ep->fd, ptr, ep->size)) != ep->size) { + logerror("ef_nbread: %s #%d read(%d, %x, %d) -> %d", + ep->name, id, ep->fd, ptr, ep->size, r); + return 0; + } + ef_zapcache(type); + if (ep->postread) + ep->postread(id, ptr); + return 1; +} +#endif + +/* + * buffered write. Modifies read cache (if applicable) + * and writes through to disk. + */ +int +ef_write(int type, int id, caddr_t ptr) +{ + register int r; + register struct empfile *ep; + s_char *to; + + if (ef_check(type) < 0) + return 0; + ep = &empfile[type]; + if (id > 65536) { + /* largest unit id; this may bite us in large games */ + logerror("ef_write: type %d id %d is too large!\n", type, id); + return 0; + } + if ((r = lseek(ep->fd, id * ep->size, 0)) < 0) { + logerror("ef_write: %s #%d lseek(%d, %d, 0) -> %d", + ep->name, id, ep->fd, id * ep->size, r); + return 0; + } + if (ep->prewrite) + ep->prewrite(id, ptr); + if ((r = write(ep->fd, ptr, ep->size)) != ep->size) { + logerror("ef_write: %s #%d write(%d, %x, %d) -> %d", + ep->name, id, ep->fd, ptr, ep->size, r); + return 0; + } + if (id >= ep->baseid && id < ep->baseid + ep->cids) { + /* update the cache if necessary */ + to = ep->cache + (id - ep->baseid) * ep->size; + bcopy(ptr, to, ep->size); + } + if (id > ep->fids) { + logerror("WARNING ef_write: expanded %s by more than one id", + ep->name); + log_last_commands(); + } + if (id >= ep->fids) { + if (ep->flags & EFF_MEM) { + logerror("file %s went beyond %d items; won't be able toread item w/o restart", ep->name, ep->fids); + } else { + /* write expanded file; ep->fids = last id + 1 */ + ep->fids = id + 1; + } + } + return 1; +} + +#ifdef notdef +/* + * no-buffered write + * zaps read cache + */ +int +ef_nbwrite(int type, int id, caddr_t ptr) +{ + register struct empfile *ep; + register int r; + + if (ef_check(type) < 0) + return 0; + ep = &empfile[type]; + if (id > 65536) { + /* largest unit id; this may bite us in large games */ + logerror("ef_nbwrite: %s id %d is too large!\n", ep->name, id); + return 0; + } + if ((r = lseek(ep->fd, id * ep->size, 0)) < 0) { + logerror("ef_nbwrite: %s #%d lseek(%d, %d, 0) -> %d", + ep->name, id, ep->fd, id * ep->size, r); + return 0; + } + if (ep->prewrite) + ep->prewrite(id, ptr); + if ((r = write(ep->fd, ptr, ep->size)) != ep->size) { + logerror("ef_nbwrite: %s #%d write(%d, %x, %d) -> %d", + ep->name, id, ep->fd, ptr, ep->size, r); + return 0; + } + ef_zapcache(type); + if (id >= ep->fids) { + /* write expanded file; ep->fids = last id + 1 */ + ep->fids = id + 1; + } + return 1; +} +#endif + +int +ef_extend(int type, int count) +{ + register struct empfile *ep; + char *ptr; + int cur, max; + int mode, how; + int r; + + if (ef_check(type) < 0) + return 0; + ep = &empfile[type]; + max = ep->fids + count; + cur = ep->fids; + ptr = (s_char *)calloc(1, ep->size); + if ((r = lseek(ep->fd, ep->fids * ep->size, 0)) < 0) { + logerror("ef_extend: %s +#%d lseek(%d, %d, 0) -> %d", + ep->name, count, ep->fd, ep->fids * ep->size, r); + return 0; + } + for (cur = ep->fids; cur < max; cur++) { + if (ep->init) + ep->init(cur, ptr); + if ((r = write(ep->fd, ptr, ep->size)) != ep->size) { + logerror("ef_extend: %s +#%d write(%d, %x, %d) -> %d", + ep->name, count, ep->fd, ptr, ep->size, r); + return 0; + } + } + free(ptr); + if (ep->flags & EFF_MEM) { + /* XXX this will cause problems if there are ef_ptrs (to the + * old allocated structure) active when we do the re-open */ + mode = ep->mode; + how = ep->flags; + ef_close(type); + ef_open(type, mode, how); + } else { + ep->fids += count; + } + return 1; +} + +void +ef_zapcache(int type) +{ + register struct empfile *ep = &empfile[type]; + if ((ep->flags & EFF_MEM) == 0) { + ep->cids = 0; + ep->baseid = -1; + } +} + +struct castr * +ef_cadef(int type) +{ + return empfile[type].cadef; +} + +int +ef_nelem(int type) +{ + return empfile[type].fids; +} + +int +ef_flags(int type) +{ + return empfile[type].flags; +} + +int +ef_lock(int type) +{ + return file_lock(empfile[type].fd); +} + +int +ef_unlock(int type) +{ + return file_unlock(empfile[type].fd); +} + +time_t +ef_mtime(int type) +{ + extern time_t fdate(int fd); + + if (empfile[type].fd <= 0) + return 0; + return fdate(empfile[type].fd); +} + +int +ef_vars(int type, register s_char *sp, u_char **nvp, u_char **vp, u_short **ap) +{ + register struct empfile *ef; + + if (ef_check(type) < 0) + return 0; + ef = &empfile[type]; + if ((ef->flags & EFF_COM) == 0) + return -1; + *nvp = (u_char *) (sp + ef->varoffs[0]); + *vp = (u_char *) (sp + ef->varoffs[1]); + *ap = (u_short *) (sp + ef->varoffs[2]); + return ef->maxvars; +} + +int +ef_byname(s_char *name) +{ + register struct empfile *ef; + register int i; + int len; + + len = strlen(name); + for (i=0; iname, name, min(len, strlen(ef->name))) == 0) + return i; + } + return -1; +} + +s_char * +ef_nameof(int type) +{ + if (type < 0 || type >= EF_MAX) + return "bad item type"; + return empfile[type].name; +} + +int +ef_check(int type) +{ + if (type < 0 || type >= EF_MAX) { + logerror("ef_ptr: bad EF_type %d\n", type); + return -1; + } + return 0; +} diff --git a/src/lib/common/fsize.c b/src/lib/common/fsize.c new file mode 100644 index 00000000..2b6990d8 --- /dev/null +++ b/src/lib/common/fsize.c @@ -0,0 +1,92 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * fsize.c: BSD dependant file and block sizing routines + * + * Known contributors to this file: + * Dave Pare, 1986 + * Doug Hay, 1998 + * Steve McClure, 1998 + */ + +#include "misc.h" +#include "common.h" + +#include +#include +#if !defined(_WIN32) +#include +#endif + +/* + * return the size of the file in bytes. + */ +int +fsize(int fd) +{ + struct stat statb; + + if (fstat(fd, &statb) < 0) + return -1; + return statb.st_size; +} + +/* + * return the block size of the filesystem + * If it's not a filesystem, return 1024. + */ +int +blksize(int fd) +{ +#if defined(_WIN32) + return 2048; +#elif (!defined (aix) && !defined (sgi)) + struct stat statb; + + if (fstat(fd, &statb) < 0) + return 1024; + return statb.st_blksize; +#else + return 1024; +#endif +} + +time_t +fdate(int fd) +{ + struct stat statb; + + if (fstat(fd, &statb) < 0) + return 0; + return statb.st_mtime; +} + +void +filetruncate(s_char *name) +{ + close(open(name, O_RDWR|O_TRUNC, 0660)); +} diff --git a/src/lib/common/getvar.c b/src/lib/common/getvar.c new file mode 100644 index 00000000..3a5499f8 --- /dev/null +++ b/src/lib/common/getvar.c @@ -0,0 +1,118 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * getvar.c: Routines for manipulating variable lists. + * + * Known contributors to this file: + * Dave Pare, 1989 + */ + +#include "misc.h" +#include "var.h" +#include "file.h" +#include "common.h" + +int +getvar(int vtype, s_char *sp, int ptype) +{ + u_char *vtypep; + u_short *vamtp; + u_char *nvp; + int amt; + + if (ef_vars(ptype, sp, &nvp, &vtypep, &vamtp) < 0) { + logerror("getvar: ptype %d has no vars", ptype); + return 0; + } + amt = vl_find(vtype, vtypep, vamtp, (int) *nvp); + if (amt < 0) { + logerror("getvar: vl_find returns %d, vtype %d", + amt, vtype); + return 0; + } + return amt; +} + +int +getvec(int class, int *vec, s_char *sp, int ptype) +{ + u_char *vtypep; + u_short *vamtp; + u_char *nvp; + int nv; + + if (ef_vars(ptype, sp, &nvp, &vtypep, &vamtp) < 0) { + logerror("getvec: ptype %d has no vars", ptype); + return 0; + } + nv = vl_getvec(vtypep, vamtp, (int)*nvp, class, vec); + if (nv < 0) { + logerror("vl_getvec: returns %d, ptype %d\n", + nv, ptype); + return 0; + } + return nv; +} + +int +putvar(int vtype, int amt, s_char *sp, int ptype) +{ + u_char *vtypep; + u_short *vamtp; + u_char *nvp; + int maxv; + + if (vtype < 0 || vtype > V_MAX) { + logerror("putvar: bad vtype %d\n", vtype); + return 0; + } + if ((maxv = ef_vars(ptype, sp, &nvp, &vtypep, &vamtp)) < 0) { + logerror("putvar: ptype %d has no vars", ptype); + return 0; + } + if (amt < 0) + amt = 0; + return vl_set(vtype, (u_int)amt, vtypep, vamtp, nvp, maxv); +} + +int +putvec(int class, int *vec, s_char *sp, int ptype) +{ + u_char *vtypep; + u_short *vamtp; + u_char *nvp; + int maxv,x; + + if ((maxv = ef_vars(ptype, sp, &nvp, &vtypep, &vamtp)) < 0) { + logerror("putvec: ptype %d has no vars", ptype); + return 0; + } + for(x=0;x +#include +#include "misc.h" +#include "player.h" +#include "var.h" +#include "xy.h" +#include "sect.h" +#include "nat.h" +#include "news.h" +#include "nsc.h" +#include "item.h" +#include "file.h" +#include "common.h" + +double hap_fact(struct natstr *tnat, struct natstr *vnat) +{ + double hap_fact; + + hap_fact = vnat->nat_level[NAT_HLEV]; + if (hap_fact && tnat->nat_level[NAT_HLEV]) + hap_fact = tnat->nat_level[NAT_HLEV] / hap_fact; + else if (!hap_fact && !tnat->nat_level[NAT_HLEV]) + hap_fact = 1.0; + else if (tnat->nat_level[NAT_HLEV]) /* Target has happy, better fighting */ + hap_fact = 2.0; + else /* Target has no happy, worse fighting */ + hap_fact = 0.8; + if (hap_fact > 2.0) + hap_fact = 2.0; + if (hap_fact < 0.8) + hap_fact = 0.8; + return hap_fact; +} diff --git a/src/lib/common/hours.c b/src/lib/common/hours.c new file mode 100644 index 00000000..5e0819b7 --- /dev/null +++ b/src/lib/common/hours.c @@ -0,0 +1,100 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * hours.c: Game hours determination; is it legal to play now? + * + * Known contributors to this file: + * Dave Pare, 1989 + * Doug Hay, 1998 + * Steve McClure, 1998 + */ + +#include +#include "misc.h" +#include "nat.h" +#include "tel.h" +#include "proto.h" +#include "com.h" +#include "deity.h" +#include "keyword.h" +#include "file.h" +#include "common.h" + +#if defined(Rel4) || defined(_WIN32) +#include +#else +#include +#endif /* Rel4 */ + +/* + * returns true if game can be played now. + * Sets the number of minutes until the hours + * function must be re-called. + */ +int +gamehours(time_t now, int *hour) +{ + extern s_char *game_days,*game_hours; + extern int errno; + extern struct tm *localtime(const time_t *); + register s_char *bp; + register struct tm *tm; + int day; + int curtime; + int okday[7]; + int tomorrow; + + tm = localtime(&now); + curtime = tm->tm_min + tm->tm_hour * 60; + bp = game_days; + if (*bp != 0) { + for (day=0; day<7; day++) + okday[day] = 0; + while (NULL != (bp = kw_parse(CF_WEEKDAY, bp, &day))) + okday[day] = 1; + } else { + for (day=0; day<7; day++) + okday[day] = 1; + } + if (!okday[tm->tm_wday]) + return 0; + bp = game_hours; + if (*bp != 0) { + while (NULL != (bp = kw_parse(CF_TIMERANGE, bp, hour))) + if (curtime >= hour[0] && curtime < hour[1]) + break; + if (bp == 0) + return 0; + } else { + hour[0] = 0; + hour[1] = 24*60; + } + tomorrow = tm->tm_wday + 1; + if (tomorrow >= 7) + tomorrow = 0; + return 1; +} diff --git a/src/lib/common/keyword.c b/src/lib/common/keyword.c new file mode 100644 index 00000000..98565382 --- /dev/null +++ b/src/lib/common/keyword.c @@ -0,0 +1,199 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * keyword.c: Find keywords in a file + * + * Known contributors to this file: + * + */ + +#include "misc.h" +#include "keyword.h" +#include "gen.h" +#include +#include +#include +#include "common.h" + +struct kwtab { + struct kwtab *next; + s_char *name; + s_char *text; +}; + +struct kwtab *kw_list; + +int +kw_read(FILE *fp) +{ + register struct kwtab *kw; + register struct kwtab *next; + s_char buf[255]; + s_char *p; + int n; + + for (kw = kw_list; kw != 0; kw = next) { + next = kw->next; + free(kw->name); + free(kw->text); + free(kw); + } + kw_list = 0; + for (n=0; fgets(buf, sizeof(buf), fp) != 0; n++) { + /* Allow for comments.. any line starting with # */ + if (buf[0] == '#') + continue; + p = rindex(buf, '\n'); + if (p != 0) + *p = 0; + if ((p = index(buf, ':')) == 0) { + logerror("kw_read: Bad keyword line #%d\n", n); + return 0; + } + *p++ = 0; + while (*p && isspace(*p)) + p++; + kw = (struct kwtab *) malloc(sizeof(*kw)); + kw->name = strcpy(malloc(strlen(buf)+1), buf); + kw->text = strcpy(malloc(strlen(p)+1), p); + kw->next = kw_list; + kw_list = kw; + } + return n; +} + +s_char * +kw_find(s_char *name) +{ + register struct kwtab *kw; + + for (kw = kw_list; kw != 0; kw = kw->next) { + if (strcmp(kw->name, name) == 0) + return kw->text; + } + return 0; +} + +#define CF_VALUE 1 +#define CF_TIME 2 +#define CF_TIMERANGE 3 +#define CF_WEEKDAY 4 + +/* + * destructive parse + */ +s_char * +kw_parse(int type, s_char *text, int *data) +{ + s_char *get_time(s_char *ptr, int *data); + s_char *weekday(s_char *ptr, int *data); + s_char *next; + + while (isspace(*text)) + text++; + switch (type) { + case CF_VALUE: + *data = atoip(&text); + break; + case CF_TIME: + text = get_time(text, &data[0]); + break; + case CF_TIMERANGE: + if ((next = index(text, '-')) == 0) + return 0; + next++; + if ((text = get_time(text, &data[0])) == 0) + return 0; + text = get_time(next, &data[1]); + break; + case CF_WEEKDAY: + text = weekday(text, &data[0]); + break; + default: + text = 0; + break; + } + return text; +} + +struct day { + s_char *string; + int day[7]; +} day[] = { + { "smtwtfs", { -1, 0, -1, 2, -1, 4, -1 } }, + { "uouehra", { 0, 1, 2, 3, 4, 5, 6 } } +}; + +s_char * +weekday(s_char *ptr, int *data) +{ + register s_char *string; + register int c; + register int n; + + c = *ptr++; + if (isupper(c)) + c = tolower(c); + string = day[0].string; + for (n=0; n<7; n++) { + if (string[n] != c) + continue; + if (day[0].day[n] >= 0) + break; + if (day[1].string[n] == *ptr) + break; + } + if (n == 7) + return 0; + *data = day[1].day[n]; + while (*ptr && !isspace(*ptr)) + ptr++; + return ptr; +} + + +s_char * +get_time(s_char *ptr, int *data) +{ + int hour; + int minute; + + if (!isdigit(*ptr)) + return 0; + hour = atoip(&ptr); + minute = 0; + if (*ptr) { + if (*ptr != ':') + return 0; + ptr++; + if (!isdigit(*ptr)) + return 0; + minute = atoip(&ptr); + } + *data = (hour * 60) + minute; + return ptr; +} diff --git a/src/lib/common/land.c b/src/lib/common/land.c new file mode 100644 index 00000000..af263b88 --- /dev/null +++ b/src/lib/common/land.c @@ -0,0 +1,98 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * land.c: Misc. land unit routines + * + * Known contributors to this file: + * + */ + +#include "misc.h" +#include "var.h" +#include "sect.h" +#include "nat.h" +#include "var.h" +#include "file.h" +#include "path.h" +#include "xy.h" +#include "land.h" +#include "nsc.h" +#include "common.h" +#include "subs.h" + +int +adj_units(coord x, coord y, natid own) +{ + register int i; + struct sctstr sect; + + for (i = DIR_FIRST; i <= DIR_LAST; i++) { + getsect(x + diroff[i][0], y + diroff[i][1], §); + if (has_units(sect.sct_x, sect.sct_y, own, 0)) + return 1; + } + return 0; +} + +int +has_units(coord x, coord y, natid cn, struct lndstr *lp) +{ + register int n; + struct lndstr land; + + for (n=0; ef_read(EF_LAND, n, (s_char *)&land); n++) { + if(land.lnd_x != x || land.lnd_y != y) + continue; + if (lp) { + /* Check this unit. If it is this one, we don't want + it included in the count. */ + if (lp->lnd_uid == land.lnd_uid) + continue; + } + if (land.lnd_own == cn) + return 1; + } + + return 0; +} + +int +has_units_with_mob(coord x, coord y, natid cn) +{ + struct nstr_item ni; + struct lndstr land; + + snxtitem_xy(&ni,EF_LAND,x,y); + while(nxtitem(&ni,(s_char *)&land)) { + if (land.lnd_own != cn) + continue; + if (land.lnd_mobil > 0) + return 1; + } + + return 0; +} diff --git a/src/lib/common/log.c b/src/lib/common/log.c new file mode 100644 index 00000000..5947a34f --- /dev/null +++ b/src/lib/common/log.c @@ -0,0 +1,164 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * log.c: Log an Empire error to a file + * + * Known contributors to this file: + * Dave Pare, 1989 + */ + +#include "misc.h" +#include +#include +#if !defined(_WIN32) +#include +#endif +#include +#include +#include +#ifdef Rel4 +#include +#endif /* Rel4 */ +#include +#include "deity.h" +#include "player.h" +#include "common.h" + +static s_char *logfile = 0; + +s_char * +getlogfile() +{ + return (s_char *)logfile; +} + +/* + * Points logfile at datadir/"program".log + */ +void +loginit(void) +{ + extern s_char program[]; + extern s_char *datadir; + s_char buf[1024]; + +#if !defined(_WIN32) + sprintf(buf, "%s/%s.log", datadir, program); +#else + sprintf(buf, "%s\\%s.log", datadir, program); +#endif + logfile = malloc(strlen(buf) + 1); + strcpy(logfile, buf); +} + +/*VARARGS*/ +void logerror(s_char *format, ...) +{ +#if !defined(Rel4) && !defined(__linux__) && !defined(__ppc__) + extern s_char *sys_errlist[]; +#endif +#ifndef sgi + extern int errno; +#endif /* sgi */ + va_list list; + time_t now; + s_char buf[512]; + s_char cbuf[512]; + s_char buf1[512]; + int logf; +/* s_char *error; */ + s_char *p; + + if (logfile == 0) + loginit(); + va_start(list, format); + vsprintf(buf, format, list); + if ((p = index(buf, '\n')) != 0) + *p = 0; + (void) time(&now); +/* error = "log"; + if (errno != 0) + error = sys_errlist[errno]; + (void) sprintf(buf1, "%s; (%s) %s", buf, error, ctime(&now)); +*/ + strcpy(cbuf, ctime(&now)); + if ((p = index(cbuf, '\n')) != 0) + *p = 0; + (void) sprintf(buf1, "%s %s\n", cbuf, buf); + if ((logf = open(logfile, O_WRONLY|O_CREAT|O_APPEND, 0666)) < 0) + return; + (void) write(logf, buf1, strlen(buf1)); + (void) close(logf); + errno = 0; +#ifdef notdef + if (player) { + pr("A system error has occured; please notify the deity.\n"); + pr(buf1); + } +#endif + va_end(list); +} + +/*VARARGS*/ +void filelogerror(s_char *format, ...) +{ +#if !defined(Rel4) && !defined(__linux__) && !defined(__ppc__) + extern s_char *sys_errlist[]; +#endif /* Rel4 */ +#ifndef sgi + extern int errno; +#endif /* sgi */ + va_list list; + time_t now; + s_char buf[512]; + s_char buf1[512]; + int logf; + s_char *error; + s_char *p; + + if (logfile == 0) + loginit(); + va_start(list, format); + vsprintf(buf, format, list); + if ((p = index(buf, '\n')) != 0) + *p = 0; + (void) time(&now); + error = "log"; + if (errno != 0) +#ifdef Rel4 + error = strerror (errno); +#else + error = (s_char *)sys_errlist[errno]; +#endif /* Rel4 */ + (void) sprintf(buf1, "%s; (%s) %s", buf, error, ctime(&now)); + if ((logf = open(logfile, O_WRONLY|O_CREAT|O_APPEND, 0666)) < 0) + return; + (void) write(logf, buf1, strlen(buf1)); + (void) close(logf); + errno = 0; + va_end(list); +} diff --git a/src/lib/common/mailbox.c b/src/lib/common/mailbox.c new file mode 100644 index 00000000..e34ed2bc --- /dev/null +++ b/src/lib/common/mailbox.c @@ -0,0 +1,45 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * mailbox.c: Return string containing telegram file + * + * Known contributors to this file: + * + */ + +#include "misc.h" +#include "tel.h" +#include + +s_char * +mailbox(s_char *buf, natid cn) +{ + (void) sprintf(buf, "%s%d", telfil, cn); + return buf; +} + + diff --git a/src/lib/common/maps.c b/src/lib/common/maps.c new file mode 100644 index 00000000..c7b363aa --- /dev/null +++ b/src/lib/common/maps.c @@ -0,0 +1,420 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * maps.c: Map routines + * + * Known contributors to this file: + * Ken Stevens, 1995 + * Steve McClure, 1998 + */ + +#include "misc.h" +#include "player.h" +#include "var.h" +#include "sect.h" +#include "xy.h" +#include "nsc.h" +#include "file.h" +#include "deity.h" +#include "nat.h" +#include "map.h" +#include "ship.h" +#include "land.h" +#include "plane.h" +#include "common.h" +#include "gen.h" +#include "subs.h" +#include "optlist.h" + +int +draw_map(int bmap, s_char origin, int map_flags, struct nstr_sect *nsp, int country) +{ + struct natstr *np; + struct range range; + struct nstr_item ni; + struct shpstr ship; + struct lndstr land; + struct plnstr plane; + coord x,y; + int i; + /* Note this is not re-entrant anyway, so we keep the buffers + around */ + static u_char *bitmap = (u_char *)0; + static s_char *wmapbuf = (s_char *)0; + static s_char **wmap = (s_char **)0; + + if (!wmapbuf) + wmapbuf = (s_char *)malloc((WORLD_Y * MAPWIDTH(1)) * sizeof(s_char)); + if (!wmap) { + wmap = (s_char **)malloc(WORLD_Y * sizeof(s_char *)); + if (wmap && wmapbuf) { + for (i = 0; i < WORLD_Y; i++) + wmap[i] = &wmapbuf[MAPWIDTH(1) * i]; + } else if (wmap) { + free((s_char *)wmap); + wmap = (s_char **)0; + } + } + if (!bitmap) + bitmap = (u_char *)malloc((WORLD_X * WORLD_Y) / 8); + if (!wmapbuf || !wmap || !bitmap) { + pr("Memory error, tell the deity.\n"); + logerror("malloc failed in draw_map\n"); + return RET_FAIL; + } + + if (bmap == EF_MAP + EF_BMAP) { + if (!confirm("Are you sure you want to revert your bmap? ")) + return RET_OK; + } + if (!player->command->c_flags & C_MOD) { + logerror("%s command needs C_MOD flag set",player->command->c_form); + player->command->c_flags |= C_MOD; + } + np = getnatp(country); + /* zap any conditionals */ + nsp->ncond = 0; + xyrelrange(np, &nsp->range, &range); + border(&range, " ", ""); + blankfill((s_char *)wmapbuf, &nsp->range, 1); + if (bmap) { + register int c; + switch (bmap) { + case EF_BMAP: + while (bmnxtsct(nsp) && !player->aborted) { + if (0 != (c = player->bmap[sctoff(nsp->x, nsp->y)])) + wmap[nsp->dy][nsp->dx] = c; + } + break; + case EF_MAP: + while (bmnxtsct(nsp) && !player->aborted) { + if (0 != (c = player->map[sctoff(nsp->x, nsp->y)])) + wmap[nsp->dy][nsp->dx] = c; + } + break; + case (EF_MAP + EF_BMAP): + while (bmnxtsct(nsp) && !player->aborted) { + player->bmap[sctoff(nsp->x, nsp->y)] = + player->map[sctoff(nsp->x, nsp->y)]; + if (0 != (c = player->bmap[sctoff(nsp->x, nsp->y)])) + wmap[nsp->dy][nsp->dx] = c; + } + ef_write(EF_BMAP, player->cnum, player->bmap); + break; + case EF_NMAP: + do { + register s_char *ptr; + struct sctstr sect; + + if ((!player->god || country)) { + bzero((s_char *)bitmap, (WORLD_X * WORLD_Y) / 8); + bitinit2(nsp, bitmap, country); + } + while (nxtsct(nsp, §) && !player->aborted) { + if ((!player->god || country) && + !emp_getbit(nsp->x, nsp->y, bitmap)) { + if (!player->god) + continue; + } + ptr = &wmap[nsp->dy][nsp->dx]; + if (sect.sct_newtype > SCT_MAXDEF) { + *ptr = '?'; + } else { + *ptr = dchr[sect.sct_newtype].d_mnem; + switch (sect.sct_newtype) { + case SCT_WATER: + case SCT_RURAL: + case SCT_MOUNT: + case SCT_WASTE: + case SCT_PLAINS: + break; + default: + if (sect.sct_own != country && + (!player->god || country)) { + if (!player->god) + *ptr = '?'; + } + break; + } + } + } + } while (0); + break; + } + } else { + register s_char *ptr; + struct sctstr sect; + int changed = 0; + + if ((!player->god || country)) { + bzero((s_char *)bitmap, (WORLD_X * WORLD_Y) / 8); + bitinit2(nsp, bitmap, country); + } + while (nxtsct(nsp, §) && !player->aborted) { + if ((!player->god || country) && !emp_getbit(nsp->x, nsp->y, bitmap)) { + if (!player->god) + continue; + } + ptr = &wmap[nsp->dy][nsp->dx]; + if (sect.sct_type > SCT_MAXDEF) { + *ptr = '?'; + } else { + *ptr = dchr[sect.sct_type].d_mnem; + switch (sect.sct_type) { + case SCT_WATER: + case SCT_RURAL: + case SCT_MOUNT: + case SCT_WASTE: + case SCT_PLAINS: + break; + default: + if (sect.sct_own != country && + (!player->god || country)) { + if(!player->god) + *ptr = '?'; + } + break; + } + changed += map_set(player->cnum, nsp->x, nsp->y, *ptr, 0); + } + } + if (changed) + writemap(player->cnum); + } + if (player->aborted) + return RET_OK; + if (map_flags & MAP_PLANE){ + snxtitem_all(&ni, EF_PLANE); + while (nxtitem(&ni, (caddr_t)&plane)) { + if (plane.pln_own == 0) + continue; + if (plane.pln_own != player->cnum && !player->god) + continue; + if (!xyinrange(plane.pln_x, plane.pln_y, &nsp->range)) + continue; + + x = xnorm(plane.pln_x-nsp->range.lx); + y = ynorm(plane.pln_y-nsp->range.ly); + wmap[y][x] = (*plchr[(int)plane.pln_type].pl_name) & ~0x20; + } + } + if (map_flags & MAP_SHIP){ + snxtitem_all(&ni, EF_SHIP); + while (nxtitem(&ni, (caddr_t)&ship)) { + if (ship.shp_own == 0) + continue; + if (ship.shp_own != player->cnum && !player->god) + continue; + if (!xyinrange(ship.shp_x, ship.shp_y, &nsp->range)) + continue; + + x = xnorm(ship.shp_x-nsp->range.lx); + y = ynorm(ship.shp_y-nsp->range.ly); + wmap[y][x] = (*mchr[(int)ship.shp_type].m_name) & ~0x20; + } + } + if (map_flags & MAP_LAND){ + snxtitem_all(&ni, EF_LAND); + while (nxtitem(&ni, (caddr_t)&land)) { + if (land.lnd_own == 0) + continue; + if (land.lnd_own != player->cnum && !player->god) + continue; + if (!xyinrange(land.lnd_x, land.lnd_y, &nsp->range)) + continue; + + x = xnorm(land.lnd_x-nsp->range.lx); + y = ynorm(land.lnd_y-nsp->range.ly); + wmap[y][x] = (*lchr[(int)land.lnd_type].l_name) & ~0x20; + } + } + if (origin) + wmap[5][10] = origin & ~0x20; + for (y=nsp->range.ly, i=0; i < nsp->range.height; y++, i++) { + int yval; + + yval = yrel(np, y); + wmap[i][nsp->range.width] = '\0'; + pr("%4d %s %-4d\n", yval, wmap[i], yval); + if (y >= WORLD_Y) + y -= WORLD_Y; + } + border(&range, " ", ""); + return RET_OK; +} + +/* + * get the next sector in the range + */ +int +bmnxtsct(register struct nstr_sect *np) +{ + while (1) { + np->dx++; + np->x++; + if (np->x >= WORLD_X) + np->x = 0; + if (np->dx >= np->range.width) { + np->dx = 0; + np->x = np->range.lx; + np->dy++; + if (np->dy >= np->range.height) + return 0; + np->y++; + if (np->y >= WORLD_Y) + np->y = 0; + } + if ((np->y + np->x) & 01) + continue; + if (np->type == NS_DIST) { + np->curdist = mapdist(np->x, np->y, np->cx, np->cy); + if (np->curdist > np->dist) + continue; + } + np->id = sctoff(np->x, np->y); + return 1; + } + /*NOTREACHED*/ +} + +void +bitinit2(struct nstr_sect *np, u_char *bitmap, int country) +{ + extern int *bitmaps[]; + struct sctstr sect; + int eff; + + while (nxtsct(np, §)) { + if (sect.sct_own != country) + continue; + eff = sect.sct_effic / 20; + if (eff > 4) + eff = 4; + emp_setbitmap(np->x, np->y, bitmap, bitmaps[eff]); + } + snxtsct_rewind(np); +} + +int +unit_map(int unit_type, int i, struct nstr_sect *nsp, s_char *originp) +{ + struct shpstr origs; + struct lndstr origl; + struct plnstr origp; + s_char what[64]; + struct natstr *np; + + np = getnatp(player->cnum); + if (unit_type == EF_LAND){ + if (!getland(i, &origl) || + (origl.lnd_own != player->cnum && !player->god) || + (origl.lnd_own == 0)) + return RET_FAIL; + sprintf(what, "%d:%d,%d:%d",xrel(np,origl.lnd_x-10), + xrel(np,origl.lnd_x+10), + yrel(np,origl.lnd_y-5), yrel(np,origl.lnd_y+5)); + *originp = *lchr[(int)origl.lnd_type].l_name; + } else if (unit_type == EF_PLANE){ + if (!getplane(i, &origp) || + (origp.pln_own != player->cnum && !player->god) || + (origp.pln_own == 0)) + return RET_FAIL; + sprintf(what, "%d:%d,%d:%d",xrel(np,origp.pln_x-10), + xrel(np,origp.pln_x+10), + yrel(np,origp.pln_y-5), yrel(np,origp.pln_y+5)); + *originp = *plchr[(int)origp.pln_type].pl_name; + } else { + if (!getship(i, &origs) || + (origs.shp_own != player->cnum && !player->god) || + (origs.shp_own == 0)) + return RET_FAIL; + sprintf(what, "%d:%d,%d:%d",xrel(np,origs.shp_x-10), + xrel(np,origs.shp_x+10), + yrel(np,origs.shp_y-5), yrel(np,origs.shp_y+5)); + unit_type = EF_SHIP; + *originp = *mchr[(int)origs.shp_type].m_name; + } + if (!snxtsct(nsp, what)) + return RET_FAIL; + return RET_OK; +} + +int +bmaps_intersect(natid a, natid b) +{ + s_char *mapa = ef_ptr(EF_MAP, a); + s_char *mapb = ef_ptr(EF_MAP, b); + int i; + + for (i = 0; i < WORLD_X*WORLD_Y/2; ++i, ++mapa, ++mapb) + if (*mapa && *mapa != ' ' && *mapb && *mapb != ' ') + return 1; + return 0; +} + +/* Note that this requires that the BMAP is mapped into memory */ + +int +share_bmap(natid from, natid to, struct nstr_sect *ns, s_char des, s_char *from_name) +{ + s_char *from_bmap = ef_ptr(EF_BMAP, from); + s_char *to_bmap = ef_ptr(EF_BMAP, to); + int n = 0; + struct sctstr sect; + s_char fromdes; + s_char todes; + s_char from_des = *from_name; + + if (isalpha(from_des)) + from_des &= ~0x20; + + while (nxtsct(ns, §)) { + if (!(fromdes = from_bmap[sctoff(ns->x, ns->y)])) + continue; + todes = to_bmap[sctoff(ns->x, ns->y)]; + if (todes && + todes != '?' && + todes != '.' && + todes != ' ' && + todes != from_des) + continue; + if (sect.sct_own == from) { + if (fromdes != '=' && + fromdes != 'h' && + fromdes != des) + fromdes = from_des; + } + if (todes == fromdes) + continue; + n += map_set(to, ns->x, ns->y, fromdes, 1); + } + + if (n) + writebmap(to); + return n; +} + diff --git a/src/lib/common/move.c b/src/lib/common/move.c new file mode 100644 index 00000000..6be00435 --- /dev/null +++ b/src/lib/common/move.c @@ -0,0 +1,75 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * move.c: Misc. move routines + * + * Known contributors to this file: + * + */ + +#include "gamesdef.h" +#include "misc.h" +#include "xy.h" +#include "var.h" +#include "sect.h" +#include "file.h" +#include "deity.h" +#include "path.h" +#include "nat.h" +#include "common.h" + +double +sector_mcost(struct sctstr *sp, int do_bonus) +{ + double d; + + if (!(d = dchr[sp->sct_type].d_mcst)) + return -1.0; + +/* Note, the best you can get is a 1.0 here. */ + + if (do_bonus == MOB_ROAD) { + d = d / (1.0 + ((double)sp->sct_road / 122.0)); + } else if (do_bonus == MOB_RAIL) { + d = d / (1.0 + ((double)sp->sct_rail / 100.0)); + } else { + if (d < 2.0) + d = 2.0; + } + if (d < 1.0) + d = 1.0; + if (dchr[sp->sct_type].d_mcst < 25) + d = (d * 100.0 - (double)sp->sct_effic) / 500.0; +/* d = (200.0 + (d - 3.0) * (double)sp->sct_effic) / 500.0;*/ + else + d = (d * 10.0 - (double)sp->sct_effic) / 115; + + if (d <= 0.0 || d < MIN_MOBCOST) + return MIN_MOBCOST; + return d; +} + diff --git a/src/lib/common/nat.c b/src/lib/common/nat.c new file mode 100644 index 00000000..76df8e8e --- /dev/null +++ b/src/lib/common/nat.c @@ -0,0 +1,170 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * nat.c: Misc. accesses on the nation file + * + * Known contributors to this file: + * Dave Pare, 1989 + */ + +#include "misc.h" +#include "nat.h" +#include "file.h" +#include "optlist.h" + +s_char * +cname(natid n) +{ + struct natstr *np; + + if ((np = getnatp(n)) == 0) + return 0; + return np->nat_cnam; +} + +s_char * +relatename(struct natstr *np, natid other) +{ + extern s_char *relates[]; + + return relates[getrel(np, other)]; +} + +s_char * +rejectname(struct natstr *np, natid other) +{ + extern s_char *rejects[]; + + return rejects[getrejects(other, np)]; +} + +s_char * +natstate(struct natstr *np) +{ + if ((np->nat_stat & STAT_INUSE) == 0) + return "FREE"; + if (np->nat_stat & STAT_GOD) + return "DEITY"; + if ((np->nat_stat & STAT_NORM) == 0) + return "VISITOR"; + return "ACTIVE"; +} + +/* This returns the relations that np has with them */ +int +getrel(struct natstr *np, natid them) +{ + return np->nat_relate[them]; +} + +int +getrejects(natid them, struct natstr *np) +{ + int ind; + int shift; + int reject; + + ind = them / 4; + shift = 12 - ((them - ((them / 4) << 2)) * 4); + /* the 07 should *really* be 017 */ + reject = (np->nat_rejects[ind] >> shift) & 0x0f; + return reject; +} + +void +agecontact(struct natstr *np) +{ + int them; + + if (opt_LOSE_CONTACT) { + for (them = 1; them < MAXNOC; ++them) { + if (them != np->nat_cnum && np->nat_contact[them]) { + --np->nat_contact[them]; + } + } + } +} + +int +getcontact(struct natstr *np, natid them) +{ + int contact; + + if (opt_LOSE_CONTACT) { + contact = np->nat_contact[them]; + } else { + int ind = them/16; + int shift = (them % 16); + + contact = (np->nat_contact[ind] >> shift) & 1; + } + return contact; +} + +void +putrel(struct natstr *np, natid them, int relate) +{ + np->nat_relate[them] = relate; +} + +void +putreject(struct natstr *np, natid them, int how, int what) +{ + int shift; + int newrej; + int ind; + + /* This 07 should be changed to 017 after the current game is over */ + what &= 0x0f; + ind = them / 4; + shift = 12 - ((them - ((them / 4) << 2)) * 4); + newrej = np->nat_rejects[ind]; + if (how) + newrej |= (what << shift); + else + newrej &= ~(what << shift); + np->nat_rejects[ind] = newrej; +} + +void +putcontact(struct natstr *np, natid them, int contact) +{ + if (opt_LOSE_CONTACT) { + if (np->nat_contact[them] > contact) + return; + np->nat_contact[them] = contact; + } else { + int ind = them/16; + int shift = them%16; + int new = np->nat_contact[ind]; + if (contact) + contact = 1; + new &= ~(1 << shift); + new |= (contact << shift); + np->nat_contact[ind] = new; + } +} diff --git a/src/lib/common/nstr_subs.c b/src/lib/common/nstr_subs.c new file mode 100644 index 00000000..efff7479 --- /dev/null +++ b/src/lib/common/nstr_subs.c @@ -0,0 +1,159 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * nstr.c: Compile and execute the item selections on sectors + * + * Known contributors to this file: + * Dave Pare, 1989 + */ + +#include +#include "struct.h" +#include "misc.h" +#include "var.h" +#include "xy.h" +#include "sect.h" +#include "nsc.h" +#include "nat.h" +#include "match.h" +#include "file.h" +#include "player.h" +#include "common.h" +#include "gen.h" + +/* + * return true if the conditions on this item + * are all true. + */ +int +nstr_exec(struct nscstr *conds, register int ncond, void *ptr, int type) +{ + register struct nscstr *nsc; + register int op; + register int lhs; + register int rhs; + register int oper; + + for (nsc=conds; --ncond >= 0; nsc++) { + oper = nsc->oper; + if (oper > 65535) { + oper = oper - 65535; + rhs = nsc->fld2; + } else + rhs = decode(player->cnum, nsc->fld2, ptr, type); + + if (oper > 255) { + oper = oper - 255; + lhs = nsc->fld1; + } else + lhs = decode(player->cnum, nsc->fld1, ptr, type); + + op = oper; + if ((op == '<' && lhs >= rhs) || + (op == '=' && lhs != rhs) || + (op == '>' && lhs <= rhs) || + (op == '#' && lhs == rhs)) + return 0; + } + return 1; +} + +int +decode(natid cnum, long int code, void *addr, int type) +{ + register int val; + register int nsc_code; + struct natstr *np; + long code_type = (code & NSC_TMASK); + + val = (code & ~NSC_MASK) & 0xffff; + + /* handle negative numbers properly */ + /* this assumes a binary two's complement number representation */ + if (val>=0x8000) val -= 0x10000; + + nsc_code = code & NSC_CMASK; + if (nsc_code == NSC_VAR) { + val = getvar(val, addr, type); + } else if (nsc_code == NSC_OFF) { + /* + * add offset to value + */ + addr = (s_char *)addr + val; + switch (code_type) { + case NSC_TIME: + val = *((time_t *)addr); + break; + case NSC_CHAR: + val = *((s_char *) addr); + break; + case NSC_UCHAR: + val = (int) *((unsigned char *) addr); + break; + case NSC_SHORT: + val = *((short *) addr); + break; + case NSC_USHORT: + val = *((u_short *) addr); + break; + case NSC_INT: + val = *((int *) addr); + break; + case NSC_LONG: + val = *((long *) addr); + break; + case NSC_XCOORD: + val = *((short *) addr); + np = getnatp(cnum); + val = xrel(np, val); + break; + case NSC_YCOORD: + val = *((short *) addr); + np = getnatp(cnum); + val = yrel(np, val); + break; + default: + logerror("bad type in decode: %x!\n", + code & NSC_TMASK); + val = 0; + break; + } + } + if (code & NSC_ROUND) + val = roundintby(val, 10); + return val; +} + +s_char * +decodep(long int code, void *addr) +{ + addr = (char *)addr + ((code & ~NSC_MASK) & 0xffff); + + if ((code & NSC_TMASK) == NSC_CHARP) + return *(s_char **)addr?*((s_char **)addr):(s_char *)""; + return addr; +} diff --git a/src/lib/common/path.c b/src/lib/common/path.c new file mode 100644 index 00000000..5cb2bc21 --- /dev/null +++ b/src/lib/common/path.c @@ -0,0 +1,541 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * path.c: Empire/A* Interface code. Provides callbacks for A* code and + * a sector cache to speed things up. Define BP_STATS for sector + * cache statistics, AS_STATS for A* statistics. + * + * Known contributors to this file: + * Phil Lapsley, 1991 + * Dave Pare, 1991 + * Thomas Ruschak, 1993 + * Steve McClure, 1997 + */ + +#include +#include +#include "../as/as.h" +#include "misc.h" +#include "path.h" +#include "xy.h" +#include "sect.h" +#include "file.h" +#include "common.h" +#include "gen.h" +#include "optlist.h" + +/* STM - The server is now reliant on the sector file being + * memory mapped for other things. So, this code has been + * setup to have the sector hashing #ifdef'd instead so that + * we don't have to do runtime checking. If someone moves + * the sector file to me non-memory mapped, they have larger + * problems than this, and can just turn this back on. Then + * again, their performance will be so bad going to a file + * all the time, it won't matter. */ + +/*#define DO_EFF_MEM_CHECKING*/ + + +/* XXX won't need sector hash when sect file is memory mapped */ + +#define BP_SCTHASHSIZE 128 /* sector cache hash table size */ +#define BP_ASHASHSIZE 128 /* A* queue hash table size */ +#define BP_NEIGHBORS 6 /* max number of neighbors */ + +struct sctcache { + coord x, y; + struct sctstr *sp; + struct sctcache *next; +}; + +struct bestp { + struct sctcache *sctcachetab[BP_SCTHASHSIZE]; + int sctcache_hits; + int sctcache_misses; + int bp_mobtype; + struct as_data *adp; +}; + +#ifdef DO_EFF_MEM_CHECKING + +static struct sctstr *bp_getsect(struct bestp *bp, coord x, coord y); +static struct sctstr *bp_sctcache_get(struct bestp *bp, coord x, coord y); +static void bp_sctcache_set(struct bestp *bp, coord x, coord y, struct sctstr *sp); +static void bp_sctcache_zap(struct bestp *bp); + +#endif /* DO_EFF_MEM_CHECKING */ + +static int bp_path(struct as_path *pp, s_char *buf); +static int bp_neighbors(struct as_coord c, struct as_coord *cp, s_char *pp); +static double bp_lbcost(struct as_coord from, struct as_coord to, s_char *pp); +static double bp_realcost(struct as_coord from, struct as_coord to, s_char *pp); +static double bp_seccost(struct as_coord from, struct as_coord to, s_char *pp); +static int bp_coord_hash(struct as_coord c); + +struct empfile *ep; + +/* We use this for caching neighbors. It never changes except + * at reboot time (maybe) so we never need to free it */ +struct sctstr **neighsects = (struct sctstr **)0; + +s_char * +bp_init(void) +{ + struct bestp *bp; + + ep = &empfile[EF_SECTOR]; + + bp = (struct bestp *) malloc(sizeof(*bp)); + bzero((s_char *)bp, sizeof(*bp)); + bp->adp = as_init(BP_NEIGHBORS, BP_ASHASHSIZE, bp_coord_hash, + bp_neighbors, bp_lbcost, bp_realcost, + bp_seccost, (s_char *)bp); + + if (bp->adp == NULL) + return NULL; + + if (neighsects == (struct sctstr **)0) + neighsects = (struct sctstr **)calloc(1, (sizeof(struct sctstr *) * + ((WORLD_X * WORLD_Y)/2)*6)); + + return (s_char *) bp; +} + +/* + * Find the best path from sector to to sector, and put the Empire movement + * string in path. Return 0 on success, -1 on error. + */ +int +best_path(struct sctstr *from, struct sctstr *to, s_char *path, int mob_type) +{ + static struct bestp *mybestpath; + struct as_data *adp; + struct as_path *ap; + + if (mybestpath == 0) + mybestpath = (struct bestp *)bp_init(); + adp = mybestpath->adp; +#ifdef DO_EFF_MEM_CHECKING + bp_sctcache_zap(mybestpath); +#endif + ap = as_find_cachepath(from->sct_x, from->sct_y, to->sct_x, to->sct_y); + if (ap == NULL) { + adp->from.x = from->sct_x; + adp->from.y = from->sct_y; + adp->to.x = to->sct_x; + adp->to.y = to->sct_y; + mybestpath->bp_mobtype = mob_type; + + if (as_search(adp) < 0) + return -1; + ap = adp->path; + } + + if (bp_path(ap, path) < 0) + return -1; + +#ifdef AS_STATS + as_stats(adp, stderr); +#endif /* AS_STATS */ +#ifdef BP_STATS + fprintf(stderr, "best path %s\n", path); + fprintf(stderr, "cache hits/misses: %d/%d\n", + bp->sctcache_hits, bp->sctcache_misses); +#endif /* BP_STATS */ + return 0; +} + +/* + * Translate an A* path into an empire movement string. Return 0 on + * success, -1 on failure. + */ +static int +bp_path(struct as_path *pp, s_char *buf) +{ + struct as_path *np; + s_char *cp = buf; + int dx, dy; + int n; + + np = pp->next; + while (np) { + dx = np->c.x - pp->c.x; + /* deal with wraparound from non-neg coords */ + if (dx < -2) + dx += WORLD_X; + else if (dx > 2) + dx -= WORLD_X; + dy = np->c.y - pp->c.y; + if (dy < -1) + dy += WORLD_Y; + else if (dy > 1) + dy -= WORLD_Y; + for (n=1;n<=6;n++) + if (dx == diroff[n][0] && dy == diroff[n][1]) + break; + if (n > 6) + return -1; + + *cp++ = dirch[n]; + pp = np; + np = np->next; + } + *cp = '\0'; + return 0; +} + +/* + * Find coords neighboring this sector; return number of such + * coords, and coordinartes themselves in an array pointed + * to by *cpp. + * XXX need to check ownership, sector types, etc. + */ +static int +bp_neighbors(struct as_coord c, struct as_coord *cp, s_char *pp) +{ +#ifdef DO_EFF_MEM_CHECKING + struct bestp *bp = (struct bestp *) pp; +#endif /* DO_EFF_MEM_CHECKING */ + coord x, y; + coord nx, ny; + int n = 0, q; + struct sctstr *sp, *from, **ssp; + /* Six pointers, just in case our cache isn't there */ + struct sctstr *tsp[] = { 0, 0, 0, 0, 0, 0 }; + int sx, sy, offset; + + x = c.x; + y = c.y; +#ifdef DO_EFF_MEM_CHECKING + if ((ep->flags & EFF_MEM) == 0) { + from = bp_getsect(bp, x, y); + } else { +#endif /* DO_EFF_MEM_CHECKING */ + sx = XNORM(x); + sy = YNORM(y); + offset = (sy * WORLD_X + sx) / 2; + from = (struct sctstr *) (ep->cache + ep->size * offset); +#ifdef DO_EFF_MEM_CHECKING + } +#endif /* DO_EFF_MEM_CHECKING */ + + if (neighsects == (struct sctstr **)0) + ssp = (struct sctstr **)&tsp[0]; + else + ssp = (struct sctstr **)&neighsects[offset * 6]; + for (q = 1; q <= 6; q++, ssp++) { + if (*ssp == (struct sctstr *)0) { + /* We haven't cached this neighbor yet */ + nx = x + diroff[q][0]; + ny = y + diroff[q][1]; + sx = XNORM(nx); + sy = YNORM(ny); +#ifdef DO_EFF_MEM_CHECKING + if ((ep->flags & EFF_MEM) == 0) { + sp = bp_getsect(bp, nx, ny); + } else { +#endif /* DO_EFF_MEM_CHECKING */ + offset = (sy * WORLD_X + sx) / 2; + sp = (struct sctstr *) (ep->cache + ep->size * offset); + /* We can only save in our neighbor cache if the + sector file is in memory */ + *ssp = sp; +#ifdef DO_EFF_MEM_CHECKING + } +#endif /* DO_EFF_MEM_CHECKING */ + } else { + sp = *ssp; + sx = XNORM(sp->sct_x); + sy = YNORM(sp->sct_y); + } + /* No need to calculate cost each time, just make sure we can + move through it. We calculate it later. */ + if (dchr[sp->sct_type].d_mcst == 0) + continue; + if (sp->sct_own != from->sct_own) + continue; + cp[n].x = sx; + cp[n].y = sy; + n++; + } + return (n); +} + +/* + * Compute a lower-bound on the cost from "from" to "to". + */ +/*ARGSUSED*/ +static double +bp_lbcost(struct as_coord from, struct as_coord to, s_char *pp) +{ + struct bestp *bp = (struct bestp *) pp; + struct sctstr *ts; + float cost; + int x, y, sx, sy, offset; + +#ifdef DO_EFF_MEM_CHECKING + if ((ep->flags & EFF_MEM) == 0) { + ts = bp_getsect(bp, (coord)to.x, (coord)to.y); + } else { +#endif /* DO_EFF_MEM_CHECKING */ + x = to.x; + y = to.y; + sx = XNORM(x); + sy = YNORM(y); + offset = (sy * WORLD_X + sx) / 2; + ts = (struct sctstr *)(ep->cache + ep->size * offset); +#ifdef DO_EFF_MEM_CHECKING + } +#endif /* DO_EFF_MEM_CHECKING */ + cost = sector_mcost(ts, bp->bp_mobtype); + return (cost); +} + +/* + * Compute the real cost to move from "from" to "to". + */ +static double +bp_realcost(struct as_coord from, struct as_coord to, s_char *pp) +{ + return (bp_lbcost(from, to, pp)); +} + +/* + * Tie breaker secondary metric (only used when lower bound costs + * are equal). + */ +/*ARGSUSED*/ +static double +bp_seccost(struct as_coord from, struct as_coord to, s_char *pp) +{ + return ((double) mapdist((coord)from.x, (coord)from.y, + (coord)to.x, (coord)to.y)); +} + +#ifdef DO_EFF_MEM_CHECKING + +/* + * Get a sector from the cache. If it's not in the cache, + * get it from disk and add it to the cache. + */ +static struct sctstr * +bp_getsect(struct bestp *bp, coord x, coord y) +{ + struct sctstr *sp; + + sp = bp_sctcache_get(bp, x, y); + if (sp == NULL) { + sp = (struct sctstr *) malloc(sizeof(*sp)); + getsect(x, y, sp); + bp_sctcache_set(bp, x, y, sp); + bp->sctcache_misses++; + } else { + bp->sctcache_hits++; + } + return (sp); +} + +/* + * Get a sector from the cache; return NULL if it's not there. + */ +static struct sctstr * +bp_sctcache_get(struct bestp *bp, coord x, coord y) +{ + int hashval; + struct as_coord c; + struct sctcache *hp; + + c.x = x; + c.y = y; + hashval = bp_coord_hash(c) % BP_SCTHASHSIZE; + for (hp = bp->sctcachetab[hashval]; hp; hp = hp->next) { + if (hp->x == x && hp->y == y) + return (hp->sp); + } + return (NULL); +} + +/* + * Put a sector in the cache. + */ +static void +bp_sctcache_set(struct bestp *bp, coord x, coord y, struct sctstr *sp) +{ + int hashval; + struct as_coord c; + struct sctcache *hp; + + hp = (struct sctcache *) calloc(1, sizeof(*hp)); + hp->x = x; + hp->y = y; + hp->sp = sp; + c.x = x; + c.y = y; + hashval = bp_coord_hash(c) % BP_SCTHASHSIZE; + hp->next = bp->sctcachetab[hashval]; + bp->sctcachetab[hashval] = hp; +} + +/* + * Zap the cache and reset statistics. + */ +static void +bp_sctcache_zap(struct bestp *bp) +{ + register struct sctcache *hp; + register struct sctcache *np; + register int i; + + for (i = 0; i < BP_SCTHASHSIZE; i++) { + for (hp = bp->sctcachetab[i]; hp; hp = np) { + np = hp->next; + free(hp->sp); + free(hp); + } + bp->sctcachetab[i] = NULL; + } + bp->sctcache_hits = 0; + bp->sctcache_misses = 0; +} + +#endif /* DO_EFF_MEM_CHECKING */ + +/* + * Hash a coordinate into an integer. + */ +static int +bp_coord_hash(struct as_coord c) +{ + return ((abs(c.x) + 1) << 3) ^ abs(c.y); +} + +void +bp_enable_cachepath() +{ + as_enable_cachepath(); +} + +void +bp_disable_cachepath() +{ + as_disable_cachepath(); +} + +void +bp_clear_cachepath() +{ + as_clear_cachepath(); +} + +double +pathcost(struct sctstr *start, s_char *path, int mob_type) +{ + register int o; + register int cx, cy; + double cost = 0.0; + struct sctstr *sp; + int sx, sy, offset; + + cx = start->sct_x; + cy = start->sct_y; + + while (*path) { + if (*path == 'h') { + path++; + continue; + } + o = dirindex[(int)((*path) - 'a')]; + cx += diroff[o][0]; + cy += diroff[o][1]; + sx = XNORM(cx); + sy = YNORM(cy); + offset = (sy * WORLD_X + sx) / 2; + sp = (struct sctstr *)(ep->cache + ep->size * offset); + cost += sector_mcost(sp, mob_type); + path++; + } + + return cost; +} + +s_char * +BestDistPath(s_char *path, + struct sctstr *from, + struct sctstr *to, + double *cost, + int mob_type) +{ + return BestLandPath(path, from, to, cost, mob_type); +} + +s_char * +BestLandPath(s_char *path, + struct sctstr *from, + struct sctstr *to, + double *cost, + int mob_type) +{ + int length; + + *path = 0; + *cost = 0.0; + if (best_path(from, to, path, mob_type) < 0) + return (s_char *)0; + *cost = pathcost(from, path, mob_type); + length = strlen(path); + path[length] = 'h'; + path[length + 1] = '\0'; + return path; +} + +s_char * +BestShipPath(s_char *path, + int fx, + int fy, + int tx, + int ty, + int owner) +{ + s_char *map; + + /* need to make sector database available to bestpath */ + map = ef_ptr(EF_BMAP, owner); + + return (bestownedpath(path, map, fx, fy, tx, ty, ".=h", owner)); +} + +s_char * +BestAirPath(s_char *path, + int fx, + int fy, + int tx, + int ty) +{ + return (bestownedpath(path, 0, fx, fy, tx, ty, "", -1)); + /* return (bestpath(path, fx, fy, tx, ty, ""));*/ +} + diff --git a/src/lib/common/res_pop.c b/src/lib/common/res_pop.c new file mode 100644 index 00000000..990ffc2e --- /dev/null +++ b/src/lib/common/res_pop.c @@ -0,0 +1,71 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * res_pop.c: Get maximum pop of a sector + * + * Known contributors to this file: + * Ken Stevens, 1995 + * Steve McClure, 1998 + */ + +#include +#include "misc.h" +#include "var.h" +#include "sect.h" +#include "nat.h" +#include "item.h" +#include "news.h" +#include "file.h" +#include "xy.h" +#include "optlist.h" +#include "common.h" + +int +max_pop(float research, struct sctstr *sp) +{ + int maxpop = 999; + + if (opt_RES_POP) { + maxpop = (((50.0+4.0*research)/(200.0+3.0*research))*600.0) + 400; + if (maxpop > 999) + maxpop = 999; + } + + if (opt_BIG_CITY) { + if (sp && dchr[sp->sct_type].d_pkg == UPKG) + maxpop = (int)(maxpop * ((9.0 * sp->sct_effic) / 100 + 1)); + } + + if (sp) { + if (sp->sct_type == SCT_MOUNT) + maxpop /= 10; + else if (sp->sct_type == SCT_PLAINS) + maxpop /= 20; + } + + return maxpop; +} diff --git a/src/lib/common/sectdamage.c b/src/lib/common/sectdamage.c new file mode 100644 index 00000000..828fbf41 --- /dev/null +++ b/src/lib/common/sectdamage.c @@ -0,0 +1,141 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * sectdamage.c: Damage a sector + * + * Known contributors to this file: + * Dave Pare, 1989 + * Steve McClure, 1996 + */ + +#include "misc.h" +#include "var.h" +#include "sect.h" +#include "ship.h" +#include "land.h" +#include "plane.h" +#include "nuke.h" +#include "xy.h" +#include "nsc.h" +#include "file.h" +#include "nat.h" +#include "optlist.h" +#include "damage.h" +#include "common.h" +#include "gen.h" +#include "subs.h" +#include "lost.h" + +int +sect_damage(struct sctstr *sp, int dam, struct emp_qelem *list) +{ + int eff; + + if (dam <= 0) + return 0; + if (dam > 100) + dam = 100; + + sp->sct_effic = damage((int)sp->sct_effic, dam); + sp->sct_road = damage((int)sp->sct_road, dam); + sp->sct_rail = damage((int)sp->sct_rail, dam); + sp->sct_defense = damage((int)sp->sct_defense, dam); + if (!opt_DEFENSE_INFRA) + sp->sct_defense = sp->sct_effic; + + eff = dam; + + if (sp->sct_mobil > 0) + sp->sct_mobil = damage((int)sp->sct_mobil, dam); + sp->sct_nv = vl_damage(dam, + sp->sct_vtype, sp->sct_vamt, + (int)sp->sct_nv); + if (opt_EASY_BRIDGES == 0) { + if (sp->sct_effic < 20 && sp->sct_type == SCT_BHEAD) + bridgefall(sp, list); + } else { + if (sp->sct_effic < 20 && sp->sct_type == SCT_BSPAN) + knockdown(sp, list); + } + putsect(sp); + return eff; +} + +int +sectdamage(struct sctstr *sp, int dam, struct emp_qelem *list) +{ + extern double unit_damage; + struct nstr_item ni; + struct lndstr land; + struct plnstr plane; + double real_dam; + int eff; + double sector_strength(); + + /* Some sectors are harder/easier to kill.. */ + /* Average sector has a dstr of 1, so adjust */ + /* the damage accordingly. Makes forts a pain */ + +/* real_dam = (double)dam * (1.0/((((double)(dchr[sp->sct_type].d_dstr - 1))*(sp->sct_effic/100.0)) + 1.0));*/ + real_dam = (double)dam * (1.0/sector_strength(sp)); + dam = ldround(real_dam,1); + + eff = sect_damage(sp, PERCENT_DAMAGE(dam), list); + + /* Damage all the land units in the sector */ + /* Units don't take full damage */ + dam = ldround(DPERCENT_DAMAGE(dam * unit_damage), 1); + if (dam <= 0) + return eff; + + snxtitem_xy(&ni,EF_LAND,sp->sct_x,sp->sct_y); + while(nxtitem(&ni,(s_char *)&land)){ + if (!land.lnd_own) + continue; + landdamage(&land,dam); + putland(land.lnd_uid,&land); + } + + dam = dam / 7; + if (dam <= 0) + return eff; + snxtitem_xy(&ni, EF_PLANE, sp->sct_x, sp->sct_y); + while (nxtitem(&ni, (s_char *)&plane)) { + if (!plane.pln_own) + continue; + if (plane.pln_flags & PLN_LAUNCHED) + continue; + if (plane.pln_ship >= 0) + continue; + /* Is this plane flying in this list? */ + if (ac_isflying(&plane, list)) + continue; + planedamage(&plane, dam); + putplane(plane.pln_uid, &plane); + } + return eff; +} diff --git a/src/lib/common/snxtit_subs.c b/src/lib/common/snxtit_subs.c new file mode 100644 index 00000000..01ff7031 --- /dev/null +++ b/src/lib/common/snxtit_subs.c @@ -0,0 +1,156 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * snxtit_subs.c: arrange item selection using one of many criteria. + * + * Known contributors to this file: + * Dave Pare, 1989 + */ + +#include "misc.h" +#include "var.h" +#include "xy.h" +#include "sect.h" +#include "nsc.h" +#include "file.h" +#include "common.h" + +void +snxtitem_area(register struct nstr_item *np, int type, struct range *range) +{ + bzero((s_char *)np, sizeof(*np)); + np->cur = -1; + np->type = type; + np->sel = NS_AREA; + np->index = -1; + np->range = *range; + np->read = ef_read; + np->flags = ef_flags(type); + xysize_range(&np->range); + ef_zapcache(type); +} + +void +snxtitem_dist(register struct nstr_item *np, int type, int cx, int cy, int dist) +{ + struct range range; + + bzero((s_char *)np, sizeof(*np)); + xydist_range(cx, cy, dist, &range); + np->cur = -1; + np->type = type; + np->sel = NS_DIST; + np->cx = cx; + np->cy = cy; + np->index = -1; + np->range = range; + np->dist = dist; + np->read = ef_read; + np->flags = ef_flags(type); +#if 0 + /* This is no longer proper. */ + /* It did the wrong thing for small, hitech worlds. */ + xysize_range(&np->range); +#endif + ef_zapcache(type); +} + +void +snxtitem_xy(register struct nstr_item *np, int type, coord x, coord y) +{ + bzero((s_char *)np, sizeof(*np)); + np->cur = -1; + np->type = type; + np->sel = NS_XY; + np->cx = xnorm(x); + np->cy = ynorm(y); + np->index = -1; + np->dist = 0; + np->read = ef_read; + np->flags = ef_flags(type); + ef_zapcache(type); +} + +void +snxtitem_all(register struct nstr_item *np, int type) +{ + bzero((s_char *)np, sizeof(*np)); + np->cur = -1; + np->sel = NS_ALL; + np->type = type; + np->index = -1; + np->read = ef_read; + np->flags = ef_flags(type); + xysize_range(&np->range); + ef_zapcache(type); +} + +void +snxtitem_group(register struct nstr_item *np, int type, s_char group) +{ + if (group == '~') + group = ' '; + bzero((s_char *)np, sizeof(*np)); + np->cur = -1; + np->sel = NS_GROUP; + np->group = group; + np->type = type; + np->index = -1; + np->read = ef_read; + np->flags = ef_flags(type); + xysize_range(&np->range); + ef_zapcache(type); +} + +void +snxtitem_rewind(struct nstr_item *np) +{ + np->cur = -1; + np->index = -1; + ef_zapcache(np->type); +} + +int +snxtitem_list(register struct nstr_item *np, int type, int *list, int len) +{ + int i; + + bzero((s_char *)np, sizeof(*np)); + np->cur = -1; + np->type = type; + np->sel = NS_LIST; + np->index = -1; + np->read = ef_read; + np->flags = ef_flags(type); + if (len <= 0 || len > NS_LSIZE) + return 0; + for (i=0; ilist[i] = list[i]; + np->size = len; + ef_zapcache(type); + return 1; +} diff --git a/src/lib/common/snxtsct_subs.c b/src/lib/common/snxtsct_subs.c new file mode 100644 index 00000000..7c3cf52c --- /dev/null +++ b/src/lib/common/snxtsct_subs.c @@ -0,0 +1,159 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * snxtsct_subs.c: arrange sector selection using either distance or area + * + * Known contributors to this file: + * Dave Pare, 1989 + */ +/* + * XXX we can *almost* treat sectors as items, but not quite. + * Items are retrieved using id's, and sectors still use x,y. + */ + +#include "misc.h" +#include "var.h" +#include "xy.h" +#include "sect.h" +#include "nsc.h" +#include "file.h" +#include "common.h" +#include "optlist.h" + +void +snxtsct_all(struct nstr_sect *np) +{ + struct range worldrange; + + worldrange.lx = -WORLD_X/2; + worldrange.ly = -WORLD_Y/2; + worldrange.hx = WORLD_X/2; + worldrange.hy = WORLD_Y/2; + worldrange.width = worldrange.height = 0; + snxtsct_area(np, &worldrange); +} + +void +snxtsct_area(register struct nstr_sect *np, struct range *range) +{ + bzero((s_char *)np, sizeof(*np)); + np->range = *range; + np->ncond = 0; + np->type = NS_AREA; + np->read = ef_read; + np->x = np->range.lx - 1; + np->y = np->range.ly; + np->dx = -1; + np->dy = 0; + xysize_range(&np->range); + ef_zapcache(EF_SECTOR); +} + +void +snxtsct_rewind(struct nstr_sect *np) +{ + np->x = np->range.lx - 1; + np->y = np->range.ly; + np->dx = -1; + np->dy = 0; + np->id = -1; + ef_zapcache(EF_SECTOR); +} + +void +snxtsct_dist(register struct nstr_sect *np, coord cx, coord cy, int dist) +{ + bzero((s_char *)np, sizeof(*np)); + xydist_range(cx, cy, dist, &np->range); + np->cx = cx; + np->cy = cy; + np->ncond = 0; + np->dist = dist; + np->type = NS_DIST; + np->read = ef_read; + np->x = np->range.lx - 1; + np->y = np->range.ly; + np->dx = -1; + np->dy = 0; +#if 0 + /* This function is now done elsewhere. */ + /* It was not doing the right thing when the world was small */ + xysize_range(&np->range); +#endif + ef_zapcache(EF_SECTOR); +} + +void +xysize_range(register struct range *rp) +{ + if (rp->lx >= rp->hx) + rp->width = WORLD_X + rp->hx - rp->lx; + else + rp->width = rp->hx - rp->lx; +#ifndef HAY + /* This is a necessary check for small, hitech worlds. */ + if (rp->width > WORLD_X) + rp->width = WORLD_X; +#endif + if (rp->ly >= rp->hy) + rp->height = WORLD_Y + rp->hy - rp->ly; + else + rp->height = rp->hy - rp->ly; +#ifndef HAY + /* This is a necessary check for small, hitech worlds. */ + if (rp->height > WORLD_Y) + rp->height = WORLD_Y; +#endif +} + +/* This is called also called in snxtitem.c */ +void +xydist_range(coord x, coord y, register int dist, struct range *rp) +{ + if (dist < WORLD_X/4) { + rp->lx = xnorm((coord)(x - 2 * dist)); + rp->hx = xnorm((coord)(x + 2 * dist) + 1); + rp->width = 4 * dist + 1; + } else { + /* Range is larger than the world */ + /* Make sure we get lx in the right place. */ + rp->lx = xnorm((coord)(x - WORLD_X/2)); + rp->hx = xnorm((coord)(rp->lx + WORLD_X - 1)); + rp->width = WORLD_X; + } + + if (dist < WORLD_Y/2) { + rp->ly = ynorm((coord)(y - dist)); + rp->hy = ynorm((coord)(y + dist) + 1); + rp->height = 2 * dist + 1; + } else { + /* Range is larger than the world */ + rp->ly = ynorm((coord)(y - WORLD_Y/2)); + rp->hy = ynorm((coord)(rp->ly + WORLD_Y - 1)); + rp->height = WORLD_Y; + } +} diff --git a/src/lib/common/stmtch.c b/src/lib/common/stmtch.c new file mode 100644 index 00000000..958a13ab --- /dev/null +++ b/src/lib/common/stmtch.c @@ -0,0 +1,82 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * stmtch.c: Matching operations on structures and commands + * + * Known contributors to this file: + * + */ +/* + * XXX These routines gamble that structures are all longword-aligned. + * If this is not true, they will BREAK! + */ + +#include "misc.h" +#include "match.h" +#include "common.h" + +/* + * find a matching string from a member string pointer + * in a structure "str". Pointer is incremented by + * the (passed) size of the structure. + */ +int +stmtch(register s_char *obj, s_char *base, int off, int size) +{ + register s_char *str; + register int stat2; + register int i; + register int n; + + stat2 = M_NOTFOUND; + str = base + off; + for (i=0; *(s_char **)str; i++, str += size) { + if ((n = mineq(obj, *(s_char **)str)) == ME_MISMATCH) + continue; + if (n == ME_EXACT) + return i; + if (stat2 != M_NOTFOUND) + return M_NOTUNIQUE; + stat2 = i; + } + return stat2; +} + +/* + * do partial match comparison. + */ +int +mineq(register s_char *a, register s_char *b) +{ + do { + if (*a++ != *b++) + return ME_MISMATCH; + } while (*b != ' ' && *a != 0); + if (*a == 0 && (*b == ' ' || *b == 0)) + return ME_EXACT; + return ME_PARTIAL; +} diff --git a/src/lib/common/tfact.c b/src/lib/common/tfact.c new file mode 100644 index 00000000..dfdd847c --- /dev/null +++ b/src/lib/common/tfact.c @@ -0,0 +1,89 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * tfact.c: return tech fact given multiplier + * + * Known contributors to this file: + * Yannick Trembley + */ + +#include "misc.h" +#include "nat.h" +#include "file.h" + +extern float fire_range_factor; + +double +tfact(natid cn, double mult) +{ + double tlev; + struct natstr *np; + + np = getnatp(cn); + tlev = np->nat_level[NAT_TLEV]; + tlev = (50.0 + tlev) / (200.0 + tlev); + return mult * tlev; +} + +double +tfactfire(natid cn, double mult) +{ + double tlev; + struct natstr *np; + + np = getnatp(cn); + tlev = np->nat_level[NAT_TLEV]; + tlev = (50.0 + tlev) / (200.0 + tlev); + return mult * tlev * fire_range_factor; +} + +double +techfact(int level, double mult) +{ + return mult * ((50.0 + level) / (200.0 + level)); +} + +/* + * added so that firing range can be different to other ranges + */ +double +techfactfire(int level, double mult) +{ + return mult * ((50.0 + level) / (200.0 + level)) * fire_range_factor; +} + +/* + * figure out relative difference between two tech levels + */ +double +reltech(int level1, int level2, double mult) +{ + int diff; + + diff = level1 - level2; + return (1.0 + ((diff + 50.0) / (level1 + 50.0))) * mult; +} diff --git a/src/lib/common/type.c b/src/lib/common/type.c new file mode 100644 index 00000000..e01a5aaf --- /dev/null +++ b/src/lib/common/type.c @@ -0,0 +1,101 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * type.c: typename to array offset translation + * + * Known contributors to this file: + * Dave Pare, 1989 + * Steve McClure, 2000 + */ + +#ifdef Rel4 +#include +#endif /* Rel4 */ +#include "misc.h" +#include "ship.h" +#include "land.h" +#include "plane.h" +#include "sect.h" +#include "nuke.h" +#include "file.h" +#include "common.h" + +int +typematch(s_char *buf, int type) +{ + register int n; + int len; + + len = strlen(buf); + switch (type) { + case EF_SECTOR: { + register struct dchrstr *dcp; + + if (!buf[0] || buf[1]) + return -1; + for (dcp=dchr,n=0; dcp->d_name; n++,dcp++) + if (dcp->d_mnem == *buf) + return n; + } + break; + case EF_SHIP: { + register struct mchrstr *mcp; + + for (mcp=mchr,n=0; *mcp->m_name; n++,mcp++) + if (strncmp(mcp->m_name, buf, len) == 0) + return n; + } + break; + case EF_LAND: { + register struct lchrstr *lcp; + + for (lcp=lchr,n=0; *lcp->l_name; n++,lcp++) + if (strncmp(lcp->l_name, buf, len) == 0) + return n; + } + break; + case EF_PLANE: { + register struct plchrstr *pcp; + + for (pcp=plchr,n=0; *pcp->pl_name; n++,pcp++) + if (strncmp(pcp->pl_name, buf, len) == 0) + return n; + } + break; + case EF_NUKE: { + register struct nchrstr *ncp; + + for (ncp=nchr,n=0; *ncp->n_name; n++,ncp++) + if (strncmp(ncp->n_name, buf, len) == 0) + return n; + } + break; + default: + break; + } + return -1; +} diff --git a/src/lib/common/vlist.c b/src/lib/common/vlist.c new file mode 100644 index 00000000..3bfd9d0b --- /dev/null +++ b/src/lib/common/vlist.c @@ -0,0 +1,284 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * vlist.c: manage variable lists + * + * Known contributors to this file: + * Dave Pare, 1989 + */ + +#include "misc.h" +#include "var.h" +#include "sect.h" +#include "ship.h" +#include "land.h" +#include "product.h" +#include "optlist.h" +#include "common.h" +#include "gen.h" + +static int freeslot(u_char *vec, register u_char *end); + +int +vl_find(register int vtype, u_char *typevec, u_short *amtvec, int nelem) +{ + register u_char *vp; + register u_short *ap; + register u_char *endp; + + if (vtype < 0 || vtype > V_MAX) + return -1; + vp = typevec; + ap = amtvec; + endp = vp + nelem; + for ( ; vp < endp; vp++, ap++) { + if (*vp == vtype) + return (int) *ap; + } + return 0; +} + +int +vl_set(register int vtype, u_int amt, u_char *typevec, u_short *amtvec, u_char *nvp, int max) +{ + register u_char *vp; + register u_char *endp; + register u_short *ap; + int n; + + if (vtype < 0 || vtype > V_MAX) + return 0; + if (amt > 65536) { + logerror("vl_set: bad amt %d (%x), vtype %d\n", (int)amt, amt, + vtype); + return 0; + } + vp = typevec; + ap = amtvec; + endp = vp + *nvp; + for ( ; vp < endp; vp++, ap++) { + if (*vp == vtype) + break; + } + if (vp == endp) { + if (amt == 0) { + /* deleting, but not present */ + return 0; + } + if (*nvp == max) { + if (isdel(vtype) || isdist(vtype)) + return -1; + /* replace any del or dst entries */ + if ((n = freeslot(typevec, endp)) < 0) + return -1; + vp = &typevec[n]; + ap = &amtvec[n]; + } else { + /* add at end */ + (*nvp)++; + } + *vp = vtype; + *ap = amt; + } else { + if (amt != 0) { + /* altering; just change value */ + *ap = amt; + return 1; + } + (*nvp)--; + if (vp < endp-1) { + /* if not last element, copy last to current */ + *ap = amtvec[*nvp]; + *vp = typevec[*nvp]; + } + } + return 1; +} + +int +vl_damage(register int pct, register u_char *typevec, register u_short *amtvec, register int nelem) +{ + register int i; + register int lose; + extern double people_damage; + + if (pct >= 100) + return 0; + if (pct <= 0) + return nelem; + for (i=0; i I_MAX) { + logerror("vl_getvec: bad I-type %d (vtype %d)\n", + item, src_type[n]); + continue; + } + dst_amt[item] = src_amt[n]; + count++; + } + return count; +} + +/* + * Copy the vec into the variable list. All items zero in + * the vec will be deleted from the vlist, and all items + * present in the vec will be added to the vlist. + */ +int +vl_setvec(register u_char *type, register u_short *amt, u_char *nvp, int max, register int class, register int *vec) +{ + register int nv; + register int n; + register int vec_n; + + nv = *nvp; + vec_n = 1; + n = 0; + while (n < nv) { + if ((type[n] & VT_TYPE) != class) { + n++; + continue; + } + /* find non-zero vec entry to overwrite current slot */ + for ( ; vec_n <= I_MAX; vec_n++) + if (vec[vec_n] != 0) + break; + if (vec_n > I_MAX) { + /* no more elements left; delete */ + nv--; + if (n < nv) { + /* copy last entry over current entry */ + type[n] = type[nv]; + amt[n] = amt[nv]; + } + } else { + /* use new (unused) entry */ + type[n] = vec_n | class; + amt[n] = vec[vec_n]; + vec_n++; + n++; + } + } + *nvp = nv; + if (n >= nv && vec_n > I_MAX) + return 1; + /* free slots at end; copy rest of vec into the vlist */ + for ( ; vec_n <= I_MAX && nv < max; vec_n++) { + if (vec[vec_n] == 0) + continue; + type[nv] = vec_n | class; + amt[nv] = vec[vec_n]; + nv++; + } + *nvp = nv; + if (vec_n <= I_MAX && (class == VT_ITEM || class == VT_COND)) { + /* + * still stuff left; make free slots out of deliveries + * and distributes and stuff 'em in (only for item or cond) + */ + for ( ; vec_n <= I_MAX; vec_n++) { + if (vec[vec_n] == 0) + continue; + if ((n = freeslot(type, &type[max])) < 0) { + logerror("vl_setvec: no free slots left\n"); + return 0; + } + logerror("vl_setvec: replacing type %d amt %d\n", + type[n], amt[n]); + type[n] = vec_n | class; + amt[n] = vec[vec_n]; + } + } + if (nv == max) { + /* checking for overflow */ + while (vec_n <= I_MAX) { + if (vec[vec_n]) + break; + } + if (vec_n <= I_MAX) { + logerror("vl_setvec: no space for i-type #%d (%d)\n", + vec_n, vec[vec_n]); + return 0; + } + } + return 1; +} + +/* + * make a free slot; deliveries and distributions + * are fair game for us. + */ +static +int +freeslot(u_char *vec, register u_char *end) +{ + register u_char *vp; + + for (vp=vec; vp < end; vp++) { + if (isdel(*vp) || isdist(*vp)) + return vp - vec; + } + return -1; +} diff --git a/src/lib/common/wantupd.c b/src/lib/common/wantupd.c new file mode 100644 index 00000000..038cda62 --- /dev/null +++ b/src/lib/common/wantupd.c @@ -0,0 +1,399 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * wantupd.c: Check to se if an update is wanted and/or allowed. + * + * Known contributors to this file: + * Doug Hay, 1990 + */ + +#include +#if !defined(_WIN32) +#include +#endif +#include "misc.h" +#include "nat.h" +#include "file.h" +#include "keyword.h" +#include "wantupd.h" +#include "optlist.h" +#include "common.h" + +#include +#include +#if defined(Rel4) || defined(_WIN32) +#include +#else /* Rel4 */ +#include +#endif /* Rel4 */ + +void +update_policy_check(void) +{ + extern int update_policy,update_demandpolicy; + extern int update_wantmin,blitz_time; + + if (update_policy < 0) update_policy = UDP_DEFAULT; + if (update_policy > UDP_MAX) update_policy = UDP_DEFAULT; + if (update_demandpolicy < 0) update_demandpolicy = UDDEM_DEFAULT; + if (update_demandpolicy > UDDEM_MAX) + update_demandpolicy = UDDEM_DEFAULT; + if (update_wantmin < 0) update_wantmin = 0; + if (update_wantmin > MAXNOC) update_wantmin = MAXNOC; + if (blitz_time < 0) blitz_time = 0; +} + +static int +demand_update_time(time_t *now) +{ + struct tm *tm; + s_char *p; + int curtime; + int hour[2]; + extern s_char *update_demandtimes; + + tm = localtime(now); + curtime = tm->tm_min + tm->tm_hour * 60; + p=update_demandtimes; + if (*p == 0) return(1); + while (NULL != (p = kw_parse(CF_TIMERANGE, p, &hour[0]))) { + if (curtime >= hour[0] && curtime < hour[1]) + return(1); + } + return(0); +} + +/* When is the next regularly scheduled update from now. */ +static void +regular_update_time(time_t *now, time_t *tim, time_t *delta) +{ + extern int s_p_etu; + extern int etu_per_update; + extern int adj_update; + s_char *p; + time_t tw; + int secs_per_update; + + tw = *now + adj_update; + secs_per_update = etu_per_update * s_p_etu; + *delta = secs_per_update - (tw % secs_per_update); + *tim = *now + *delta; +} + +/* Is this a valid time for a scheduled update. */ +static int +scheduled_update_time(time_t *now, int *which) +{ + struct tm *tm; + s_char *p, *p1; + int curtime; + int hour; + extern int hourslop; + extern s_char *update_times; + + *which = -1; + p=update_times; + if (*p == 0) return(0); + + tm = localtime(now); + curtime = tm->tm_min + tm->tm_hour * 60; + while (NULL != (p = kw_parse(CF_TIME, p, &hour))) { + (*which) ++; + if (curtime >= hour && + curtime < hour+hourslop) + return(1); + } + + return 0; +} + +static int +next_scheduled_time(time_t *now, time_t *tim, time_t *delta) +{ + struct tm *tm; + s_char *p; + int curtime; + int hour; + int mintime; + extern s_char *update_times; + + p=update_times; + if (*p == 0) return(0); + + tm = localtime(now); + curtime = tm->tm_min + tm->tm_hour * 60; /* now - in minutes */ + mintime = curtime + 24*60+1; /* start with now + 1 day */ + while (NULL != (p = kw_parse(CF_TIME, p, &hour))) { + if (hour <= curtime) + hour += 24 * 60; /* this must be tomorrow */ + if (hour < mintime) + mintime = hour; /* this is best bet so far */ + } + *delta = 60*(mintime - curtime); + *tim = *now + *delta - tm->tm_sec; + return(1); +} + +int +demand_update_want(int *want, int *pop, int which) +{ + natid cn; + struct natstr *natp; + int totpop; + int totwant; + int whichwants; + + whichwants = totpop = totwant = 0; + for (cn = 1; 0 != (natp = getnatp(cn)); cn++) { + /* Only countries which are normal. */ + /* Should probably include sanctuaries ..... */ + if (((natp->nat_stat & NORM) == NORM) && + ((natp->nat_stat & GOD) != GOD)) { + totpop++; + if ((natp->nat_update & WUPD_WANT) == WUPD_WANT) { + totwant++; + if (which == cn) + whichwants++; + } + } + } + *want = totwant; + *pop = totpop; + return(whichwants); +} + +static int +demand_check(void) +{ + extern int update_wantmin,update_missed; + struct natstr *natp; + int want, pop, cn, veto; + time_t now; + time_t cur; + extern long last_demand_update; + + time(&cur); + +/* + if (last_demand_update == 0){ + natp=getnatp(0); + last_demand_update = natp->nat_reserve; + } + + logerror("last_demand_update = %d\n",last_demand_update); + logerror("update_between = %d\n",update_between()); + logerror("now = %d\n",cur); + diff = (cur-(last_demand_update + update_between())); + logerror("diff = %d\n",diff); + if (diff >= 0){ + logerror("Forced update!\n"); + last_demand_update = cur; + for (cn = 1; natp = getnatp(cn); cn++){ + if (((natp->nat_stat & NORM) == NORM) && + ((natp->nat_stat & GOD) != GOD)){ + natp->nat_missed = 0; + } + } + return(1); + } + + logerror("No forced update!\n"); +*/ + if (0 == update_wantmin) { + logerror("no demand update allowed, wantmin = 0"); + return(0); + } + + demand_update_want(&want, &pop, 0); + if (want < update_wantmin) { + logerror("no demand update, want = %d, min = %d", + want, update_wantmin); + return(0); + } + + time(&now); + if (!demand_update_time(&now)) { + logerror("no demand update, not within hours allowed."); + return(0); + } + + + veto=0; + for (cn = 1; 0 != (natp = getnatp(cn)); cn++){ + if (((natp->nat_stat & NORM) == NORM) && + ((natp->nat_stat & GOD) != GOD)){ + if (natp->nat_missed >= update_missed) + veto=cn+1; + } + } + + if (veto){ + logerror("no demand update, %d has missed more than %d updates", + veto-1, update_missed); + return(0); + } + + last_demand_update = cur; + natp=getnatp(0); + /* A dumb way to do it, but simple */ + last_demand_update = natp->nat_reserve; + return(1); +} + +/* Check if enough countries want an update, + * and if demand updates are allowed now. + */ +int +demandupdatecheck(void) +{ + extern int update_demandpolicy; + + if (UDDEM_COMSET != update_demandpolicy) { + logerror("no demand update, not policy."); + return(0); + } + + return(demand_check()); +} + +/* Is it time for a regular or scheduled update? + * As well, if none of the above, check to see if + * a demand update can occur. + */ +int +updatetime(time_t *now) +{ + extern int update_policy; + int which; + + if (opt_BLITZ && update_policy == UDP_BLITZ) { + logerror("BLITZ Update."); + return(1); + } + + if (UDP_NORMAL == update_policy) { + logerror("Regular update, etu type."); + return(1); + } + + if (UDP_TIMES == update_policy) { + if (scheduled_update_time(now, &which)) { + logerror("Scheduled update, %d.", which); + return(1); + } + } + if (opt_DEMANDUPDATE) { + if (demand_check()) { + logerror("Demand update, at check time."); + return(1); + } + } + return(0); +} + +/* Return the time, and delta seconds, of the next update. + * If the policy is no regular updates, return the time of + * the next possible check. + */ +void +next_update_time(time_t *now, time_t *tim, time_t *delta) + /* From when */ + /* Time of next update */ + /* Seconds till next update */ +{ + extern int update_policy; + time_t stim, sdelta; + extern int blitz_time; + + switch (update_policy) { + case UDP_NORMAL: + regular_update_time(now, tim, delta); + break; + case UDP_TIMES: + if (!next_scheduled_time(now, tim, delta)) + regular_update_time(now, tim, delta); + break; + case UDP_BLITZ: + *delta = (blitz_time * 60) - (*now % (blitz_time * 60)); + *tim = *now + *delta; + break; + + case UDP_NOREG: + default: + regular_update_time(now, tim, delta); + if (next_scheduled_time(now, &stim, &sdelta)) { + if (*delta > sdelta) { + *delta = sdelta; + *tim = stim; + } + } + break; + } +} + +void +next_update_check_time(time_t *now, time_t *tim, time_t *delta) + /* From when */ + /* Time of next update */ + /* Seconds till next update check */ +{ + extern int update_policy; + time_t stim, sdelta; + extern int blitz_time; + + switch (update_policy) { + case UDP_NORMAL: + regular_update_time(now, tim, delta); + break; + case UDP_BLITZ: + *delta = (blitz_time * 60) - (*now % (blitz_time * 60)); + *tim = *now + *delta; + break; + case UDP_TIMES: + case UDP_NOREG: + default: + regular_update_time(now, tim, delta); + if (next_scheduled_time(now, &stim, &sdelta)) { + if (*delta > sdelta) { + *delta = sdelta; + *tim = stim; + } + } + } +} + +int +updates_disabled(void) +{ + extern s_char *disablefil; + int fd; + + if ((fd = open(disablefil, O_RDONLY, 0)) < 0) + return 0; + close(fd); + return 1; +} diff --git a/src/lib/common/xy.c b/src/lib/common/xy.c new file mode 100644 index 00000000..2ba3c2cd --- /dev/null +++ b/src/lib/common/xy.c @@ -0,0 +1,212 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * xy.c: x-y related conversion routines + * + * Known contributors to this file: + * Dave Pare, 1989 + */ + +#include +#include +#include "misc.h" +#include "xy.h" +#include "nat.h" +#include "sect.h" +#include "deity.h" +#include "file.h" +#include +#include "common.h" +#include "optlist.h" + +/* + * return pointer to a string containing the x,y + * coords as desired by a particular target country. + */ +s_char * +xyas(coord x, coord y, natid country) +{ + struct natstr *np; + + np = getnatp(country); + return prbuf("%d,%d", xrel(np, x), yrel(np, y)); +} + +s_char * +ownxy(struct sctstr *sp) +{ + return xyas(sp->sct_x, sp->sct_y, sp->sct_own); +} + +coord +xrel(struct natstr *np, coord absx) +{ + coord x; + + if ((np->nat_stat & STAT_ABS) == 0) { + x = XNORM(absx - np->nat_xorg); + } else { + x = XNORM(absx); + } + if (x >= WORLD_X/2) + x -= WORLD_X; + else if (x < -WORLD_X/2) + x += WORLD_X; + return x; +} + +coord +yrel(struct natstr *np, coord absy) +{ + coord y; + + if ((np->nat_stat & STAT_ABS) == 0) { + y = YNORM(absy - np->nat_yorg); + } else { + y = YNORM(absy); + } + if (y >= WORLD_Y/2) + y -= WORLD_Y; + else if (y < -WORLD_Y/2) + y += WORLD_Y; + return y; +} + +void +xyrelrange(struct natstr *np, struct range *src, struct range *dst) +{ + dst->lx = xrel(np, src->lx); + dst->hx = xrel(np, src->hx); + dst->ly = yrel(np, src->ly); + dst->hy = yrel(np, src->hy); + dst->width = src->width; + dst->height = src->height; +} + +void +xyabsrange(struct natstr *np, struct range *src, struct range *dst) +{ + dst->lx = xabs(np, src->lx); + dst->hx = xabs(np, src->hx); + dst->ly = yabs(np, src->ly); + dst->hy = yabs(np, src->hy); + dst->width = src->width; + dst->height = src->height; +} + +void +inputxy(coord *xp, coord *yp, natid cn) +{ + struct natstr *np; + + np = getnatp(cn); + *xp = xabs(np, *xp); + *yp = yabs(np, *yp); +} + +coord +xabs(struct natstr *np, coord relx) +{ + if ((np->nat_stat & STAT_ABS) == 0) + relx += np->nat_xorg; + return XNORM(relx); +} + +coord +yabs(struct natstr *np, coord rely) +{ + if ((np->nat_stat & STAT_ABS) == 0) + rely += np->nat_yorg; + return YNORM(rely); +} + +int +sctoff(coord x, coord y) +{ + if ((x + y) & 01) { + logerror("%d,%d is an invalid sector specification!\n", x, y); + return -1; + } + return (YNORM(y) * WORLD_X + XNORM(x))/2; +} + +coord +xnorm(register coord x) +{ + if (x < 0) + x = WORLD_X - (-x % WORLD_X); + return x % WORLD_X; +} + +coord +ynorm(register coord y) +{ + if (y < 0) + y = WORLD_Y - (-y % WORLD_Y); + return y % WORLD_Y; +} + +int +xyinrange(coord x, coord y, struct range *rp) +{ + if (rp->lx < rp->hx) { + /* xrange doesn't wrap */ + if (x < rp->lx || x > rp->hx) + return 0; + } else { + if (x < rp->lx && x > rp->hx) + return 0; + } + if (rp->ly < rp->hy) { + /* yrange doesn't wrap */ + if (y < rp->ly || y > rp->hy) + return 0; + } else { + if (y < rp->ly && y > rp->hy) + return 0; + } + return 1; +} + + +s_char * +prbuf(s_char *format, ...) +{ + static int nbuf = -1; + static s_char buf[20][1024]; + va_list ap; + + if (++nbuf > 19) + nbuf = 0; + + va_start(ap, format); + (void) vsprintf(buf[nbuf], format, ap); + va_end(ap); + + return buf[nbuf]; +} + diff --git a/src/lib/empthread/Makefile b/src/lib/empthread/Makefile new file mode 100644 index 00000000..6c3940a3 --- /dev/null +++ b/src/lib/empthread/Makefile @@ -0,0 +1,60 @@ +# +# Empire - A multi-player, client/server Internet based war game. +# Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, +# Ken Stevens, Steve McClure +# +# 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 2 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, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# --- +# +# See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the +# related information and legal notices. It is expected that any future +# projects/authors will amend these files as needed. +# +# Makefile - Wolfpack, 1996 + +# Note that these could have been listed 1 per line, but I chose to just +# stick them all together this way to shorten the file. + +include ../../../build.conf +include ../../make.src +include ../../make.defs + +LIB = $(SRCDIR)/lib/libempth.a +NTLIB = $(SRCDIR)\lib\libempth.lib + +OBJS = lwp.o pthread.o ntthread.o + +NTOBJS = lwp.obj pthread.obj ntthread.obj + +all: $(LIB) + +nt: $(NTLIB) + +$(NTLIB): $(NTOBJS) + -del /q $@ + lib /OUT:$@ /DEBUGTYPE:CV $(NTOBJS) + +$(LIB): $(OBJS) + rm -f $(LIB) + ar cq $(LIB) $(OBJS) + $(RANLIB) $(LIB) + +clean: + -(rm -f $(OBJS)) + -(del /q $(NTOBJS)) + +include ../../make.rules +include Makedepend diff --git a/src/lib/empthread/lwp.c b/src/lib/empthread/lwp.c new file mode 100644 index 00000000..7e876409 --- /dev/null +++ b/src/lib/empthread/lwp.c @@ -0,0 +1,147 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * lwp.c: Interface from Empire threads to LWP threads + * + * Known contributors to this file: + * Sasha Mikheev + */ + +#include +#include "prototypes.h" +#include "empthread.h" + +#ifdef _EMPTH_LWP + +int +empth_init (char **ctx, int flags) +{ + lwpInitSystem(7, ctx, flags); + return 0; +} + + +empth_t * +empth_create (int prio, void (*entry)(), int size, int flags, char *name, + char *desc, void *ud) +{ + /* inherit flags */ + if(!flags) + flags = LwpCurrent->flags; + return lwpCreate(prio, entry, size, flags, name, desc, 0, 0, ud); +} + +#if 0 +/* This is unused now? */ +void +empth_setctx(void *ctx) +{ + /* lwp does it automatically */ + return; +} +#endif + +empth_t * +empth_self(void) +{ + return LwpCurrent; +} + +void +empth_exit (void) +{ + time_t now; + + /* We want to leave the main thread around forever, until it's time + for it to die for real (in a shutdown) */ + if (!strcmp(LwpCurrent->name, "Main")) { + while(1) { + time(&now); + lwpSleepUntil(now + 60); + } + } + lwpExit(); +} + +void +empth_yield (void) +{ + /* a hack! */ + lwpReschedule(); +} + +void +empth_terminate(empth_t *a) +{ + lwpTerminate(a); +} + +void +empth_select(int fd, int flags) +{ + lwpSleepFd(fd, flags); +} + +void +empth_wakeup(empth_t *a) +{ + lwpWakeupFd(a); +} + +void +empth_sleep(long int until) +{ + lwpSleepUntil(until); +} + + +empth_sem_t * +empth_sem_create(char *name, int cnt) +{ + return lwpCreateSem(name, cnt); +} + +void +empth_sem_signal(empth_sem_t *sm) +{ + lwpSignal(sm); +} + +void +empth_sem_wait (empth_sem_t *sm) +{ + lwpWait(sm); +} + +emp_sig_t +empth_alarm(int sig) +{ + /* no way we can be here while using LWP threads */ + panic(sig); +} +#endif + diff --git a/src/lib/empthread/ntthread.c b/src/lib/empthread/ntthread.c new file mode 100644 index 00000000..a373a25c --- /dev/null +++ b/src/lib/empthread/ntthread.c @@ -0,0 +1,728 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * ntthread.c: Interface from Empire threads to Windows NT threads + * + * Known contributors to this file: + * Doug Hay, 1998 + * Steve McClure, 1998 + */ + +/* + * EMPTHREADs for Windows NT. + * + * Actually, threads for any Win32 platform, + * like Win95, Win98, WinCE, and whatever other + * toy OSs are in our future from Microsoft. + * + * WIN32 has a full pre-emptive threading environment. + * But, Empire can not handle pre-emptive threading. + * Thus, we will use the threads, but limit the preemption + * using a Mutex semaphore. + * + */ + +#include +#include +#include +#include +#include "misc.h" +#include "empthread.h" +#include "prototypes.h" + +#if defined(_WIN32) && defined(_EMPTH_WIN32) +#include +#include + + +#define loc_MIN_THREAD_STACK 16384 + +/************************ + * loc_Thread_t + * + * The REAL empth_t thread structure. + * The external world only gets + * a void pointer to this. + */ +typedef struct { + + /* The thread name, passed in at create time. */ + char szName[17]; + /* The thread description, passed in at create time. */ + char szDesc[80]; + + /* True if this is the main line, and not a real thread. */ + BOOL bMainThread; + + /* The user data passed in at create time. */ + void *pvUserData; + + /* True if this thread has been killed. */ + BOOL bKilled; + + /* The entry function for the thread. */ + void (*pfnEntry)(void *); + + /* The system thread ID. */ + unsigned long ulThreadID; + + /* An Event sem that the thread will wait/sleep on. */ + HANDLE hThreadEvent; +} loc_Thread_t; + + +/************************ + * loc_Sem_t + * + * The REAL empth_sem_t structure. + * The external world only gets + * a void pointer to this. + */ +typedef struct { + + char szName[17]; + + /* An exclusion semaphore for this sem. */ + HANDLE hMutex; + /* An Event sem that the thread(s) will sleep on. */ + + HANDLE hEvent; + /* The count variable */ + int count; +} loc_Sem_t; + +static struct +{ + /* This is the thread exclusion/non-premption mutex. */ + /* The running thread has this MUTEX, and all others are */ + /* either blocked on it, or waiting for some OS response. */ + HANDLE hThreadMutex; + + /* This is the thread startup event sem. */ + /* We use this to lockstep when we are starting up threads. */ + HANDLE hThreadStartEvent; + + /* The Thread Local Storage index. We store the pThread pointer */ + /* for each thread at this index. */ + DWORD dwTLSIndex; + + /* The current running thread. */ + loc_Thread_t *pCurThread; + + /* Ticks at start */ + unsigned long ulTickAtStart; + + /* Pointer out to global context. "player". */ + /* From empth_init parameter. */ + char **ppvUserData; + + /* Global flags. From empth_init parameter. */ + int flags; +} loc_GVAR; + + +/************************ + * loc_debug + * + * Print out the current thread's status?? + */ +static void +loc_debug(const char *pszFmt, ...) +{ + va_list vaList; + unsigned long ulCurTick; + unsigned long ulRunTick; + unsigned long ulMs, ulSec, ulMin, ulHr; + loc_Thread_t *pThread = + (loc_Thread_t *) TlsGetValue(loc_GVAR.dwTLSIndex); + char buf[1024]; + + if ((loc_GVAR.flags & EMPTH_PRINT) != 0) { + + /* Ticks are in milliseconds */ + ulCurTick = GetTickCount(); + + ulRunTick = ulCurTick - loc_GVAR.ulTickAtStart; + ulMs = ulRunTick % 1000L; + ulSec = (ulRunTick / 1000L) % 60L; + ulMin = (ulRunTick / (60L * 1000L)) % 60L; + ulHr = (ulRunTick / (60L * 60L * 1000L)); + + va_start(vaList, pszFmt); + vsprintf(buf, pszFmt, vaList); + va_end(vaList); + + if (pThread) { + printf("%ld:%02ld:%02ld.%03ld %17s: %s\n", + ulHr, ulMin, ulSec, ulMs, + pThread->szName, + buf); + } else { + printf("%ld:%02ld:%02ld.%03ld %17s: %s\n", + ulHr, ulMin, ulSec, ulMs, + "UNKNOWN", + buf); + } + + } +} + +/************************ + * loc_FreeThreadInfo + * + */ +static void +loc_FreeThreadInfo(loc_Thread_t *pThread) +{ + if (pThread) { + if (pThread->hThreadEvent) + CloseHandle(pThread->hThreadEvent); + memset(pThread, 0, sizeof(*pThread)); + free(pThread); + } +} + +/************************ + * loc_RunThisThread + * + * This thread wants to run. + * When this function returns, the + * globals are set to this thread info, + * and the thread owns the MUTEX sem. + */ +static void +loc_RunThisThread() +{ + loc_Thread_t *pThread = + (loc_Thread_t *) TlsGetValue(loc_GVAR.dwTLSIndex); + + if (pThread->bKilled) { + if (!pThread->bMainThread) { + TlsSetValue(loc_GVAR.dwTLSIndex, NULL); + loc_FreeThreadInfo(pThread); + _endthread(); + } + } + + /* Get the MUTEX semaphore, wait forever. */ + WaitForSingleObject(loc_GVAR.hThreadMutex, INFINITE); + + if (!loc_GVAR.pCurThread) { + /* Set the globals to this thread. */ + *loc_GVAR.ppvUserData = pThread->pvUserData; + + loc_GVAR.pCurThread = pThread; + } else { + /* Hmm, a problem, eh? */ + logerror("RunThisThread, someone already running."); + } +} + +/************************ + * loc_BlockThisThread + * + * This thread was running. It no longer wants to. + */ +static void +loc_BlockThisThread() +{ + loc_Thread_t *pThread = + (loc_Thread_t *) TlsGetValue(loc_GVAR.dwTLSIndex); + + if (loc_GVAR.pCurThread == pThread) { + /* Reset the globals back to original */ + + loc_GVAR.pCurThread = NULL; + *loc_GVAR.ppvUserData = NULL; + + /* Release the MUTEX */ + ReleaseMutex(loc_GVAR.hThreadMutex); + } else { + /* Hmm, this thread was not the running one. */ + logerror("BlockThisThread, not running."); + } +} + + +/************************ + * loc_SleepThisThread + */ +static void +loc_SleepThisThread(unsigned long ulMillisecs) +{ + loc_Thread_t *pThread = + (loc_Thread_t *) TlsGetValue(loc_GVAR.dwTLSIndex); + + /* Make sure the event thread is clean. */ + ResetEvent(pThread->hThreadEvent); + + /* Get the MUTEX semaphore, wait the number of MS */ + WaitForSingleObject(pThread->hThreadEvent, ulMillisecs); +} + + +/************************ + * empth_threadMain + * + * This is the main line of each thread. + * This is really a static local func.... + */ +void +empth_threadMain(void *pvData) +{ + loc_Thread_t *pThread = (loc_Thread_t *)pvData; + + /* Out of here... */ + if (!pvData) return; + + /* Store pThread on this thread. */ + TlsSetValue(loc_GVAR.dwTLSIndex, pvData); + + /* Get the ID of the thread. */ + pThread->ulThreadID = GetCurrentThreadId(); + + /* Signal that the thread has started. */ + SetEvent(loc_GVAR.hThreadStartEvent); + + /* Switch to this thread context */ + loc_RunThisThread(); + + /* Run the thread. */ + if (pThread->pfnEntry) + pThread->pfnEntry(pThread->pvUserData); + + /* Kill the thread. */ + empth_exit(); +} + +/************************ + * empth_init + * + * Initialize the thread environment. + * + * This is called from the program + * main line. + */ +int +empth_init (char **ctx_ptr, int flags) +{ + loc_Thread_t *pThread = NULL; + + loc_GVAR.ulTickAtStart = GetTickCount(); + loc_GVAR.ppvUserData = ctx_ptr; + loc_GVAR.flags = flags; + loc_GVAR.dwTLSIndex = TlsAlloc(); + + /* Create the thread mutex sem. */ + /* Initally unowned. */ + loc_GVAR.hThreadMutex = CreateMutex(NULL, FALSE, NULL); + if (!loc_GVAR.hThreadMutex) { + logerror("Failed to create mutex"); + return 0; + } + + /* Create the thread start event sem. */ + /* Automatic state reset. */ + loc_GVAR.hThreadStartEvent = CreateEvent(NULL, FALSE, FALSE, NULL); + if (!loc_GVAR.hThreadStartEvent) { + logerror("Failed to create mutex"); + return 0; + } + + /* Create the global Thread context. */ + pThread = (loc_Thread_t *) malloc(sizeof(*pThread)); + if (!pThread) { + logerror("not enough memory to create main thread."); + return 0; + } + memset(pThread, 0, sizeof(*pThread)); + + strncpy(pThread->szName, "Main", sizeof(pThread->szName)-1); + strncpy(pThread->szDesc, "The main process", sizeof(pThread->szDesc)-1); + pThread->ulThreadID = GetCurrentThreadId(); + pThread->bMainThread = TRUE; + + TlsSetValue(loc_GVAR.dwTLSIndex, pThread); + + /* Make this the running thread. */ + loc_RunThisThread(); + + logerror("NT pthreads initialized"); + return 0; +} + + +/************************ + * empth_create + * + * Create a new thread. + * + * prio - priority, not particularly useful in our context. + * entry - entry point function for thread. + * size - stack size. + * flags - debug control. + * LWP_STACKCHECK - not needed + * name - name of the thread, for debug. + * desc - description of thread, for debug. + * ud - "user data". The "ctx_ptr" gets this value + * when the thread is active. + * It is also passed to the entry function... + */ +empth_t * +empth_create (int prio, void (*entry)(), int size, int flags, + char *name, char *desc, void *ud) +{ + loc_Thread_t *pThread = NULL; + + loc_debug("creating new thread %s:%s", name, desc); + + pThread = (loc_Thread_t *) malloc(sizeof(*pThread)); + if (!pThread) { + logerror("not enough memory to create thread: %s (%s)", name, desc); + return NULL; + } + memset(pThread, 0, sizeof(*pThread)); + + strncpy(pThread->szName, name, sizeof(pThread->szName)-1); + strncpy(pThread->szDesc, desc, sizeof(pThread->szDesc)-1); + pThread->pvUserData = ud; + pThread->pfnEntry = entry; + pThread->bMainThread = FALSE; + + /* Create thread event sem, auto reset. */ + pThread->hThreadEvent = CreateEvent(NULL, FALSE, FALSE, NULL); + + if (size < loc_MIN_THREAD_STACK) + size = loc_MIN_THREAD_STACK; + + pThread->ulThreadID = _beginthread(empth_threadMain, size, + (void *)pThread); + if (pThread->ulThreadID == -1) { + logerror("can not create thread: %s (%s): %s", name, desc, + strerror(errno)); + goto bad; + } + + loc_debug("new thread id is %ld", pThread->ulThreadID); + return pThread; + +bad: + if (pThread) { + loc_FreeThreadInfo(pThread); + } + return NULL; +} + + +/************************ + * empth_self + */ +empth_t * +empth_self(void) +{ + loc_Thread_t *pThread = + (loc_Thread_t *) TlsGetValue(loc_GVAR.dwTLSIndex); + + return pThread; +} + +/************************ + * empth_exit + */ +void +empth_exit (void) +{ + s_char *getlogfile(); + + loc_Thread_t *pThread = + (loc_Thread_t *) TlsGetValue(loc_GVAR.dwTLSIndex); + + loc_BlockThisThread(); + + loc_debug("empth_exit"); + + if (pThread->bMainThread) { + char buf[20]; + /* The main line. Wait forever. */ + if (getlogfile() == (s_char *)0) + loginit(); + printf("log file: %s\n", getlogfile()); + while (1) { + printf("\nEmpire Server>"); + fgets(buf, sizeof(buf), stdin); + if (!strnicmp(buf, "quit", 4)) + break; + } + TlsSetValue(loc_GVAR.dwTLSIndex, NULL); + loc_FreeThreadInfo(pThread); + } else { + TlsSetValue(loc_GVAR.dwTLSIndex, NULL); + loc_FreeThreadInfo(pThread); + _endthread(); + } +} + +/************************ + * empth_yield + * + * Yield processing to another thread. + */ +void +empth_yield (void) +{ + loc_BlockThisThread(); + loc_RunThisThread(); +} + +/************************ + * empth_terminate + * + * Kill off the thread. + */ +void +empth_terminate(empth_t *a) +{ + loc_Thread_t *pThread = (loc_Thread_t *) a; + + loc_debug("killing thread %s", pThread->szName); + pThread->bKilled = TRUE; + + SetEvent(pThread->hThreadEvent); +} + +/************************ + * empth_select + * + * Do a select on the given file. + * Wait for IO on it. + * + * This would be one of the main functions used within + * gen\io.c + */ +void +empth_select(int fd, int flags) +{ + loc_Thread_t *pThread = + (loc_Thread_t *) TlsGetValue(loc_GVAR.dwTLSIndex); + fd_set readmask; + fd_set writemask; + struct lwpProc *proc; + struct timeval tv; + int n; + + loc_debug("%s select on %d", + flags == EMPTH_FD_READ ? "read" : "write", fd ); + loc_BlockThisThread(); + + while (1) { + tv.tv_sec = 1000000; + tv.tv_usec = 0; + + FD_ZERO(&readmask); + FD_ZERO(&writemask); + + switch(flags) { + case EMPTH_FD_READ: + FD_SET(fd, &readmask); + break; + case EMPTH_FD_WRITE: + FD_SET(fd, &writemask); + break; + default: + logerror("bad flag %d passed to empth_select", flags); + empth_exit(); + } + + n = select(fd + 1, &readmask, &writemask, (fd_set *)0, &tv); + + if (n < 0) { + if (errno == EINTR) { + /* go handle the signal */ + loc_debug("select broken by signal"); + goto done; + return; + } + /* strange but we dont get EINTR on select broken by signal */ + loc_debug("select failed (%s)", strerror(errno)); + goto done; + return; + } + + if (flags == EMPTH_FD_READ && FD_ISSET(fd, &readmask)) { + loc_debug("input ready"); + break; + } + if (flags == EMPTH_FD_WRITE && FD_ISSET(fd, &writemask)) { + loc_debug("output ready"); + break; + } + } + +done: + loc_RunThisThread(); +} + +/************************ + * empth_alarm + */ +emp_sig_t +empth_alarm(int sig) +{ + loc_Thread_t *pThread = + (loc_Thread_t *) TlsGetValue(loc_GVAR.dwTLSIndex); + + loc_debug("got alarm signal %d", sig); + + /* Let it run if it is blocked like... */ + SetEvent(pThread->hThreadEvent); +} + +/************************ + * empth_wakeup + * + * Wake up the specified thread. + */ +void +empth_wakeup(empth_t *a) +{ + loc_Thread_t *pThread = (loc_Thread_t *)a; + + loc_debug("waking up thread %s", pThread->szName); + + /* Let it run if it is blocked... */ + SetEvent(pThread->hThreadEvent); +} + +/************************ + * empth_sleep + * + * Put the given thread to sleep... + */ +void +empth_sleep(long until) +{ + loc_Thread_t *pThread = + (loc_Thread_t *) TlsGetValue(loc_GVAR.dwTLSIndex); + unsigned long ulSec; + + ulSec = until - time(0); + + loc_debug("going to sleep %ld sec", ulSec); + + loc_BlockThisThread(); + + WaitForSingleObject(pThread->hThreadEvent, (ulSec * 1000)); + + loc_debug("sleep done. Waiting to run."); + + loc_RunThisThread(); +} + + +/************************ + * empth_sem_create + * + * Create a signalling semaphore. + */ +empth_sem_t * +empth_sem_create(char *name, int cnt) +{ + loc_Sem_t *pSem; + + pSem = (loc_Sem_t *) malloc(sizeof(*pSem)); + if (!pSem) { + logerror("out of memory at %s:%d", __FILE__, __LINE__); + return NULL; + } + + memset(pSem, 0, sizeof(pSem)); + strncpy(pSem->szName, name, sizeof(pSem->szName)-1); + + pSem->hMutex = CreateMutex(NULL, FALSE, NULL); + pSem->hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); + pSem->count = cnt; + + return pSem; +} + +/************************ + * empth_sem_signal + * + * Hit/signal the specified semaphore. + */ +void +empth_sem_signal(empth_sem_t *sm) +{ + loc_Sem_t *pSem = (loc_Sem_t *) sm; + + loc_debug("signal on semaphore %s:%d", pSem->szName, pSem->count); + + /* Wait for the Semaphore */ + WaitForSingleObject(pSem->hMutex, INFINITE); + + if (pSem->count++ < 0) { + SetEvent(pSem->hEvent); + } + + ReleaseMutex(pSem->hMutex); +} + +/************************ + * empth_sem_wait + * + * Wait for the specified signal semaphore + * to be signaled. + */ +void +empth_sem_wait (empth_sem_t *sm) +{ + loc_Thread_t *pThread = + (loc_Thread_t *) TlsGetValue(loc_GVAR.dwTLSIndex); + loc_Sem_t *pSem = (loc_Sem_t *) sm; + + loc_debug("wait on semaphore %s:%d", pSem->szName, pSem->count); + + /* Remove the thread from the running state. */ + loc_BlockThisThread(); + + /* Wait for the Semaphore */ + WaitForSingleObject(pSem->hMutex, INFINITE); + if (--pSem->count < 0) { + loc_debug("blocking"); + ReleaseMutex(pSem->hMutex); + + WaitForSingleObject(pSem->hEvent, INFINITE); + + loc_debug("waking up"); + } + else + ReleaseMutex(pSem->hMutex); + + loc_RunThisThread(); +} + +#endif /* _WIN32 */ diff --git a/src/lib/empthread/pthread.c b/src/lib/empthread/pthread.c new file mode 100644 index 00000000..cc6d41bc --- /dev/null +++ b/src/lib/empthread/pthread.c @@ -0,0 +1,518 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * pthread.c: Interface from Empire threads to POSIX threads + * + * Known contributors to this file: + * Sasha Mikheev + * Steve McClure, 1998 + */ + +#include +#if !defined(_WIN32) +#include +#include +#endif +#include +#include +#include +#include + +#include "misc.h" +#include "empthread.h" +#include "prototypes.h" + +#include + +#ifdef _EMPTH_POSIX +static pthread_key_t ctx_key; +static int empth_flags; +static char **udata; /* pointer to out global context */ + +static pthread_mutex_t mtx_ctxsw; /* thread in critical section */ + + +#if 0 +static void empth_setctx _PROTO((void *)); +#endif +static void empth_restorectx _PROTO(()); + +void * +empth_start(void *ctx) +{ + struct sigaction act; + extern emp_sig_t panic(); + extern emp_sig_t shutdwn(); + + + /* actually it should inherit all this from main but... */ +#ifdef SA_SIGINFO + act.sa_flags = SA_SIGINFO; +#endif + sigemptyset (&act.sa_mask); + act.sa_handler = shutdwn; + /* pthreads on Linux use SIGUSR1 (*shrug*) so only catch it if not on + a Linux box running POSIX threads -- STM */ +#if !(defined(__linux__) && defined(_EMPTH_POSIX)) + sigaction (SIGUSR1, &act, NULL); +#endif + sigaction (SIGTERM, &act, NULL); + sigaction (SIGINT, &act, NULL); + act.sa_handler = panic; + sigaction (SIGBUS, &act, NULL); + sigaction (SIGSEGV, &act, NULL); + sigaction (SIGILL, &act, NULL); + sigaction (SIGFPE, &act, NULL); + act.sa_handler = SIG_IGN; + sigaction(SIGPIPE, &act, NULL); + + act.sa_handler = empth_alarm; + sigaction(SIGALRM, &act, NULL); + + ((empth_t *)ctx)->id = pthread_self(); + pthread_setspecific(ctx_key, ctx); + pthread_mutex_lock(&mtx_ctxsw); + *udata = ((empth_t *)ctx)->ud; + ((empth_t *)ctx)->ep(((empth_t *)ctx)->ud); + empth_exit(); + return NULL; +} + +static void +empth_status(char *format, ...) +{ + va_list ap; + static struct timeval startTime; + struct timeval tv; + char buf[1024]; + int sec, msec; + empth_t *a; + + va_start(ap, format); + if (empth_flags & EMPTH_PRINT) { + if (startTime.tv_sec == 0) + gettimeofday(&startTime, 0); + gettimeofday(&tv, 0); + sec = tv.tv_sec - startTime.tv_sec; + msec = (tv.tv_usec - startTime.tv_usec) / 1000; + if (msec < 0) { + sec++; + msec += 1000; + } + vsprintf(buf, format, ap); + a = empth_self(); + printf("%d:%02d.%03d %17s: %s\n", sec/60, sec%60, msec/10, + a->name, + buf); + + } + va_end(ap); +} + + +int +empth_init (char **ctx_ptr, int flags) +{ + empth_t *ctx; + struct sigaction act; + + + pthread_key_create(&ctx_key, 0); +#ifdef _DECTHREADS_ + pthread_mutex_init(&mtx_ctxsw, pthread_mutexattr_default); +#else + pthread_mutex_init(&mtx_ctxsw, 0); +#endif + + act.sa_flags = 0; + sigemptyset (&act.sa_mask); + act.sa_handler = empth_alarm; + sigaction(SIGALRM, &act, NULL); + + udata = ctx_ptr; + ctx = (empth_t *)malloc(sizeof(empth_t)); + if(!ctx) { + logerror("pthread init failed: not enough memory"); + exit(1); + } + ctx->name = "Main"; + ctx->desc = "empire main"; + ctx->ep = 0; + ctx->ud = 0; + ctx->id = pthread_self(); + ctx->state = 0; + pthread_setspecific(ctx_key, ctx); + pthread_mutex_lock(&mtx_ctxsw); + empth_flags = flags; + logerror("pthreads initialized"); + return 0; +} + + +/* + * prio can be used for setting scheeduling policy but... + * it seems to be optional in POSIX threads and Solaris + * for example just ignores it. + * More then that priority is not needed even in lwp threads. + */ +empth_t * +empth_create (int prio, void (*entry)(), int size, int flags, + char *name, char *desc, void *ud) +{ + pthread_t t; + pthread_attr_t attr; + empth_t *ctx; + int eno; + + empth_status("creating new thread %s:%s", name, desc); + + ctx = (empth_t *)malloc(sizeof(empth_t)); + if(!ctx) { + logerror("not enough memoty to create thread: %s (%s)", name, desc); + return NULL; + } + ctx->name = strdup(name); + ctx->desc = strdup(desc); + ctx->ud = ud; + ctx->state = 0; + ctx->ep = entry; + +#ifdef _DECTHREADS_ + eno = pthread_attr_init(&attr) ? errno : 0; +#else + eno = pthread_attr_init(&attr); +#endif + if(eno) { + logerror("can not create thread attribute %s (%s): %s", name, desc, + strerror(eno)); + goto bad; + } + +#if defined(__linux__) + /* Linux doesn't let you adjust the stack */ +#elif defined(_DECTHREADS_) + /* DEC does not have PTHREAD_STACK_MIN constant */ + /* Do not go below default size */ + if(size > pthread_attr_getstacksize(attr)) + pthread_attr_setstacksize(&attr, size); +#else + if(size < PTHREAD_STACK_MIN) + size = PTHREAD_STACK_MIN + 1; + + pthread_attr_setstacksize(&attr, size); +#endif + + pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED); + +#ifdef _DECTHREADS_ + eno = pthread_create(&t, attr, empth_start, (void *)ctx) ? errno : 0; +#else + eno = pthread_create(&t, &attr, empth_start, (void *)ctx); +#endif + if (eno) { + logerror("can not create thread: %s (%s): %s", name, desc, + strerror(eno)); + goto bad; + } + empth_status("new thread id is %d", t); + return ctx; + pthread_attr_destroy(&attr); +bad: + pthread_attr_destroy(&attr); + free(ctx); + return NULL; +} + + +#if 0 +static void +empth_setctx(void *ct) +{ + empth_t *ctx_ptr; + +#ifdef _DECTHREADS_ + pthread_getspecific(ctx_key, (pthread_addr_t *)&ctx_ptr); +#else + ctx_ptr = (empth_t *)pthread_getspecific(ctx_key); +#endif + ctx_ptr->ud = ct; + *udata = ((empth_t *)ctx_ptr)->ud; + pthread_setspecific(ctx_key, (void *)ctx_ptr); + empth_status("context saved"); +} +#endif + +static void +empth_restorectx(void) +{ + empth_t *ctx_ptr; + +#ifdef _DECTHREADS_ + pthread_getspecific(ctx_key, (pthread_addr_t *)&ctx_ptr); +#else + ctx_ptr = (empth_t *)pthread_getspecific(ctx_key); +#endif + *udata = (char *)ctx_ptr->ud; + if (ctx_ptr->state == EMPTH_KILLED) { + empth_status("i am dead"); + empth_exit(); + } + empth_status("context restored"); +} + +empth_t * +empth_self(void) +{ +#ifdef _DECTHREADS_ + empth_t *ctx_ptr; + + pthread_getspecific(ctx_key, (pthread_addr_t *)&ctx_ptr); + return ctx_ptr; +#else + return (empth_t *)pthread_getspecific(ctx_key); +#endif +} + +void +empth_exit (void) +{ + empth_t *ctx_ptr; + + pthread_mutex_unlock(&mtx_ctxsw); + empth_status("empth_exit"); +#ifdef _DECTHREADS_ + pthread_getspecific(ctx_key, (pthread_addr_t *)&ctx_ptr); +#else + ctx_ptr = (empth_t *)pthread_getspecific(ctx_key); +#endif + /* We want to leave the main thread around forever, until it's time + for it to die for real (in a shutdown) */ + if (!strcmp(ctx_ptr->name, "Main")) { + while(1) { +#ifdef _DECTHREADS_ + pthread_yield(); +#endif + sleep(60); + } + } + + free(ctx_ptr); + pthread_exit(0); +} + +void +empth_yield (void) +{ + pthread_mutex_unlock(&mtx_ctxsw); + sleep(10); /* take a nap pthread_yield(); */ + pthread_mutex_lock(&mtx_ctxsw); + empth_restorectx(); +} + +void +empth_terminate(empth_t *a) +{ + /* logerror("calling non supported function empth_terminate: %s:%d", + __FILE__, __LINE__); */ + empth_status("killing thread %s", a->name); + a->state = EMPTH_KILLED; +#ifndef _DECTHREADS_ + /* DEC and OSX do not have pthread_kill. Not sure that cancel is correct. */ + #if (!defined __ppc__) + pthread_kill(a->id, SIGALRM); + #endif +#endif + return; +} + +void +empth_select(int fd, int flags) +{ + + fd_set readmask; + fd_set writemask; + struct timeval tv; + int n; + + pthread_mutex_unlock(&mtx_ctxsw); + empth_status("%s select on %d", + flags == EMPTH_FD_READ ? "read" : "write", fd ); + while (1) { + tv.tv_sec = 1000000; + tv.tv_usec = 0; + + FD_ZERO(&readmask); + FD_ZERO(&writemask); + + switch(flags) { + case EMPTH_FD_READ: + FD_SET(fd, &readmask); + break; + case EMPTH_FD_WRITE: + FD_SET(fd, &writemask); + break; + default: + logerror("bad flag %d passed to empth_select", flags); + empth_exit(); + } + + n = select(fd + 1, &readmask, &writemask, (fd_set *)0, &tv); + + if (n < 0) { + if (errno == EINTR) { + /* go handle the signal */ + empth_status("select broken by signal"); + goto done; + return; + } + /* strange but we dont get EINTR on select broken by signal */ + empth_status("select failed (%s)", strerror(errno)); + goto done; + return; + } + + if (flags == EMPTH_FD_READ && FD_ISSET(fd, &readmask)) { + empth_status("input ready"); + break; + } + if (flags == EMPTH_FD_WRITE && FD_ISSET(fd, &writemask)) { + empth_status("output ready"); + break; + } + } + +done: + pthread_mutex_lock(&mtx_ctxsw); + empth_restorectx(); + +} + + +emp_sig_t +empth_alarm(int sig) +{ + struct sigaction act; + empth_status("got alarm signal"); +#ifdef SA_RESTART + act.sa_flags &= ~SA_RESTART; +#endif + sigemptyset (&act.sa_mask); + act.sa_handler = empth_alarm; + sigaction(SIGALRM, &act, NULL); +} + +void +empth_wakeup(empth_t *a) +{ + empth_status("waking up thread %s", a->name); +#ifndef _DECTHREADS_ + #if (!defined __ppc__) + pthread_kill(a->id, SIGALRM); + #endif +#endif + empth_status("waiting for it to run"); + /* empth_yield(); */ +} + +void +empth_sleep(long until) +{ + struct timeval tv; + + empth_status("going to sleep %ld sec", until - time(0)); + pthread_mutex_unlock(&mtx_ctxsw); + tv.tv_sec = until - time(NULL); + tv.tv_usec = 0; + do { + select (0, NULL, NULL, NULL, &tv); + } while ((tv.tv_sec = until - time(NULL)) > 0); + empth_status("sleep done. Waiting for lock"); + pthread_mutex_lock(&mtx_ctxsw); + empth_restorectx(); +} + + +empth_sem_t * +empth_sem_create(char *name, int cnt) +{ + empth_sem_t *sm; + + sm = (empth_sem_t *)malloc(sizeof(empth_sem_t)); + if(!sm) { + logerror("out of memory at %s:%d", __FILE__, __LINE__); + return NULL; + } + strncpy(sm->name, name, sizeof(sm->name)-1); + sm->count = cnt; +#ifdef _DECTHREADS_ + pthread_mutex_init(&sm->mtx_update, pthread_mutexattr_default); + pthread_mutex_init(&sm->mtx_sem, pthread_mutexattr_default); + pthread_cond_init(&sm->cnd_sem, pthread_condattr_default); +#else + pthread_mutex_init(&sm->mtx_update, 0); + pthread_mutex_init(&sm->mtx_sem, 0); + pthread_cond_init(&sm->cnd_sem, 0); +#endif + return sm; +} + +void +empth_sem_signal(empth_sem_t *sm) +{ + empth_status("signal on semaphore %s:%d", sm->name, sm->count); + pthread_mutex_lock(&sm->mtx_update); + if(sm->count++ < 0) { + pthread_mutex_unlock(&sm->mtx_update); + pthread_mutex_lock(&sm->mtx_sem); + pthread_cond_signal(&sm->cnd_sem); + pthread_mutex_unlock(&sm->mtx_sem); + } + else + pthread_mutex_unlock(&sm->mtx_update); +} + +void +empth_sem_wait (empth_sem_t *sm) +{ + empth_status("wait on semaphore %s:%d", sm->name, sm->count); + pthread_mutex_lock(&sm->mtx_update); + if(--sm->count < 0) { + pthread_mutex_unlock(&sm->mtx_update); + empth_status("blocking"); + pthread_mutex_unlock(&mtx_ctxsw); + pthread_mutex_lock(&sm->mtx_sem); + pthread_cond_wait(&sm->cnd_sem, &sm->mtx_sem); + empth_status("waking up"); + pthread_mutex_unlock(&sm->mtx_sem); + pthread_mutex_lock(&mtx_ctxsw); + empth_restorectx(); + } + else + pthread_mutex_unlock(&sm->mtx_update); +} + +#endif diff --git a/src/lib/gen/Makefile b/src/lib/gen/Makefile new file mode 100644 index 00000000..eb18783c --- /dev/null +++ b/src/lib/gen/Makefile @@ -0,0 +1,68 @@ +# +# Empire - A multi-player, client/server Internet based war game. +# Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, +# Ken Stevens, Steve McClure +# +# 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 2 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, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# --- +# +# See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the +# related information and legal notices. It is expected that any future +# projects/authors will amend these files as needed. +# +# Makefile - Wolfpack, 1996 + +# Note that these could have been listed 1 per line, but I chose to just +# stick them all together this way to shorten the file. + +include ../../../build.conf +include ../../make.src +include ../../make.defs + +LIB = $(SRCDIR)/lib/libgen.a +NTLIB = $(SRCDIR)\lib\libgen.lib + +OBJS = atoip.o atopi.o bit.o chance.o copy.o disassoc.o dtable.o \ + emp_config.o getstarg.o getstring.o hpux.o iceil.o inet.o io.o \ + io_mask.o ioqueue.o lock.o mapdist.o minmax.o numstr.o onearg.o \ + parse.o plur.o queue.o round.o same.o scthash.o signal.o \ + strdup.o strscan.o vsprintf.o + +NTOBJS = atoip.obj atopi.obj bit.obj chance.obj copy.obj disassoc.obj \ + dtable.obj emp_config.obj getstarg.obj getstring.obj hpux.obj iceil.obj \ + inet.obj io.obj io_mask.obj ioqueue.obj lock.obj mapdist.obj minmax.obj \ + numstr.obj onearg.obj parse.obj plur.obj queue.obj round.obj same.obj \ + scthash.obj signal.obj strdup.obj strscan.obj vsprintf.obj + +all: $(LIB) + +nt: $(NTLIB) + +$(NTLIB): $(NTOBJS) + -del /q $@ + lib /OUT:$@ /DEBUGTYPE:CV $(NTOBJS) + +$(LIB): $(OBJS) + rm -f $(LIB) + ar cq $(LIB) $(OBJS) + $(RANLIB) $(LIB) + +clean: + -(rm -f $(OBJS)) + -(del /q $(NTOBJS)) + +include ../../make.rules +include Makedepend diff --git a/src/lib/gen/atoip.c b/src/lib/gen/atoip.c new file mode 100644 index 00000000..5e13dd82 --- /dev/null +++ b/src/lib/gen/atoip.c @@ -0,0 +1,59 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * atoip.c: Convert from decimal string to integer. + * + * Known contributors to this file: + * + */ + +#include "gen.h" + +int +atoip(s_char **ptrptr) +{ + register int num; + register s_char *cp; + register int neg; + + if (ptrptr == 0 || *ptrptr == 0) return 0; + cp = *ptrptr; + num = 0; + neg = 0; +loop: + while (*cp == ' ' || *cp == '\t') + cp++; + if (*cp == '-') { + neg++; + cp++; + goto loop; + } + while (*cp >= '0' && *cp <= '9') + num = num * 10 + *cp++ - '0'; + *ptrptr = cp; + return(neg ? -num : num); +} diff --git a/src/lib/gen/atopi.c b/src/lib/gen/atopi.c new file mode 100644 index 00000000..5807b609 --- /dev/null +++ b/src/lib/gen/atopi.c @@ -0,0 +1,55 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * atopi.c: Return positive integer from string. + * + * Known contributors to this file: + * + */ + +#include "gen.h" + +/* + * atopi.c + * + * from PSL Empire, 1985 + */ + +int +atopi(s_char *p) +{ + register int r11; + + if (p) { + r11 = atoi(p); + if (r11 < 0) + r11 = -r11; + return r11; + } else { + return (0); + } +} diff --git a/src/lib/gen/bit.c b/src/lib/gen/bit.c new file mode 100644 index 00000000..47ea9e37 --- /dev/null +++ b/src/lib/gen/bit.c @@ -0,0 +1,206 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * bit.c: Allocate and search select bitfields + * + * Known contributors to this file: + * Steve McClure, 2000 + */ + +#include "misc.h" +#include "bit.h" +#include "gen.h" /* getfdtablesize etc. */ + +static int bit_nbytes; + +bit_fdmask +bit_newfdmask(void) +{ + bit_fdmask mask; + int nfile; + + if (bit_nbytes == 0) { + nfile = getfdtablesize(); + bit_nbytes = (nfile + (BIT_BITSPERMASK-1)) / BIT_NBBY; + } + mask = (bit_fdmask) malloc(bit_nbytes); + (void) bit_zero(mask); + return mask; +} + +/* + * zero the bitfield + */ +void +bit_zero(bit_fdmask bitp) +{ + bit_mask *mask; + register int i; + register int nwords; + + mask = bitp; + nwords = bit_nbytes / sizeof(*mask); + for (i=0; i roll/32768.0) + return 1; + return 0; +} + +int +roll(int n) +{ + return (random() % n) + 1; +} + +/* + * round value to nearest int (on the average). E.g. rounds up + * with a chance proportional to the size of the fractional part. + */ +int +roundavg(double val) +{ + int flr; + + flr = (int) val; + if (val < 0) + flr -= chance(flr - val); + else + flr += chance(val - flr); + return flr; +} diff --git a/src/lib/gen/copy.c b/src/lib/gen/copy.c new file mode 100644 index 00000000..ebed9296 --- /dev/null +++ b/src/lib/gen/copy.c @@ -0,0 +1,83 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * copy.c: Copy and return pointer to end of copied string. + * + * Known contributors to this file: + * + */ + +#include "misc.h" +#include "xy.h" +#include "map.h" +#include "gen.h" +#include "optlist.h" + +s_char * +copy(register s_char *s1, register s_char *s2) +{ + while ((*s2++ = *s1++) != 0) + ; + return s2 - 1; +} + +#ifdef hpux +#include + +void +bzero(s_char *ptr, int len) +{ + memset(ptr, 0, len); +} + +void +bcopy(s_char *src, s_char *dst, int len) +{ + memcpy(dst, src, len); +} +#endif + +/* + * space-fill a map or radar scan; + * null terminate + */ +void +blankfill(s_char *ptr, register struct range *range, int size) +{ + register s_char *p; + register int row; + register int col; + + for (row=0; rowheight; row++) { + col = (range->width + 1) * (size + 1) / 2 - 1; + p = ptr; + while (--col >= 0) + *p++ = ' '; + *p++ = 0; + ptr += MAPWIDTH(size); + } +} diff --git a/src/lib/gen/disassoc.c b/src/lib/gen/disassoc.c new file mode 100644 index 00000000..b4559f56 --- /dev/null +++ b/src/lib/gen/disassoc.c @@ -0,0 +1,72 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * disassoc.c: Fork and close + * + * Known contributors to this file: + * Doug Hay, 1998 + */ + +/* + * boilerplate daemon code; disassociate from + * the current tty by forking, closing all file + * descriptors, opening slash, and ioctl-ing + * TIOCNOTTY + */ + +#include +#if !defined(_WIN32) +#include +#include /* fork close dup2 */ +#endif +#include +#include "gen.h" + +void +disassoc(void) +{ +#if !defined(_WIN32) + int i; + + if (fork() != 0) + exit(0); + for (i = 0; i < 10; i++) + (void) close(i); + (void) open("/", O_RDONLY, 0); + (void) dup2(0, 1); + (void) dup2(0, 2); +#if defined hpux || defined Rel4 + setsid(); +#else + i = open("/dev/tty", O_RDWR, 0); + if (i > 0) { + (void) ioctl(i, TIOCNOTTY, 0); + (void) close(i); + } +#endif +#endif +} diff --git a/src/lib/gen/dtable.c b/src/lib/gen/dtable.c new file mode 100644 index 00000000..0f07a665 --- /dev/null +++ b/src/lib/gen/dtable.c @@ -0,0 +1,65 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * dtable.c: Machine-dependant descriptor table management + * + * Known contributors to this file: + * Doug Hay, 1998 + */ + +#if !defined(_WIN32) +#include /* getdtablesize */ +#endif +#include "gen.h" + +/*ARGSUSED*/ +void +setfdtablesize(int min, int start) +{ +#ifdef sequent + extern int errno; + + while (start >= min) { + if (setdtablesize(start) > 0) + break; + start -= 16; + } + errno = 0; +#endif +} + +int +getfdtablesize(void) +{ +#if defined(_WIN32) + return (_NFILE); +#elif defined(hpux) + return (int)sysconf(_SC_OPEN_MAX); +#else + return getdtablesize(); +#endif +} diff --git a/src/lib/gen/emp_config.c b/src/lib/gen/emp_config.c new file mode 100644 index 00000000..7aa228df --- /dev/null +++ b/src/lib/gen/emp_config.c @@ -0,0 +1,679 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * emp_config.c: Allows config file to control server config. from a file + * + * Known contributors to this file: + * Julian Onions, 1995 + * Steve McClure, 1998-2000 + */ + +/* + * STILL TO DO + * + * 1. Change other constants - such as Num Countries etc. + * Just requires variables to be assigned, then dynamic allocation in + * a few places. Some checks needed in the server to check the world + * hasn't changed size etc. + * 2. Could look at loading in planes, units etc. Should be easy enough. + * + */ + +#include +#include /* atoi free atol */ +#ifdef Rel4 +#include +#endif /* Rel4 */ + +#include "misc.h" +#include "com.h" +#include "match.h" +#include "file.h" +#include "optlist.h" +#include "gen.h" /* parse */ + +/* for systems without strdup */ +#ifdef NOSTRDUP +extern char *strdup(); +#endif /* NOSTRDUP */ + +/* All the configurable variables ... */ +extern s_char *infodir, *datadir, *gamedir, *loginport, *privname, *privlog; + +extern double buil_tower_bt, buil_tower_bc; +extern double buytax, flakscale, maxmult, minmult, tradetax, uwbrate; +extern double buil_bc, buil_bt, combat_mob, edu_cons, hap_cons, money_civ; +extern double money_land, money_mil, money_plane, money_res, money_ship; +extern double money_uw, people_damage, powe_cost, unit_damage, babyeat; +extern double collateral_dam, assault_penalty; +extern double bankint, eatrate, fcrate, fgrate, obrate, mission_mob_cost; + +extern float btu_build_rate, easy_tech, hard_tech, land_mob_scale; +extern float level_age_rate, plane_mob_scale, sect_mob_scale; +extern float ship_mob_scale, tech_log_base, ally_factor, edu_avg, hap_avg; + +extern int buil_tower_bh; +extern int startmob, at_least_one_100, buil_bh, etu_per_update; +extern int land_grow_scale, land_mob_max, m_m_p_d, max_btus, max_idle; +extern int plane_grow_scale, plane_mob_max, players_at_00, sect_mob_max; +extern int ship_grow_scale, ship_mob_max, torpedo_damage; +extern int fort_max_interdiction_range; +extern int land_max_interdiction_range; +extern int ship_max_interdiction_range; +extern int sect_mob_neg_factor; +extern int lost_items_timeout; +extern int WORLD_X; +extern int WORLD_Y; +extern int MARK_DELAY; +extern int TRADE_DELAY; + +extern int morale_base; +extern float fire_range_factor; + +extern long adj_update; +extern long s_p_etu; +extern int update_policy; +extern s_char *update_times; +extern int hourslop; +extern int update_window; +extern int blitz_time; +extern int update_demandpolicy; +extern s_char *update_demandtimes; +extern int update_wantmin; +extern int update_missed; +extern s_char *game_days; +extern s_char *game_hours; + +/* conditional ones */ +extern double decay_per_etu, fallout_spread; + +extern int fuel_mult; + +extern int War_Cost; +extern long last_demand_update; + +extern float drnuke_const; +extern float start_education, start_happiness; +extern float start_technology, start_research; + +extern int trade_1_dist, trade_2_dist, trade_3_dist; +extern float trade_1, trade_2, trade_3, trade_ally_bonus, trade_ally_cut; + +/* Dummy one */ +static int emp_config_dummy; + +/* things that can be changed */ +struct keymatch configkeys[] = { +{ "", intset, (caddr_t)&emp_config_dummy, 0, "\n### Server configuration and information" }, +{ "data", optstrset, (caddr_t) &datadir, 0, + "Directory the data is stored in" }, +{ "info", optstrset, (caddr_t) &infodir, 0, + "Directory the info pages are stored in" }, +{ "port", optstrset, (caddr_t) &loginport, 0, + "TCP/IP port the server will start up on" }, +{ "privname", optstrset, (caddr_t) &privname, 0, + "Name of the deity" }, +{ "privlog", optstrset, (caddr_t) &privlog, 0, + "E-mail of the deity" }, +{ "WORLD_X", worldxset, (caddr_t) &WORLD_X, 0, + "World size X dimension (enforced to be even by subtracting 1 if necessary)" }, +{ "WORLD_Y", intset, (caddr_t) &WORLD_Y, 0, + "World size Y dimension" }, + +{ "", intset, (caddr_t)&emp_config_dummy, 0, "\n\n### Update policy" }, +{ "update_policy", intset, (caddr_t) &update_policy, 0, + "0 - normal, 1 - update_times, 2 - blitz, 3 - demand only" }, +{ "etu_per_update", intset, (caddr_t) &etu_per_update, 0, + "Number of ETUs per update" }, +{ "s_p_etu", longset, (caddr_t) &s_p_etu, 0, + "Seconds per etu, updates will occur every s_p_etu * etu_per_update seconds" }, +{ "adj_update", longset, (caddr_t) &adj_update, 0, + "Move the update forward or backward (in seconds)" }, +{ "update_window", intset, (caddr_t) &update_window, 0, + "Window the update will occur in (in seconds) before and after the update time" }, +{ "update_times", optstrset, (caddr_t) &update_times, 0, + "Times when updates occur under policy #1. Must coincide with schedule." }, +{ "hourslop", intset, (caddr_t) &hourslop, 0, + "Number of minutes update check can slip to match update_times" }, +{ "blitz_time", intset, (caddr_t) &blitz_time, 0, + "Number of minutes between updates under policy #2." }, + +{ "", intset, (caddr_t)&emp_config_dummy, 0, "\n\n### Demand update policy" }, +{ "update_demandpolicy",intset, (caddr_t) &update_demandpolicy, 0, + "0 - emp_tm checks, 1 - after setting, 2 - demand updates disabled" }, +{ "update_wantmin", intset, (caddr_t) &update_wantmin, 0, + "number of requests needed for demand update" }, +{ "update_missed", intset, (caddr_t) &update_missed, 0, + "number of demand updates country can miss before veto update" }, +{ "update_demandtimes", optstrset, (caddr_t) &update_demandtimes, 0, + "Times when demand updates can occur. Ranges CANNOT cross midnight." }, + +{ "", intset, (caddr_t)&emp_config_dummy, 0, "\n\n### Game hours restrictions" }, +{ "game_days", optstrset, (caddr_t) &game_days, 0, + "Days game is up and running (Su Mo Tu We Th Fr Sa)" }, +{ "game_hours", optstrset, (caddr_t) &game_hours, 0, + "Hours game is up and running (6:00-18:00)" }, + +{ "", intset, (caddr_t)&emp_config_dummy, 0, "\n\n### Options\n" }, +{ "option", optionset, (caddr_t) NULL, 0, NULL }, +{ "nooption", optiondel, (caddr_t) NULL, 0, NULL }, + + +{ "", intset, (caddr_t)&emp_config_dummy, 0, "\n\n### Countries" }, +{ "btu_build_rate", floatset, (caddr_t) &btu_build_rate, 0, + "Rate at which BTUs accumulate (etu * civ * eff * btu_build_rate)" }, +{ "m_m_p_d", intset, (caddr_t) &m_m_p_d, 0, + "Maximum minutes per day a country is allowed to be logged in" }, +{ "max_btus", intset, (caddr_t) &max_btus, 0, + "Maximum number of BTUs a country can have" }, +{ "max_idle", intset, (caddr_t) &max_idle, 0, + "Maximum number of minutes a player can sit idle while logged in" }, +{ "players_at_00", intset, (caddr_t) &players_at_00, 0, + "Players have their coordinate system at deity 0,0 (0 - no, 1 - yes)" }, +{ "at_least_one_100", intset, (caddr_t) &at_least_one_100, 0, + "Initialize new countries with at least one sector with 100 of all resource" }, +{ "powe_cost", doubleset, (caddr_t) &powe_cost, 0, + "Number of BTUs needed to generate a new power report" }, +{ "war_cost", intset, (caddr_t) &War_Cost, 0, + "Cost to declare war (if SLOW_WAR is on)" }, + +{ "", intset, (caddr_t)&emp_config_dummy, 0, "\n\n### Technology/Research/Education/Happiness" }, +{ "easy_tech", floatset, (caddr_t) &easy_tech, 0, + "Amount of tech built with no penalty" }, +{ "hard_tech", floatset, (caddr_t) &hard_tech, 0, + "Amount of in-efficiently built tech" }, +{ "start_tech", floatset, (caddr_t) &start_technology, 0, + "Starting technology for new countries" }, +{ "start_happy", floatset, (caddr_t) &start_happiness, 0, + "Starting happiness for new countries" }, +{ "start_research", floatset, (caddr_t) &start_research, 0, + "Starting research for new countries" }, +{ "start_edu", floatset, (caddr_t) &start_education, 0, + "Starting education for new countries" }, +{ "level_age_rate", floatset, (caddr_t) &level_age_rate, 0, + "ETU rate at which tech decays (0 -> no decline)" }, +{ "tech_log_base", floatset, (caddr_t) &tech_log_base, 0, + "Log base to apply to tech breakthroughs above the easy tech level" }, +{ "ally_factor", floatset, (caddr_t) &ally_factor, 0, + "Shared tech with allies (1 / ally_factor)" }, +{ "edu_avg", floatset, (caddr_t) &edu_avg, 0, + "Number of ETUs education is averaged over" }, +{ "hap_avg", floatset, (caddr_t) &hap_avg, 0, + "Number of ETUs happiness is averaged over" }, +{ "edu_cons", doubleset, (caddr_t) &edu_cons, 0, + "Education consumption (1 breakthrough per edu_cons)" }, +{ "hap_cons", doubleset, (caddr_t) &hap_cons, 0, + "Happiness consumption (1 breakthrough per hap_cons)" }, + +{ "", intset, (caddr_t)&emp_config_dummy, 0, "\n\n### Sectors" }, +{ "startmob", intset, (caddr_t) &startmob, 0, + "Starting mobility for sanctuaries" }, +{ "sect_mob_scale", floatset, (caddr_t) §_mob_scale, 0, + "Sector mobility accumulation (sect_mob_scale * ETUs per update)" }, +{ "sect_mob_max", intset, (caddr_t) §_mob_max, 0, + "Maximum mobility for sectors" }, +{ "buil_bh", intset, (caddr_t) &buil_bh, 0, + "Number of hcms required to build a bridge span" }, +{ "buil_bc", doubleset, (caddr_t) &buil_bc, 0, + "Cash required to build a bridge span" }, +{ "buil_bt", doubleset, (caddr_t) &buil_bt, 0, + "Technology required to build a bridge span" }, +{ "buil_tower_bh", intset, (caddr_t) &buil_tower_bh, 0, + "Number of hcms required to build a bridge tower" }, +{ "buil_tower_bc", doubleset, (caddr_t) &buil_tower_bc, 0, + "Cash required to build a bridge tower" }, +{ "buil_tower_bt", doubleset, (caddr_t) &buil_tower_bt, 0, + "Technology required to build a bridge tower" }, + +{ "", intset, (caddr_t)&emp_config_dummy, 0, "\n\n### Land Units" }, +{ "land_mob_scale", floatset, (caddr_t) &land_mob_scale, 0, + "Land unit mobility accumulation (land_mob_scale * ETUs per update)" }, +{ "land_grow_scale", intset, (caddr_t) &land_grow_scale, 0, + "How fast efficiency grows for land units each update (* ETUs)" }, +{ "land_mob_max", intset, (caddr_t) &land_mob_max, 0, + "Maximum mobility for land units" }, +{ "money_land", doubleset, (caddr_t) &money_land, 0, + "Cost per ETU to maintain land units (percentage of unit price)" }, +{ "morale_base", intset, (caddr_t) &morale_base, 0, + "Base level for setting morale of land units" }, + +{ "", intset, (caddr_t)&emp_config_dummy, 0, "\n\n### Planes" }, +{ "plane_mob_scale", floatset, (caddr_t) &plane_mob_scale, 0, + "Plane mobility accumulation (plane_mob_scale * ETUs per update)" }, +{ "plane_grow_scale", intset, (caddr_t) &plane_grow_scale, 0, + "How fast efficiency grows for planes each update (* ETUs)" }, +{ "plane_mob_max", intset, (caddr_t) &plane_mob_max, 0, + "Maximum mobility for planes" }, +{ "money_plane", doubleset, (caddr_t) &money_plane, 0, + "Cost per ETU to maintain planes (percentage of plane price)" }, + +{ "", intset, (caddr_t)&emp_config_dummy, 0, "\n\n### Ships" }, +{ "ship_mob_scale", floatset, (caddr_t) &ship_mob_scale, 0, + "Ship mobility accumulation (ship_mob_scale * ETUs per update)" }, +{ "ship_grow_scale", intset, (caddr_t) &ship_grow_scale, 0, + "How fast efficiency grows for ships each update (* ETUs)" }, +{ "ship_mob_max", intset, (caddr_t) &ship_mob_max, 0, + "Maximum mobility for ships" }, +{ "money_ship", doubleset, (caddr_t) &money_ship, 0, + "Cost per ETU to maintain ships (percentage of ship price)" }, +{ "torpedo_damage", intset, (caddr_t) &torpedo_damage, 0, + "Torpedo damage (damage is X + 1dX + 1dX)" }, + +{ "", intset, (caddr_t)&emp_config_dummy, 0, "\n\n### Combat/Damage" }, +{ "fort_max_interdiction_range", intset, (caddr_t)&fort_max_interdiction_range, 0, + "Maximum range (in sectors) a fort will try to interdict another country" }, +{ "land_max_interdiction_range", intset, (caddr_t)&land_max_interdiction_range, 0, + "Maximum range (in sectors) a land unit will try to interdict another country" }, +{ "ship_max_interdiction_range", intset, (caddr_t)&ship_max_interdiction_range, 0, + "Maximum range (in sectors) a ship will try to interdict another country" }, +{ "flakscale", doubleset, (caddr_t) &flakscale, 0, + "Scale factor for flak damage" }, +{ "combat_mob", doubleset, (caddr_t) &combat_mob, 0, + "How much mobility do units spend for combat (* casualties/bodies)" }, +{ "people_damage", doubleset, (caddr_t) &people_damage, 0, + "People take this amount of normal damage" }, +{ "unit_damage", doubleset, (caddr_t) &unit_damage, 0, + "Land units take this amount of normal damage" }, +{ "collateral_dam", doubleset, (caddr_t) &collateral_dam, 0, + "Side effect damage amount done to sector" }, +{ "assault_penalty", doubleset, (caddr_t) &assault_penalty, 0, + "Amount of normal attacking efficiency for paratroopers and assaulting" }, +{ "fire_range_factor", floatset, (caddr_t) &fire_range_factor, 0, + "Scale normal firing ranges by this amount" }, +{ "sect_mob_neg_factor", intset, (caddr_t) §_mob_neg_factor, 0, + "Amount of negative mobility a sector has after takeover (ETU / x) (MOB_ACCESS)" }, +{ "mission_mob_cost", doubleset, (caddr_t) &mission_mob_cost, 0, + "Cost to put something on a mission (percentage of max mob)" }, + +{ "", intset, (caddr_t)&emp_config_dummy, 0, "\n\n### Populace" }, +{ "uwbrate", doubleset, (caddr_t) &uwbrate, 0, + "Birth rate for uw's" }, +{ "money_civ", doubleset, (caddr_t) &money_civ, 0, + "Money gained from taxes on a civilian in one ETU" }, +{ "money_mil", doubleset, (caddr_t) &money_mil, 0, + "Money gained from taxes on an active soldier in one ETU" }, +{ "money_res", doubleset, (caddr_t) &money_res, 0, + "Money gained from taxes on a soldier on active reserve in one ETU" }, +{ "money_uw", doubleset, (caddr_t) &money_uw, 0, + "Money gained from taxes on an uncompensated worker in one ETU" }, +{ "babyeat", doubleset, (caddr_t) &babyeat, 0, + "Amount of food to mature 1 baby into a civilian" }, +{ "bankint", doubleset, (caddr_t) &bankint, 0, + "Bank dollar gain (per bar per etu)" }, +{ "eatrate", doubleset, (caddr_t) &eatrate, 0, + "Food eating rate for mature people" }, +{ "fcrate", doubleset, (caddr_t) &fcrate, 0, + "Food cultivation rate (* workforce in sector)" }, +{ "fgrate", doubleset, (caddr_t) &fgrate, 0, + "Food growth rate (* fertility of sector)" }, +{ "obrate", doubleset, (caddr_t) &obrate, 0, + "Civilian birth rate" }, + +{ "", intset, (caddr_t)&emp_config_dummy, 0, "\n\n### Nukes" }, +{ "decay_per_etu", doubleset, (caddr_t) &decay_per_etu, 0, + "Decay of fallout per ETU" }, +{ "fallout_spread", doubleset, (caddr_t) &fallout_spread, 0, + "Amount of fallout that leaks into surrounding sectors" }, +{ "drnuke_const", floatset, (caddr_t) &drnuke_const, 0, + "Amount of research to tech needed to build a nuke (if DR_NUKE is on)" }, + +{ "", intset, (caddr_t)&emp_config_dummy, 0, "\n\n### Market/Trade" }, +{ "MARK_DELAY", intset, (caddr_t) &MARK_DELAY, 0, + "Number of seconds commodities stay on the market for bidding" }, +{ "TRADE_DELAY", intset, (caddr_t) &TRADE_DELAY, 0, + "Number of seconds ships, planes, and units stay on the market for bidding" }, +{ "maxmult", doubleset, (caddr_t) &maxmult, 0, + "Maximum trade multiple (used for mult command)" }, +{ "minmult", doubleset, (caddr_t) &minmult, 0, + "Minimum trade multiple (used for mult command)" }, +{ "buytax", doubleset, (caddr_t) &buytax, 0, + "Tax (in percentage points) charged to the buyer on market purchases" }, +{ "tradetax", doubleset, (caddr_t) &tradetax, 0, + "Amount of a trade transaction the seller makes (the rest is tax)" }, + +{ "", intset, (caddr_t)&emp_config_dummy, 0, "\n\n### Trade ships" }, +{ "trade_1_dist", intset, (caddr_t) &trade_1_dist, 0, + "Less than this distance no money for cashing in" }, +{ "trade_2_dist", intset, (caddr_t) &trade_2_dist, 0, + "Less than this distance gets trade_1 money for cashing in" }, +{ "trade_3_dist", intset, (caddr_t) &trade_3_dist, 0, + "Less than this distance gets trade_2 money for cashing in (>= gets trade_3" }, +{ "trade_1", floatset, (caddr_t) &trade_1, 0, + "Return per sector on trade_1 distance amount" }, +{ "trade_2", floatset, (caddr_t) &trade_2, 0, + "Return per sector on trade_2 distance amount" }, +{ "trade_3", floatset, (caddr_t) &trade_3, 0, + "Return per sector on trade_3 distance amount" }, +{ "trade_ally_bonus", floatset, (caddr_t) &trade_ally_bonus, 0, + "Bonus you get for cashing in with an ally" }, +{ "trade_ally_cut", floatset, (caddr_t) &trade_ally_cut, 0, + "Bonus your ally gets for you cashing in with them" }, + +{ "", intset, (caddr_t)&emp_config_dummy, 0, "\n\n### Misc." }, +{ "fuel_mult", intset, (caddr_t) &fuel_mult, 0, + "Multiplier for fuel to mobility calculation" }, +{ "lost_items_timeout", intset, (caddr_t) &lost_items_timeout, 0, + "Seconds before a lost item is timed out of the database" }, +{ "last_demand_update", longset, (caddr_t) &last_demand_update, 0, + "When was the last demand update occured" }, + +{ NULL, NULL, (caddr_t)0, 0, NULL } +}; + +static void fixup_files _PROTO((void)); +static struct keymatch *keylookup _PROTO((s_char *key, struct keymatch tbl[])); + + +/* + * read in empire configuration + */ +int +emp_config (char *file) +{ + FILE *fp; + s_char scanspace[1024]; + s_char *av[65]; + char buf[BUFSIZ]; + struct keymatch *kp; + + if (file == NULL || (fp = fopen (file, "r")) == NULL) { + fixup_files (); + return RET_OK; + } + while (fgets (buf, sizeof buf, fp) != NULL) { + if (buf[0] == '#' || buf[0] == '\n') + continue; + if (parse (buf, av, 0, scanspace, 0) < 0) { + fprintf (stderr, "Can't parse line %s", buf); + continue; + } + if ((kp = keylookup (av[0], configkeys)) != NULL) { + (*kp -> km_func) (kp, av + 1); + } + else { + fprintf (stderr, "Unknown config key %s\n", av[0]); + } + } + fclose (fp); + fixup_files (); + + return RET_OK; +} + +struct otherfiles { + s_char **files; + char *name; +}; + +extern s_char *upfil, *downfil, *disablefil, *banfil, *authfil; +extern s_char *commfil, *annfil, *telfil, *teldir, *timestampfil; + +/* list of other well known files... -maybe tailor these oneday + * anyway - meantime they are all relative to datadir */ +static struct otherfiles ofiles[] = { +{ &upfil, "up" }, +{ &downfil, "down"}, +{ &disablefil, "disable"}, +{ &banfil, "ban" }, +{ &authfil, "auth" }, +{ &commfil, "comm" }, +{ &annfil, "ann" }, +{ ×tampfil, "timestamp" }, +{ &teldir, "tel" }, +#if !defined(_WIN32) +{ &telfil, "tel/tel" }, +#else +{ &telfil, "tel\\tel" }, +#endif +{ NULL, NULL } +}; + +/* fix up the empfile struct to reference full path names */ +static void fixup_files (void) +{ + struct empfile *ep; + struct otherfiles *op; + s_char buf[1024]; + + for (ep = empfile; ep < &empfile[EF_MAX]; ep ++) { +#if !defined(_WIN32) + sprintf (buf, "%s/%s", datadir, ep->name); +#else + sprintf (buf, "%s\\%s", datadir, ep->name); +#endif + ep->file = strdup (buf); + } + + for (op = ofiles; op -> files; op ++) { +#if !defined(_WIN32) + sprintf (buf, "%s/%s", datadir, op -> name); +#else + sprintf (buf, "%s\\%s", datadir, op -> name); +#endif + *op -> files = strdup (buf); + } +} + +/* find the key in the table */ +static struct keymatch *keylookup (register s_char *command, struct keymatch *tbl) +{ + register struct keymatch *kp; + + if (command == 0 || *command == 0) + return 0; + for (kp = tbl; kp->km_key != 0; kp++) { + if (strcmp (kp -> km_key, command) == 0) + return kp; + } + return NULL; +} + +/* worldx int setting function */ +void worldxset (struct keymatch *kp, s_char **av) +{ + int *intptr = (int *)kp -> km_data; + + if (*av == NULL || intptr == NULL) + return; + *intptr = atoi (*av); + if (!((*intptr % 2) == 0)) { + /* Must be div / 2, so subtract one */ + *intptr = *intptr - 1; + } +} + +/* generic int setting function */ +void intset (struct keymatch *kp, s_char **av) +{ + int *intptr = (int *)kp -> km_data; + + if (*av == NULL || intptr == NULL) + return; + *intptr = atoi (*av); +} + +/* generic float set function */ +void floatset (struct keymatch *kp, s_char **av) +{ + float *floatptr = (float *)kp -> km_data; + + if (*av == NULL || floatptr == NULL) + return; + *floatptr = atof (*av); +} + + + +/* generic string set function */ +void optstrset (struct keymatch *kp, s_char **av) +{ + s_char **confstrp = (s_char **)kp -> km_data; + + if (*av == NULL || confstrp == NULL) + return; + if (kp -> km_flags & KM_ALLOC) + free (*confstrp); + *confstrp = strdup (*av); + kp -> km_flags |= KM_ALLOC; +} + +/* generic double set function */ +void doubleset (struct keymatch *kp, s_char **av) +{ + double *doublep = (double *)kp -> km_data; + + if (*av == NULL || doublep == NULL) + return; + *doublep = atof (*av); +} + +/* generic long set function */ +void longset (struct keymatch *kp, s_char **av) +{ + long int *longp = (long int *)kp -> km_data; + + if (*av == NULL || longp == NULL) + return; + *longp = atol (*av); +} + +void +print_config (FILE *fp) +{ + struct empfile *ep; + struct otherfiles *op; + struct keymatch *kp; + + fprintf(fp, "# Empire Configuration File:\n"); + for (kp = configkeys; kp -> km_key; kp ++) { + /* We print a few special things here */ + if (kp->km_comment) { + if (kp->km_comment[0]) { + if (kp->km_comment[0] != '\n') + fprintf(fp, "\n# "); + fprintf(fp, "%s\n", kp->km_comment); + } + } + if (!kp->km_key[0]) + continue; + if (kp -> km_func == optstrset) { + fprintf (fp, "%s \"%s\"\n", kp -> km_key, + *(s_char **)kp -> km_data); + } + else if (kp -> km_func == intset) { + fprintf (fp, "%s %d\n", kp -> km_key, + *(int *)kp -> km_data); + } + else if (kp -> km_func == worldxset) { + fprintf (fp, "%s %d\n", kp -> km_key, + *(int *)kp -> km_data); + } + else if (kp -> km_func == floatset) { + fprintf (fp, "%s %g\n", kp -> km_key, + *(float *)kp -> km_data); + } + else if (kp -> km_func == doubleset) { + fprintf (fp, "%s %g\n", kp -> km_key, + *(double *)kp -> km_data); + } + else if (kp -> km_func == longset) { + fprintf (fp, "%s %ld\n", kp -> km_key, + *(long *)kp -> km_data); + } + else if (kp -> km_func == optionset) { + struct option_list *op; + + for (op = Options; op -> opt_key; op++) { + if (*op -> opt_valuep) + fprintf (fp, "%s %s\n", kp -> km_key, + op -> opt_key); + } + } + else if (kp -> km_func == optiondel) { + struct option_list *op; + + for (op = Options; op -> opt_key; op++) { + if (*op -> opt_valuep == 0) + fprintf (fp, "%s %s\n", kp -> km_key, + op -> opt_key); + } + } + else fprintf (fp, "# Unknown format %s\n", kp -> km_key); + } + + fprintf(fp, "\n"); + for (ep = empfile; ep < &empfile[EF_MAX]; ep ++) + fprintf (fp, "# File %s -> %s\n", ep -> name, ep -> file); + for (op = ofiles; op -> files; op ++) + fprintf (fp, "# File %s -> %s\n", op -> name, *(op -> files)); + +} + + +/* add an option to the list */ +void set_option (const char *s) +{ + struct option_list *op; + + for (op = Options; op -> opt_key; op++) { + if (strcmp (op -> opt_key, s) == 0) + *op -> opt_valuep = 1; + } +} + +/* delete an option from the list */ +void delete_option (const char *s) +{ + struct option_list *op; + + for (op = Options; op -> opt_key; op++) { + if (strcmp (op -> opt_key, s) == 0) + *op -> opt_valuep = 0; + } +} + +/* config interface */ +void optionset (struct keymatch *kp, s_char **av) + /* unused - we have a well known global */ + +{ + char **cpp; + + for (cpp = (char **)av; *cpp; cpp++) + set_option (*cpp); +} + +/* config interface */ +void optiondel (struct keymatch *kp, s_char **av) + /* unused - we have a well known global */ + +{ + char **cpp; + + for (cpp = (char **)av; *cpp; cpp++) + delete_option (*cpp); +} diff --git a/src/lib/gen/getstarg.c b/src/lib/gen/getstarg.c new file mode 100644 index 00000000..a6c12a0a --- /dev/null +++ b/src/lib/gen/getstarg.c @@ -0,0 +1,50 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * getstarg.c: Get a string argument (ask if not there) + * + * Known contributors to this file: + * + */ + +#include "misc.h" +#include "gen.h" + +s_char * +getstarg(s_char *input, s_char *prompt, s_char *buf) +{ + extern s_char *getstring(s_char *prompt, s_char *buf); + + *buf = '\0'; + if (input == 0 || *input == 0) { + if (getstring(prompt, buf) == 0) + return 0; + } else { + strcpy(buf, input); + } + return buf; +} diff --git a/src/lib/gen/getstring.c b/src/lib/gen/getstring.c new file mode 100644 index 00000000..56a7706d --- /dev/null +++ b/src/lib/gen/getstring.c @@ -0,0 +1,45 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * getstring.c: get string, printing a prompt if there is one + * + * Known contributors to this file: + * + */ + +#include "misc.h" +#include "gen.h" +#include "subs.h" + +s_char * +getstring(s_char *prompt, s_char *buf) +{ + *buf = '\0'; + if (prmptrd(prompt, buf, 1024) < 0) + return 0; + return buf; +} diff --git a/src/lib/gen/hpux.c b/src/lib/gen/hpux.c new file mode 100644 index 00000000..b5cf0812 --- /dev/null +++ b/src/lib/gen/hpux.c @@ -0,0 +1,90 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * hpux.c: Things specific to hpux + * + * Known contributors to this file: + * + */ + +#include "misc.h" + +#ifdef hpux +#include + +setbuffer(fp, buf, size) + FILE *fp; + s_char *buf; + int size; +{ + if (size > BUFSIZ) + setbuf(fp, buf); + /* XXX else report error */ +} + +s_char * +rindex(sp, c) + register s_char *sp; + register int c; +{ + register s_char *r; + + r = NULL; + do { + if (*sp == c) + r = sp; + } while (*sp++); + return r; +} + +s_char * +index(sp, c) + register s_char *sp; + register int c; +{ + do { + if (*sp == c) + return (sp); + } while (*sp++); + return NULL; +} + +int +ffs(marg) + register unsigned marg; +{ + register unsigned bval; + register int i; + + if (marg == 0) + return 0; + for (bval=1, i=1; i <= 32; i++, bval <<= 1) + if (marg & bval) + return i; + return 0; +} +#endif diff --git a/src/lib/gen/iceil.c b/src/lib/gen/iceil.c new file mode 100644 index 00000000..6b3c45d2 --- /dev/null +++ b/src/lib/gen/iceil.c @@ -0,0 +1,52 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * iceil.c: integer ceiling/floor functions + * + * Known contributors to this file: + * + */ + +#include "gen.h" + +int +iceil(double arg) +{ + register int i; + + i = arg; + return(i >= arg ? i : i + 1); +} + +int +ifloor(double arg) +{ + register int i; + + i = arg; + return(i <= arg ? i : i - 1); +} diff --git a/src/lib/gen/inet.c b/src/lib/gen/inet.c new file mode 100644 index 00000000..a888a54d --- /dev/null +++ b/src/lib/gen/inet.c @@ -0,0 +1,53 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * inet.c: network format conversion routines + * + * Known contributors to this file: + * Doug Hay, 1998 + */ + +#include +#if !defined(_WIN32) +#include +#endif +#include /* sprintf */ +#include "misc.h" +#include "gen.h" + +#if !defined(NeXT) && !defined(_WIN32) +s_char * +inet_ntoa(struct in_addr addr) +{ + static s_char str[18]; + register u_char *p; + + p = (u_char *)&addr; + sprintf(str, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]); + return str; +} +#endif /* NeXT */ diff --git a/src/lib/gen/io.c b/src/lib/gen/io.c new file mode 100644 index 00000000..fae8b84a --- /dev/null +++ b/src/lib/gen/io.c @@ -0,0 +1,535 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * io.c: Arrange for input and output on a file descriptor to be queued. + * + * Known contributors to this file: + * Doug Hay, 1998 + * Steve McClure, 1998 + */ + +/* + * Arrange for input and output on a file descriptor + * to be queued. Provide main loop -- a mechanism for + * blocking across all registered file descriptors, and + * reading or writing when appropriate. + */ + +#include +#include +#if !defined(_WIN32) +#include +#include +#include /* close read shutdown select */ +#include +#endif +#include +#include +#include /* malloc calloc free */ + +#if defined(_WIN32) +#include +#endif + +#include "misc.h" +#include "bit.h" +#include "queue.h" +#include "ioqueue.h" +#include "io_mask.h" +#include "empio.h" +#include "gen.h" /* getfdtablesize */ + +#include "empthread.h" + +extern struct player *player; /* XXX */ + +static struct iop **io_list; +static struct io_mask *iom; +static bit_fdmask newoutput; + +struct iop { + int fd; + struct ioqueue *input; + struct ioqueue *output; + int flags; + s_char *assoc; + int bufsize; + int (*notify)(); +}; + +extern int errno; + +void +io_init(void) +{ + iom = iom_create(IO_READ|IO_WRITE); + io_list = (struct iop **) calloc(getfdtablesize(), sizeof(*io_list)); + newoutput = bit_newfdmask(); +} + +struct iop * +io_open(int fd, int flags, int bufsize, int (*notify) (void), s_char *assoc) +{ + struct iop *iop; + + if (io_list[fd] != 0) { + /* already exists */ + return 0; + } + flags = flags & (IO_READ|IO_WRITE|IO_NBLOCK|IO_NEWSOCK); + if ((flags & (IO_READ|IO_WRITE)) == 0) + return 0; + iop = (struct iop *) malloc(sizeof(struct iop)); + iop->fd = fd; + iop->input = 0; + iop->output = 0; + iop->flags = 0; + iop->bufsize = bufsize; + if ((flags & IO_READ) && (flags & IO_NEWSOCK) == 0) + iop->input = ioq_create(bufsize); + if ((flags & IO_WRITE) && (flags & IO_NEWSOCK) == 0) + iop->output = ioq_create(bufsize); + if (flags & IO_NBLOCK) + io_noblocking(iop, 1); + iop->flags = flags; + iop->assoc = assoc; + iop->notify = notify; + io_list[fd] = iop; + iom_set(iom, flags, fd); + return iop; +} + +void +io_close(struct iop *iop) +{ + + if (iop->input != 0) + ioq_destroy(iop->input); + if (iop->output != 0) + ioq_destroy(iop->output); + iom_clear(iom, iop->flags, iop->fd); + BIT_CLRB(iop->fd, newoutput); + io_list[iop->fd] = 0; +#if !defined(_WIN32) + (void) close(iop->fd); +#else + closesocket(iop->fd); +#endif + free((s_char *)iop); +} + +int +io_input(struct iop *iop, int waitforinput) +{ + s_char buf[IO_BUFSIZE]; + int cc; + + /* Not a read IOP */ + if ((iop->flags & IO_READ) == 0) + return -1; + /* IOP is markes as in error. */ + if (iop->flags & IO_ERROR) + return -1; + /* Wait for the file to have input. */ + if (waitforinput) { + empth_select(iop->fd, EMPTH_FD_READ); + } +#if !defined(_WIN32) + /* Do the actual read. */ + cc = read(iop->fd, buf, sizeof(buf)); + if (cc < 0) { + /* would block, so nothing to read. */ + if (errno == EWOULDBLOCK) + return 0; + + /* Some form of file error occurred... */ + iop->flags |= IO_ERROR; + iom_clear(iom, IO_READ, iop->fd); + return -1; + } +#else + cc = recv(iop->fd, buf, sizeof(buf), 0); + if (cc == SOCKET_ERROR) { + int err = WSAGetLastError(); + /* Hmm, it would block. file is opened noblock, soooooo.. */ + if (err == WSAEWOULDBLOCK) + return 0; + + /* Some form of file error occurred... */ + iop->flags |= IO_ERROR; + iom_clear(iom, IO_READ, iop->fd); + return -1; + } +#endif + + /* We eof'd */ + if (cc == 0) { + iop->flags |= IO_EOF; + return 0; + } + + /* Append the input to the IOQ. */ + ioq_append(iop->input, buf, cc); + return cc; +} + +int +io_inputwaiting(struct iop *iop) +{ + return ioq_qsize(iop->input); +} + +int +io_outputwaiting(struct iop *iop) +{ + return ioq_qsize(iop->output); +} + +int +io_output(struct iop *iop, int waitforoutput) +{ +#if !defined(_WIN32) + struct iovec iov[16]; +#else + s_char buf[IO_BUFSIZE]; +#endif + int cc; + int n; + int remain; + + /* If there is no output waiting. */ + if (!io_outputwaiting(iop)) + return 0; + + /* bit clear */ + BIT_CLRB(iop->fd, newoutput); + + /* If the iop is not write enabled. */ + if ((iop->flags & IO_WRITE) == 0) + return -1; + + /* If the io is marked as in error... */ + if (iop->flags & IO_ERROR) + return -1; + + /* This is the same test as io_outputwaiting.... */ + if (ioq_qsize(iop->output) == 0) + return 0; + +#if !defined(_WIN32) + /* make the iov point to the data in the queue. */ + /* I.E., each of the elements in the queue. */ + /* returns the number of elements in the iov. */ + n = ioq_makeiov(iop->output, iov, IO_BUFSIZE); +#else + /* Make a buffer containing the output to write. */ + n = ioq_makebuf(iop->output, buf, sizeof(buf)); +#endif + + if (n <= 0) { + /* If we got no elements, we have no output.... */ + iom_clear(iom, IO_WRITE, iop->fd); + return 0; + } + + /* wait for the file to be output ready. */ + if (waitforoutput != IO_NOWAIT) { + /* This waits for the file to be ready for writing, */ + /* and lets other threads run. */ + empth_select(iop->fd, EMPTH_FD_WRITE); + } + + /* Do the actual write. */ +#if !defined(_WIN32) + cc = writev(iop->fd, iov, n); + + /* if it failed.... */ + if (cc < 0) { + /* Hmm, it would block. file is opened noblock, soooooo.. */ + if (errno == EWOULDBLOCK) { + /* If there are remaining bytes, set the IO as remaining.. */ + remain = ioq_qsize(iop->output); + if (remain > 0) + iom_set(iom, IO_WRITE, iop->fd); + return remain; + } + iop->flags |= IO_ERROR; + iom_clear(iom, IO_WRITE, iop->fd); + return -1; + } +#else + cc = send(iop->fd, buf, n, 0); + + /* if it failed.... */ + if (cc == SOCKET_ERROR) { + int err = WSAGetLastError(); + /* Hmm, it would block. file is opened noblock, soooooo.. */ + if (err == WSAEWOULDBLOCK) { + /* If there are remaining bytes, set the IO as remaining.. */ + remain = ioq_qsize(iop->output); + if (remain > 0) + iom_set(iom, IO_WRITE, iop->fd); + return remain; + } + iop->flags |= IO_ERROR; + iom_clear(iom, IO_WRITE, iop->fd); + return -1; + } +#endif + + + /* If no bytes were written, something happened.. Like an EOF. */ +#ifndef hpux + if (cc == 0) { + iop->flags |= IO_EOF; + return 0; + } +#else + if (cc == 0) { + remain = ioq_qsize(iop->output); + if (remain > 0) + iom_set(iom, IO_WRITE, iop->fd); + return remain; + } +#endif /* hpux */ + + /* Remove the number of written bytes from the queue. */ + ioq_dequeue(iop->output, cc); + + /* If the queue has stuff remaining, set it still needing output. */ + remain = ioq_qsize(iop->output); + if (remain == 0) { + iom_clear(iom, IO_WRITE, iop->fd); + } else { + iom_set(iom, IO_WRITE, iop->fd); + } + return cc; +} + +int +io_select(struct timeval *tv) +{ + bit_fdmask readmask; + bit_fdmask writemask; + int n; + int nfds; + int fd; + struct iop *iop; + + iom_getmask(iom, &nfds, &readmask, &writemask); + n = select(nfds + 1, (fd_set *)readmask, (fd_set *)writemask, 0, tv); + if (n <= 0) { + if (errno == EINTR) + return 0; + return -1; + } + while ((fd = bit_fd(readmask)) >= 0) { + iop = io_list[fd]; + if ((iop->flags & IO_NEWSOCK) == 0) + (void) io_input(iop, IO_NOWAIT); + if (iop->notify != 0) + iop->notify(iop, IO_READ, iop->assoc); + BIT_CLRB(fd, readmask); + } + while ((fd = bit_fd(writemask)) >= 0) { + iop = io_list[fd]; + if (io_output(iop, IO_NOWAIT) < 0 && iop->notify != 0) + iop->notify(iop, IO_WRITE, iop->assoc); + BIT_CLRB(fd, writemask); + } + return n; +} + +void +io_flush(int doWait) +{ + int fd; + struct iop *iop; + + while ((fd = bit_fd(newoutput)) >= 0) { + iop = io_list[fd]; + if (io_output(iop, doWait) < 0 && iop->notify != 0) + iop->notify(iop, IO_WRITE, iop->assoc); + } +} + +int +io_peek(struct iop *iop, s_char *buf, int nbytes) +{ + if ((iop->flags & IO_READ) == 0) + return -1; + return ioq_peek(iop->input, buf, nbytes); +} + +int +io_read(struct iop *iop, s_char *buf, int nbytes) +{ + int cc; + + if ((iop->flags & IO_READ) == 0) + return -1; + cc = ioq_peek(iop->input, buf, nbytes); + if (cc > 0) + ioq_dequeue(iop->input, cc); + return cc; +} + +int +io_write(struct iop *iop, s_char *buf, int nbytes, int doWait) +{ + int len; + + if ((iop->flags & IO_WRITE) == 0) + return -1; + ioq_append(iop->output, buf, nbytes); + BIT_SETB(iop->fd, newoutput); + len = ioq_qsize(iop->output); + if (len > iop->bufsize) { + if (doWait) { + io_output_all(iop); + } else { + /* only try a write every BUFSIZE characters */ + if (((len-nbytes) % iop->bufsize) < + (len % iop->bufsize)) + io_output(iop, 0); + } + } + return nbytes; +} + +int +io_output_all(struct iop *iop) +{ + int n; + + while ((n = io_output(iop, IO_NOWAIT)) > 0) { + empth_select(iop->fd, EMPTH_FD_WRITE); + } + return n; +} + +int +io_gets(struct iop *iop, s_char *buf, int nbytes) +{ + if ((iop->flags & IO_READ) == 0) + return -1; + return ioq_gets(iop->input, buf, nbytes); +} + +int +io_puts(struct iop *iop, s_char *buf) +{ + if ((iop->flags & IO_WRITE) == 0) + return -1; + BIT_SETB(iop->fd, newoutput); + return ioq_puts(iop->output, buf); +} + +int +io_shutdown(struct iop *iop, int flags) +{ + flags &= (IO_READ|IO_WRITE); + if ((iop->flags & flags) != flags) + return -1; + if (flags & IO_READ) { + shutdown(iop->fd, 0); + ioq_drain(iop->input); + } + if (flags & IO_WRITE) { + shutdown(iop->fd, 1); + ioq_drain(iop->output); + } + return 0; +} + +int +io_noblocking(struct iop *iop, int value) +{ +#if !defined(_WIN32) + int flags; + + flags = fcntl(iop->fd, F_GETFL, 0); + if (flags < 0) + return -1; + if (value == 0) + flags &= ~FNDELAY; + else + flags |= FNDELAY; + if (fcntl(iop->fd, F_SETFL, flags) < 0) + return -1; +#else + u_long arg = value; + ioctlsocket(iop->fd, FIONBIO, &arg); +#endif + if (value == 0) + iop->flags &= ~IO_NBLOCK; + else + iop->flags |= IO_NBLOCK; + return 0; +} + +int +io_conn(struct iop *iop) +{ + return (iop->flags & IO_CONN); +} + +int +io_error(struct iop *iop) +{ + return (iop->flags & IO_ERROR); +} + +int +io_eof(struct iop *iop) +{ + return (iop->flags & IO_EOF); +} + +int +io_fileno(struct iop *iop) +{ + return iop->fd; +} + +struct iop * +io_iopfromfd(int fd) +{ + return io_list[fd]; +} + + + + + + + + + + + + diff --git a/src/lib/gen/io_mask.c b/src/lib/gen/io_mask.c new file mode 100644 index 00000000..d96e3a24 --- /dev/null +++ b/src/lib/gen/io_mask.c @@ -0,0 +1,113 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * iom.c: implements the io mask routines + * + * Known contributors to this file: + * + */ + +#include /* malloc */ +#include +#include "misc.h" +#include "bit.h" +#include "empio.h" +#include "io_mask.h" + +extern int errno; + +struct io_mask * +iom_create(int what) +{ + struct io_mask *imp; + + imp = (struct io_mask *) malloc(sizeof(*imp)); + if (what & IO_READ) { + imp->readmask = bit_newfdmask(); + imp->user_readmask = bit_newfdmask(); + } else { + imp->readmask = 0; + imp->user_readmask = 0; + } + if (what & IO_WRITE) { + imp->writemask = bit_newfdmask(); + imp->user_writemask = bit_newfdmask(); + } else { + imp->writemask = 0; + imp->user_writemask = 0; + } + imp->what = what; + imp->maxfd = 0; + return imp; +} + +void +iom_getmask(struct io_mask *mask, int *nfdp, bit_fdmask *readp, bit_fdmask *writep) +{ + if (mask->what & IO_READ) + bit_copy(mask->readmask, mask->user_readmask); + if (mask->what & IO_WRITE) + bit_copy(mask->writemask, mask->user_writemask); + *readp = mask->user_readmask; + *writep = mask->user_writemask; + *nfdp = mask->maxfd; +} + +void +iom_set(struct io_mask *mask, int what, int fd) +{ + if ((mask->what & what) == 0) + return; + if (what & IO_READ) + BIT_SETB(fd, mask->readmask); + if (what & IO_WRITE) + BIT_SETB(fd, mask->writemask); + if (fd > mask->maxfd) + mask->maxfd = fd; +} + +void +iom_clear(struct io_mask *mask, int what, int fd) +{ + if ((mask->what & what) == 0) + return; + if (what & IO_READ) + BIT_CLRB(fd, mask->readmask); + if (what & IO_WRITE) + BIT_CLRB(fd, mask->writemask); +} + +void +iom_zero(struct io_mask *mask, int what) +{ + if ((mask->what & what) == 0) + return; + if (what & IO_READ) + bit_zero(mask->readmask); + if (what & IO_WRITE) + bit_zero(mask->writemask); +} diff --git a/src/lib/gen/ioqueue.c b/src/lib/gen/ioqueue.c new file mode 100644 index 00000000..123607a5 --- /dev/null +++ b/src/lib/gen/ioqueue.c @@ -0,0 +1,456 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * ioqueue.c: Read and write i/o queues + * + * Known contributors to this file: + * + */ + +/* + * Read and write onto io queues. Note that + * the io queues don't actually do any writing; + * that is left for a higher level. + */ + +#include +#include /* malloc free */ +#include +#if !defined(_WIN32) +#include +#endif +#include "misc.h" +#include "queue.h" +#include "ioqueue.h" + +static int ioqtocbuf(struct ioqueue *ioq, s_char *buf, int cc, register int stopc); +#if !defined(_WIN32) +static int ioqtoiov(struct ioqueue *ioq, struct iovec *iov, register int max); +#endif +static int ioqtobuf(struct ioqueue *ioq, s_char *buf, int cc); +static int appendcc(struct ioqueue *ioq, s_char *buf, int cc); +static int removecc(struct ioqueue *ioq, register int cc); + +#if defined(_WIN32) +static void loc_StripDels(char *pBuf); +#endif + +struct ioqueue * +ioq_create(int size) +{ + struct ioqueue *ioq; + + ioq = (struct ioqueue *) malloc(sizeof(struct ioqueue)); + emp_initque(&ioq->list.queue); + ioq->list.nbytes = 0; + ioq->list.offset = 0; + ioq->list.size = 0; + ioq->list.data = 0; + ioq->bufsize = size; + ioq->cc = 0; + return ioq; +} + +void +ioq_destroy(struct ioqueue *ioq) +{ +#if !defined(aix) && !defined(NeXT) +/* ioq_drain doesn't work under aix or NeXT... dunno why --ts */ + ioq_drain(ioq); +#endif /* aix */ + free((s_char *)ioq); +} + +void +ioq_drain(struct ioqueue *ioq) +{ + struct emp_qelem *qp; + struct io *io; + + while ((qp = ioq->list.queue.q_forw) != &ioq->list.queue){ + io = (struct io *) qp; + (void) emp_remque(&io->queue); + (void) free((s_char *)io->data); + (void) free((s_char *)io); + } + + ioq->cc = 0; +} + +/* + * copy batch of pointers into the passed + * iovec, but don't actually dequeue the data. + * return # of iovec initialized. + */ +#if !defined(_WIN32) +int +ioq_makeiov(struct ioqueue *ioq, struct iovec *iov, int cc) +{ + if (ioq->cc <= 0) + return 0; + return ioqtoiov(ioq, iov, cc); +} +#endif + +/* + * Copy the specified number of characters into the buffer + * provided, without actually dequeueing the data. Return + * number of bytes actually found. + */ +int +ioq_peek(struct ioqueue *ioq, s_char *buf, int cc) +{ + return ioqtobuf(ioq, buf, cc); +} + +int +ioq_dequeue(struct ioqueue *ioq, int cc) +{ + return removecc(ioq, cc); +} + +void +ioq_append(struct ioqueue *ioq, s_char *buf, int cc) +{ + appendcc(ioq, buf, cc); +} + +int +ioq_qsize(struct ioqueue *ioq) +{ + return ioq->cc; +} + +/* + * read a line of text up to (but not including) + * the newline. return -1 and read nothing if + * no input is available + */ +int +ioq_gets(struct ioqueue *ioq, s_char *buf, int cc) +{ + int nbytes; + int actual; + + nbytes = ioqtocbuf(ioq, buf, cc - 1, '\n'); + if (nbytes >= 0) { + actual = nbytes; + if (actual > cc - 1) + actual = cc - 1; + buf[actual] = '\0'; + /* remove the newline too */ + removecc(ioq, nbytes + 1); +#if defined(_WIN32) + loc_StripDels(buf); +#endif + } + return nbytes; +} + +int +ioq_puts(struct ioqueue *ioq, s_char *buf) +{ + return appendcc(ioq, buf, strlen(buf)); +} + +/* + * all the rest are local to this module + */ + + +/* + * copy cc bytes from ioq to buf. + * this routine doesn't free memory; this is + * left for a higher level. + */ +static +int +ioqtobuf(struct ioqueue *ioq, s_char *buf, int cc) +{ + struct io *io; + struct emp_qelem *qp; + struct emp_qelem *head; + register int nbytes; + register int nleft; + register s_char *offset; + + nleft = cc; + offset = buf; + head = &ioq->list.queue; + for (qp = head->q_forw; qp != head && nleft > 0; qp = qp->q_forw) { + io = (struct io *) qp; + if ((nbytes = io->nbytes - io->offset) < 0) { + /* XXX log something here */ + continue; + } + if (nbytes > 0) { + if (nleft < nbytes) + nbytes = nleft; + bcopy(io->data + io->offset, offset, nbytes); + offset += nbytes; + nleft -= nbytes; + } + } + return offset - buf; +} + +/* + * copy at most cc bytes from ioq to buf, + * terminating on the stop character. + */ +static +int +ioqtocbuf(struct ioqueue *ioq, s_char *buf, int cc, register int stopc) +{ + register int nbytes; + register s_char *p; + register int n; + struct io *io; + struct emp_qelem *qp; + struct emp_qelem *head; + int total; + int found; + + head = &ioq->list.queue; + found = 0; + total = 0; + for (qp = head->q_forw; qp != head; qp = qp->q_forw) { + io = (struct io *) qp; + if ((nbytes = io->nbytes - io->offset) <= 0) + continue; + p = io->data + io->offset; + for (n=0; n < nbytes && p[n] != stopc; n++) + ; + total += n; + if (n < nbytes) { + found++; + break; + } + } + if (found == 0) + return -1; + ioqtobuf(ioq, buf, cc < total ? cc : total); + return total; +} + +/* + * initialize an iovec to point at max bytes worth + * of data from the ioqueue. + */ +#if !defined(_WIN32) +static +int +ioqtoiov(struct ioqueue *ioq, struct iovec *iov, register int max) +{ + struct io *io; + register int cc; + register int niov; + register int len; + struct emp_qelem *qp; + + cc = max; + niov = 0; + qp = ioq->list.queue.q_forw; + while (qp != &ioq->list.queue && cc > 0) { + io = (struct io *) qp; + len = io->nbytes - io->offset; + if (len > cc) + len = cc; + iov->iov_base = io->data + io->offset; + iov->iov_len = len; + cc -= len; + niov++; + iov++; + qp = qp->q_forw; + if (niov >= 16) + break; + } + return niov; +} +#endif + +/* + * append a buffer to the end of the ioq. + */ +static +int +appendcc(struct ioqueue *ioq, s_char *buf, int cc) +{ + struct io *io; + int len; + s_char *ptr; + int avail; + + /* determine if any space is left */ + io = (struct io *)ioq->list.queue.q_back; + avail = io->size - io->nbytes; + if (avail > 0) { + /* append to existing buffer */ + len = cc > avail ? avail : cc; + bcopy(buf, io->data + io->nbytes, len); + io->nbytes += len; + ioq->cc += len; + if (avail < cc) + appendcc(ioq, buf + len, cc - len); + } else { + /* create a new buffer, minimum bufsize bytes */ + len = cc > ioq->bufsize ? cc : ioq->bufsize; + ptr = malloc(len); + bcopy(buf, ptr, cc); + io = (struct io *) malloc(sizeof(struct io)); + io->nbytes = cc; + io->size = len; + io->offset = 0; + io->data = ptr; + emp_insque(&io->queue, ioq->list.queue.q_back); + ioq->cc += cc; + } + return cc; +} + +/* + * remove cc bytes from ioqueue ioq + * free memory, dequeue io elements + * which are no longer used. + */ +static +int +removecc(struct ioqueue *ioq, register int cc) +{ + struct io *io; + struct emp_qelem *qp; + register int nbytes; + register int there; + register int remain; + + nbytes = 0; + remain = cc; + while ((qp = ioq->list.queue.q_forw) != &ioq->list.queue) { + io = (struct io *) qp; + there = io->nbytes - io->offset; + if (there < 0) { + /* error */ + (void) emp_remque(&io->queue); + (void) free((s_char *)io); + continue; + } + if (remain >= there) { + /* not enough or exact; free entry */ + nbytes += there; + remain -= there; + (void) emp_remque(&io->queue); + (void) free(io->data); + (void) free((s_char *)io); + } else { + /* too much; increment offset */ + io->offset += remain; + nbytes += remain; + remain = 0; + } + if (remain <= 0) + break; + } + ioq->cc -= nbytes; + return nbytes; +} +#if defined(_WIN32) +/* + * Make an (output) buffer up to the + * maximum size of the buffer. + * + * We don't free the bytes... + */ +int +ioq_makebuf(struct ioqueue *ioq, char *pBuf, int nBufLen) +{ + struct io *io; + struct emp_qelem *qp; + struct emp_qelem *head; + int nbytes; + int nleft; + int ncopied; + s_char *offset; + + ncopied = 0; + nleft = nBufLen; + offset = pBuf; + head = &ioq->list.queue; + + for (qp = head->q_forw; + (qp != head) && (nleft > 0); + qp = qp->q_forw) { + io = (struct io *) qp; + nbytes = io->nbytes - io->offset; + if (nbytes < 0) { + /* Paranoid check for bad buffer. */ + continue; + } + + /* too many bytes, wait till next time. */ + if (nbytes > nleft) + break; + + bcopy(io->data + io->offset, offset, nbytes); + offset += nbytes; + nleft -= nbytes; + ncopied += nbytes; + } + return ncopied; +} +#endif /* _WIN32 */ + +#if defined(_WIN32) +/* + * Remove backspaces and DELs from the buffer. + * + * Why? Because I got tired of telneting into the + * server and having to type perfectly... + */ +static void +loc_StripDels(char *pBuf) +{ + char *cp; + char *dp; + char *sp; + + for (cp = pBuf; *cp;) { + /* Remove Backspace and DEL */ + if (*cp == '\b' || *cp == '\x8F') { + if (cp == pBuf) + dp = cp; + else + dp = cp - 1; + sp = cp + 1; + while (*sp) + *dp++ = *sp++; + *dp = 0; + } else + cp++; + } +} +#endif + diff --git a/src/lib/gen/lock.c b/src/lib/gen/lock.c new file mode 100644 index 00000000..cc08b25e --- /dev/null +++ b/src/lib/gen/lock.c @@ -0,0 +1,140 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * lock.c: Lock a file + * + * Known contributors to this file: + * Doug Hay, 1998 + */ + +#ifdef aix +#define L_SET 0 +#endif /* aix */ + +#include "misc.h" +#include "gen.h" +#include "common.h" +#include + +#ifdef sys5 +#include +#endif +#if !defined(L_SET) && !defined(_WIN32) +#include +#endif + +#ifdef aix +#define L_SET 0 +#endif /* aix */ + +#if defined(_WIN32) +#include + +int +file_lock(int fd) +{ + if (_locking(fd, _LK_LOCK, 0) < 0) { + logerror("file lock (fd %d) failed", fd); + return 0; + } + return 1; +} + +int +file_unlock(int fd) +{ + if (_locking(fd, _LK_UNLCK, 0) < 0) { + logerror("file lock (fd %d) failed", fd); + return 0; + } + return 1; +} + +#else + +#ifndef NOFLOCK + +int flock(); + +int +file_lock(int fd) +{ + if (flock(fd, LOCK_EX) < 0) { + logerror("file lock (fd %d) failed", fd); + return 0; + } + return 1; +} + +int +file_unlock(int fd) +{ + if (flock(fd, LOCK_UN) < 0) { + logerror("file unlock (fd %d) failed", fd); + return 0; + } + return 1; +} + +#else + +int +file_lock(int fd) +{ + struct flock lock; + + lock.l_type = F_WRLCK; + lock.l_whence = L_SET; + lock.l_start = 0; + lock.l_len = 0; + lock.l_pid = 0; + if (fcntl(fd, F_SETLKW, &lock) < 0) { + logerror("file lock (fd %d) failed", fd); + return 0; + } + return 1; +} + +int +file_unlock(int fd) +{ + struct flock lock; + + lock.l_type = F_UNLCK; + lock.l_whence = L_SET; + lock.l_start = 0; + lock.l_len = 0; + lock.l_pid = 0; + if (fcntl(fd, F_SETLKW, &lock) < 0) { + logerror("file unlock (fd %d) failed", fd); + return 0; + } + return 1; +} +#endif + +#endif /* _WIN32 */ diff --git a/src/lib/gen/mapdist.c b/src/lib/gen/mapdist.c new file mode 100644 index 00000000..f728bc6d --- /dev/null +++ b/src/lib/gen/mapdist.c @@ -0,0 +1,118 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * mapdist.c: Return the distance between two sectors + * + * Known contributors to this file: + * + */ + +/* + * mapdist returns (integer) distance between two sectors. + * mapdsq returns the square of the distance -- more efficient. + */ + +#include "misc.h" +#include "gen.h" +#include "optlist.h" + +int +diffx(int x1, int x2) +{ + int dx; + + dx = x1 - x2; + dx = dx % WORLD_X; + if (dx > WORLD_X/2) + dx = dx - WORLD_X; + if (dx < -WORLD_X/2) + dx = dx + WORLD_X; + return dx; +} + +int +diffy(int y1, int y2) +{ + int dy; + + dy = y1 - y2; + dy = dy % WORLD_Y; + if (dy > WORLD_Y/2) + dy = dy - WORLD_Y; + if (dy < -WORLD_Y/2) + dy = dy + WORLD_Y; + return dy; +} + +int +deltax(int x1, int x2) +{ + int dx; + + dx = abs(x1 - x2); + dx = dx % WORLD_X; + if (dx > WORLD_X/2) + dx = WORLD_X - dx; + return dx; +} + +int +deltay(int y1, int y2) +{ + int dy; + + dy = abs(y1 - y2); + dy = dy % WORLD_Y; + if (dy > WORLD_Y/2) + dy = WORLD_Y - dy; + return dy; +} + +int +mapdist(int x1, int y1, int x2, int y2) +{ + int dx, dy; + + x1 = x1 % WORLD_X; + y1 = y1 % WORLD_Y; + x2 = x2 % WORLD_X; + y2 = y2 % WORLD_Y; + dx = deltax(x1, x2); + dy = deltay(y1, y2); + if (dx > dy) + return (dx - dy) / 2 + dy; + return dy; +} + +int +mapdsq(int x1, int y1, int x2, int y2) +{ + int sq; + + sq = mapdist(x1, y1, x2, y2); + return sq * sq; +} diff --git a/src/lib/gen/minmax.c b/src/lib/gen/minmax.c new file mode 100644 index 00000000..ae98726a --- /dev/null +++ b/src/lib/gen/minmax.c @@ -0,0 +1,71 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * minmax.c: Misc min and max routines + * + * Known contributors to this file: + * Doug Hay, 1998 + * Steve McClure, 1998 + */ + +#include "gen.h" + +double +dmax(double n1, double n2) +{ + if (n1 > n2) + return n1; + return n2; +} + +double +dmin(double n1, double n2) +{ + if (n1 < n2) + return n1; + return n2; +} + +#if !defined(_WIN32) +int +max(int n1, int n2) +{ + if (n1 > n2) + return n1; + return n2; +} + + +int +min(int n1, int n2) +{ + if (n1 < n2) + return n1; + return n2; +} + +#endif diff --git a/src/lib/gen/numstr.c b/src/lib/gen/numstr.c new file mode 100644 index 00000000..b50d4b47 --- /dev/null +++ b/src/lib/gen/numstr.c @@ -0,0 +1,74 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * numstr.c: Turn a number into a word + * + * Known contributors to this file: + * Steve McClure, 2000 + */ + +#ifdef Rel4 +#include +#endif /* Rel4 */ +#include "misc.h" +#include "gen.h" + +s_char * +numstr(s_char *buf, int n) +{ + extern s_char *numnames[]; + extern s_char *tennames[]; + + if (n > 100) { + (void) strcpy(buf, "several"); + } else if (n < 0) { + (void) strcpy(buf, "a negative number of"); + } else { + if (n >= 20) { + (void) strcpy(buf, tennames[n / 10]); + if (n % 10) { + (void) strcat(buf, "-"); + (void) strcat(buf, numnames[n % 10]); + } + } else { + (void) strcpy(buf, numnames[n % 20]); + } + } + return buf; +} + +s_char * +effadv(int n) +{ + extern s_char *effadv_list[]; + + if (n < 0) + n = 0; + if (n >= 100) + n = 99; + return effadv_list[n/25]; +} diff --git a/src/lib/gen/onearg.c b/src/lib/gen/onearg.c new file mode 100644 index 00000000..7146b2fb --- /dev/null +++ b/src/lib/gen/onearg.c @@ -0,0 +1,52 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * onearg.c: Get one argument, or ask if not there + * + * Known contributors to this file: + * + */ + +#include "misc.h" +#include "gen.h" + +int +onearg(s_char *arg, s_char *prompt) +{ + extern s_char *getstring(s_char *prompt, s_char *buf); + int n; + s_char buf[1024]; + + if (arg == 0 || *arg == 0) { + if ((arg = getstring(prompt, buf)) == 0) + return -1; + } + n = atoi(arg); + if (n < 0) + return -1; + return n; +} diff --git a/src/lib/gen/parse.c b/src/lib/gen/parse.c new file mode 100644 index 00000000..b688564f --- /dev/null +++ b/src/lib/gen/parse.c @@ -0,0 +1,96 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * parse.c: Parse an Empire command line + * + * Known contributors to this file: + * + */ + +/* + * parse empire command line, chop into argp + * If values argpp and spacep passed, parse will use them. + * otherwise, parse will use static space and global argp. + * parse assumes that argpp is a char *buf[16], and that spacep + * points to a buf of at least 256 bytes. + */ + +#include +#include "misc.h" +#include "gen.h" + +int +parse(register s_char *buf, s_char **argpp, s_char **condp, s_char *space, s_char **redir) +{ + register s_char *bp2; + register s_char *bp1 = space; + register s_char **arg = argpp; + int fs; + int quoted; + int argnum; + + if (space == 0) + return -1; + if (redir) + *redir = 0; + if (condp != 0) + *condp = 0; + for (argnum=0; *buf && argnum < 100; ) { + arg[argnum] = bp1; + argnum++; + while (isspace(*buf)) + buf++; + if (redir && (*buf == '>' || *buf == '|')) { + *redir = buf; + argnum--; + arg[argnum] = 0; + break; + } + quoted = 0; + for (bp2 = bp1; *buf; ) { + if (!quoted && isspace(*buf)) { + buf++; + break; + } + if (*buf == '"'){ + quoted = !quoted; + buf++; + } else { + *bp1++ = *buf++; + } + } + *bp1++ = 0; + if (*bp2 == '?' && condp != 0) { + *condp = bp2 + 1; + argnum--; + } + } + arg[argnum] = 0; + for (fs = argnum + 1; fs < 16; fs++) + arg[fs] = 0; + return argnum; +} diff --git a/src/lib/gen/plur.c b/src/lib/gen/plur.c new file mode 100644 index 00000000..97b19942 --- /dev/null +++ b/src/lib/gen/plur.c @@ -0,0 +1,59 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * plur.c: Pluralize (is that a word?) something + * + * Known contributors to this file: + * + */ + +#include "misc.h" +#include "gen.h" + +s_char * +plur(int n, s_char *no, s_char *yes) +{ + return (n == 1 ? no : yes); +} + +s_char * +splur(int n) +{ + return (n == 1 ? "" : "s"); +} + +s_char * +esplur(int n) +{ + return (n == 1 ? "" : "es"); +} + +s_char * +iesplur(int n) +{ + return (n == 1 ? "y" : "ies"); +} diff --git a/src/lib/gen/queue.c b/src/lib/gen/queue.c new file mode 100644 index 00000000..c454ebd0 --- /dev/null +++ b/src/lib/gen/queue.c @@ -0,0 +1,65 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * queue.c: Various queue routines (for lists) + * + * Known contributors to this file: + * + */ + +#include "queue.h" + +void +emp_insque(struct emp_qelem *elem, struct emp_qelem *queue) +{ + struct emp_qelem *next; + + next = queue->q_forw; + queue->q_forw = elem; + elem->q_forw = next; + elem->q_back = queue; + next->q_back = elem; +} + +void +emp_remque(struct emp_qelem *elem) +{ + if (elem == (struct emp_qelem *)0) + return; + if (elem->q_forw != (struct emp_qelem *)0) + elem->q_forw->q_back = elem->q_back; + if (elem->q_back != (struct emp_qelem *)0) + elem->q_back->q_forw = elem->q_forw; +} + +void +emp_initque(struct emp_qelem *elem) +{ + elem->q_forw = elem; + elem->q_back = elem; +} + diff --git a/src/lib/gen/round.c b/src/lib/gen/round.c new file mode 100644 index 00000000..db711654 --- /dev/null +++ b/src/lib/gen/round.c @@ -0,0 +1,52 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * round.c: Round off functions + * + * Known contributors to this file: + * + */ + +#include "gen.h" + +int +roundintby(int n, int m) +{ + register int r11; + + r11 = (m >> 1) + n; + return (r11 / m * m); +} + +int +ldround(double a4, int ac) +{ + int f4; + + f4 = ac / 2.0 + a4; + return (f4 / ac * ac); +} diff --git a/src/lib/gen/same.c b/src/lib/gen/same.c new file mode 100644 index 00000000..dc460476 --- /dev/null +++ b/src/lib/gen/same.c @@ -0,0 +1,45 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * same.c: Return true if strings are the same + * + * Known contributors to this file: + * + */ + +#include "misc.h" +#include "gen.h" + +int +same(register s_char *s1, register s_char *s2) +{ + while (*s1 == *s2++) { + if (*s1++ == 0) + return 1; + } + return 0; +} diff --git a/src/lib/gen/scthash.c b/src/lib/gen/scthash.c new file mode 100644 index 00000000..391cf613 --- /dev/null +++ b/src/lib/gen/scthash.c @@ -0,0 +1,44 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * scthash.c: Create a hash function based on the sector x-y mod table size + * + * Known contributors to this file: + * Dave Pare, 1986 + */ + +#include "gen.h" + +int +scthash(register int x, register int y, int tsize) +{ + if (x < 0) + x = -x; + if (y < 0) + y = -y; + return ((x*10 + y) % tsize); +} diff --git a/src/lib/gen/signal.c b/src/lib/gen/signal.c new file mode 100644 index 00000000..3dc64ff3 --- /dev/null +++ b/src/lib/gen/signal.c @@ -0,0 +1,105 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * sig.c: block and unblock signals for critical sections + * + * Known contributors to this file: + * Doug Hay, 1998 + * Steve McClure, 1998 + */ + +#include "misc.h" +#include "gen.h" +#include + +u_int mask; + +void +blocksig(void) +{ +#if !defined(_WIN32) + mask = sigsetmask(0xffffffff); +#endif +} + +void +unblocksig(void) +{ +#if !defined(_WIN32) + sigsetmask(mask); +#endif +} + +#ifdef sys5 +const s_char *sys_siglist[] = { + "no signal", + "interrupt", + "quit", + "illegal instruction", + "trace trap", + "IOT instruction", + "system crash imminent", + "floating point exception", + "kill", + "bus error", + "segmentation violation", + "bad argument to system call", + "write on a pipe with no one to read it", + "alarm clock", + "software termination", + "user defined signal 1", + "user defined signal 2", + "death of a child", + "power-fail restart", + "asychronous i/o", + "PTY read/write", + "I/O intervention required", + "monitor mode granted", + "monitor mode retracted", + "sound ack", + "data pending", +}; +#else +#if (!defined __ppc__) && (!defined linux) && (!defined FBSD) && (!defined __linux__) +/* linux and osx declare sys_siglist in signal.h */ +extern s_char *sys_siglist[]; +#endif /* linux */ +#endif /* sys5 */ + +const s_char * +signame(int sig) +{ +#ifdef POSIX_SIGNALS + if (sig <= 0 || sig > _sys_nsig) + return "bad signal"; + return _sys_siglist[sig]; +#else /* POSIX_SIGNALS */ + if (sig <= 0 || sig > NSIG) + return "bad signal"; + return sys_siglist[sig]; +#endif /* POSIX_SIGNALS */ +} diff --git a/src/lib/gen/strdup.c b/src/lib/gen/strdup.c new file mode 100644 index 00000000..59165b26 --- /dev/null +++ b/src/lib/gen/strdup.c @@ -0,0 +1,48 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * strdup.c: For systems without a strdup function + * + * Known contributors to this file: + * Yannick Tremblay + */ + +/* for systems without strdup() define NOSTRDUP */ + +#include "gen.h" +#ifdef NOSTRDUP + +char *strdup(char *x) +{ + char *y; + + y=(char *)malloc((sizeof(char)*strlen(x))+1); + strcpy(y,x); + return y; +} +#endif /* NOSTRDUP */ + diff --git a/src/lib/gen/strscan.c b/src/lib/gen/strscan.c new file mode 100644 index 00000000..838571cb --- /dev/null +++ b/src/lib/gen/strscan.c @@ -0,0 +1,57 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * strscan.c: scan a string for any occurence of another string + * + * Known contributors to this file: + * Steve McClure, 2000 + */ + +#ifdef Rel4 +#include +#endif /* Rel4 */ +#include +#include "misc.h" + +int +strscan(s_char *target, s_char *string) +{ + int i,n,delta; + + if ((string == NULL) || (target == NULL)) + return(1); + n = strlen(target); + delta = strlen(string); + if (delta < n) + return(1); + delta -= n; + for (i = 0; i <= delta; i++) { + if (!strncmp(target,&(string[i]),n)) + return(0); + } + return(1); +} diff --git a/src/lib/gen/vsprintf.c b/src/lib/gen/vsprintf.c new file mode 100644 index 00000000..858579fe --- /dev/null +++ b/src/lib/gen/vsprintf.c @@ -0,0 +1,185 @@ +#if !defined(_WIN32) +#ifndef __STDC__ + +/* Portable vsprintf by Robert A. Larson */ + +/* Copyright 1989 Robert A. Larson. + * Distribution in any form is allowed as long as the author + * retains credit, changes are noted by their author and the + * copyright message remains intact. This program comes as-is + * with no warentee of fitness for any purpouse. + * + * Thanks to Doug Gwen, Chris Torek, and others who helped clarify + * the ansi printf specs. + * + * Please send any bug fixes and improvments to blarson@skat.usc.edu . + * The use of goto is NOT a bug. + */ + +/* Feb 7, 1989 blarson First usenet release */ + +/* This code implements the vsprintf function, without relying on + * the existance of _doprint or other system specific code. + * + * Define NOVOID if void * is not a supported type. + * + * Two compile options are available for efficency: + * INTSPRINTF should be defined if sprintf is int and returns + * the number of chacters formated. + * LONGINT should be defined if sizeof(long) == sizeof(int) + * + * They only make the code smaller and faster, they need not be + * defined. + * + * UNSIGNEDSPECIAL should be defined if unsigned is treated differently + * than int in argument passing. If this is definded, and LONGINT is not, + * the compiler must support the type unsingned long. + * + * Most quirks and bugs of the available sprintf fuction are duplicated, + * however * in the width and precision fields will work correctly + * even if sprintf does not support this, as will the n format. + * + * Bad format strings, or those with very long width and precision + * fields (including expanded * fields) will cause undesired results. + */ +#include "misc.h" +#include "gen.h" + +#ifdef OSK /* os9/68k can take advantage of both */ +#define LONGINT +#define INTSPRINTF +#endif + +#define NOVOID + +/* This must be a typedef not a #define! */ +#ifdef NOVOID +typedef s_char *pointer; +#else +typedef void *pointer; +#endif + +#ifdef INTSPRINTF +#define Sprintf(string,format,arg) (sprintf((string),(format),(arg))) +#else +#define Sprintf(string,format,arg) (\ + sprintf((string),(format),(arg)),\ + strlen(string)\ +) +#endif + +#include + +typedef int *intp; + +int vsprintf(dest, format, args) +s_char *dest; +register s_char *format; +va_list args; +{ + register s_char *dp = dest; + register s_char c; + register s_char *tp; + s_char tempfmt[64]; +#ifndef LONGINT + int longflag; +#endif + + tempfmt[0] = '%'; + while(c = *format++) { + if(c=='%') { + tp = &tempfmt[1]; +#ifndef LONGINT + longflag = 0; +#endif +continue_format: + switch(c = *format++) { + case 's': + *tp++ = c; + *tp = '\0'; + dp += Sprintf(dp, tempfmt, va_arg(args, s_char *)); + break; + case 'u': + case 'x': + case 'o': + case 'X': +#ifdef UNSIGNEDSPECIAL + *tp++ = c; + *tp = '\0'; +#ifndef LONGINT + if(longflag) + dp += Sprintf(dp, tempfmt, va_arg(args, unsigned long)); + else +#endif + dp += Sprintf(dp, tempfmt, va_arg(args, unsigned)); + break; +#endif + case 'd': + case 'c': + case 'i': + *tp++ = c; + *tp = '\0'; +#ifndef LONGINT + if(longflag) + dp += Sprintf(dp, tempfmt, va_arg(args, long)); + else +#endif + dp += Sprintf(dp, tempfmt, va_arg(args, int)); + break; + case 'f': + case 'e': + case 'E': + case 'g': + case 'G': + *tp++ = c; + *tp = '\0'; + dp += Sprintf(dp, tempfmt, va_arg(args, double)); + break; + case 'p': + *tp++ = c; + *tp = '\0'; + dp += Sprintf(dp, tempfmt, va_arg(args, pointer)); + break; + case '-': + case '+': + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case '.': + case ' ': + case '#': + case 'h': + *tp++ = c; + goto continue_format; + case 'l': +#ifndef LONGINT + longflag = 1; + *tp++ = c; +#endif + goto continue_format; + case '*': + tp += Sprintf(tp, "%d", va_arg(args, int)); + goto continue_format; + case 'n': + *va_arg(args, intp) = dp - dest; + break; + case '%': + default: + *dp++ = c; + break; + } + } else *dp++ = c; + } + *dp = '\0'; + return dp - dest; +} + +#endif /* __STDC__ */ +#endif diff --git a/src/lib/global/Makefile b/src/lib/global/Makefile new file mode 100644 index 00000000..a886e838 --- /dev/null +++ b/src/lib/global/Makefile @@ -0,0 +1,64 @@ +# +# Empire - A multi-player, client/server Internet based war game. +# Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, +# Ken Stevens, Steve McClure +# +# 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 2 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, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# --- +# +# See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the +# related information and legal notices. It is expected that any future +# projects/authors will amend these files as needed. +# +# Makefile - Wolfpack, 1996 + +# Note that these could have been listed 1 per line, but I chose to just +# stick them all together this way to shorten the file. + +include ../../../build.conf +include ../../make.src +include ../../make.defs + +LIB = $(SRCDIR)/lib/libglobal.a +NTLIB = $(SRCDIR)\lib\libglobal.lib + +OBJS = constants.o dir.o file.o init.o item.o land.o misc.o news.o nsc.o \ + nuke.o numnames.o options.o path.o plane.o product.o sect.o ship.o\ + treaty.o + +NTOBJS = constants.obj dir.obj file.obj init.obj item.obj land.obj misc.obj \ + news.obj nsc.obj nuke.obj numnames.obj options.obj path.obj plane.obj \ + product.obj sect.obj ship.obj treaty.obj + +all: $(LIB) + +nt: $(NTLIB) + +$(NTLIB): $(NTOBJS) + -del /q $@ + lib /OUT:$@ /DEBUGTYPE:CV $(NTOBJS) + +$(LIB): $(OBJS) + rm -f $(LIB) + ar cq $(LIB) $(OBJS) + $(RANLIB) $(LIB) + +clean: + -(rm -f $(OBJS)) + -(del /q $(NTOBJS)) + +include ../../make.rules +include Makedepend diff --git a/src/lib/global/constants.c b/src/lib/global/constants.c new file mode 100644 index 00000000..a69c920e --- /dev/null +++ b/src/lib/global/constants.c @@ -0,0 +1,251 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * constants.c: Global constants file. Note that the "hours" file can + * override these, as does the global "econfig" file. + * + * Known contributors to this file: + * Ken Stevens, 1995 + * Steve McClure, 1996 + * + */ + +#include "gamesdef.h" +#include "misc.h" +#include "xy.h" + +s_char *privname = PRVNAM; /* name of priv user */ +s_char *privlog = PRVLOG; /* logname of priv user */ + +int WORLD_X = DEF_WORLD_X; /* World size - x */ +int WORLD_Y = DEF_WORLD_Y; /* World size - y */ + +int MARK_DELAY = 7200; /* Seconds to bid on commodities */ +int TRADE_DELAY = 7200; /* Seconds to bid on units */ + +int m_m_p_d = 1440; /* max mins of play per day (per country) */ +long s_p_etu = DEF_S_P_ETU; /* seconds per Empire time unit */ +int etu_per_update = ETUS; /* # of etu's per update, from misc.h */ +long adj_update = 0; /* update time adjustment */ +int update_window = 0; /* update window adjustment */ +int hourslop = 5; /* amount of slop to match update times */ +s_char *update_times = ""; /* times regular update is allowed */ +int update_policy = 0; /* update policy for regular updates */ +int update_demandpolicy = 2;/* update policy for demand updates */ +int update_missed = 999; /* demand updates missed before veto */ +int update_wantmin = 0; /* number of votes required for demand update */ +int blitz_time = 10; /* number of minutes between blitz updates */ +s_char *update_demandtimes = "";/* times demand update is allowed */ +s_char *game_days = ""; /* days game is running */ +s_char *game_hours = ""; /* hours game is running */ +int max_idle = 15; /* session dies after max_idle minutes idle */ + +int sect_mob_max = 127; /* sector mobility limits */ +float sect_mob_scale = 1.0; /* accumulation multiplier */ +int land_mob_max = 127; /* land mobility limits */ +float land_mob_scale = 1.0; /* accumulation multiplier */ +int ship_mob_max = 127; /* ship mobility limits */ +float ship_mob_scale = 1.5; /* accumulation multiplier */ +int plane_mob_max = 127; /* plane mobility limits */ +float plane_mob_scale = 1.0; /* accumulation multiplier */ + +float fire_range_factor = 1.0;/* Increase/reduce firing ranges */ + +int morale_base = 42; /* base for morale */ + +/* opt_MOB_ACCESS */ +int sect_mob_neg_factor = 2;/* ETU/neg_factor = negative amount of mobility + a sector has after being taken */ +int updating_mob = 1; /* If we are currently updating mob */ +int timestamp_fixing = 0; /* If we are currently fixing timestamps */ + +int lost_items_timeout = 172800; /* How long before removing from database */ + +double combat_mob=5.0; /* how much mob do units spend for combat? */ + +/* if you find that naving is taking too long, try reducing these */ +int fort_max_interdiction_range = 8; +int ship_max_interdiction_range = 8; +int land_max_interdiction_range = 8; + +double mission_mob_cost = 0.0; /* Cost is percentage of max mob */ + +double unit_damage = 0.30; /* Units take this % of normal damage */ +double people_damage = 1.00; /* Civs/Mil/Uw take this % of normal damage */ +double collateral_dam = 0.10; /* Side effect damage to sector */ +double assault_penalty = 0.50; /* attack factor for para & assault troops */ + +/* START_UNITS */ +#ifdef START_UNITS +int start_unit_type[START_UNITS] = {0, 1}; /* type of unit */ +#endif /* START_UNITS */ + +/* opt_FUEL */ +int fuel_mult = 10; /* 1 fuel = 10 mob */ + +int land_grow_scale = 2; /* how fast eff grows for land units (xETUS) */ +int ship_grow_scale = 3; /* how fast eff grows for ships (xETUS) */ +int plane_grow_scale = 2; /* how fast eff grows for planes (xETUS) */ + +double fgrate = 0.0012; /* food growth rate (dt * fert) */ +double fcrate = 0.0013; /* food cultivate rate (dt * workforce) */ +double eatrate = 0.0005; /* food eating rate (dt * people) */ +/*double eatrate = 0.0001;*/ /* food eating rate (dt * people) */ +double babyeat = 0.0060; /* food to mature 1 baby into a civilian */ +/*double babyeat = 0.0000;*/ /* food to mature 1 baby into a civilian */ + +double obrate = 0.005; /* other sectors birth rate */ +double uwbrate = 0.0025; /* uncompensated worker birth rate */ + /* values > 0.25 for either will overflow */ + +/* opt_FALLOUT */ +/* these are the radioactive decay constants */ +/* fraction of commodity destroyed is + etus*fallout/(1000*melt_item_denom[item]) + higher denominators for tougher commodities */ +int melt_item_denom[] = + /* civ mil shell gun pet iron dust bar*/ + { 0, 4, 20, 80, 100,50, 100, 100, 200, + 2, 50, 100,100,2, 1000 }; + /*food oil lcm hcm UW rads */ +double decay_per_etu = 0.006; /* This gives a half life of ? etus, + about ? days. + half life in Jt + log(.5) / log(1-decay_per_etu) + Calculate your own if you don't like it. + If you want a specific half life you can + calc it with this formula: + decay_per_etu = 1 - (.5)^(1/etus) + due to the discrete nature of empire + you can not get a precise number + without intensive simulation + (more than 3 digits). */ +double fallout_spread = 0.005; /* fraction of fallout that leaks into + each surrounding sector */ +/* end opt_FALLOUT */ + +double bankint = 0.25; /* bank interest rate (dt * bars) */ + +/* Note in the taxes below: + tradetax - this is charged to the seller, so it is < 1 (because the seller + gets the (price paid * tradetax) + buytax - this is charged to the buyer, so it is > 1 (because the buyer is + charged (price paid * buytax). + Not perfect, but it works. :) */ + +double minmult = 0.5; /* minimum trade mulitple */ +double maxmult = 10.0; /* maximum trade multiple */ +double tradetax = 0.99; /* Tax charged on trade */ +double buytax = 1.0; /* Tax charged on market purchases */ +int startmob = 127; /* Sanctuary starting mobility */ +double flakscale = 1.75; /* Scale factor for flak damage */ + +/* money gained from taxes, paid to military, and reservists */ +double money_civ = 0.0083333; +double money_uw = 0.0017777; +double money_mil = -0.0833333; +double money_res = -0.0083333; + +/* pct cost per ETU for maintaining a ship or plane or land unit */ +double money_plane = -0.001; +double money_ship = -0.001; +double money_land = -0.001; + +/* edu and hap consumption factors -- hap_cons civs need 1 hap --> hlev++ */ +double hap_cons = 600000.0; +double edu_cons = 600000.0; + +/* hap and edu avg mean that the weight on current happiness is + * (cur_hap * hap_avg + hap_prod * etu) / (hap_avg + etu); */ +float hap_avg = 16.0 * 3.0; +float edu_avg = 16.0 * 12.0; + + +/* tech build limitations. Tech limits only apply after easy_tech. + * Two ways of limiting tech: asymptotic or logrithmic: + * tech_hard is asymptopic limitation, tech_log_base is the logrithmic + * limitation. set tech_log_base > 1.0 to have it take effect, + * set hard_tech > 0 to have it take effect + * for log based, only tech values where the slop is < 1 are used */ + +float easy_tech = 1.00; /* amount of tech built with no penality */ +float hard_tech = 10.0; /* amount of in-efficiently built tech */ +float tech_log_base = 2.0; /* base of log to take of in-efficient tech */ + +float ally_factor = 2.0; /* shared tech with allies = 1/factor */ +float level_age_rate = 96.0; /* 1% per 96 etu's; 0 -> no decline */ + + +int players_at_00 = 0; /* players coord system on deity 0,0? */ +int at_least_one_100 = 1; /* init player with 100/100/100/100 sector? */ + + + +float btu_build_rate = 0.0012;/* etu * civ * eff * btu_build_rate */ + /* 8 * 999 * 100 * 0.0004 = 319 */ +int max_btus = 640; /* maximum # of btu's */ +double powe_cost = 10.0; /* btu cost to gen a power report */ + +double buil_bt = 10.0; /* tech level required to build a bridge */ +int buil_bh = 100; /* hcm required to build a bridge */ +double buil_bc = 2000.0; /* cash required to build a bridge */ + +double buil_tower_bt = 100.0; /* tech level required to build a tower */ +int buil_tower_bh = 400; /* hcm required to build a bridge tower */ +double buil_tower_bc = 7500.0; /* cash required to build a bridge tower */ + +/* opt_SLOW_WAR */ +int War_Cost = 1000; /* Cost to declare war */ + +/* opt_DEMANDUPDATE */ +long last_demand_update=0; /* When was last demand update? */ + + +/* opt_DRNUKE */ +float drnuke_const = .33; /* research must be at least drnuke_const*tech*/ + /* in order to build a nuke. For example, if + * drnuke_const is .25, you need a 75 res to + * build a nuke that takes 300 tech + */ +/* opt_TRADESHIPS */ +int trade_1_dist = 8; /* less than this gets no money */ +int trade_2_dist = 14; /* less than this gets trade_1 money */ +int trade_3_dist = 25; /* less than this gets trade_2 money */ +float trade_1 = 0.025; /* return on trade_1 distance */ +float trade_2 = 0.035; /* return on trade_2 distance */ +float trade_3 = 0.050; /* return on trade_3 distance */ +float trade_ally_bonus = 0.20; /* 20% bonus for trading with allies */ +float trade_ally_cut = 0.10; /* 10% bonus for ally you trade with */ +/* end opt_TRADESHIPS */ + +int torpedo_damage = 40; /* damage is X + 1dX + 1dX, so 40+1d40+1d40 */ + +/* initial levels */ +float start_education = 0.0; +float start_happiness = 0.0; +float start_technology = 0.0; +float start_research = 0.0; diff --git a/src/lib/global/dir.c b/src/lib/global/dir.c new file mode 100644 index 00000000..eef55bce --- /dev/null +++ b/src/lib/global/dir.c @@ -0,0 +1,71 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * dir.c: Directional orientation descriptions. Must agree with defines + * in path.h + * + * Known contributors to this file: + */ + +#include "misc.h" +#include "var.h" +#include "xy.h" + +/* must agree with DIR_ defines */ +s_char dirch[] = { + 'h', /* stop */ + 'u', /* up-right */ + 'j', /* right */ + 'n', /* down-right */ + 'b', /* down-left */ + 'g', /* left */ + 'y', /* up-left */ + 'v', /* view */ + 'm', /* map */ + '\0', +}; + +/* must agree with dirch[] and DIR_ defines */ +int diroff[][2] = { + {0,0}, {1,-1}, {2,0}, {1,1}, {-1,1}, {-2,0}, {-1,-1}, {0,0}, {0,0} +}; + +/* this maps a character from a to z into the diroff mappings. It + keeps us from having to loop if we don't want to */ +int dirindex[] = { 0, 4, 0, 0, 0, 0, 5, 0, 0, 2, 0, 0, 8, + 3, 0, 0, 0, 0, 0, 0, 1, 7, 0, 0, 6, 0 }; + +/* must agree with dirch[] and DIR_ defines */ +s_char *routech[7][2] = { + { " ", "$ $" }, + { " /", "$ /" }, + { " >", "$ >" }, + { " \\", "$ \\" }, + { "/ ", "/ $" }, + { "< ", "< $" }, + { "\\ ", "\\ $" } +}; diff --git a/src/lib/global/file.c b/src/lib/global/file.c new file mode 100644 index 00000000..a00cb9ac --- /dev/null +++ b/src/lib/global/file.c @@ -0,0 +1,106 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * fileglb.c: Empire selection global structures. + * + * Known contributors to this file: + * + */ + +#include +#include "misc.h" +#include "var.h" +#include "xy.h" +#include "loan.h" +#include "nsc.h" +#include "nuke.h" +#include "plane.h" +#include "ship.h" +#include "land.h" +#include "sect.h" +#include "trade.h" +#include "treaty.h" +#include "file.h" +#include "power.h" +#include "news.h" +#include "nat.h" +#include "lost.h" +#include "optlist.h" + +#include "gamesdef.h" +#include "commodity.h" + +#if !defined(_WIN32) +#define FILEPATH(p) EMPPATH(data/p) +#else +#define FILEPATH(p) EMPPATH(data\\p) +#endif + +struct empfile empfile[] = { + { "sect", FILEPATH(sector), EFF_COM|EFF_XY|EFF_OWNER, + 0, sizeof(struct sctstr), + 0, 0, 0, { fldoff(sctstr, sct_nv), fldoff(sctstr, sct_vtype[0]), + fldoff(sctstr, sct_vamt[0]) }, MAXSCTV, + -1, -1, 0, 0, 0, 0, 0 }, + { "ship", FILEPATH(ship), EFF_COM|EFF_XY|EFF_OWNER|EFF_GROUP, + 0, sizeof(struct shpstr), + 0, 0, 0, { fldoff(shpstr, shp_nv), fldoff(shpstr, shp_vtype[0]), + fldoff(shpstr, shp_vamt[0]) }, MAXSHPV, + -1, -1, 0, 0, 0, 0, 0 }, + { "plane", FILEPATH(plane), EFF_XY|EFF_OWNER|EFF_GROUP, + 0, sizeof(struct plnstr), + 0, 0, 0, { 0, 0, 0 }, 0, -1, -1, 0, 0, 0, 0, 0 }, + { "land", FILEPATH(land), EFF_COM|EFF_XY|EFF_OWNER|EFF_GROUP, + 0, sizeof(struct lndstr), + 0, 0, 0, { fldoff(lndstr, lnd_nv), fldoff(lndstr, lnd_vtype[0]), + fldoff(lndstr, lnd_vamt[0]) }, MAXLNDV, + -1, -1, 0, 0, 0, 0, 0 }, + { "nuke", FILEPATH(nuke), EFF_XY|EFF_OWNER, 0, sizeof(struct nukstr), + 0, 0, 0, { 0, 0, 0 }, 0, -1, -1, 0, 0, 0, 0, 0 }, + { "news", FILEPATH(news), 0, + 0, sizeof(struct nwsstr), + 0, 0, 0, { 0, 0, 0 }, 0, -1, -1, 0, 0, 0, 0, 0 }, + { "treaty", FILEPATH(treaty), 0, 0, sizeof(struct trtstr), + 0, 0, 0, { 0, 0, 0 }, 0, -1, -1, 0, 0, 0, 0, 0 }, + { "trade", FILEPATH(trade), 0, 0, sizeof(struct trdstr), + 0, 0, 0, { 0, 0, 0 }, 0, -1, -1, 0, 0, 0, 0, 0 }, + { "pow", FILEPATH(power), 0, 0, sizeof(struct powstr), + 0, 0, 0, { 0, 0, 0 }, 0, -1, -1, 0, 0, 0, 0, 0 }, + { "nat", FILEPATH(nation), 0, 0, sizeof(struct natstr), + 0, 0, 0, { 0, 0, 0 }, 0, -1, -1, 0, 0, 0, 0, 0 }, + { "loan", FILEPATH(loan), 0, + 0, sizeof(struct lonstr), + 0, 0, 0, { 0, 0, 0 }, 0, -1, -1, 0, 0, 0, 0, 0 }, + { "map", FILEPATH(map), 0, 0, DEF_WORLD_X*DEF_WORLD_Y/2, + 0, 0, 0, { 0, 0, 0 }, 0, -1, -1, 0, 0, 0, 0, 0 }, + { "bmap", FILEPATH(bmap), 0, 0, DEF_WORLD_X*DEF_WORLD_Y/2, + 0, 0, 0, { 0, 0, 0 }, 0, -1, -1, 0, 0, 0, 0, 0 }, + { "commodity", FILEPATH(commodity),0,0,sizeof(struct comstr), + 0, 0, 0, { 0, 0, 0 }, 0, -1, -1, 0, 0, 0, 0, 0 }, + { "lost", FILEPATH(lostitems), 0, 0, sizeof(struct loststr), + 0, 0, 0, { 0, 0, 0 }, 0, -1, -1, 0, 0, 0, 0, 0 } +}; diff --git a/src/lib/global/init.c b/src/lib/global/init.c new file mode 100644 index 00000000..240ceb7a --- /dev/null +++ b/src/lib/global/init.c @@ -0,0 +1,95 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * init.c: Initialize global unit arrays + * + * Known contributors to this file: + * Ken Stevens, 1995 + * Steve McClure, 1997 + */ + +#include "misc.h" +#include "var.h" +#include "ship.h" +#include "plane.h" +#include "product.h" +#include "nat.h" +#include "optlist.h" +#include "global.h" + +void +global_init(void) +{ + init_pchr(); + init_mchr(); + init_plchr(); + /* the same thing should be done for units... */ +} + +void +init_mchr(void) +{ + register struct mchrstr *mp; + register int n; + + for (mp = mchr, n = 0; n < shp_maxno; n++, mp++) { + if (mp->m_nxlight) + mp->m_flags |= M_XLIGHT; + if (mp->m_nchoppers) + mp->m_flags |= M_CHOPPER; + if (mp->m_nplanes && !(mp->m_flags & M_MSL || mp->m_flags & M_FLY)) + mp->m_flags |= M_MSL; + if (mp->m_nland) + mp->m_flags |= M_UNIT; + } +} + +void +init_plchr(void) +{ + register struct plchrstr *pp; + int pcount; + + for (pp = plchr, pcount = 0; pcount < pln_maxno; pcount++, pp++) { + if (pp->pl_flags & P_M) + pp->pl_flags |= P_V; + } +} + +void +init_pchr(void) +{ + register struct pchrstr *p; + int pcount; + + for (p = pchr, pcount = 0; pcount < prd_maxno; pcount++, p++) { + if (opt_GO_RENEW) { + if (p->p_type == V_DUST || p->p_type == V_OIL) + p->p_nrdep = 0; + } + } +} diff --git a/src/lib/global/item.c b/src/lib/global/item.c new file mode 100644 index 00000000..13b25661 --- /dev/null +++ b/src/lib/global/item.c @@ -0,0 +1,63 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * item.c: Item characteristics + * + * Known contributors to this file: + * + */ + +/* + * must be in same order as defines in var.h + */ + +#include "misc.h" +#include "var.h" +#include "item.h" + +struct ichrstr ichr[I_MAX+2] = { +/* mnem vtype val sell lbs rg,wh,ur,bnk name */ + { '?', 0, 0, 0, 0, { 0, 0, 0, 0}, "unused" }, +/* STM CHANGED HERE */ + { 'c', V_CIVIL, 1, 0, 1, {10,10,10,10}, "civilians" }, + { 'm', V_MILIT, 0, 0, 1, { 1, 1, 1, 1}, "military" }, + { 's', V_SHELL, 5, 1, 1, { 1,10, 1, 1}, "shells" }, + { 'g', V_GUN, 60, 1, 10,{ 1,10, 1, 1}, "guns" }, + { 'p', V_PETROL, 4, 1, 1, { 1,10, 1, 1}, "petrol" }, + { 'i', V_IRON, 2, 1, 1, { 1,10, 1, 1}, "iron ore" }, + { 'd', V_DUST, 20, 1, 5, { 1,10, 1, 1}, "dust (gold)" }, + { 'b', V_BAR, 280, 1, 50,{ 1, 5, 1, 4}, "bars of gold" }, + { 'f', V_FOOD, 0, 1, 1, { 1,10, 1, 1}, "food" }, + { 'o', V_OIL, 8, 1, 1, { 1,10, 1, 1}, "oil" }, + { 'l', V_LCM, 2, 1, 1, { 1,10, 1, 1}, "light products" }, + { 'h', V_HCM, 4, 1, 1, { 1,10, 1, 1}, "heavy products" }, + { 'u', V_UW, 1, 1, 2, { 1, 2, 1, 1}, "uncompensated workers"}, + { 'r', V_RAD, 150, 1, 8, { 1,10, 1, 1}, "radioactive materials"}, + { 0, 0, 0, 0, 0, { 0, 0, 0, 0}, 0 } +}; + +int itm_maxno = (sizeof(ichr) / sizeof(struct ichrstr)) - 1; diff --git a/src/lib/global/land.c b/src/lib/global/land.c new file mode 100644 index 00000000..ec648201 --- /dev/null +++ b/src/lib/global/land.c @@ -0,0 +1,266 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * land.c: Land unit characteristics + * + * Known contributors to this file: + * Thomas Ruschak, 1992 + * Ken Stevens, 1995 + * Steve McClure, 1998-2000 + */ + +#include "misc.h" +#include "var.h" +#include "land.h" + +struct lchrstr lchr[] = { + +/* name + lcm, hcm, mil, gun, shell, tech, $, + att, def, vul, spd, vis, spy, rad, frg, acc, dam, amm, aaf, fc, fu, xpl, mxl + flags, nv + cargo +*/ +/* ((int)((ETUS*4)/(mil/1000)) is enough food for 3 updates */ + +{ 2, + { V_FOOD, V_MILIT }, + { ((int)((ETUS*4)/20)), 20 }, +"cav cavalry", + 10, 5, 0, 0, 0, 30, 500, + 1.2, 0.5, 80, 32, 18, 4, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, + L_RECON|L_LIGHT, + }, + +{ 3, + { V_FOOD, V_SHELL, V_MILIT }, + { ((int)((ETUS)/4)), 1, 25 }, +"linf light infantry", + 8, 4, 0, 0, 0, 40, 300, + 1.0, 1.5, 60, 28, 15, 2, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, + L_ASSAULT|L_LIGHT, +}, + +{ 2, + { V_FOOD, V_MILIT }, + { ((int)((ETUS*4)/10)), 100 }, +"inf infantry", + 10, 5, 0, 0, 0, 50, 500, + 1.0, 1.5, 60, 25, 15, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + L_ASSAULT|L_LIGHT, +}, + +{ 3, + { V_FOOD, V_SHELL, V_MILIT }, + { ((int)((ETUS*5)/5)), 8, 100 }, +"mtif motor inf", + 15, 10, 0, 0, 0, 190, 400, + 1.2, 2.2, 60, 33, 17, 1, 3, 0, 0, 0, 2, 3, 13, 1, 0, 0, + L_LIGHT, +}, + +{ 3, + { V_FOOD, V_SHELL, V_MILIT }, + { ((int)((ETUS*5)/5)), 8, 100 }, +"mif mech inf", + 15, 10, 0, 0, 0, 190, 800, + 1.5, 2.5, 50, 33, 17, 1, 3, 0, 0, 0, 2, 3, 13, 1, 0, 0, + L_LIGHT, +}, + +{ 3, + { V_FOOD, V_SHELL, V_MILIT }, + { ((int)((ETUS*5)/5)), 4, 100 }, +"mar marines", + 10, 5, 0, 0, 0, 140,1000, + 1.4, 2.4, 60, 25, 14, 2, 1, 0, 0, 0, 1, 2, 0, 0, 0, 0, + L_MARINE|L_ASSAULT|L_LIGHT, +}, + +{ 10, + { V_SHELL,V_GUN,V_FOOD,V_LCM,V_HCM,V_DUST,V_BAR,V_IRON,V_PETROL,V_MILIT}, + { 200, 10, 300, 200, 100, 100, 10, 100, 300, 25}, +"sup supply", + 10, 5, 0, 0, 0, 50, 500, + 0.1, 0.2, 80, 25, 20, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + L_LIGHT|L_SUPPLY, +}, + +{ 12, + { V_SHELL,V_GUN,V_FOOD,V_LCM,V_HCM,V_DUST,V_BAR,V_IRON,V_PETROL,V_MILIT,V_OIL,V_RAD}, + { 990, 200, 990, 990, 990, 500, 100, 500, 990, 990, 990, 150}, +"tra train", + 100, 50, 0, 0, 0, 40, 3500, + 0.0, 0.0, 120, 10, 25, 3, 0, 0, 0, 0, 0, 0, 0, 0, 5, 12, + L_XLIGHT|L_TRAIN|L_HEAVY|L_SUPPLY, +}, + +{ 0, + { V_FOOD }, + { 0, }, +"spy infiltrator", + 10, 5, 0, 0, 0, 40, 750, + 0.0, 0.0, 80, 32, 18, 4, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, + L_ASSAULT|L_RECON|L_LIGHT|L_SPY, + }, + +{ 1, + { V_SHELL }, + { 3, }, +"com commando", + 10, 5, 0, 0, 0, 55, 1500, + 0.0, 0.0, 80, 32, 18, 4, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, + L_ASSAULT|L_RECON|L_LIGHT|L_SPY, + }, + +{ 3, + { V_FOOD, V_SHELL, V_MILIT }, + { ((int)((ETUS)/5)), 5, 20 }, +"aau aa unit", + 20, 10, 0, 0, 0, 70, 500, + 0.5, 1.0, 60, 18, 20, 1, 1, 0, 0, 0, 1, 2, 0, 0, 0, 0, + L_FLAK|L_LIGHT, +}, + +{ 4, + { V_FOOD, V_SHELL, V_MILIT, V_GUN}, + { ((int)((ETUS*4)/10)), 40, 25, 10 }, +"art artillery", + 20, 10, 0, 0, 0, 35, 800, + 0.1, 0.4, 70, 18, 20, 1, 0, 8, 50, 5, 2, 1, 0, 0, 0, 0, + L_LIGHT, +}, + +{ 4, + { V_FOOD, V_SHELL, V_MILIT, V_GUN }, + { ((int)((ETUS*4)/20)), 20, 25, 6 }, +"lat lt artillery", + 20, 10, 0, 0, 0, 70, 500, + 0.2, 0.6, 60, 30, 18, 1, 1, 5, 10, 3, 1, 1, 0, 0, 0, 0, + L_LIGHT, +}, + +{ 4, + { V_FOOD, V_SHELL, V_MILIT, V_GUN }, + { ((int)((ETUS*4)/10)), 80, 25, 12 }, +"hat hvy artillery", + 40, 20, 0, 0, 0, 100, 800, + 0.0, 0.2, 60, 12, 20, 1, 0, 11, 99, 8, 4, 1, 0, 0, 0, 0, + 0, +}, + +{ 4, + { V_FOOD, V_SHELL, V_MILIT, V_GUN }, + { ((int)((ETUS*5)/20)), 40, 25, 10 }, +"mat mech artillery", + 20, 10, 0, 0, 0, 200, 1000, + 0.2, 0.6, 50, 35, 17, 1, 1, 8, 35, 6, 3, 3, 13, 1, 0, 0, + L_LIGHT, +}, + +{ 3, + { V_FOOD, V_SHELL, V_MILIT }, + { ((int)((ETUS*4)/20)), 3, 20}, +"eng engineer", + 10, 5, 0, 0, 0, 130,3000, + 1.2, 2.4, 50, 25, 14, 2, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, + L_ENGINEER|L_ASSAULT|L_LIGHT, +}, + +{ 3, + { V_FOOD, V_SHELL, V_MILIT }, + { ((int)((ETUS*5)/20)), 4, 20 }, +"meng mech engineer", + 10, 5, 0, 0, 0, 260,4500, + 1.8, 3.5, 45, 33, 15, 3, 3, 0, 0, 0, 1, 5, 25, 2, 0, 0, + L_ENGINEER|L_ASSAULT|L_LIGHT, +}, + +{ 3, + { V_FOOD, V_SHELL,V_MILIT }, + { ((int)((ETUS*5)/10)), 4, 50}, +"lar lt armor", + 10, 5, 0, 0, 0, 150, 600, + 2.0, 1.0, 50, 42, 15, 4, 4, 0, 0, 0, 1, 2, 25, 1, 0, 0, + L_RECON|L_LIGHT, +}, + +{ 3, + { V_FOOD, V_SHELL, V_MILIT }, + { ((int)((ETUS*4)/5)), 3, 100 }, +"har hvy armor", + 20, 10, 0, 0, 0, 120, 500, + 2.0, 0.8, 50, 18, 17, 1, 1, 0, 0, 0, 2, 1, 10, 2, 0, 0, + 0, +}, + +{ 3, + { V_FOOD, V_SHELL, V_MILIT}, + { ((int)((ETUS*5)/10)), 4, 50 }, +"arm armor", + 20, 10, 0, 0, 0, 170,1000, + 3.0, 1.5, 40, 33, 16, 2, 2, 0, 0, 0, 1, 2, 13, 1, 0, 0, + L_LIGHT, +}, + +{ 3, + { V_FOOD, V_SHELL, V_MILIT }, + { ((int)((ETUS*5)/10)), 4, 50 }, +"sec security", + 10, 5, 0, 0, 0, 170, 600, + 1.0, 2.0, 60, 25, 15, 2, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, + L_SECURITY|L_LIGHT, +}, + +{ 2, + { V_FOOD, V_MILIT }, + { ((int)((ETUS*5)/40)), 10 }, +"rad radar unit", + 10, 5, 0, 0, 0, 270,1000, + 0.0, 0.0, 50, 33, 15, 3, 0, 0, 0, 0, 0, 2, 25, 2, 1, 0, + L_XLIGHT|L_RADAR|L_LIGHT, +}, + +/* name + lcm, hcm, mil, gun, shell, tech, $, + att, def, vul, spd, vis, spy, rad, frg, acc, dam, amm, aaf, fc, fu, xpl, + flags, nv + cargo +*/ + +{ 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, +} +}; + +int lnd_maxno = (sizeof(lchr) / sizeof(struct lchrstr)) - 1; + diff --git a/src/lib/global/misc.c b/src/lib/global/misc.c new file mode 100644 index 00000000..616b5a3d --- /dev/null +++ b/src/lib/global/misc.c @@ -0,0 +1,72 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * misc.c: Misc type description lists + * + * Known contributors to this file: + * + */ + +#include "misc.h" + +s_char *effadv_list[] = { + "minimally", "partially", "moderately", "completely", 0, +}; + +/* must follow nation relation defines in nat.h */ +s_char *relates[] = { + "At War", "Sitzkrieg", "Mobilizing", "Hostile", "Neutral", "Friendly", "Allied" +}; + +/* must follow reject flags defined in nat.h */ +s_char *rejects[] = { + " YES YES YES YES", + " NO YES YES YES", + " YES NO YES YES", + " NO NO YES YES", + " YES YES NO YES", + " NO YES NO YES", + " YES NO NO YES", + " NO NO NO YES", + " YES YES YES NO ", + " NO YES YES NO ", + " YES NO YES NO ", + " NO NO YES NO ", + " YES YES NO NO ", + " NO YES NO NO ", + " YES NO NO NO ", + " NO NO NO NO " +}; + +/* must follow TEL_ defines in tel.h */ +s_char *telnames[] = { + "Telegram", "Announcement", "BULLETIN", "Production Report" +}; + +s_char *att_mode[] = { + "defend", "attack", "assault", "paradrop", "board", "lboard" +}; diff --git a/src/lib/global/news.c b/src/lib/global/news.c new file mode 100644 index 00000000..c6584941 --- /dev/null +++ b/src/lib/global/news.c @@ -0,0 +1,229 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * news.c: News item characteristics + * + * Known contributors to this file: + * + */ +/* + * News item characteristics; one entry (and two different + * strings) per news item. Be sure and increase N_MAX_VERB + * in news.h if you add a news item. + * + * Order must correspond to ordering in news.h + */ + +#include "misc.h" +#include "news.h" + +s_char *page_headings[N_MAX_PAGE+1] = { +/* not used */ "Comics", +/* N_FOR */ "Foreign Affairs", +/* N_FRONT */ "The Front Line", +/* N_SEA */ "The High Seas", +/* N_SKY */ "Sky Watch", +/* N_MISS */ "Guidance Systems", +/* N_ARTY */ "Firestorms", +/* N_ECON */ "Business & Economics", +/* N_COLONY */ "The Frontier", +/* N_HOME */ "The Home Front", +/* N_SPY */ "Espionage", +/* N_TELE */ "Telecommunications" +}; + +struct rptstr rpt[N_MAX_VERB+1] = { +/* nice page text +*/{ 0, 0, { "does nothing in particular to %s", +/* 0*/ "does nothing to %s" } }, + { -4, N_FRONT, { "infantry capture %s territory", +/* 1*/ "shock troops overrun one of %s's sectors" } }, + { -4, N_FRONT, { "infantry beaten back by %s troops", +/* 2*/ "shock troops annihilated in failed attack on %s" } }, + { -1, N_SPY, { "spy shot by %s firing squad", +/* 3*/ "spy captured and shot by %s" } }, + { 1, N_TELE, { "sends a telegram to %s", +/* 4*/ "telexes %s" } }, + { 3, N_FOR, { "diplomats sign a treaty with %s", +/* 5*/ "ambassador agrees to a treaty with %s" } }, + { 2, N_ECON, { "bankers make a loan to %s", +/* 6*/ "Ministry of Finance lends money to %s" } }, + { 1, N_ECON, { "repays a loan from %s", +/* 7*/ "makes last payment on loan from %s" } }, + { 0, N_ECON, { "makes a sale to %s", +/* 8*/ "sells goods to %s" } }, + { -1, N_SKY, { "violates %s airspace", +/* 9*/ "overflies %s territory" } }, + { -2, N_ARTY, { "gunners bombard %s territory", +/* 10*/ "artillery fires on %s sectors" } }, + { -2, N_SEA, { "shells a ship owned by %s", +/* 11*/ "fires on %s ships" } }, + { 0, N_FRONT, { "takes over unoccupied land", +/* 12*/ "attacks unowned land for some reason" } }, + { 0, N_SEA, { "ships torpedoed by enemy wolf-packs", +/* 13*/ "ships torpedoed by marauding U-boats" } }, + { 0, N_ARTY, { "gunners fire on %s in self-defense", +/* 14*/ "gunners decimate %s aggressors" } }, + { 0, N_FOR, { "breaks sanctuary", +/* 15*/ "no longer has a sanctuary" } }, + { -2, N_SKY, { "planes divebomb one of %s's sectors", +/* 16*/ "bombers wreak havoc on %s" } }, + { -2, N_SEA, { "divebombs a ship flying the flag of %s", +/* 17*/ "airforce bombs %s ships" } }, + { -2, N_SEA, { "seadogs board one of %s's ships", +/* 18*/ "pirates board %s ship" } }, + { -3, N_SEA, { "is repelled by %s while attempting to board a ship", +/* 19*/ "pirates prove inept at boarding %s's ships" } }, + { -1, N_SKY, { "anti-aircraft gunners fire on %s airforce", +/* 20*/ "attempts to shoot down %s aircraft" } }, + { -2, N_ECON, { "seizes a sector from %s to collect on a loan", +/* 21*/ "collects one of %s's sectors in repayment of a loan" } }, + { -1, N_FOR, { "considers an action which would violate a treaty with %s", +/* 22*/ "decides not to violate treaty with %s (yet)" } }, + { -4, N_FOR, { "violates a treaty with %s", +/* 23*/ "actions violate treaty with %s" } }, + { 0, N_FOR, { "dissolves its government", +/* 24*/ "throws in the towel" } }, + { 0, N_SEA, { "ship hits a mine", +/* 25*/ "ship severely damaged in mine field" } }, + { 5, N_FOR, { "announces an alliance with %s", +/* 26*/ "/ %s alliance declared" } }, + { 0, N_FOR, { "declares their neutrality toward %s", /* no longer used */ +/* 27*/ "announces neutral relations with %s" } }, + { -5, N_FOR, { "declares TOTAL WAR on %s", +/* 28*/ "gets serious with %s and declares WAR" } }, + { 0, N_FOR, { "diplomats disavow former alliance with %s", +/* 29*/ "is no longer allied with %s" } }, + { 5, N_FOR, { "is no longer at war with %s", +/* 30*/ "Foreign Ministry declares \"No more war with %s\"" } }, + { 0, N_HOME, { "reports outbreak of the black plague", +/* 31*/ "sector infected with bubonic plague" } }, + { 0, N_HOME, { "citizens die from bubonic plague", +/* 32*/ "sector reports plague deaths" } }, + { 0, N_FOR, { "goes through a name change", +/* 33*/ "adopts a new country name" } }, + { 0, N_HOME, { "citizens starve in disastrous famine", +/* 34*/ "loses citizens to mass starvation" } }, + { 0, N_HOME, { "endures lawless rioting", +/* 35*/ "suffers from outbreaks of rioting" } }, + { -3, N_SKY, { "pilots down %s planes", +/* 36*/ "victorious in air-to-air combat against %s" } }, + { -10, N_MISS, { "nuclear device devastates %s sector", +/* 37*/ "explodes a nuclear device damaging %s territory" } }, + { 0, N_HOME, { "terrorists shoot it out with %s special forces", +/* 38*/ "underground rises up against %s occupation" } }, + { -2, N_HOME, { "execution squads gun down helpless %s civilians", +/* 39*/ "firing squads massacre defenseless %s workers" } }, + { 0, N_MISS, { "launches a satellite into orbit", +/* 40*/ "continues its conquest of space with a successful launch" } }, + { -8, N_MISS, { "strikes a %s big bird", +/* 41*/ "rockets damage a %s satellite" } }, + { 4, N_ECON, { "makes a contribution to %s", +/* 42*/ "helps out %s" } }, + { 2, N_HOME, { "aids %s with divine intervention", +/* 43*/ "smiles upon %s" } }, + { -3, N_HOME, { "hurts %s with divine intervention", +/* 44*/ "frowns upon %s" } }, + { -4, N_ECON, { "sacrifices to %s", +/* 45*/ "makes divine payment to %s" } }, + { -10, N_MISS, { "abms intercept a %s missile", +/* 46*/ "strategic defense systems destroy a %s missile" } }, + { -2, N_MISS, { "missile fired at one of %s's sectors", +/* 47*/ "missile wreaks havoc on %s" } }, + { -2, N_MISS, { "missile fired at a ship flying the flag of %s", +/* 48*/ "missiles hit %s ships" } }, + { 2, N_ECON, { "engages in friendly trade with %s", +/* 49*/ "profits from a merchant venture with %s" } }, + { 0, N_ECON, { "pirates dispose of %s booty in trade", +/* 50*/ "buccaneers sell their %s goods" } }, + { 0, N_ECON, { "pirates keep their %s booty", +/* 51*/ "buccaneers laugh and bury their %s goods" } }, + { 0, N_SEA, { "ships torpedoed by %s torpedo-boats", +/* 52*/ "ships sunk by marauding %s torpedo-boats" } }, + { 0, N_SEA, { "planes bomb a skulking %s submarine", +/* 53*/ "planes drop depth-charges on a %s sub" } }, + { -2, N_SEA, { "ship is blown up in a failed assault on %s", +/* 54*/ "has a ship destroyed while assaulting %s" } }, + { -2, N_SKY, { "divebombs a brave %s unit", +/* 55*/ "airforce bombs %s units" } }, + { 0, N_FRONT, { "troops run afoul of a landmine", +/* 56*/ "troops severely damaged in mine field" } }, + { -2, N_ARTY, { "fortress gunners support troops attacking %s", +/* 57*/ "fortress artillery massacres %s defenders" } }, + { -2, N_ARTY, { "gunners support troops attacking %s", +/* 58*/ "artillery battery massacres %s defenders" } }, + { -2, N_ARTY, { "naval gunners support troops attacking %s", +/* 59*/ "naval gunfire massacres %s defenders" } }, + {-10, N_FOR, { "sacks %s capital", +/* 60*/ "captures and pillages %s's capital" } }, + { 3, N_FOR, { "announces friendly trade relations with %s", +/* 61*/ "upgrades %s's trade status to triple-A" } }, + { 0, N_FOR, { "downgrades relations with %s to friendly", +/* 62*/ "cools relations with %s to friendly" } }, + { 2, N_FOR, { "upgrades relations with %s to neutral", +/* 63*/ "Foreign Ministry declares \"%s is A-OK.\"" } }, + { 0, N_FOR, { "downgrades relations with %s to neutral", +/* 64*/ "gives the cold shoulder to %s and declares neutral relations" } }, + { 3, N_FOR, { "upgrades relations with %s to hostile", +/* 65*/ "forgives %s of past war crimes but remains hostile" } }, + {-3, N_FOR, { "downgrades relations with %s to hostile", +/* 66*/ "is suspicious that %s has hostile intentions" } }, + { 0, N_MISS, { "sector is struck by a sub-launched missile", +/* 67*/ "sector devastated by missile" } }, + { 0, N_MISS, { "ship is hit by a sub-launched missile", +/* 68*/ "ship damaged by marine missile" } }, + { 0, N_COLONY,{ "pilgrims settle on a new island", +/* 69*/ "discovers new land and starts a colony" } }, + { 0, N_MISS, { "abms intercept an incoming nuclear device", +/* 70*/ "strategic defense systems destroy an incoming nuclear warhead" } }, + {-2, N_MISS, { "missile fired at %s ground troops", +/* 71*/ "missile hits %s troops" } }, + { 0, N_MISS, { "regiment struck by sub-launched missile", +/* 72*/ "ground troops hit by missile" } }, + { -4, N_FRONT, { "navy secures a beachhead on %s territory", +/* 73*/ "sailors take a coastal sector from %s" } }, + { -4, N_FRONT, { "paratroopers comandeer a sector from %s", +/* 74*/ "air force parachutists overwhelm a %s sector" } }, + { 0, N_COLONY,{ "parachutists grab unoccupied land", +/* 75*/ "paratroopers break new ground" } }, + {-4, N_FRONT, { "sailors repelled by %s coast-guard", +/* 76*/ "naval forces massacred in failed assault of %s" } }, + {-4, N_FRONT, { "paratroopers destroyed in failed air-assault on %s", +/* 77*/ "loses parachutists in failed air-assault of %s" } }, + { 0, N_ECON, { "is forced into debt to %s by bad management", +/* 78*/ "shows bad financial planning" } }, + { 0, N_ECON, { "has its credit rating downgraded to unworthy status", +/* 79*/ "is denied credit by %s due to lack of collatoral" } }, + { 0, N_ECON, { "is unable to fulfill its financial obligations to %s", +/* 80*/ "welches on a deal with %s" } }, + { -3, N_FRONT, { "is repelled by %s while attempting to board a land unit", +/* 81*/ "forces prove inept at boarding %s's land unit" } }, + { -2, N_FRONT, { "mercenaries board one of %s's land units", +/* 82*/ "elite forces board %s land unit" } } +}; + +int nws_maxno = (sizeof(rpt) / sizeof(struct rptstr)) - 1; diff --git a/src/lib/global/nsc.c b/src/lib/global/nsc.c new file mode 100644 index 00000000..8dbd3f53 --- /dev/null +++ b/src/lib/global/nsc.c @@ -0,0 +1,370 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * nscglb.c: Empire selection global structures + * + * Known contributors to this file: + * + */ + +#include +#include "misc.h" +#include "var.h" +#include "xy.h" +#include "loan.h" +#include "nsc.h" +#include "news.h" +#include "nuke.h" +#include "plane.h" +#include "ship.h" +#include "land.h" +#include "sect.h" +#include "trade.h" +#include "treaty.h" +#include "genitem.h" +#include "nat.h" +#include "map.h" +#include "commodity.h" +#include "lost.h" + +struct castr var_ca[] = { +{ NSC_DEITY | NSC_VAR | V_PSTAGE, "pstage",0,0 }, +{ NSC_DEITY | NSC_VAR | V_PTIME, "ptime",0,0 }, +{ NSC_DEITY | NSC_VAR | V_CHE, "che",0,0 }, +{ NSC_DEITY | NSC_VAR | V_MINE, "lmine",0,0 }, +{ NSC_VAR | V_FALLOUT, "fallout",0,0 }, +{ NSC_ROUND | NSC_VAR | V_CIVIL, "civil",0,0 }, +{ NSC_ROUND | NSC_VAR | V_MILIT, "milit",0,0 }, +{ NSC_ROUND | NSC_VAR | V_SHELL, "shell",0,0 }, +{ NSC_ROUND | NSC_VAR | V_GUN, "gun",0,0 }, +{ NSC_ROUND | NSC_VAR | V_PETROL, "petrol",0,0 }, +{ NSC_ROUND | NSC_VAR | V_IRON, "iron",0,0 }, +{ NSC_ROUND | NSC_VAR | V_DUST, "dust",0,0 }, +{ NSC_ROUND | NSC_VAR | V_BAR, "bar",0,0 }, +{ NSC_ROUND | NSC_VAR | V_FOOD, "food",0,0 }, +{ NSC_ROUND | NSC_VAR | V_OIL, "oil",0,0 }, +{ NSC_ROUND | NSC_VAR | V_LCM, "lcm",0,0 }, +{ NSC_ROUND | NSC_VAR | V_HCM, "hcm",0,0 }, +{ NSC_ROUND | NSC_VAR | V_UW, "uw",0,0 }, +{ NSC_ROUND | NSC_VAR | V_RAD, "rad",0,0 }, +{ NSC_VAR | V_CDIST, "c_dist",0,0 }, +{ NSC_VAR | V_MDIST, "m_dist",0,0 }, +{ NSC_VAR | V_UDIST, "u_dist",0,0 }, +{ NSC_VAR | V_SDIST, "s_dist",0,0 }, +{ NSC_VAR | V_GDIST, "g_dist",0,0 }, +{ NSC_VAR | V_PDIST, "p_dist",0,0 }, +{ NSC_VAR | V_IDIST, "i_dist",0,0 }, +{ NSC_VAR | V_DDIST, "d_dist",0,0 }, +{ NSC_VAR | V_BDIST, "b_dist",0,0 }, +{ NSC_VAR | V_FDIST, "f_dist",0,0 }, +{ NSC_VAR | V_ODIST, "o_dist",0,0 }, +{ NSC_VAR | V_LDIST, "l_dist",0,0 }, +{ NSC_VAR | V_HDIST, "h_dist",0,0 }, +{ NSC_VAR | V_RDIST, "r_dist",0,0 }, +{ NSC_VAR | V_CDEL, "c_del",0,0 }, +{ NSC_VAR | V_MDEL, "m_del",0,0 }, +{ NSC_VAR | V_UDEL, "u_del",0,0 }, +{ NSC_VAR | V_SDEL, "s_del",0,0 }, +{ NSC_VAR | V_GDEL, "g_del",0,0 }, +{ NSC_VAR | V_PDEL, "p_del",0,0 }, +{ NSC_VAR | V_IDEL, "i_del",0,0 }, +{ NSC_VAR | V_DDEL, "d_del",0,0 }, +{ NSC_VAR | V_BDEL, "b_del",0,0 }, +{ NSC_VAR | V_FDEL, "f_del",0,0 }, +{ NSC_VAR | V_ODEL, "o_del",0,0 }, +{ NSC_VAR | V_LDEL, "l_del",0,0 }, +{ NSC_VAR | V_HDEL, "h_del",0,0 }, +{ NSC_VAR | V_RDEL, "r_del",0,0 }, +{ 0, 0, 0,0 } +}; + +struct castr sect_ca[] = { +#ifndef apollo +{ NSC_UCHAR|fldoff(sctstr, sct_own),"owner",0,0 }, +{ NSC_XCOORD|fldoff(sctstr, sct_x), "xloc",0,0 }, +{ NSC_YCOORD|fldoff(sctstr, sct_y), "yloc",0,0 }, +{ NSC_UCHAR|fldoff(sctstr, sct_type), "des",0,0 }, +{ NSC_ROUND|NSC_UCHAR|fldoff(sctstr, sct_effic), "effic",0,0 }, +{ NSC_SHORT|fldoff(sctstr, sct_mobil), "mobil",0,0 }, +{ NSC_UCHAR|fldoff(sctstr, sct_terr), "terr",0,0 }, +{ NSC_UCHAR|fldoff(sctstr, sct_terr), "terr0",0,0 }, +{ NSC_UCHAR|fldoff(sctstr, sct_terr1), "terr1",0,0 }, +{ NSC_UCHAR|fldoff(sctstr, sct_terr2), "terr2",0,0 }, +{ NSC_UCHAR|fldoff(sctstr, sct_terr3), "terr3",0,0 }, +{ NSC_UCHAR|fldoff(sctstr, sct_work), "work",0,0 }, +{ NSC_UCHAR|fldoff(sctstr, sct_coastal), "coastal",0,0 }, +{ NSC_UCHAR|fldoff(sctstr, sct_newtype), "newdes",0,0 }, +{ NSC_UCHAR|fldoff(sctstr, sct_min), "min",0,0 }, +{ NSC_UCHAR|fldoff(sctstr, sct_gmin), "gold",0,0 }, +{ NSC_UCHAR|fldoff(sctstr, sct_fertil), "fert",0,0 }, +{ NSC_UCHAR|fldoff(sctstr, sct_oil), "ocontent",0,0 }, +{ NSC_UCHAR|fldoff(sctstr, sct_uran), "uran",0,0 }, +{ NSC_UCHAR|fldoff(sctstr, sct_oldown), "oldown",0,0 }, +{ NSC_UCHAR|fldoff(sctstr, sct_off), "off",0,0 }, +{ NSC_XCOORD|fldoff(sctstr, sct_dist_x), "xdist",0,0 }, +{ NSC_YCOORD|fldoff(sctstr, sct_dist_y), "ydist",0,0 }, +{ NSC_SHORT|fldoff(sctstr, sct_avail), "avail",0,0 }, +{ NSC_UCHAR|fldoff(sctstr, sct_road), "road",0,0 }, +{ NSC_UCHAR|fldoff(sctstr, sct_rail), "rail",0,0 }, +{ NSC_UCHAR|fldoff(sctstr, sct_defense), "dfense",0,0 }, +{ NSC_TIME|fldoff(sctstr, sct_timestamp), "timestamp",0,0 }, +#endif +{ 0, 0, 0,0 } +}; + +#define NSC_GENITEM \ +{ NSC_UCHAR | fldoff(genitem, own), "owner",0,0 },\ +{ NSC_SHORT | fldoff(genitem, uid), "uid",0,0 },\ +{ NSC_XCOORD | fldoff(genitem, x), "xloc",0,0 },\ +{ NSC_YCOORD | fldoff(genitem, y), "yloc",0,0 },\ +{ NSC_UCHAR | fldoff(genitem, type), "type",0,0 },\ +{ NSC_ROUND | NSC_UCHAR | fldoff(genitem, effic), "effic",0,0 },\ +{ NSC_CHAR | fldoff(genitem, mobil), "mobil",0,0 },\ +{ NSC_SHORT | fldoff(genitem, sell), "sell",0,0 },\ +{ NSC_ROUND | NSC_SHORT | fldoff(genitem, tech), "tech",0,0 },\ +{ NSC_CHAR | fldoff(genitem, group), "group",0,0 },\ +{ NSC_XCOORD | fldoff(genitem, opx), "opx",0,0 },\ +{ NSC_YCOORD | fldoff(genitem, opy), "opy",0,0 },\ +{ NSC_SHORT | fldoff(genitem, mission), "mission",0,0 } + +struct castr genitem_ca[] = { +#ifndef apollo +NSC_GENITEM, +#endif +{0, 0, 0,0 } +}; + +struct castr ship_ca[] = { +#ifndef apollo +NSC_GENITEM, +{ NSC_CHAR | fldoff(shpstr, shp_fleet), "fleet",0,0 }, +{ NSC_CHAR | fldoff(shpstr, shp_nplane), "nplane",0,0 }, +{ NSC_TIME | fldoff(shpstr, shp_timestamp), "timestamp",0,0 }, +{ NSC_UCHAR | fldoff(shpstr, shp_fuel), "fuel",0,0 }, +{ NSC_UCHAR | fldoff(shpstr, shp_nxlight), "nxlight",0,0 }, +{ NSC_UCHAR | fldoff(shpstr, shp_nchoppers), "nchoppers",0,0 }, +{ NSC_UCHAR | fldoff(shpstr, shp_autonav), "autonav",0,0 }, +#endif +{ 0, 0, 0,0 } +}; + +struct castr plane_ca[] = { +#ifndef apollo +NSC_GENITEM, +{ NSC_UCHAR | fldoff(plnstr, pln_wing), "wing",0,0 }, +{ NSC_UCHAR | fldoff(plnstr, pln_range), "range",0,0 }, +{ NSC_SHORT | fldoff(plnstr, pln_ship), "ship",0,0 }, +{ NSC_UCHAR | fldoff(plnstr, pln_att), "att",0,0 }, +{ NSC_UCHAR | fldoff(plnstr, pln_def), "def",0,0 }, +{ NSC_UCHAR | fldoff(plnstr, pln_harden), "harden",0,0 }, +{ NSC_UCHAR | fldoff(plnstr, pln_nuketype), "nuketype",0,0 }, +{ NSC_UCHAR | fldoff(plnstr, pln_flags), "flags",0,0 }, +{ NSC_SHORT | fldoff(plnstr, pln_land), "land",0,0 }, +{ NSC_TIME | fldoff(plnstr, pln_timestamp), "timestamp",0,0 }, +#endif +{ 0, 0, 0,0 } +}; + +struct castr land_ca[] = { +#ifndef apollo +NSC_GENITEM, +{ NSC_CHAR | fldoff(lndstr, lnd_army), "army",0,0 }, +{ NSC_SHORT | fldoff(lndstr, lnd_ship), "ship",0,0 }, +{ NSC_SHORT | fldoff(lndstr, lnd_land), "land",0,0 }, +{ NSC_CHAR | fldoff(lndstr, lnd_harden), "harden",0,0 }, +{ NSC_SHORT | fldoff(lndstr, lnd_retreat), "retreat",0,0 }, +{ NSC_UCHAR | fldoff(lndstr, lnd_fuel), "fuel",0,0 }, +{ NSC_UCHAR | fldoff(lndstr, lnd_nxlight), "nxlight",0,0 }, +{ NSC_FLOAT | fldoff(lndstr, lnd_att), "att",0,0 }, +{ NSC_FLOAT | fldoff(lndstr, lnd_def), "def",0,0 }, +{ NSC_INT | fldoff(lndstr, lnd_vul), "vul",0,0 }, +{ NSC_INT | fldoff(lndstr, lnd_spd), "spd",0,0 }, +{ NSC_INT | fldoff(lndstr, lnd_vis), "vis",0,0 }, +{ NSC_INT | fldoff(lndstr, lnd_spy), "spy",0,0 }, +{ NSC_INT | fldoff(lndstr, lnd_rad), "rad",0,0 }, +{ NSC_INT | fldoff(lndstr, lnd_frg), "frg",0,0 }, +{ NSC_INT | fldoff(lndstr, lnd_acc), "acc",0,0 }, +{ NSC_INT | fldoff(lndstr, lnd_dam), "dam",0,0 }, +{ NSC_INT | fldoff(lndstr, lnd_ammo), "ammo",0,0 }, +{ NSC_INT | fldoff(lndstr, lnd_aaf), "aaf",0,0 }, +{ NSC_UCHAR | fldoff(lndstr, lnd_fuelc), "fuelc",0,0 }, +{ NSC_UCHAR | fldoff(lndstr, lnd_fuelu), "fuelu",0,0 }, +{ NSC_UCHAR | fldoff(lndstr, lnd_maxlight), "maxlight",0,0 }, +{ NSC_TIME | fldoff(lndstr, lnd_timestamp), "timestamp",0,0 }, +#endif +{ 0, 0, 0,0 } +}; + +struct castr nuke_ca[] = { +#ifndef apollo +{ NSC_UCHAR | fldoff(nukstr, nuk_own), "owner",0,0 }, +{ NSC_SHORT | fldoff(nukstr, nuk_uid), "uid",0,0 }, +{ NSC_XCOORD | fldoff(nukstr, nuk_x), "xloc",0,0 }, +{ NSC_YCOORD | fldoff(nukstr, nuk_y), "yloc",0,0 }, +{ NSC_CHAR | fldoff(nukstr, nuk_n), "number",0,0 }, +#if !defined(_WIN32) +{ NSC_CHAR | fldoff(nukstr, nuk_types[0]),"types",N_MAXNUKE,0 }, +#else +{ NSC_CHAR | fldoff(nukstr, nuk_types),"types",N_MAXNUKE,0 }, +#endif +{ NSC_TIME | fldoff(nukstr, nuk_timestamp), "timestamp",0,0 }, +#endif +{ 0, 0, 0,0 } +}; + +struct castr treaty_ca[] = { +#ifndef apollo +{ NSC_UCHAR | fldoff(trtstr, trt_cna), "cna",0,0 }, +{ NSC_UCHAR | fldoff(trtstr, trt_cnb), "cnb",0,0 }, +{ NSC_UCHAR | fldoff(trtstr, trt_status), "status",0,0 }, +{ NSC_SHORT | fldoff(trtstr, trt_acond), "acond",0,0 }, +{ NSC_SHORT | fldoff(trtstr, trt_bcond), "bcond",0,0 }, +{ NSC_LONG | fldoff(trtstr, trt_exp), "exp",0,0 }, +#endif +{ 0, 0, 0,0 } +}; + +struct castr loan_ca[] = { +#ifndef apollo +{ NSC_UCHAR | fldoff(lonstr, l_loner), "loaner",0,0 }, +{ NSC_SHORT | fldoff(lonstr, l_uid), "uid", 0, 0 }, +{ NSC_UCHAR | fldoff(lonstr, l_lonee), "loanee",0,0 }, +{ NSC_CHAR | fldoff(lonstr, l_status), "status",0,0 }, +{ NSC_SHORT | fldoff(lonstr, l_sell), "sell",0,0 }, +{ NSC_INT | fldoff(lonstr, l_irate), "irate",0,0 }, +{ NSC_INT | fldoff(lonstr, l_ldur), "ldur",0,0 }, +{ NSC_LONG | fldoff(lonstr, l_amtpaid), "amtpaid",0,0 }, +{ NSC_LONG | fldoff(lonstr, l_amtdue), "amtdue",0,0 }, +{ NSC_TIME | fldoff(lonstr, l_lastpay), "lastpay",0,0 }, +{ NSC_TIME | fldoff(lonstr, l_duedate), "duedate",0,0 }, +#endif +{ 0, 0, 0,0 } +}; + +struct castr news_ca[] = { +#ifndef apollo +{ NSC_CHAR | fldoff(nwsstr, nws_ano), "actor",0,0 }, +{ NSC_CHAR | fldoff(nwsstr, nws_vrb), "action",0,0 }, +{ NSC_CHAR | fldoff(nwsstr, nws_vno), "victim",0,0 }, +{ NSC_CHAR | fldoff(nwsstr, nws_ntm), "times",0,0 }, +{ NSC_LONG | fldoff(nwsstr, nws_when), "time",0,0 }, +#endif +{ 0, 0, 0,0 } +}; + +struct castr lost_ca[] = { +{ NSC_UCHAR | fldoff(loststr, lost_owner), "owner", 0, 0 }, +{ NSC_INT | fldoff(loststr, lost_uid), "uid", 0, 0 }, +{ NSC_UCHAR | fldoff(loststr, lost_type), "type", 0, 0 }, +{ NSC_XCOORD | fldoff(loststr, lost_x), "x", 0, 0 }, +{ NSC_YCOORD | fldoff(loststr, lost_y), "y", 0, 0 }, +{ NSC_TIME | fldoff(loststr, lost_timestamp), "timestamp", 0, 0 }, +{ 0, 0, 0, 0 } +}; + +struct castr commodity_ca[] = { +{ NSC_UCHAR | fldoff(comstr, com_owner), "owner",0,0 }, +{ NSC_SHORT | fldoff(comstr, com_uid), "uid",0,0 }, +{ NSC_UCHAR | fldoff(comstr, com_type), "type",0,0 }, +{ NSC_INT | fldoff(comstr, com_amount), "amount",0,0 }, +{ NSC_FLOAT | fldoff(comstr, com_price), "price",0,0 }, +{ NSC_INT | fldoff(comstr, com_maxbidder), "maxbidder",0,0 }, +{ NSC_FLOAT | fldoff(comstr, com_maxprice), "maxprice",0,0 }, +{ NSC_TIME | fldoff(comstr, com_markettime), "markettime",0,0 }, +{ NSC_INT | fldoff(comstr, com_x), "xloc",0,0 }, +{ NSC_INT | fldoff(comstr, com_y), "yloc",0,0 }, +{ NSC_XCOORD | fldoff(comstr, sell_x), "xsell",0,0 }, +{ NSC_YCOORD | fldoff(comstr, sell_y), "ysell",0,0 }, +{ 0, 0, 0,0 } +}; + +struct castr trade_ca[] = { +#ifndef apollo +{ NSC_UCHAR | fldoff(trdstr, trd_owner), "owner",0,0 }, +{ NSC_SHORT | fldoff(trdstr, trd_uid), "uid", 0, 0 }, +{ NSC_UCHAR | fldoff(trdstr, trd_type), "type",0,0 }, +{ NSC_SHORT | fldoff(trdstr, trd_unitid), "unitid",0,0 }, +{ NSC_LONG | fldoff(trdstr, trd_price), "price",0,0 }, +{ NSC_INT | fldoff(trdstr, trd_maxbidder), "maxbidder",0,0 }, +{ NSC_INT | fldoff(trdstr, trd_maxprice), "maxprice",0,0 }, +{ NSC_TIME | fldoff(trdstr, trd_markettime), "markettime",0,0 }, +{ NSC_XCOORD | fldoff(trdstr, trd_x), "xloc",0,0 }, +{ NSC_YCOORD | fldoff(trdstr, trd_y), "yloc",0,0 }, +#endif +{ 0, 0, 0,0 } +}; + +struct castr nat_ca[] = { +{ NSC_UCHAR | fldoff(natstr, nat_cnum),"cnum",0,0 }, +#if !defined(_WIN32) +{ NSC_CHAR | fldoff(natstr, nat_cnam[0]),"cnam",20,0 }, +{ NSC_DEITY | NSC_CHAR | fldoff(natstr, nat_pnam[0]),"pnam",20,0 }, +#else +{ NSC_CHAR | fldoff(natstr, nat_cnam),"cnam",20,0 }, +{ NSC_DEITY | NSC_CHAR | fldoff(natstr, nat_pnam),"pnam",20,0 }, +#endif +{ NSC_XCOORD | fldoff(natstr, nat_xstart),"xstart",0,0 }, +{ NSC_YCOORD | fldoff(natstr, nat_ystart),"ystart",0,0 }, +{ NSC_XCOORD | fldoff(natstr, nat_xcap),"xcap",0,0 }, +{ NSC_YCOORD | fldoff(natstr, nat_ycap),"ycap",0,0 }, +{ NSC_DEITY | NSC_XCOORD | fldoff(natstr, nat_xorg),"xorg",0,0 }, +{ NSC_DEITY | NSC_YCOORD | fldoff(natstr, nat_yorg),"yorg",0,0 }, +#ifdef MAYBE_LATER +{ NSC_CHAR | fldoff(natstr, nat_stat),"stat",0,0 }, +{ NSC_CHAR | fldoff(natstr, nat_dayno),"dayno",0,0 }, +{ NSC_CHAR | fldoff(natstr, nat_update),"update",0,0 }, +{ NSC_UCHAR | fldoff(natstr, nat_missed),"missed",0,0 }, +#endif /* MAYBE_LATER */ +{ NSC_USHORT | fldoff(natstr, nat_tgms),"tgms",0,0 }, +{ NSC_USHORT | fldoff(natstr, nat_ann),"ann",0,0 }, +{ NSC_USHORT | fldoff(natstr, nat_minused),"minused",0,0 }, +{ NSC_SHORT | fldoff(natstr, nat_btu),"btu",0,0 }, +{ NSC_LONG | fldoff(natstr, nat_reserve),"reserve",0,0 }, +{ NSC_LONG | fldoff(natstr, nat_money),"money",0,0 }, +#ifdef MAYBE_LATER +{ NSC_LONG | fldoff(natstr, nat_last_login),"last_login",0,0 }, +{ NSC_LONG | fldoff(natstr, nat_last_logout),"last_logout",0,0 }, +{ NSC_LONG | fldoff(natstr, nat_newstim),"newstim",0,0 }, +#endif /* MAYBE_LATER */ +#if !defined(_WIN32) +{ NSC_FLOAT | fldoff(natstr, nat_level[0]),"level",4,0 }, +#else +{ NSC_FLOAT | fldoff(natstr, nat_level),"level",4,0 }, +#endif +/* NSC_SHORT | fldoff(natstr, nat_relate[0]),"relate",MAXNOC,0, */ +/* NSC_CHAR | fldoff(natstr, nat_priorities[0]),"priorities",39,0, */ +/* NSC_LONG | fldoff(natstr, nat_flags),"flags",0,0, */ +{ 0, 0, 0,0 } +}; + +struct castr map_ca[] = { +{ NSC_XCOORD | fldoff(mapstr, map_x),"x",0,0 }, +{ NSC_YCOORD | fldoff(mapstr, map_y),"y",0,0 }, +{ NSC_CHAR | fldoff(mapstr, map_des),"des",0,0 }, +{ 0, 0, 0,0 } +}; + diff --git a/src/lib/global/nuke.c b/src/lib/global/nuke.c new file mode 100644 index 00000000..7bea0852 --- /dev/null +++ b/src/lib/global/nuke.c @@ -0,0 +1,57 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * nuke.c: Nuke characteristics + * + * Known contributors to this file: + * + */ + +#include "misc.h" +#include "nuke.h" + + +struct nchrstr nchr[N_MAXNUKE] = { + /* name lcm hcm oil rads blst dam cost tech lbs flags */ + { "10kt fission", 50, 50, 25, 70, 3, 70, 10000, 280, 4, 0 }, + { "15kt fission", 50, 50, 25, 80, 3, 90, 15000, 290, 5, 0 }, + { "50kt fission", 60, 60, 30, 90, 3, 100, 25000, 300, 6, 0 }, + { "100kt fission", 75, 75, 40, 120, 4, 125, 30000, 310, 8, 0 }, + { "5kt fusion", 15, 15, 15, 30, 2, 80, 12500, 315, 1, 0 }, + { "75kt fusion", 40, 40, 35, 50, 3, 90, 20000, 320, 3, 0 }, + { "250kt fusion", 50, 50, 45, 60, 4, 110, 25000, 330, 4, 0 }, + { "500kt fusion", 60, 60, 50, 80, 5, 120, 35000, 340, 5, 0 }, + { "1mt fusion", 75, 75, 50, 110, 6, 150, 40000, 350, 5, 0 }, + { "60kt neutron", 60, 60, 30, 100, 3, 30, 30000, 355, 2, N_NEUT }, + { "3mt fusion", 100, 100, 75, 130, 7, 170, 45000, 360, 6, 0 }, + { "5mt fusion", 120, 120, 100, 150, 8, 190, 50000, 370, 8, 0 }, + { "120kt neutron", 75, 75, 40, 120, 5, 50, 36000, 375, 3, N_NEUT }, + { "", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } +}; + +int nuk_maxno = (sizeof(nchr) / sizeof(struct nchrstr)) - 1; diff --git a/src/lib/global/numnames.c b/src/lib/global/numnames.c new file mode 100644 index 00000000..b9f18006 --- /dev/null +++ b/src/lib/global/numnames.c @@ -0,0 +1,48 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * numnames.c: Strings used to convert numbers to strings + * + * Known contributors to this file: + * + */ + +#include "misc.h" + +s_char *numnames[] = { + "zero", "one", "two", "three", "four", "five", "six", + "seven", "eight", "nine", "ten", "eleven", "twelve", + "thirteen", "fourteen", "fifteen", "sixteen", + "seventeen", "eighteen", "nineteen", +}; + +s_char *tennames[] = { + "", "", "twenty", "thirty", "forty", "fifty", + "sixty", "seventy", "eighty", "ninety", + "hundred", "hundred ten", "hundred twenty", + "hundred thirty", 0, +}; diff --git a/src/lib/global/options.c b/src/lib/global/options.c new file mode 100644 index 00000000..89bb0faf --- /dev/null +++ b/src/lib/global/options.c @@ -0,0 +1,380 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * options.c: Options definitions + * + * Known contributors to this file: + * Steve McClure, 1998 + * + */ + +#include +#include "misc.h" +#include "options.h" +#include "optlist.h" + +/* there must be an easier way - but can't think of one off hand */ + +#ifdef NO_FORT_FIRE +int opt_NO_FORT_FIRE = 1; +#else +int opt_NO_FORT_FIRE = 0; +#endif + +#ifdef BRIDGETOWERS +int opt_BRIDGETOWERS = 1; +#else +int opt_BRIDGETOWERS = 0; +#endif + +#ifdef GODNEWS +int opt_GODNEWS = 1; +#else +int opt_GODNEWS = 0; +#endif + +#ifdef TREATIES +int opt_TREATIES = 1; +#else +int opt_TREATIES = 0; +#endif + +#ifdef GO_RENEW +int opt_GO_RENEW = 1; +#else +int opt_GO_RENEW = 0; +#endif + +#ifdef DEFENSE_INFRA +int opt_DEFENSE_INFRA = 1; +#else +int opt_DEFENSE_INFRA = 0; +#endif + +#ifdef SHIP_DECAY +int opt_SHIP_DECAY = 1; +#else +int opt_SHIP_DECAY = 0; +#endif + +#ifdef NO_HCMS +int opt_NO_HCMS = 1; +#else +int opt_NO_HCMS = 0; +#endif + +#ifdef NO_LCMS +int opt_NO_LCMS = 1; +#else +int opt_NO_LCMS = 0; +#endif + +#ifdef NO_OIL +int opt_NO_OIL = 1; +#else +int opt_NO_OIL = 0; +#endif + +#ifdef PLANENAMES +int opt_PLANENAMES = 1; +#else +int opt_PLANENAMES = 0; +#endif + +#ifdef LANDSPIES +int opt_LANDSPIES = 1; +#else +int opt_LANDSPIES = 0; +#endif + +#ifdef MOB_ACCESS +int opt_MOB_ACCESS = 1; +#else +int opt_MOB_ACCESS = 0; +#endif + +#ifdef LOANS +int opt_LOANS = 1; +#else +int opt_LOANS = 0; +#endif + +#ifdef MARKET +int opt_MARKET = 1; +#else +int opt_MARKET = 0; +#endif + +#ifdef NOFOOD +int opt_NOFOOD = 1; +#else +int opt_NOFOOD = 0; +#endif + +#ifdef SNEAK_ATTACK +int opt_SNEAK_ATTACK = 1; +#else +int opt_SNEAK_ATTACK = 0; +#endif + +#ifdef BLITZ +int opt_BLITZ = 1; +#else +int opt_BLITZ = 0; +#endif + +#ifdef HIDDEN +int opt_HIDDEN = 1; +#else +int opt_HIDDEN = 0; +#endif + +#ifdef LOSE_CONTACT +int opt_LOSE_CONTACT = 1; +#else +int opt_LOSE_CONTACT = 0; +#endif + +#ifdef NONUKES +int opt_NONUKES = 1; +#else +int opt_NONUKES = 0; +#endif + +#ifdef FUEL +int opt_FUEL = 1; +#else +int opt_FUEL = 0; +#endif + +#ifdef TRADESHIPS +int opt_TRADESHIPS = 1; +#else +int opt_TRADESHIPS = 0; +#endif + +#ifdef NEWPOWER +int opt_NEWPOWER = 1; +#else +int opt_NEWPOWER = 0; +#endif + +#ifdef NOMOBCOST +int opt_NOMOBCOST = 1; +#else +int opt_NOMOBCOST = 0; +#endif + +#ifdef SUPER_BARS +int opt_SUPER_BARS = 1; +#else +int opt_SUPER_BARS = 0; +#endif + +#ifdef EASY_BRIDGES +int opt_EASY_BRIDGES = 1; +#else +int opt_EASY_BRIDGES = 0; +#endif + +#ifdef ALL_BLEED +int opt_ALL_BLEED = 1; +#else +int opt_ALL_BLEED = 0; +#endif + +#ifdef DRNUKE +int opt_DRNUKE = 1; +#else +int opt_DRNUKE = 0; +#endif + +#ifdef SLOW_WAR +int opt_SLOW_WAR = 1; +#else +int opt_SLOW_WAR = 0; +#endif + +#ifdef NO_PLAGUE +int opt_NO_PLAGUE = 1; +#else +int opt_NO_PLAGUE = 0; +#endif + +#ifdef NEW_STARVE +int opt_NEW_STARVE = 1; +#else +int opt_NEW_STARVE = 0; +#endif + +#ifdef NEW_WORK +int opt_NEW_WORK = 1; +#else +int opt_NEW_WORK = 0; +#endif + +#ifdef RES_POP +int opt_RES_POP = 1; +#else +int opt_RES_POP = 0; +#endif + +#ifdef GRAB_THINGS +int opt_GRAB_THINGS = 1; +#else +int opt_GRAB_THINGS = 0; +#endif + +#ifdef SHOWPLANE +int opt_SHOWPLANE = 1; +#else +int opt_SHOWPLANE = 0; +#endif + +#ifdef ORBIT +int opt_ORBIT = 1; +#else +int opt_ORBIT = 0; +#endif + +#ifdef PINPOINTMISSILE +int opt_PINPOINTMISSILE = 1; +#else +int opt_PINPOINTMISSILE = 0; +#endif + +#ifdef FALLOUT +int opt_FALLOUT = 1; +#else +int opt_FALLOUT = 0; +#endif + +#ifdef SAIL +int opt_SAIL = 1; +#else +int opt_SAIL = 0; +#endif + +#ifdef NUKEFAILDETONATE +int opt_NUKEFAILDETONATE = 1; +#else +int opt_NUKEFAILDETONATE = 0; +#endif + +#ifdef SHIPNAMES +int opt_SHIPNAMES = 1; /* not used currently */ +#else +int opt_SHIPNAMES = 0; /* not used currently */ +#endif + +#ifdef NEUTRON +int opt_NEUTRON = 1; +#else +int opt_NEUTRON = 0; +#endif + +#ifdef UPDATESCHED +int opt_UPDATESCHED = 1; +#else +int opt_UPDATESCHED = 0; +#endif + +#ifdef DEMANDUPDATE +int opt_DEMANDUPDATE = 1; +#else +int opt_DEMANDUPDATE = 0; +#endif + +#ifdef BIG_CITY +int opt_BIG_CITY = 1; +#else +int opt_BIG_CITY = 0; +#endif + +#ifdef INTERDICT_ATT +int opt_INTERDICT_ATT = 1; +#else +int opt_INTERDICT_ATT = 0; +#endif + +#ifdef TECH_POP +int opt_TECH_POP = 1; +#else +int opt_TECH_POP = 0; +#endif + +struct option_list Options[] = { +{ "ALL_BLEED", &opt_ALL_BLEED }, +{ "BIG_CITY", &opt_BIG_CITY }, +{ "BLITZ", &opt_BLITZ }, +{ "BRIDGETOWERS", &opt_BRIDGETOWERS }, +{ "DEFENSE_INFRA", &opt_DEFENSE_INFRA }, +{ "DEMANDUPDATE", &opt_DEMANDUPDATE }, +{ "DRNUKE", &opt_DRNUKE }, +{ "EASY_BRIDGES", &opt_EASY_BRIDGES }, +{ "FALLOUT", &opt_FALLOUT }, +{ "FUEL", &opt_FUEL }, +{ "GODNEWS", &opt_GODNEWS }, +{ "GO_RENEW", &opt_GO_RENEW }, +{ "GRAB_THINGS", &opt_GRAB_THINGS }, +{ "HIDDEN", &opt_HIDDEN }, +{ "INTERDICT_ATT", &opt_INTERDICT_ATT }, +{ "LANDSPIES", &opt_LANDSPIES }, +{ "LOANS", &opt_LOANS }, +{ "LOSE_CONTACT", &opt_LOSE_CONTACT }, +{ "MARKET", &opt_MARKET }, +{ "MOB_ACCESS", &opt_MOB_ACCESS }, +{ "NEUTRON", &opt_NEUTRON }, +{ "NEW_STARVE", &opt_NEW_STARVE }, +{ "NEW_WORK", &opt_NEW_WORK }, +{ "NEWPOWER", &opt_NEWPOWER }, +{ "NO_FORT_FIRE", &opt_NO_FORT_FIRE }, +{ "NO_HCMS", &opt_NO_HCMS }, +{ "NO_LCMS", &opt_NO_LCMS }, +{ "NO_OIL", &opt_NO_OIL }, +{ "NO_PLAGUE", &opt_NO_PLAGUE }, +{ "NOFOOD", &opt_NOFOOD }, +{ "NOMOBCOST", &opt_NOMOBCOST }, +{ "NONUKES", &opt_NONUKES }, +{ "NUKEFAILDETONATE", &opt_NUKEFAILDETONATE }, +{ "ORBIT", &opt_ORBIT }, +{ "PINPOINTMISSILE", &opt_PINPOINTMISSILE }, +{ "PLANENAMES", &opt_PLANENAMES }, +{ "RES_POP", &opt_RES_POP }, +{ "SAIL", &opt_SAIL }, +{ "SHIP_DECAY", &opt_SHIP_DECAY }, +{ "SHIPNAMES", &opt_SHIPNAMES }, +{ "SHOWPLANE", &opt_SHOWPLANE }, +{ "SLOW_WAR", &opt_SLOW_WAR }, +{ "SNEAK_ATTACK", &opt_SNEAK_ATTACK }, +{ "SUPER_BARS", &opt_SUPER_BARS }, +{ "TECH_POP", &opt_TECH_POP }, +{ "TRADESHIPS", &opt_TRADESHIPS }, +{ "TREATIES", &opt_TREATIES }, +{ "UPDATESCHED", &opt_UPDATESCHED }, +{ NULL, NULL }, +}; diff --git a/src/lib/global/path.c b/src/lib/global/path.c new file mode 100644 index 00000000..2ec2df25 --- /dev/null +++ b/src/lib/global/path.c @@ -0,0 +1,71 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * path.c: Path initializations needed outside of the file initialization + * tables + * + * Known contributors to this file: + * + */ + +#include "gamesdef.h" +#include "misc.h" + +#if !defined(_WIN32) +#define FILEPATH(p) EMPPATH(data/p) +#else +#define FILEPATH(p) EMPPATH(data\\p) +#endif + +s_char *gamedir = EMPPATH(.); +s_char *infodir = EMPPATH(info.nr); +s_char *datadir = EMPPATH(data); +s_char *teldir = FILEPATH(tel); + +s_char *upfil = FILEPATH(up); +s_char *downfil = FILEPATH(down); +s_char *disablefil = FILEPATH(disable); +#if !defined(_WIN32) +s_char *telfil = FILEPATH(tel/tel); +#else +s_char *telfil = FILEPATH(tel\\tel); +#endif +s_char *annfil = FILEPATH(ann); +s_char *commfil = FILEPATH(comm); +s_char *banfil = FILEPATH(ban); +s_char *authfil = FILEPATH(auth); +s_char *timestampfil = FILEPATH(timestamp); +s_char *lostfil = FILEPATH(lostitems); + +#if !defined(_WIN32) +s_char *playerbin = EMPPATH(bin/emp_player); +s_char *updatebin = EMPPATH(bin/emp_update); +#else +s_char *playerbin = EMPPATH(bin\\emp_player); +s_char *updatebin = EMPPATH(bin\\emp_update); +#endif +s_char *loginport = EMP_PORT; diff --git a/src/lib/global/plane.c b/src/lib/global/plane.c new file mode 100644 index 00000000..7636416c --- /dev/null +++ b/src/lib/global/plane.c @@ -0,0 +1,344 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * plane.c: Plane characteristics + * + * Known contributors to this file: + * Dave Pare, 1986 + * Jeff Bailey + * Thomas Ruschak, 1992 + * Ken Stevens, 1995 + * Steve McClure, 1998 + */ + +/* + * plane characteristics + * flags indicate capabilities of craft... + * P_T: tactical, P_F: fighter/interceptor, P_B: bomber, + * P_C: cargo, P_G: glider, P_V: vtol, P_M: (one-shot) missile + * P_L: light, can land on carriers. + * P_O: orbits (sat's & anti-sats), P_N: nuke killer (SDI) + * P_X: stealthy + * P_E: Extra light + * P_K: Chopper + * P_P: Can paratroop + * P_A: ASW plane, can find subs when reconning, can bomb subs + * P_R: recon plane, gets some info + * P_I: Image capability (advanced spying) + * + * Note if a plane is P_M (a missile) then it will automatically be made + * P_V (vtol) in init_global() + */ + +#include "misc.h" +#include "plane.h" + +struct plchrstr plchr[] = { + +/* name lcm hcm $$$ tch acc ld at/df ran mil gas stlth flags */ +{ +"f1 fighter 1", +"f1 Sopwith Camel", + 8, 2, 400, 50, 90, 1, 1,1, 4, 1, 1, + 0, + P_V|P_T|P_F }, + +/* name lcm hcm $$$ tch acc ld at/df ran mil gas stlth flags */ +{ +"f2 fighter 2", +"f2 P-51 Mustang", + 8, 2, 400, 80, 80, 1, 4,4, 8, 1, 1, + 0, + P_L|P_T|P_F }, + +/* name lcm hcm $$$ tch acc ld at/df ran mil gas stlth flags */ +{ +"jf1 jet fighter 1", +"jf1 F-4 Phantom", + 12, 4, 1000, 125, 45, 1, 14,14, 11, 2, 3, + 0, + P_T|P_F|P_L }, + + +/* name lcm hcm $$$ tch acc ld at/df ran mil gas stlth flags */ +{ +"jf2 jet fighter 2", +"jf2 AV-8B Harrier", + 12, 4, 1400, 195, 30, 1, 17,17, 14, 2, 3, + 0, + P_T|P_F|P_L|P_V }, + +/* name lcm hcm $$$ tch acc ld at/df ran mil gas stlth flags */ +{ +"sf stealth fighter", +"sf F-117A Nighthawk", + 15, 5, 3000, 325, 45, 3, 19,19, 20, 2, 4, + 80, + P_T|P_F|P_L }, + +/* name lcm hcm $$$ tch acc ld at/df ran mil gas stlth flags */ +{ +"es escort", +"es P-38 Lightning", + 9, 3, 700, 90, 60, 1, 5,5, 15, 1, 2, + 0, + P_ESC|P_T }, + +/* name lcm hcm $$$ tch acc ld at/df ran mil gas stlth flags */ +{ +"jes jet escort", +"jes F-14E jet escort", + 14, 8,1400,160, 60, 1, 10,10, 25, 2, 3, + 0, + P_ESC|P_T }, + +/* name lcm hcm $$$ tch acc ld at/df ran mil gas stlth flags */ +{ +"lb lt bomber", +"lb TBD-1 Devastator", + 10, 3, 550, 60, 50, 2, 0,3, 7, 1, 1, + 0, + P_L|P_V|P_T|P_B }, + +/* name lcm hcm $$$ tch acc ld at/df ran mil gas stlth flags */ +{ +"jl jet lt bomber", +"jl A-6 Intruder", + 14, 4, 1000, 130, 25, 3, 0,9, 11, 2, 3, + 0, + P_T|P_B|P_L }, + +/* name lcm hcm $$$ tch acc ld at/df ran mil gas stlth flags */ +{ +"mb medium bomber", +"mb medium bomber", + 14, 5, 1000, 80, 45, 4, 0,5, 14, 3, 3, + 0, + P_T|P_B }, + +/* name lcm hcm $$$ tch acc ld at/df ran mil gas stlth flags */ +{ +"jmb jet med bomber", +"jfb FB-111 Aardvark f/b", + 20, 10, 1800, 140, 30, 7, 8, 8, 20, 5, 5, + 0, + P_T|P_B }, +{ +"hb hvy bomber", +"hb B-26B Marauder", + 20, 6, 1100, 90, 90, 5, 0,4, 15, 2, 2, + 0, + P_B }, + +/* name lcm hcm $$$ tch acc ld at/df ran mil gas stlth flags */ +{ +"jhb jet hvy bomber", +"jhb B-52 Strato-Fortress", + 26, 13, 3200, 150, 80,12, 0,11, 35, 5, 6, + 0, + P_B }, + +/* name lcm hcm $$$ tch acc ld at/df ran mil gas stlth flags */ +{ +"sb stealth bomber", +"sb B-2 stealth bomber", + 15, 5, 4000, 325, 25, 8, 0,15, 28, 2, 5, + 80, + P_T|P_B }, + + +/* name lcm hcm $$$ tch acc ld at/df ran mil gas stlth flags */ +{ +"as anti-sub plane", +"as anti-sub plane", + 10, 3, 550, 100, 85, 2, 0,3, 15, 2, 2, + 0, + P_SWEEP|P_MINE|P_T|P_A }, + +/* name lcm hcm $$$ tch acc ld at/df ran mil gas stlth flags */ +{ +"np naval plane", +"np naval plane", + 20, 10, 1800, 135, 70, 3, 0,4, 28, 4, 2, + 0, + P_SWEEP|P_MINE|P_C|P_T|P_A|P_L }, + +/* name lcm hcm $$$ tch acc ld at/df ran mil gas stlth flags */ +{ +"nc naval chopper", +"nc AH-1 Cobra", + 8, 2, 800, 160, 55, 2, 0,3, 11, 2, 2, + 0, + P_V|P_SWEEP|P_T|P_A|P_K }, + +/* name lcm hcm $$$ tch acc ld at/df ran mil gas stlth flags */ +{ +"ac attack chopper", +"ac AH-64 Apache", + 8, 2, 800, 200, 15, 1, 0,9, 11, 2, 2, + 40, + P_V|P_T|P_K }, + +/* name lcm hcm $$$ tch acc ld at/df ran mil gas stlth flags */ +{ +"tc transport chopper", +"tc transport chopper", + 8, 2, 800, 135, 0, 5, 0,3, 7, 2, 2, + 40, + P_V|P_C|P_P|P_L|P_K }, + +/* name lcm hcm $$$ tch acc ld at/df ran mil gas stlth flags */ +{ +"tr transport", +"tr C-56 Lodestar", + 14, 5, 1000, 85, 0, 7, 0,2, 15, 3, 3, + 0, + P_C|P_P }, + +/* name lcm hcm $$$ tch acc ld at/df ran mil gas stlth flags */ +{ +"jt jet transport", +"jt C-141 Starlifter", + 18, 5, 1500, 160, 0,16, 0,9, 35, 3, 4, + 0, + P_C|P_P }, + +/* name lcm hcm $$$ tch acc ld at/df ran mil gas stlth flags */ +{ +"zep Zeppelin", +"zep Zeppelin", + 6, 2, 1000, 70, 60, 2, 0,-3, 15, 3, 2, + 0, + P_S|P_V|P_T|P_C }, +/* name lcm hcm $$$ tch acc ld at/df ran mil gas stlth flags */ +{ +"re recon", +"re recon", + 12, 4, 800, 130, 0, 0, 0,4, 15, 2, 2, + 20, + P_S }, + +/* name lcm hcm $$$ tch acc ld at/df ran mil gas stlth flags */ +{ +"sp spyplane", +"sp E2-C Hawkeye", + 15, 5, 2000, 190, 0, 0, 0,11, 32, 2, 5, + 50, + P_S }, + +/* name lcm hcm $$$ tch acc ld at/df ran mil gas stlth flags */ +{ +"lst landsat", +"lst landsat", + 20, 20, 2000, 245, 0, 0, 0,3, 41, 0, 9, + 0, + P_O }, + +/* name lcm hcm $$$ tch acc ld at/df ran mil gas stlth flags */ +{ +"ss spysat", +"ss KH-7 spysat", + 20, 20, 4000, 305, 0, 0, 0,3, 61, 0, 9, + 0, + P_I|P_O|P_S }, + +/* name lcm hcm $$$ tch acc ld at/df ran mil gas stlth flags */ +{ +"mi naval missile", +"mi Harpoon", + 8, 2, 300, 160, 50, 6, 0,5, 6, 0, 0, + 0, + P_L|P_T|P_M|P_MAR }, +/* name lcm hcm $$$ tch acc ld at/df ran mil gas stlth flags */ +{ +"sam sam", +"sam Sea Sparrow", + 3, 1, 200, 180, 0, 0, 0,18, 2, 0, 0, + 0, + P_L|P_F|P_E|P_M }, + +/* name lcm hcm $$$ tch acc ld at/df ran mil gas stlth flags */ +{ +"ssm", +"ssm V2", + 15, 15, 800, 145, 60, 3, 0,3, 4, 0, 0, + 0, + P_T|P_M }, + +/* name lcm hcm $$$ tch acc ld at/df ran mil gas stlth flags */ +{ +"srbm", +"srbm Atlas", + 20, 20, 1000, 200, 60, 6, 0,5, 9, 0, 0, + 0, + P_T|P_M }, + +/* name lcm hcm $$$ tch acc ld at/df ran mil gas stlth flags */ +{ +"irbm", +"irbm Titan", + 20, 20, 1500, 260, 60, 8, 0,10, 15, 0, 0, + 0, + P_T| P_M }, + +/* name lcm hcm $$$ tch acc ld at/df ran mil gas stlth flags */ +{ +"icbm", +"icbm Minuteman", + 20, 20, 3000, 310, 60,10, 0,15, 41, 0, 0, + 0, + P_T|P_M }, +/* name lcm hcm $$$ tch acc ld at/df ran mil gas stlth flags */ +{ +"slbm", +"slbm Trident", + 20, 20, 2000, 280, 60, 8, 0,6, 23, 0, 0, + 0, + P_T|P_L|P_M }, + +/* name lcm hcm $$$ tch acc ld at/df ran mil gas stlth flags */ +{ +"asat anti-sat", +"asat anti-sat", + 20, 20, 2000, 305, 50, 6, 0,7, 13, 0, 4, + 0, + P_O|P_M }, + +/* name lcm hcm $$$ tch acc ld at/df ran mil gas stlth flags */ +{ +"abm anti-ballistic missile", +"abm Patriot", + 16, 8, 1500, 270, 50, 0, 0,31, 12, 0, 0, + 0, + P_N|P_M }, +{ +"", "", 0, 0, 0, 0, 0, 0, 0,0, 0, 0, 0, + 0, + 0 } +}; + +int pln_maxno = (sizeof(plchr) / sizeof(struct plchrstr)) - 1; diff --git a/src/lib/global/product.c b/src/lib/global/product.c new file mode 100644 index 00000000..6b551d41 --- /dev/null +++ b/src/lib/global/product.c @@ -0,0 +1,98 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * product.c: Product information + * + * Known contributors to this file: + * + */ + +#include "misc.h" +#include "product.h" +#include "sect.h" +#include "nat.h" +#include "var.h" + + +struct pchrstr pchr[] = { +/* level cost nrndx nrdep nlndx nlmin nllag effic sname name */ +{ 0, { 0 }, { 0 }, +0, 0, 0, 0, 0, 0, 0, 0, 0, + "unused", "", }, +{ 2, { V_LCM, V_HCM}, { 2, 1 }, +V_SHELL, -1, 3, 0, 0, NAT_TLEV, 20, 10, 100, + "shells", "shells", }, +{ 3, { V_OIL, V_LCM, V_HCM }, { 1, 5, 10 }, +V_GUN, -1, 30, 0, 0, NAT_TLEV, 20, 10, 100, + "guns", "guns",}, +{ 1, { V_OIL }, { 1 }, +V_PETROL,-1, 1, 0, 0, NAT_TLEV, 20, 10, 1000, + "petrol", "petrol",}, +{ 0, { 0 }, { 0 }, +V_IRON, -1, 0,OFFSET(sctstr, sct_min),0, -1, 0, 0, 100, + "iron ore", "iron", }, +{ 0, { 0 }, { 0 }, +V_DUST, -1, 0,OFFSET(sctstr, sct_gmin),20, -1, 0, 0, 100, + "gold dust", "dust",}, +{ 1, { V_DUST }, { 5 }, +V_BAR, -1, 10, 0, 0, -1, 0, 0, 100, + "gold bars", "bars",}, +{ 0, { 0 }, { 0 }, +V_FOOD, -1, 0,OFFSET(sctstr, sct_fertil),0, NAT_TLEV, -10, 10, 900, + "food", "food",}, +{ 0, { 0 }, { 0 }, +V_OIL, -1, 0,OFFSET(sctstr, sct_oil),10, NAT_TLEV, -10, 10, 100, + "oil", "oil",}, +{ 1, { V_IRON }, { 1 }, +V_LCM, -1, 0, 0, 0, NAT_TLEV, -10, 10, 100, + "light construction materials", "lcm",}, +{ 1, { V_IRON }, { 2 }, +V_HCM, -1, 0, 0, 0, NAT_TLEV, -10, 10, 100, + "heavy construction materials", "hcm", }, +{3,{V_DUST,V_OIL,V_LCM}, {1,5,10}, +0, NAT_TLEV, 5*ETUS, 0, 0, NAT_ELEV, 5, 10, 100, + "technological breakthroughs", "tech",}, +{3,{V_DUST,V_OIL,V_LCM }, { 1, 5, 10 }, +0, NAT_RLEV, 90, 0, 0, NAT_ELEV, 5, 10, 100, + "medical discoveries", "medical",}, +{ 1, { V_LCM }, { 1 }, +0, NAT_ELEV, 9, 0, 0, -1, 0, 0, 100, + "a class of graduates", "edu",}, +{ 1, { V_LCM }, { 1 }, +0, NAT_HLEV, 9, 0, 0, -1, 0, 0, 100, + "happy strollers", "happy",}, +{ 0, { 0 }, { 0 }, +V_RAD, -1, 2,OFFSET(sctstr, sct_uran),35, NAT_TLEV, 40, 10, 100, + "radioactive materials", "rad",}, +{ 0, { 0 }, { 0 }, +V_DUST, -1, 0,OFFSET(sctstr, sct_gmin),20, -1, 0, 0, 75, + "gold dust", "dust",}, +{ 0, {0}, {0}, +0, 0, 0, 0, 0, 0, 0, 0, 0, "", "",} +}; + +int prd_maxno = (sizeof(pchr) / sizeof(struct pchrstr)) - 1; diff --git a/src/lib/global/sect.c b/src/lib/global/sect.c new file mode 100644 index 00000000..b2a166cc --- /dev/null +++ b/src/lib/global/sect.c @@ -0,0 +1,97 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * sect.c: Sector designation characteristics + * + * Known contributors to this file: + * Dave Pare, 1986 + * Jeff Bailey + * Thomas Ruschak, 1992 + * Ken Stevens, 1995 + * Steve McClure, 1998 + */ + +/* order must agree with sect.h */ + +#include "misc.h" +#include "sect.h" +#include "product.h" + +struct dchrstr bigcity_dchr = { + 'c', 0, 2, NAV_02, UPKG,1.0, 2.0, 30, 0, 10, 1, 2, "city" +}; + +struct dchrstr dchr[SCT_MAXDEF+2] = { +/* + mnem prd mcst flg pkg ostr dstr value $ bld lcm hcm name */ +{ '.', 0, 0, NAVOK, NPKG,0.0, 0.0, 0, 0, 0, 0, 0, "sea" }, +{ '^', P_MDUST, 25, 0, NPKG,1.0, 4.0, 5, 0, 1, 0, 0, "mountain" }, +{ 's', 0, 0, 0, NPKG,0.0,99.0, 127, 0, 0, 0, 0, "sanctuary" }, +{ '\\',0, 0, 0, NPKG,0.0,99.0, 0, 0, 0, 0, 0, "wasteland" }, +{ '-', 0, 3, 0, NPKG,1.0, 2.0, 1, 0, 0, 0, 0, "wilderness" }, +{ 'c', 0, 2, 0, NPKG,1.0, 2.0, 30, 0, 1, 0, 0, "capital" }, +{ 'u', P_URAN, 2, 0, NPKG,1.0, 2.0, 15, 0, 1, 0, 0, "uranium mine" }, +{ 'p', P_HLEV, 2, 0, NPKG,1.0, 1.5, 5, 0, 1, 0, 0, "park" }, +{ 'd', P_GUN, 2, 0, NPKG,1.0, 1.5, 7, 0, 1, 0, 0, "defense plant" }, +{ 'i', P_SHELL, 2, 0, NPKG,1.0, 1.5, 6, 0, 1, 0, 0, "shell industry" }, +{ 'm', P_IRON, 2, 0, NPKG,1.0, 2.0, 5, 0, 1, 0, 0, "mine" }, +{ 'g', P_DUST, 2, 0, NPKG,1.0, 2.0, 8, 0, 1, 0, 0, "gold mine" }, +{ 'h', 0, 2, NAV_02, WPKG,1.0, 1.5, 12, 0, 1, 0, 0, "harbor" }, +{ 'w', 0, 2, 0, WPKG,1.0, 1.5, 7, 0, 1, 0, 0, "warehouse" }, +{ '*', 0, 2, 0, NPKG,1.0,1.25, 12, 0, 1, 0, 0, "airfield" }, +{ 'a', P_FOOD, 2, 0, NPKG,1.0, 1.5, 2, 0, 1, 0, 0, "agribusiness" }, +{ 'o', P_OIL, 2, 0, NPKG,1.0, 1.5, 5, 0, 1, 0, 0, "oil field" }, +{ 'j', P_LCM, 2, 0, NPKG,1.0, 1.5, 3, 0, 1, 0, 0, "light manufacturing" }, +{ 'k', P_HCM, 2, 0, NPKG,1.0, 1.5, 4, 0, 1, 0, 0, "heavy manufacturing" }, +{ 'f', 0, 2, 0, NPKG,2.0, 4.0, 10, 0, 5, 0, 1, "fortress" }, +{ 't', P_TLEV, 2, 0, NPKG,1.0, 1.5, 10, 0, 1, 0, 0, "technical center" }, +{ 'r', P_RLEV, 2, 0, NPKG,1.0, 1.5, 9, 0, 1, 0, 0, "research lab" }, +{ 'n', 0, 2, 0, NPKG,1.0, 2.0, 10, 0, 1, 0, 0, "nuclear plant" }, +{ 'l', P_ELEV, 2, 0, NPKG,1.0, 1.5, 4, 0, 1, 0, 0, "library/school" }, +{ '+', 0, 1, 0, NPKG,1.0, 1.0, 3, 0, 1, 0, 0, "highway" }, +{ ')', 0, 2, 0, NPKG,1.0, 1.5, 4, 0, 1, 0, 0, "radar installation" }, +{ '!', 0, 2, 0, NPKG,1.0, 1.5, 12, 0, 1, 0, 0, "headquarters" }, +{ '#', 0, 1, 0, NPKG,1.0, 1.5, 4, 0, 1, 0, 0, "bridge head" }, +{ '=', 0, 1, NAV_60, NPKG,1.0, 1.0, 5, 0, 1, 0, 0, "bridge span" }, +{ 'b', P_BAR, 2, 0, BPKG,1.0,2.25, 10, 0, 1, 0, 0, "bank" }, +{ '%', P_PETROL, 2, 0, NPKG,1.0, 1.5, 2, 0, 1, 0, 0, "refinery" }, +{ 'e', 0, 2, 0, NPKG,1.0, 2.0, 7, 0, 1, 0, 0, "enlistment center" }, +{ '~', 0, 2, 0, NPKG,1.0, 1.5, 1, 0, 1, 0, 0, "plains" }, +{ '@', 0, 1, 0, NPKG,1.0, 1.5, 4, 0, 1, 0, 0, "bridge tower" }, +{ 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 } +}; + +int sct_maxno = (sizeof(dchr) / sizeof(struct dchrstr)) - 1; + +struct sctintrins intrchr[] = { +/* name lcm hcm dollars mobility */ +{ "road network", 2, 2, 2, 1 }, +{ "rail network", 1, 1, 1, 1 }, +{ "defense factor", 1, 1, 1, 1 }, +{ 0, 0, 0, 0, 0 } +}; diff --git a/src/lib/global/ship.c b/src/lib/global/ship.c new file mode 100644 index 00000000..8a14dfab --- /dev/null +++ b/src/lib/global/ship.c @@ -0,0 +1,326 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * ship.c: Ship characteristics + * + * Known contributors to this file: + * Dave Pare, 1986 + * Jeff Bailey + * Thomas Ruschak, 1992 + * Ken Stevens, 1995 + * Steve McClure, 1998 + */ + +/* + * marine characteristics -- ship capabilities descriptions + * + * Note, that you should not set the flags M_XLIGHT, M_UNIT, or M_CHOPPER + * here. They will be automatically set by init_global() when the server + * starts if the ship can carry a non-zero amount of those things. + * Also note that if nplanes > 0 and M_FLY is not set, then M_MSL will + * automatically be set. + */ + +#include "misc.h" +#include "var.h" +#include "ship.h" + +struct mchrstr mchr[] = { +/* a s v v f E K f f */ +/* r p i r r g | | u u */ +/* l h m e s n n l x V e e */ +/* c c o e i g g i p p l l */ +/* m m r d b e e m l l c u name tech Cost*/ + +{ 4, + { V_CIVIL, V_MILIT, V_FOOD, V_UW }, + { 300, 10, 900, 15 }, +25, 15, 10, 10, 15, 2, 0, 0, 0, 0, 0, 0, "fb fishing boat", 0, 180, + M_FOOD, 0, 0, +}, + +{ 4, + { V_CIVIL, V_MILIT, V_FOOD, V_UW }, + { 300, 10, 900, 15 }, +25, 15, 10, 25, 15, 2, 0, 0, 0, 0, 20, 1, "ft fishing trawler", 35, 300, + M_FOOD, 0, 0, +}, + +{ 8, + { V_CIVIL, V_MILIT, V_SHELL, V_GUN, V_FOOD, V_LCM, V_HCM, V_UW }, + { 600, 50, 300, 50, 900, 1400, 900, 250 }, +60, 40, 20, 25, 35, 3, 0, 0, 1, 0, 0, 0, "cs cargo ship", 20, 500, + M_SUPPLY, 0, 2, +}, + +{ 7, + { V_CIVIL, V_MILIT, V_IRON, V_DUST, V_FOOD, V_UW, V_RAD }, + { 30, 5, 990, 990, 200, 45, 990 }, +60, 40, 20, 25, 35, 3, 0, 0, 1, 0, 30, 1, "os ore ship", 20, 500, + 0, 0, 0, +}, + +{ 4, + { V_CIVIL, V_MILIT, V_FOOD, V_UW }, + { 20, 80, 200, 1200 }, +60, 40, 20, 10, 35, 3, 0, 0, 1, 0, 0, 0, "ss slave ship", 0, 300, + 0, 0, 0, +}, + +{ 3, + { V_CIVIL, V_MILIT, V_FOOD }, + { 50, 50, 100 }, +200, 100, 20, 25, 35, 3, 0, 0, 1, 0, 30, 1, "ts trade ship", 30, 1750, + M_TRADE, 0, 0, +}, + +{ 4, + { V_MILIT, V_SHELL, V_GUN, V_FOOD }, + { 60, 10, 2, 60 }, +30, 30, 50, 25, 25, 3, 1, 1, 1, 0, 0, 0, "frg frigate", 0, 600, + M_SEMILAND, 0, 2, +}, + +{ 4, + { V_CIVIL, V_MILIT, V_FOOD, V_OIL }, + { 10, 5, 100, 1 }, +25, 15, 10, 25, 15, 2, 0, 0, 0, 0, 20, 1, "oe oil exploration boat", 40, 800, + M_OIL, 0, 0, +}, + +{ 5, + { V_CIVIL, V_MILIT, V_FOOD, V_OIL, V_UW }, + { 990, 80, 990, 990, 990 }, +60, 60, 30, 15, 65, 3, 0, 0, 2, 0, 0, 0, "od oil derrick", 50, 1500, + M_OIL, 0, 0, +}, + +{ 4, + { V_MILIT, V_GUN, V_SHELL, V_FOOD }, + { 2, 2, 12, 5 }, +20, 10, 10, 38, 10, 2, 1, 1, 0, 0, 4, 1, "pt patrol boat", 40, 300, + M_TORP, 0, 0, +}, + +{ 4, + { V_MILIT, V_SHELL, V_GUN, V_FOOD }, + { 100, 40, 5, 100 }, +30, 40, 50, 30, 30, 5, 6, 3, 1, 0, 40, 1, "lc light cruiser", 45, 800, + M_MINE, 0, 2, +}, + +{ 4, + { V_MILIT, V_SHELL, V_GUN, V_FOOD }, + { 120, 100, 8, 200 }, +40, 50, 70, 30, 30, 5, 8, 4, 1, 0, 30, 1, "hc heavy cruiser", 50, 1200, + 0, 0, 4, +}, + +{ 4, + { V_MILIT, V_SHELL, V_GUN, V_FOOD }, + { 120, 20, 4, 120 }, +50, 50, 60, 20, 35, 3, 1, 2, 1, 0, 0, 0, "tt troop transport", 10, 800, + M_SEMILAND, 0, 2, +}, + +{ 4, + { V_MILIT, V_SHELL, V_GUN, V_FOOD }, + { 200, 200, 10, 900 }, +50, 70, 95, 25, 35, 6, 10, 7, 1, 0, 50, 2, "bb battleship", 45, 1800, + 0, 0, 2, +}, + +{ 4, + { V_MILIT, V_SHELL, V_GUN, V_FOOD }, + { 180, 100, 10, 400 }, +50, 60, 55, 30, 35, 6, 10, 6, 1, 0, 60, 2, "bbc battlecruiser", 75, 1500, + 0, 0, 2, +}, + +{ 6, + { V_CIVIL, V_MILIT, V_PETROL, V_FOOD, V_OIL, V_UW }, + { 30, 5, 990, 200, 990, 25 }, +60, 40, 75, 25, 45, 3, 0, 0, 1, 0, 30, 1, "tk tanker", 35, 600, + M_OILER|M_SUPPLY, 0, 0, +}, + +{ 4, + { V_MILIT, V_FOOD, V_SHELL, V_GUN }, + { 10, 90, 100, 1 }, +25, 15, 10, 25, 15, 2, 0, 0, 0, 0, 20, 1, "ms minesweeper", 40, 400, + M_MINE|M_SWEEP, 0, 0, +}, + +{ 4, + { V_MILIT, V_SHELL, V_GUN, V_FOOD }, + { 60, 40, 4, 80 }, +30, 30, 45, 35, 20, 4, 6, 3, 1, 0, 30, 1, "dd destroyer", 70, 600, + M_MINE|M_DCH|M_SONAR, 0, 1, +}, + +{ 4, + { V_MILIT, V_SHELL, V_GUN, V_FOOD }, + { 25, 36, 5, 80 }, +30, 30, 25, 20, 5, 4, 3, 3, 0, 0, 30, 1, "sb submarine", 60, 650, + M_TORP|M_SUB|M_MINE|M_SONAR, 0, 0, +}, + +{ 8, + { V_CIVIL, V_MILIT, V_SHELL, V_GUN, V_FOOD, V_LCM, V_HCM, V_PETROL }, + { 5, 10, 104, 20, 900, 500, 300, 100 }, +40, 40, 50, 30, 2, 3, 0, 0, 0, 0, 50, 2, "sbc cargo submarine", 150, 1200, + M_SUPPLY|M_OILER|M_SUB|M_SONAR, 0, 0, +}, + +{ 5, + { V_MILIT, V_SHELL, V_GUN, V_PETROL, V_FOOD }, + { 175, 250, 4, 300, 180 }, +50, 60, 60, 30, 40, 5, 2, 2, 4, 20, 50, 2, "cal light carrier", 80, 2700, + M_FLY, 20, 0, +}, + +{ 5, + { V_MILIT, V_SHELL, V_GUN, V_PETROL, V_FOOD }, + { 350, 500, 4, 500, 900 }, +60, 70, 80, 35, 40, 7, 2, 2, 10, 40, 120, 3, "car aircraft carrier", 160, 4500, + M_FLY, 40, 0, +}, + +{ 5, + { V_MILIT, V_SHELL, V_GUN, V_PETROL, V_FOOD }, + { 350, 999, 4, 999, 900 }, +70, 80, 100, 45, 40, 9, 2, 2, 20, 4, 0, 0, "can nuc carrier", 305, 8000, + M_OILER|M_FLY|M_SUPPLY, 60, 0, +}, + +{ 4, + { V_MILIT, V_FOOD , V_GUN , V_SHELL }, + { 400, 300 , 1 , 10 }, +60, 40, 40, 30, 30, 2, 0, 0, 2, 0, 30, 1, "ls landing ship", 145, 1000, + M_LAND, 0, 6, +}, + +{ 4, + { V_MILIT, V_SHELL, V_GUN, V_FOOD }, + { 60, 60, 4, 120 }, +40, 30, 50, 35, 30, 5, 2, 2, 4, 0, 40, 1, "af asw frigate", 220, 800, + M_TORP|M_SUBT|M_DCH|M_SONAR, 0, 0, +}, + +{ 4, + { V_MILIT, V_SHELL, V_GUN, V_FOOD }, + { 25, 60, 6, 500 }, +30, 40, 45, 40, 3, 6, 5, 3, 0, 0, 0, 0, "na nuc attack sub", 260, 1200, + M_TORP|M_SUB|M_MINE|M_SONAR|M_SUBT, 0, 0, +}, + +{ 5, + { V_MILIT, V_SHELL, V_GUN, V_PETROL, V_FOOD }, + { 100, 80, 6, 40, 500 }, +40, 40, 60, 40, 35, 6, 8, 3, 10, 2, 80, 2, "ad asw destroyer", 240, 1500, + M_TORP|M_SUBT|M_DCH|M_SONAR, 0, 0, +}, + +{ 4, + { V_MILIT, V_SHELL, V_FOOD, V_GUN }, + { 25, 200, 500, 1 }, +30, 40, 55, 35, 2, 6, 0, 0, 0, 0, 0, 0, "nm nuc miss sub", 270, 1500, + M_SUB|M_SONAR, 20, 0, +}, + +{ 4, + { V_MILIT, V_SHELL, V_FOOD, V_GUN }, + { 25, 100, 500, 1 }, +30, 30, 35, 30, 3, 3, 0, 0, 0, 0, 30, 1, "msb missile sub", 230, 1200, + M_SUB|M_SONAR, 10, 0, +}, + +{ 4, + { V_MILIT, V_SHELL, V_GUN, V_FOOD }, + { 5, 100, 3, 500 }, +20, 20, 15, 40, 15, 3, 2, 2, 0, 0, 7, 1, "mb missile boat", 180, 500, + 0, 10, 0, +}, + +{ 4, + { V_MILIT, V_SHELL, V_GUN, V_FOOD }, + { 60, 220, 4, 120 }, +40, 30, 50, 35, 30, 5, 2, 2, 2, 0, 30, 1, "mf missile frigate", 280, 1000, + 0, 20, 0, +}, + +{ 5, + { V_MILIT, V_SHELL, V_GUN, V_PETROL, V_FOOD }, + { 120, 500, 6, 160, 200 }, +50, 50, 70, 35, 35, 8, 8, 6, 8, 8, 35, 1, "mc missile cruiser", 290, 1500, + M_ANTIMISSILE, 40, 0, +}, + +{ 4, + { V_MILIT, V_SHELL, V_GUN, V_FOOD }, + { 100, 100, 15, 200 }, +50, 60, 80, 35, 30, 6, 1, 8, 1, 0, 60, 2, "aac aa cruiser", 130, 1500, + M_ANTIMISSILE, 0, 4, +}, + +{ 5, + { V_MILIT, V_SHELL, V_GUN, V_PETROL, V_FOOD }, + { 200, 400, 25, 40, 900 }, +50, 60, 80, 35, 30, 6, 1, 16, 30, 2, 0, 0, "agc aegis cruiser", 265, 4000, + M_ANTIMISSILE, 32, 0, +}, + +{ 5, + { V_MILIT, V_SHELL, V_GUN, V_PETROL, V_FOOD }, + { 200, 400, 8, 40, 900 }, +50, 50, 100, 45, 35, 6, 14, 7, 10, 2, 0, 0, "ncr nuc cruiser", 325, 1800, + M_ANTIMISSILE, 20, 0, +}, + +{ 5, + { V_MILIT, V_SHELL, V_GUN, V_PETROL, V_FOOD }, + { 200, 120, 6, 160, 500 }, +50, 50, 80, 45, 35, 9, 10, 4, 25, 8, 0, 0, "nas nuc asw cruiser", 330, 1800, + M_TORP|M_SUBT|M_DCH|M_SONAR, 0, 0, +}, + +{ 8, + { V_CIVIL, V_MILIT, V_SHELL, V_GUN, V_PETROL, V_FOOD, V_LCM, V_HCM }, + { 50, 50, 600, 50, 999, 999, 1500, 900 }, +60, 40, 40, 45, 35, 6, 0, 0, 10, 2, 0, 0, "nsp nuc supply ship", 360, 1500, + M_SUPPLY,0,2, +}, + +{ 0, + { 0 }, + { 0 }, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "", 0, 0, + 0, 0, 0, +} +}; + +int shp_maxno = (sizeof(mchr) / sizeof(struct mchrstr)) - 1; diff --git a/src/lib/global/treaty.c b/src/lib/global/treaty.c new file mode 100644 index 00000000..176fb917 --- /dev/null +++ b/src/lib/global/treaty.c @@ -0,0 +1,53 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * treaty.c: Treaty clause characteristics + * + * Known contributors to this file: + * Steve McClure, 1998 + * + */ + +#include "misc.h" +#include "treaty.h" + +struct tchrstr tchr[] = { + { LNDATT, "no attacks on any land units" }, + { SEAATT, "no attacks on any ships" }, + { SEAFIR, "no shelling any ships" }, + { SUBFIR, "no depth-charging any subs" }, + { LANATT, "no sector attacks" }, + { LANFIR, "no shelling any land" }, + { NEWSHP, "no building ships" }, + { NEWNUK, "no new nuclear weapons" }, + { NEWPLN, "no building planes" }, + { NEWLND, "no building land units" }, + { TRTENL, "no enlistment" }, + { 0, 0 } +}; + +int trt_maxno = (sizeof(tchr) / sizeof(struct tchrstr)) - 1; diff --git a/src/lib/lwp/Makefile b/src/lib/lwp/Makefile new file mode 100644 index 00000000..baa60e1c --- /dev/null +++ b/src/lib/lwp/Makefile @@ -0,0 +1,64 @@ +# +# Empire - A multi-player, client/server Internet based war game. +# Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, +# Ken Stevens, Steve McClure +# +# 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 2 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, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# --- +# +# See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the +# related information and legal notices. It is expected that any future +# projects/authors will amend these files as needed. +# +# Makefile - Wolfpack, 1996 + +# Note that these could have been listed 1 per line, but I chose to just +# stick them all together this way to shorten the file. + +include ../../../build.conf +include ../../make.src +include ../../make.defs + +LIB = $(SRCDIR)/lib/liblwp.a + +OBJS = arch.o lwp.o queue.o sel.o sem.o status.o + +MIPSOBJS = mipsarch.o + +AIXOBJS = lwpInit.o lwpRestore.o lwpSave.o + +GENMASTER = GLOBALCFLAGS="$(GLOBALCFLAGS)" GLOBALLFLAGS="$(GLOBALLFLAGS)" + +all: $(LIB) + +$(LIB): $(OBJS) $(EXTRAOBJS) + rm -f $(LIB) + ar cq $(LIB) $(OBJS) $(EXTRAOBJS) + $(RANLIB) $(LIB) + +nt: + +mipsultrix: + make EXTRAOBJS="$(MIPSOBJS)" $(GENMASTER) + +aix: + make EXTRAOBJS="$(AIXOBJS)" $(GENMASTER) + +clean: + -(rm -f $(OBJS) $(AIXOBJS) $(MIPSOBJS)) + +include ../../make.rules +include Makedepend diff --git a/src/lib/lwp/arch.c b/src/lib/lwp/arch.c new file mode 100644 index 00000000..a1966ae8 --- /dev/null +++ b/src/lib/lwp/arch.c @@ -0,0 +1,428 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * arch.c: architecture-dependant process context code + * + * Known contributors to this file: + * Dave Pare, 1994 + * Steve McClure, 1994-2000 + */ + +#include "prototypes.h" + +#if defined(_EMPTH_LWP) + +#if (!defined(AIX32)) + +#include "lwp.h" + +#include "lwpint.h" + +#if defined(hpc) + +static struct lwpProc *tempcontext; +struct lwpProc *initcontext=NULL; +int startpoint; + +startcontext() +{ + int space[10000]; + int x; + + startpoint = (void *) &x; + if (!setjmp(initcontext->context)) longjmp(tempcontext->context,1); + + if (!setjmp(tempcontext->context)) longjmp(LwpCurrent->context,1); + + lwpEntryPoint(); +} + +void lwpInitContext(newp, sp) + struct lwpProc *newp; + void *sp; +{ + struct lwpProc holder; + int endpoint; + + if (initcontext == NULL) { + initcontext = (struct lwpProc *) malloc (sizeof(struct lwpProc)); + tempcontext = &holder; + if (!setjmp(tempcontext->context)) startcontext(); + } + + tempcontext = newp; + endpoint = &endpoint; + if (endpoint < startpoint) { + if (!setjmp(LwpCurrent->context)) longjmp(initcontext->context,1); + } else { + LwpCurrent->size = endpoint - startpoint; + LwpCurrent->sbtm = realloc(LwpCurrent->sbtm, LwpCurrent->size); + memcpy(LwpCurrent->sbtm, startpoint, LwpCurrent->size); + if (!setjmp(LwpCurrent->context)) longjmp(initcontext->context,1); + memcpy(startpoint, LwpCurrent->sbtm, LwpCurrent->size); + } +} + +#elif defined(hpux) + +void lwpInitContext(newp, sp) + volatile struct lwpProc *volatile newp; + void *sp; +{ + static jmp_buf *cpp; + extern struct lwpProc *LwpCurrent; + + if (!lwpSave(LwpCurrent->context)) { + cpp = (jmp_buf *)&newp->context; + asm volatile ("ldw %0, %%sp": : "o" (sp)); + if (!lwpSave(*cpp)) + lwpRestore(LwpCurrent->context); + lwpEntryPoint(); + } +} + +int lwpSave(jb) + jmp_buf jb; +{ + /* save stack pointer and return program counter */ + asm ("stw %sp, 4(%arg0)"); + asm ("stw %rp, 8(%arg0)"); + + /* save "callee save" registers */ + asm ("stw %r3, 12(%arg0)"); + asm ("stw %r4, 16(%arg0)"); + asm ("stw %r5, 20(%arg0)"); + asm ("stw %r6, 24(%arg0)"); + asm ("stw %r7, 28(%arg0)"); + asm ("stw %r8, 32(%arg0)"); + asm ("stw %r9, 36(%arg0)"); + asm ("stw %r10, 40(%arg0)"); + asm ("stw %r11, 44(%arg0)"); + asm ("stw %r12, 48(%arg0)"); + asm ("stw %r13, 52(%arg0)"); + asm ("stw %r14, 56(%arg0)"); + asm ("stw %r15, 60(%arg0)"); + asm ("stw %r16, 64(%arg0)"); + asm ("stw %r17, 68(%arg0)"); + asm ("stw %r18, 72(%arg0)"); + + /* save "callee save" space register */ + asm volatile ("mfsp %sr3, %r1"); + asm ("stw %r1, 0(%arg0)"); + + /* indicate "true return" from saved() */ + asm ("ldi 0, %ret0"); + + asm (".LABEL _comefrom_"); +} + +void +lwpRestore(jb) + jmp_buf jb; +{ + /* restore stack pointer and program counter */ + asm volatile ("ldw 4(%arg0), %sp"); + asm volatile ("ldw 8(%arg0), %rp"); + + /* restore "callee save" space register */ + asm volatile ("ldw 0(%arg0), %r1"); + asm volatile ("mtsp %r1, %sr3"); + + /* restore "callee save" registers */ + asm volatile ("ldw 12(%arg0), %r3"); + asm volatile ("ldw 16(%arg0), %r4"); + asm volatile ("ldw 20(%arg0), %r5"); + asm volatile ("ldw 24(%arg0), %r6"); + asm volatile ("ldw 28(%arg0), %r7"); + asm volatile ("ldw 32(%arg0), %r8"); + asm volatile ("ldw 36(%arg0), %r9"); + asm volatile ("ldw 40(%arg0), %r10"); + asm volatile ("ldw 44(%arg0), %r11"); + asm volatile ("ldw 48(%arg0), %r12"); + asm volatile ("ldw 52(%arg0), %r13"); + asm volatile ("ldw 56(%arg0), %r14"); + asm volatile ("ldw 60(%arg0), %r15"); + asm volatile ("ldw 64(%arg0), %r16"); + asm volatile ("ldw 68(%arg0), %r17"); + asm volatile ("ldw 72(%arg0), %r18"); + + /* warp to saved() to unwind the frame correctly */ + asm volatile ("bl _comefrom_, %r0"); + asm volatile ("ldi 1, %ret0"); +} + +#elif defined(BSD386) +void lwpInitContext(newp, sp) + struct lwpProc *newp; + void *sp; +{ + newp->context[2] = (int)sp; + newp->context[0] = (int)lwpEntryPoint; +} + +#elif defined(FBSD) + +void lwpInitContext(newp, sp) + struct lwpProc *newp; + void *sp; +{ + setjmp (newp->context); + newp->context->_jb[2] = (int)sp; + newp->context->_jb[3] = (int)sp; + newp->context->_jb[0] = (int)lwpEntryPoint; +} + +#elif defined(__linux__) + +void lwpInitContext(newp, sp) + struct lwpProc *newp; + void *sp; +{ +#if defined(__GLIBC__) && (__GLIBC__ >= 2) +#if defined(__PPC__) + newp->context->__jmpbuf[JB_GPR1] = (int) sp; + newp->context->__jmpbuf[JB_LR] = (int) lwpEntryPoint; +#else + newp->context->__jmpbuf[JB_SP] = (int) sp; + newp->context->__jmpbuf[JB_BP] = (int) sp; + newp->context->__jmpbuf[JB_PC] = (int) lwpEntryPoint; +#endif +#else + newp->context->__sp = sp; + newp->context->__bp = sp; + newp->context->__pc = (void *)lwpEntryPoint; +#endif +} + +#elif defined(SUN3) + +void lwpInitContext(newp, sp) + struct lwpProc *newp; + void *sp; +{ + newp->context[2] = (int)sp; + newp->context[3] = (int)lwpEntryPoint; +} + +#elif defined(__vax) + +#include + +void lwpInitContext(newp, stack) + struct lwpProc *newp; + void *stack; +{ + int *sp = (int*)stack; + int *fp = 0; + + /* Build root frame on new stack for lwpEntryPoint */ + *--sp = 0; /* pc */ + *--sp = (int)fp; /* fp */ + *--sp = 0; /* ap */ + *--sp = 0; /* psw */ + *--sp = 0; /* condition handler */ + fp = sp; + + /* Build stack frame to return from. */ + *--sp = (int)lwpEntryPoint+2;/* pc */ + *--sp = (int)fp; /* fp */ + *--sp = 0; /* ap */ + *--sp = 0; /* psw */ + *--sp = 0; /* condition handler */ + fp = sp; + + /* Fill in the context */ + /* Note: This is *not* how libc fills out jump buffers. */ + newp->context[0] = 0; /* r6 */ + newp->context[1] = 0; + newp->context[2] = 0; + newp->context[3] = 0; + newp->context[4] = 0; + newp->context[5] = 0; /* r11 */ + newp->context[6] = 0; /* ap */ + newp->context[7] = (int)fp; /* fp */ + return; +} + +int lwpSave(jb) + jmp_buf jb; +{ + asm("movl 4(ap), r0"); /* r0 = &jb */ + asm("movl r6, (r0)"); /* jb[0] = r6 */ + asm("movl r7, 4(r0)"); + asm("movl r8, 8(r0)"); + asm("movl r9, 12(r0)"); + asm("movl r10, 16(r0)"); + asm("movl r11, 20(r0)"); + asm("movl ap, 24(r0)"); + asm("movl fp, 28(r0)"); /* jb[7] = fp */ + return 0; +} + +void lwpRestore(jb) + jmp_buf jb; +{ + asm("movl 4(ap), r0"); /* r0 = &jb */ + asm("movl (r0), r6"); /* r6 = jb[0] */ + asm("movl 4(r0), r7"); + asm("movl 8(r0), r8"); + asm("movl 12(r0), r9"); + asm("movl 16(r0), r10"); + asm("movl 20(r0), r11"); + asm("movl 24(r0), ap"); + asm("movl 28(r0), fp"); /* fp = jb[7] */ + asm("movl $1, r0"); /* faked return 1 from lwpSave() */ + asm("ret"); + return; +} + + +#elif defined(SUN4) + +void lwpInitContext(newp, sp) + struct lwpProc *newp; + void *sp; +{ + static jmp_buf *cpp; + extern struct lwpProc *LwpCurrent; + + bzero(newp->context, sizeof(newp->context)); + newp->context[0] = (int)sp; + /* preserve cpp for new context */ + cpp = (jmp_buf *)&newp->context; + if (!_setjmp(LwpCurrent->context)) { + /* create new context */ + /* flush registers */ + asm ("ta 0x03"); + /* %o0 <- newp */ + asm ("ld [%fp+0x44], %o0"); + /* %o1 <- newp->context[0] */ + asm ("ld [%o0], %o1"); + /* create min frame on new stack */ + asm ("save %o1,-96, %sp"); + if (!_setjmp(*cpp)) + _longjmp(LwpCurrent->context, 1); + lwpEntryPoint(); + } +} + +#elif defined(__USLC__) && defined(i386) + +/* USL/Unixware on an Intel 386/486/... processor. + * Tested on Unixware v1.1.2, based on SYSV R4.2 + */ + +/* As per normal empire documentation, there is none. + * + * But, what we are attempting to do here is set up a longjump + * context buffer so that the lwpEntryPoint is called when + * the thread starts. + * + * I.E., what a setjmp/longjmp call set would do. + * + * How to figure this out? Well, without the setjmp code, you + * need to reverse engineer it by printing out the context buffer + * and the processor registers, and mapping which ones need + * to be set. + * + * Alternatively, you can single instruction step through the longjmp + * function, and figure out the offsets that it uses. + * + * Using offsets in bytes, + * context + 0x04 [1] -> esi (general purpose reg) + * context + 0x08 [2] -> edi (general purpose reg) + * context + 0x0C [3] -> ebp (general purpose or parameter passing) + * context + 0x10 [4] -> esp (stack) + * context + 0x14 [5] -> jump location for return + */ + +void lwpInitContext(newp, sp) + struct lwpProc *newp; + void *sp; +{ + newp->context[4] = (int)sp; + newp->context[5] = (int)lwpEntryPoint; +} + +#elif defined UCONTEXT + +/* + * Alternate aproach using setcontext en getcontext in stead of setjmp and + * longjump. This should work on any SVr4 machine independant of + * architecture. Unfortunaltely some changes are still nessesary in lwp.c. + * Tested on IRIX 5.3 + */ + +void lwpInitContext(newp, spp) + struct lwpProc *newp; + stack_t *spp; +{ + getcontext (&(newp->context)); + newp->context.uc_stack.ss_sp = spp->ss_sp; + newp->context.uc_stack.ss_size = spp->ss_size; + makecontext (&(newp->context), lwpEntryPoint, 0); +} + +#elif defined(ALPHA) + +#include + +void lwpInitContext(newp, sp) + struct lwpProc *newp; + void *sp; +{ + extern long *_gp; + + /* register values obtained from setjmp.h */ + _setjmp(newp->context); + newp->context[2] = (long)lwpEntryPoint; /* program counter */ + newp->context[30] = (long)lwpEntryPoint; /* return address */ + newp->context[31] = (long)lwpEntryPoint; /* fake program value (!) */ + newp->context[34] = (long)sp; /* stack pointer */ +} + +int lwpSave(jb) + jmp_buf jb; +{ + return _setjmp(jb); +} + +void lwpRestore(jb) + jmp_buf jb; +{ + /* resume, but get the pv from the jmp_buf */ + asm("ldq %pv, 248(%a0)"); + asm("stq %a0, 16(%sp)"); + /* generates a warning, but functions just fine */ + asm("bsr %ra, __longjump_resume"); +} + +#endif + +#endif + +#endif diff --git a/src/lib/lwp/lwp.c b/src/lib/lwp/lwp.c new file mode 100644 index 00000000..f6b3b12f --- /dev/null +++ b/src/lib/lwp/lwp.c @@ -0,0 +1,625 @@ +/* + * lwp.c -- lightweight process creation, destruction and manipulation. + * Copyright (C) 1991-3 Stephen Crane. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * author: Stephen Crane, (jsc@doc.ic.ac.uk), Department of Computing, + * Imperial College of Science, Technology and Medicine, 180 Queen's + * Gate, London SW7 2BZ, England. + */ + +#include +#include +#include +#include +#include "lwp.h" +#include "lwpint.h" +#include "prototypes.h" + +#if defined(_EMPTH_LWP) + +#ifdef BOUNDS_CHECK +#include +#include +#endif + +#ifdef hpc +extern struct lwpProc *initcontext; +extern int startpoint; +#endif + +struct lwpQueue LwpSchedQ[LWP_MAX_PRIO], LwpDeadQ; + +struct lwpProc *LwpCurrent = NULL; +char **LwpContextPtr; +int LwpMaxpri=0; /* maximum priority so far */ + +#ifdef POSIXSIGNALS +static sigset_t oldmask; +#else /* POSIXSIGNALS */ +static int oldmask; +#endif /* POSIXSIGNALS */ + +/* for systems without strdup */ +#ifdef NOSTRDUP +extern char *strdup(); +#endif /* NOSTRDUP */ + +static void lwpStackCheckInit(); +static int lwpStackCheck(); +static void lwpStackCheckUsed(); + +/* check stack direction */ +static int growsdown (x) + void *x; +{ + int y; + +#ifdef BOUNDS_CHECK + BOUNDS_CHECKING_OFF; +#endif + y = (x > (void *)&y); + +#ifdef BOUNDS_CHECK + BOUNDS_CHECKING_ON; +#endif + + return y; +} + +/* + * lwpReschedule -- schedule another process. we also check for dead + * processes here and free them. + */ +void lwpReschedule() +{ + extern struct lwpQueue LwpSchedQ[]; + static int lcount = LCOUNT; + static struct lwpProc *nextp; + static int i; +#ifdef POSIXSIGNALS + static sigset_t tmask; +#endif /* POSIXSIGNALS */ + + if (LwpCurrent && (LwpCurrent->flags & LWP_STACKCHECK)) { + lwpStackCheck(LwpCurrent); + } + if (!--lcount) { + int p = lwpSetPriority(LWP_MAX_PRIO-1); + lcount = LCOUNT; +#ifdef POSIXSIGNALS + sigprocmask (SIG_SETMASK, &oldmask, &tmask); + sigprocmask (SIG_SETMASK, &tmask, &oldmask); +#else /* POSIXSIGNALS */ + sigsetmask(sigsetmask(oldmask)); +#endif /* POSIXSIGNALS */ + LwpCurrent->pri = p; + } + + /* destroy dead threads */ + lwpStatus(LwpCurrent, "Cleaning dead queue"); + while (NULL != (nextp = lwpGetFirst(&LwpDeadQ))) { + if (nextp == LwpCurrent) { + lwpStatus(nextp, + "OOOPS, we are running already dead thread"); + exit(1); + } + lwpDestroy(nextp); + lwpStatus(LwpCurrent, "Destroying done"); + } + + for (i=LwpMaxpri+1; i--; ) { + while (NULL != (nextp = lwpGetFirst(&LwpSchedQ[i]))) { + if (!nextp->dead) + break; + /* clean up after dead bodies */ + lwpStatus(nextp, "got a dead body"); + if (nextp == LwpCurrent) { + lwpStatus(nextp, + "we are in it -- will bury later"); + lwpAddTail(&LwpDeadQ, nextp); + } + else{ + lwpDestroy(nextp); +/* fprintf(stderr, "Destroying done\n"); */ + } + nextp = 0; + } + if (nextp) + break; + } + if (LwpCurrent == 0 && nextp == 0) { + fprintf(stderr, "No processes to run!\n"); + exit(1); + } + if (LwpCurrent) + lwpStatus(LwpCurrent, "switch out"); + /* do context switch */ +#ifdef BOUNDS_CHECK + BOUNDS_CHECKING_OFF; +#endif + +#if defined(hpc) + { + int endpoint; + + endpoint = &endpoint; + if (initcontext == NULL || endpoint < startpoint) { + i = lwpSave(LwpCurrent->context); + } else { + LwpCurrent->size = endpoint - startpoint; + LwpCurrent->sbtm = realloc(LwpCurrent->sbtm, LwpCurrent->size); + memcpy(LwpCurrent->sbtm, startpoint, LwpCurrent->size); + if (i = lwpSave(LwpCurrent->context)) { + memcpy(startpoint, LwpCurrent->sbtm, LwpCurrent->size); + i = 1; + } + } + } +#else + i = lwpSave(LwpCurrent->context); +#endif +#ifdef BOUNDS_CHECK + BOUNDS_CHECKING_ON; +#endif + + if (LwpCurrent != nextp && + !(LwpCurrent && i)) { + /* restore previous context */ + lwpStatus(nextp, "switch in", nextp->pri); + LwpCurrent = nextp; + *LwpContextPtr = LwpCurrent->ud; +#ifdef BOUNDS_CHECK + BOUNDS_CHECKING_OFF; +#endif + lwpRestore(LwpCurrent->context); + +#ifdef BOUNDS_CHECK + BOUNDS_CHECKING_ON; +#endif + } +} + +/* + * lwpEntryPoint -- process entry point. + */ +void lwpEntryPoint() +{ + extern struct lwpProc *LwpCurrent; +#ifdef POSIXSIGNALS + sigset_t set; +#endif /* POSIXSIGNALS */ + +#ifdef BOUNDS_CHECK + BOUNDS_CHECKING_OFF; +#endif +#ifdef POSIXSIGNALS + sigemptyset (&set); + sigaddset (&set, SIGALRM); + sigprocmask (SIG_SETMASK, &set, &oldmask); +#else /* POSIXSIGNALS */ + sigsetmask(SIGNALS); +#endif /* POSIXSIGNALS */ + *LwpContextPtr = LwpCurrent->ud; + + lwpStatus(LwpCurrent, "starting at entry point"); + (*LwpCurrent->entry)(LwpCurrent->argc, LwpCurrent->argv, + LwpCurrent->ud); + lwpExit(); +#ifdef BOUNDS_CHECK + BOUNDS_CHECKING_ON; +#endif + + +} + +/* + * lwpCreate -- create a process. + */ +struct lwpProc * +lwpCreate(priority, entry, size, flags, name, desc, argc, argv, ud) + int priority; + void (*entry)(); + int size; + int flags; + char *name; + char *desc; + int argc; + char *argv[]; + void *ud; +{ + extern struct lwpProc *LwpCurrent; + struct lwpProc *newp; + int *s, x; +#ifdef UCONTEXT + stack_t sp; +#else /* UCONTEXT */ + void *sp; +#endif /* UCONTEXT */ + unsigned long stackp; + + if (!(newp = (struct lwpProc *)malloc(sizeof(struct lwpProc)))) + return (0); + if (flags & LWP_STACKCHECK) { + /* Add a 1K buffer on each side of the stack */ + size += 2 * LWP_REDZONE; + } + size += LWP_EXTRASTACK; + size += sizeof(stkalign_t); + if (!(s = (int *)malloc(size))) + return (0); + newp->flags = flags; + newp->name = strdup(name); + newp->desc = strdup(desc); + newp->entry = entry; + newp->argc = argc; + newp->argv = argv; + newp->ud = ud; + if ((newp->flags & LWP_STACKCHECK) == 0) { + stackp = growsdown((void *)&x) ? + (((long)s) + size - sizeof(stkalign_t) - LWP_EXTRASTACK) : + (long) s + LWP_EXTRASTACK; +#ifdef UCONTEXT + sp.ss_sp = (void *)(stackp & -sizeof(stkalign_t)); + sp.ss_size = size; + sp.ss_flags = 0; +#else /* UCONTEXT */ + sp = (void *)(stackp & -sizeof(stkalign_t)); +#endif /* UCONTEXT */ + } else { + if (growsdown(&x)) { + /* round address off to stkalign_t */ + stackp = ((long)s) + size - LWP_REDZONE - + LWP_EXTRASTACK - sizeof(stkalign_t); +#ifdef UCONTEXT + sp.ss_sp = (void *)(stackp & -sizeof(stkalign_t)); + sp.ss_size = size; + sp.ss_flags = 0; + newp->lowmark = (void *)(((long) sp.ss_sp) + LWP_EXTRASTACK); +#else /* UCONTEXT */ + sp = (void *)(stackp & -sizeof(stkalign_t)); + newp->lowmark = (void *)(((long) sp) + LWP_EXTRASTACK); +#endif /* UCONTEXT */ + newp->himark = s; + } else { + stackp = ((long)s) + LWP_REDZONE + LWP_EXTRASTACK; +#ifdef UCONTEXT + sp.ss_sp = (void *)(((long)stackp) & + -sizeof(stkalign_t)); + sp.ss_size = size; + sp.ss_flags = 0; +#else /* UCONTEXT */ + sp = (void *)(((long)stackp) & -sizeof(stkalign_t)); +#endif /* UCONTEXT */ + newp->lowmark = (void *)s; + newp->himark = (void *)(((long)s) + size - LWP_REDZONE); + } + } + if (LWP_MAX_PRIO <= priority) + priority = LWP_MAX_PRIO-1; + if (LwpMaxpri < (newp->pri = priority)) + LwpMaxpri = priority; + newp->sbtm = (void *)s; + newp->size = size; + newp->dead = 0; + if (flags & LWP_STACKCHECK) + lwpStackCheckInit(newp); + lwpStatus(newp, "creating process structure sbtm: %d", + (int)newp->sbtm); + lwpReady(newp); + lwpReady(LwpCurrent); +#ifdef UCONTEXT + lwpInitContext(newp, &sp); /* architecture-dependent: from arch.c */ +#else /* UCONTEXT */ + lwpInitContext(newp, sp); /* architecture-dependent: from arch.c */ +#endif /* UCONTEXT */ + lwpReschedule(); + return (newp); +} + +void lwpDestroy(proc) + struct lwpProc *proc; +{ + if (proc->flags & LWP_STACKCHECK){ + lwpStackCheckUsed(proc); + lwpStackCheck(proc); + } + lwpStatus(proc, "destroying sbtm: %d", (int)proc->sbtm); + proc->entry = 0; + proc->ud = 0; + proc->argv = 0; + free((char *)proc->sbtm); + free(proc->name); + free(proc->desc); + proc->name = 0; + proc->desc = 0; + proc->sbtm = 0; + proc->lowmark = 0; + proc->himark = 0; + free((char *)proc); +} + +/* + * lwpReady -- put process on ready queue. if null, assume current. + */ +void lwpReady(p) + struct lwpProc *p; +{ + extern struct lwpProc *LwpCurrent; + extern struct lwpQueue LwpSchedQ[]; + + if (!p) + p = LwpCurrent; + lwpStatus(p, "added to run queue"); + lwpAddTail(&LwpSchedQ[p->pri], p); +} + +/* + * return user's data + */ +void *lwpGetUD(p) + struct lwpProc *p; +{ + if (!p) + p = LwpCurrent; + return (p->ud); +} + +/* + * set user's data + */ +void lwpSetUD(p, ud) + struct lwpProc *p; + char *ud; +{ + if (!p) + p = LwpCurrent; + p->ud = ud; +} + +/* + * set name & desc + */ +void lwpSetDesc(p, name, desc) + struct lwpProc *p; + char *name; + char *desc; +{ + if (!p) + p = LwpCurrent; + free(p->name); + free(p->desc); + p->name = strdup(name); + p->desc = strdup(desc); +} + +/* + * lwpYield -- yield the processor to another thread. + */ +void lwpYield() +{ + lwpStatus(LwpCurrent, "yielding control"); + lwpReady(LwpCurrent); + lwpReschedule(); +} + +/* + * cause the current process to be scheduled for deletion. + */ +void lwpExit() +{ + lwpStatus(LwpCurrent, "marking self as dead"); + LwpCurrent->dead = 1; + lwpYield(); +} + +/* + * mark another process as dead, so it will never be rescheduled. + * remove any lingering FD action + */ +void lwpTerminate(p) + struct lwpProc *p; +{ + lwpStatus(p, "terminating process"); + p->dead = 1; + if (p->fd >= 0) + lwpWakeupFd(p); +} + +/* + * set the thread's priority, returning the old. + * if the new priority is lower than the old, we reschedule. + */ +int lwpSetPriority(new) + int new; +{ + int old = LwpCurrent->pri; + + if (LWP_MAX_PRIO <= new) + new = LWP_MAX_PRIO-1; + if (LwpMaxpri < new) + LwpMaxpri = new; + LwpCurrent->pri = new; + lwpStatus(LwpCurrent, "resetting priority (%d -> %d)", old, new); + if (new < old) + lwpYield(); + return (old); +} + +/* + * initialise the coroutine structures + */ +struct lwpProc *lwpInitSystem(pri, ctxptr, flags) + int pri; + char **ctxptr; + int flags; +{ + extern struct lwpQueue LwpSchedQ[]; + extern struct lwpProc *LwpCurrent; + struct lwpQueue *q; + int i, *stack; + struct lwpProc *sel; + + LwpContextPtr = ctxptr; + if (pri < 1) + pri = 1; + /* *LwpContextPtr = 0; */ + if (!(LwpCurrent = (struct lwpProc *)calloc (1, sizeof(struct lwpProc)))) + return (0); + if (!(stack = (int *)malloc(64))) + return (0); + if (LWP_MAX_PRIO <= pri) + pri = LWP_MAX_PRIO-1; + if (LwpMaxpri < pri) + LwpMaxpri = pri; + LwpCurrent->next = 0; + LwpCurrent->sbtm = stack; /* dummy stack for "main" */ + LwpCurrent->pri = pri; + LwpCurrent->dead = 0; + LwpCurrent->flags = flags; + LwpCurrent->name = "Main"; + for (i=LWP_MAX_PRIO, q=LwpSchedQ; i--; q++) + q->head = q->tail = 0; + LwpDeadQ.head = LwpDeadQ.tail = 0; + /* must be lower in priority than us for this to work right */ + sel = lwpCreate(0, lwpSelect, 16384, flags, "EventHandler", + "Select (main loop) Event Handler", 0, 0, 0); + lwpInitSelect(sel); + return (LwpCurrent); +} + +/* lwpStackCheckInit + * + * Initialize the entire stack (including both redzones) with the stack + * check mark. Thus, we can get some indication of how much stack was + * used. + */ +static void lwpStackCheckInit(newp) + struct lwpProc *newp; +{ + register int i; + register long *lp; + + int lim = newp->size/sizeof(long); + if (!newp || !newp->sbtm) + return; + for (lp=newp->sbtm,i=0; i < lim; i++,lp++) { + *lp = LWP_CHECKMARK; + } +} + +/* lwpStackCheck + * + * Check if the thread has overflowed/underflowed its stack. + * NOTE: + * If an problem occurs, it is not corrected. + * The buffer is not cleaned up, nor is the thread terminated. + * Cleaning up the buffer would be a mistake, and terminating + * the thread, well, could be done. Should more like take + * down the entire process. + */ +static int lwpStackCheck(newp) + struct lwpProc *newp; +{ + register int end, amt; + register unsigned int i; + register long *lp; + register int growsDown; + int marker; + + if (!newp || !newp->himark || !newp->lowmark) + return(1); + growsDown = growsdown(&marker); + for (lp=newp->himark,i=0; i < LWP_REDZONE/sizeof(long); i++,lp++) { + if (*lp == LWP_CHECKMARK) + continue; + /* Stack overflow. */ + if (growsDown) { + end = i; + while (i < LWP_REDZONE/sizeof(long)) { + if (*lp++ != LWP_CHECKMARK) + end = i; + i++; + } + amt = (end+1) * sizeof(long); + } else { + amt = (i+1) * sizeof(long); + } + lwpStatus(newp, "Thread stack overflowed %d bytes (of %u)", + amt, newp->size - 2*LWP_REDZONE - sizeof(stkalign_t)); + return(0); + } + for (lp=newp->lowmark,i=0; i < LWP_REDZONE/sizeof(long); i++,lp++) { + if (*lp == LWP_CHECKMARK) + continue; + /* Stack underflow. */ + if (growsDown) { + end = i; + while (i < LWP_REDZONE/sizeof(long)) { + if (*lp++ != LWP_CHECKMARK) + end = i; + i++; + } + amt = (end+1) * sizeof(long); + } else { + amt = (LWP_REDZONE - i+1) * sizeof(long); + } + lwpStatus(newp, "Thread stack underflow %d bytes (of %u)", + amt, newp->size - 2*LWP_REDZONE - sizeof(stkalign_t)); + return(0); + } + return(1); +} + +/* lwpStackCheckUsed + * + * Figure out how much stack was used by this thread. + */ +static void lwpStackCheckUsed(newp) + struct lwpProc *newp; +{ + register int i; + register long *lp; + register int lim; + int marker; + + if (!newp || !newp->sbtm) + return; + lim = newp->size/sizeof(long); + if (growsdown(&marker)) { + /* Start at the bottom and find first non checkmark. */ + for (lp=newp->sbtm,i=0; i < lim; i++,lp++) { + if (*lp != LWP_CHECKMARK) { + break; + } + } + } else { + /* Start at the top and find first non checkmark. */ + lp = newp->sbtm; + lp += newp->size/sizeof(long); + lp--; + for (i=0; i < lim; i++, lp--) { + if (*lp != LWP_CHECKMARK) { + break; + } + } + } + lwpStatus(newp, "stack use: %u bytes (of %u total)", + (i * sizeof(long)) - LWP_REDZONE, + newp->size - 2*LWP_REDZONE - sizeof(stkalign_t)); +} + +#endif diff --git a/src/lib/lwp/lwpInit.s b/src/lib/lwp/lwpInit.s new file mode 100644 index 00000000..62d69de4 --- /dev/null +++ b/src/lib/lwp/lwpInit.s @@ -0,0 +1,76 @@ +.set r0,0; .set SP,1; .set RTOC,2; .set r3,3; .set r4,4 +.set r5,5; .set r6,6; .set r7,7; .set r8,8; .set r9,9 +.set LR,8 + + .rename LwpInitContext{PR},"" + .rename LwpInitContext{TC},"lwpInitContext" + .rename LwpEntryPoint{TC},"lwpEntryPoint" + + .lglobl LwpInitContext{PR} + .globl .lwpInitContext + .globl lwpInitContext{DS} + .extern lwpEntryPoint{DS} + + +# .text section + + + .csect LwpInitContext{PR} + .function .lwpInitContext{PR},.lwpInitContext,2,0 +.lwpInitContext: # 0x00000000 (LwpInitContext) + stu SP,-0x40(SP) + st r3,0x58(SP) # r3 = newp pointer + st r4,0x5c(SP) # r4 = sp pointer + .bf 234 + st SP,0x0(r4) + st SP,0xf8(r3) # store prev SP + st r4,0xc(r3) # store entrypoint at newp[3] + l r3,LWPEntryPoint(RTOC) + l r4,0x0(r3) + l r3,0x58(SP) # load newp into r3 + st r4,0x8(r3) # store sp at newp[2] + st RTOC,0x10(r3) # store RTOC at newp[4] + ai SP,SP,0x40 + br + .ef 236 +# traceback table + .long 0x00000000 + .byte 0x00 # VERSION=0 + .byte 0x00 # LANG=TB_C + .byte 0x20 # IS_GL=0,IS_EPROL=0,HAS_TBOFF=1 + # INT_PROC=0,HAS_CTL=0,TOCLESS=0 + # FP_PRESENT=0,LOG_ABORT=0 + .byte 0x40 # INT_HNDL=0,NAME_PRESENT=1 + # USES_ALLOCA=0,CL_DIS_INV=WALK_ONCOND + # SAVES_CR=0,SAVES_LR=0 + .byte 0x80 # STORES_BC=1,FPR_SAVED=0 + .byte 0x00 # GPR_SAVED=0 + .byte 0x02 # FIXEDPARMS=2 + .byte 0x01 # FLOATPARMS=0,PARMSONSTK=1 + .long 0x00000000 # + .long 0x0000002c # TB_OFFSET + .short 14 # NAME_LEN + .byte "lwpInitContext" +# End of traceback table +# End csect LwpInitContext{PR} + +# .data section + + + .toc # 0x00000050 +LWPInitContext: + .tc LwpInitContext{TC},lwpInitContext{DS} +LWPEntryPoint: + .tc LwpEntryPoint{TC},lwpEntryPoint{DS} + + + .csect lwpInitContext{DS} + .long .lwpInitContext # "\0\0\0\0" + .long TOC{TC0} # "\0\0\0P" + .long 0x00000000 # "\0\0\0\0" +# End csect lwpInitContext{DS} + + + +# .bss section + diff --git a/src/lib/lwp/lwpRestore.s b/src/lib/lwp/lwpRestore.s new file mode 100644 index 00000000..6e0a55bc --- /dev/null +++ b/src/lib/lwp/lwpRestore.s @@ -0,0 +1,62 @@ +.set r0,0; .set SP,1; .set RTOC,2; .set r3,3; .set r4,4 +.set r5,5; .set r6,6; .set r7,7; .set r8,8; .set r9,9 +.set LR,8 + + .rename lwpRestore{PR},"" + .rename lwpRestore{TC},"lwpRestore" + + .lglobl lwpRestore{PR} + .globl .lwpRestore + .globl lwpRestore{DS} + + +# .text section + + + .csect lwpRestore{PR} +.lwpRestore: # 0x00000000 (lwpRestore) + l r5,0x8(r3) + l SP,0xc(r3) + l RTOC,0x10(r3) + mtlr r5 + lil r3,0x1 + br +# traceback table + .long 0x00000000 + .byte 0x00 # VERSION=0 + .byte 0x00 # LANG=TB_C + .byte 0x20 # IS_GL=0,IS_EPROL=0,HAS_TBOFF=1 + # INT_PROC=0,HAS_CTL=0,TOCLESS=0 + # FP_PRESENT=0,LOG_ABORT=0 + .byte 0x40 # INT_HNDL=0,NAME_PRESENT=1 + # USES_ALLOCA=0,CL_DIS_INV=WALK_ONCOND + # SAVES_CR=0,SAVES_LR=0 + .byte 0x80 # STORES_BC=1,FPR_SAVED=0 + .byte 0x00 # GPR_SAVED=0 + .byte 0x01 # FIXEDPARMS=1 + .byte 0x01 # FLOATPARMS=0,PARMSONSTK=1 + .long 0x00000000 # + .long 0x00000010 # TB_OFFSET + .short 10 # NAME_LEN + .byte "lwpRestore" +# End of traceback table +# End csect lwpRestore{PR} + +# .data section + + + .toc # 0x00000030 +LWPRestore: + .tc lwpRestore{TC},lwpRestore{DS} + + + .csect lwpRestore{DS} + .long .lwpRestore # "\0\0\0\0" + .long TOC{TC0} # "\0\0\0000" + .long 0x00000000 # "\0\0\0\0" +# End csect lwpRestore{DS} + + + +# .bss section + diff --git a/src/lib/lwp/lwpSave.s b/src/lib/lwp/lwpSave.s new file mode 100644 index 00000000..b4bc6949 --- /dev/null +++ b/src/lib/lwp/lwpSave.s @@ -0,0 +1,66 @@ +.set r0,0; .set SP,1; .set RTOC,2; .set r3,3; .set r4,4 +.set r5,5; .set r6,6; .set r7,7; .set r8,8; .set r9,9 +.set LR,8 + + .rename lwpSave{PR},"" + .rename lwpSave{TC},"lwpSave" + + .lglobl lwpSave{PR} + .globl .lwpSave + .globl lwpSave{DS} + + +# .text section + + + .csect lwpSave{PR} +.lwpSave: # 0x00000000 (lwpSave) + st SP,0xc(r3) + st RTOC,0x10(r3) + mflr r4 + st r4,0x8(r3) + lil r3,0x0 + br +# traceback table + .long 0x00000000 + .byte 0x00 # VERSION=0 + .byte 0x00 # LANG=TB_C + .byte 0x20 # IS_GL=0,IS_EPROL=0,HAS_TBOFF=1 + # INT_PROC=0,HAS_CTL=0,TOCLESS=0 + # FP_PRESENT=0,LOG_ABORT=0 + .byte 0x40 # INT_HNDL=0,NAME_PRESENT=1 + # USES_ALLOCA=0,CL_DIS_INV=WALK_ONCOND + # SAVES_CR=0,SAVES_LR=0 + .byte 0x80 # STORES_BC=1,FPR_SAVED=0 + .byte 0x00 # GPR_SAVED=0 + .byte 0x01 # FIXEDPARMS=1 + .byte 0x01 # FLOATPARMS=0,PARMSONSTK=1 + .long 0x00000000 # + .long 0x00000014 # TB_OFFSET + .short 7 # NAME_LEN + .byte "lwpSave" + .byte 0 # padding + .byte 0 # padding + .byte 0 # padding +# End of traceback table + .long 0x00000000 # "\0\0\0\0" +# End csect lwpSave{PR} + +# .data section + + + .toc # 0x00000038 +LWPSave: + .tc lwpSave{TC},lwpSave{DS} + + + .csect lwpSave{DS} + .long .lwpSave # "\0\0\0\0" + .long TOC{TC0} # "\0\0\0008" + .long 0x00000000 # "\0\0\0\0" +# End csect lwpSave{DS} + + + +# .bss section + diff --git a/src/lib/lwp/lwpint.h b/src/lib/lwp/lwpint.h new file mode 100644 index 00000000..0d822660 --- /dev/null +++ b/src/lib/lwp/lwpint.h @@ -0,0 +1,105 @@ +/* + * lwpint.h -- lwp internal structures + * + * Copyright (C) 1991-3 Stephen Crane. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * author: Stephen Crane, (jsc@doc.ic.ac.uk), Department of Computing, + * Imperial College of Science, Technology and Medicine, 180 Queen's + * Gate, London SW7 2BZ, England. + */ +#ifndef _LWPINT_H +#define _LWPINT_H + +/* `liveness' counter: check signals every `n' visits to the scheduler */ +/* note: the lower this value, the more responsive the system but the */ +/* more inefficient the context switch time */ +#define LCOUNT -1 + +#ifdef hpux +int lwpSave _PROTO((jmp_buf)); +void lwpRestore _PROTO((jmp_buf)); +#endif + +#if defined(MIPS) || defined(AIX32) || defined(ALPHA) || defined(__vax) +int lwpSave _PROTO((jmp_buf)); +void lwpRestore _PROTO((jmp_buf)); +#elif defined(SUN4) +#define lwpSave(x) _setjmp(x) +#define lwpRestore(x) _longjmp(x, 1) +#elif defined (UCONTEXT) +#define lwpSave(x) getcontext(&(x)) +#define lwpRestore(x) setcontext(&(x)) +#else +#ifdef hpc +#define lwpSave(x) setjmp(x) +#define lwpRestore(x) longjmp(x, 1) +#else +#ifndef hpux +#define lwpSave(x) setjmp(x) +#define lwpRestore(x) longjmp(x, 1) +#endif /* hpux */ +#endif /* hpc */ +#endif + +#ifdef AIX32 +/* AIX needs 12 extra bytes above the stack; we add it here */ +#define LWP_EXTRASTACK 3*sizeof(long) +#else +#define LWP_EXTRASTACK 0 +#endif + +#define LWP_REDZONE 1024 /* make this a multiple of 1024 */ + +/* XXX Note that this assumes sizeof(long) == 4 */ +#define LWP_CHECKMARK 0x5a5a5a5aL + +#define SIGNALS sigmask(SIGALRM) + +#ifndef hpux +typedef double stkalign_t; +#else +typedef struct { + char x[64]; +} stkalign_t; +#endif + +/* internal routines */ +void lwpAddTail _PROTO((struct lwpQueue *, struct lwpProc *)); +struct lwpProc *lwpGetFirst _PROTO((struct lwpQueue *)); +void lwpReschedule _PROTO((void)); +void lwpReady _PROTO((struct lwpProc *)); +void lwpOnalarm _PROTO((void)); + +#ifdef UCONTEXT +void lwpInitContext _PROTO((struct lwpProc *, stack_t *)); +#else /* GETCONTEXT */ +#ifdef hpc +void lwpInitContext _PROTO((struct lwpProc *, void *)); +#else +#ifdef hpux +void lwpInitContext _PROTO((volatile struct lwpProc *volatile, void *)); +#else +void lwpInitContext _PROTO((struct lwpProc *, void *)); +#endif /* hpux */ +#endif /* hpc */ +#endif /* GETCONTEXT */ +void lwpEntryPoint _PROTO((void)); +void lwpInitSelect _PROTO((struct lwpProc *self)); +void lwpDestroy _PROTO((struct lwpProc *proc)); + +#endif /* _LWP_H */ + diff --git a/src/lib/lwp/mipsarch.s b/src/lib/lwp/mipsarch.s new file mode 100644 index 00000000..29e143b2 --- /dev/null +++ b/src/lib/lwp/mipsarch.s @@ -0,0 +1,71 @@ + .verstamp 3 0 + .extern tzname 0 + .extern LwpCurrent 4 + .lcomm $$9 4 + .text + .align 2 + .file 2 "arch.new.c" + .globl lwpSave + .ent lwpSave 2 +lwpSave: + .option O1 + subu $sp, 32 + sw $31, 28($sp) + sw $4, 32($sp) + .mask 0x80000000, -4 + .frame $sp, 32, $31 + sw $0, $$9 + sw $30, 0($4) + sw $sp, 4($4) + sw $31, 8($4) + sd $16, 12($4) + sd $18, 20($4) + sd $20, 28($4) + sd $22, 36($4) + lw $2, $$9 + .livereg 0x2000FF0E,0x00000FFF + lw $31, 28($sp) + addu $sp, 32 + j $31 + .end lwpSave + .text + .align 2 + .file 2 "arch.new.c" + .globl lwpRestore + .ent lwpRestore 2 +lwpRestore: + .option O1 + subu $sp, 32 + sw $31, 28($sp) + sw $4, 32($sp) + .mask 0x80000000, -4 + .frame $sp, 32, $31 + li $14, 1 + sw $14, $$9 + lw $30, 0($4) + lw $sp, 4($4) + lw $31, 8($4) + ld $16, 12($4) + ld $18, 20($4) + ld $20, 28($4) + ld $22, 36($4) + lw $2, $$9 + .livereg 0x0000FF0E,0x00000FFF + addu $sp, 32 + j $31 + .end lwpRestore + .text + .align 2 + .file 2 "arch.new.c" + .globl lwpInitContext + .ent lwpInitContext 2 +lwpInitContext: + .option O1 + .frame $sp, 0, $31 + sw $5, 4($4) + la $14, lwpEntryPoint + sw $14, 8($4) + .livereg 0x0000FF0E,0x00000FFF + j $31 + .end lwpInitContext + diff --git a/src/lib/lwp/misc/echo.c b/src/lib/lwp/misc/echo.c new file mode 100644 index 00000000..6c2a949f --- /dev/null +++ b/src/lib/lwp/misc/echo.c @@ -0,0 +1,115 @@ +/* + * server.c + * + * lwp (echo) connection handler server + * + */ + +#include +#include +#include +#include +#include +#include + +#define SP_ACCEPT 3 +#define SP_READER 3 + +#include "lwp.h" + +struct context { + struct lwpProc *us; + struct sockaddr_in addr; + int fd; +}; + +/*ARGSUSED*/ +int readConn(argc, argv, ud) + int argc; + char **argv; + void *ud; +{ + struct context *ctx = (struct context *) ud; + char buf[1024]; + int n; + + while (1) { + printf("sleeping\n"); + lwpSleepFd(ctx->fd, LWP_FD_READ); + printf("waiting to read\n"); + if ((n = read(ctx->fd, buf, sizeof(buf))) <= 0) + break; + printf("got %d char\n", n); + lwpSleepFd(ctx->fd, LWP_FD_WRITE); + printf("waiting to write\n"); + if (write(ctx->fd, buf, n) < 0) + break; + printf("wrote %d char\n", n); + } + printf("process/fd %d exiting\n", ctx->fd); + close(ctx->fd); + lwpExit(); + /*NOTREACHED*/ +} + +int acceptConn(argc, argv) + int argc; + char **argv; +{ + struct sockaddr_in sin; + int s; + int ns; + int len; + int maxfd; + struct context *ctx; + + if (argc != 2) { + fprintf(stderr, "Usage: %s port\n", *argv); + exit(-1); + } + if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) { + perror("inet socket"); + exit(-1); + } + sin.sin_family = AF_INET; + sin.sin_port = htons(atoi(argv[1])); + sin.sin_addr.s_addr = 0; + if (bind(s, &sin, sizeof(sin)) < 0) { + perror("inet socket bind"); + exit(-1); + } + if (listen(s, LISTENMAXCONN) < 0) { + perror("inet socket listen"); + exit(-1); + } + maxfd = getdtablesize() - 1; + while (1) { + lwpSleepFd(s, LWP_FD_READ); + len = sizeof(sin); + ns = accept(s, &sin, &len); + if (ns < 0) { + perror("accept"); + exit(-1); + } + if (ns == maxfd) { + fprintf(stderr, "no more connections"); + close(ns); + } + printf("got connection from %s\n", inet_ntoa(sin.sin_addr)); + ctx = (struct context *) malloc(sizeof(*ctx)); + ctx->addr = sin; + ctx->fd = ns; + ctx->us = lwpCreate(SP_READER, readConn, 8192, 0, 0, ctx); + } + /*NOTREACHED*/ +} + +int main(argc, argv) + int argc; + char **argv; +{ + lwpInitSystem(1); + lwpCreate(SP_ACCEPT, acceptConn, 8192, argc, argv, 0); + lwpReschedule(); + /*NOTREACHED*/ +} diff --git a/src/lib/lwp/misc/lwp.h b/src/lib/lwp/misc/lwp.h new file mode 100644 index 00000000..06d49dd0 --- /dev/null +++ b/src/lib/lwp/misc/lwp.h @@ -0,0 +1,90 @@ +/* + * lwp.h -- prototypes and structures for lightweight processes + * Copyright (C) 1991-3 Stephen Crane. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * author: Stephen Crane, (jsc@doc.ic.ac.uk), Department of Computing, + * Imperial College of Science, Technology and Medicine, 180 Queen's + * Gate, London SW7 2BZ, England. + */ +#ifndef _LWP_H +#define _LWP_H + +#ifndef _PROTO +#ifdef __cplusplus +#define _PROTO(x) x +#else +#define _PROTO(x) () +#endif +#endif + +#include +#include + +/* process control block. do *not* change the position of context */ +struct lwpProc { + jmp_buf context; /* processor context area */ + void *sbtm; /* bottom of stack attached to it */ + int size; /* size of stack */ + void (*entry)(); /* entry point */ + int dead; /* whether the process can be rescheduled */ + int pri; /* which scheduling queue we're on */ + long runtime; /* time at which process is restarted */ + int fd; /* fd we're blocking on */ + int argc; /* initial arguments */ + char **argv; + void *ud; /* user data */ + struct lwpProc *next; +}; + +/* queue */ +struct lwpQueue { + struct lwpProc *head; + struct lwpProc *tail; +}; + +/* semaphore */ +struct lwpSem { + int count; + struct lwpQueue q; +}; + +#define LWP_FD_READ 0x1 +#define LWP_FD_WRITE 0x2 + +#define LWP_MAX_PRIO 8 + +struct lwpProc *lwpInitSystem _PROTO((int)); +struct lwpProc *lwpCreate _PROTO((int, void (*)(), int, int, char **, void *)); +void lwpExit _PROTO((void)); +void lwpTerminate _PROTO((struct lwpProc *)); +void lwpYield _PROTO((void)); +void lwpSleepFd _PROTO((int fd, int flags)); +void lwpSleepUntil _PROTO((long until)); +void lwpWakeupFd _PROTO((struct lwpProc *)); +void *lwpGetUD _PROTO((struct lwpProc *)); +void lwpSetUD _PROTO((struct lwpProc *, char *)); +int lwpSetPriority _PROTO((int)); +void lwpReschedule _PROTO(()); + +struct lwpSem *lwpCreateSem _PROTO((int)); +void lwpSignal _PROTO((struct lwpSem *)); +void lwpWait _PROTO((struct lwpSem *)); +void lwpSelect _PROTO((int argc, char **argv)); + +extern struct lwpProc *LwpCurrent; + +#endif /* _LWP_H */ diff --git a/src/lib/lwp/misc/lwp.tar.gz b/src/lib/lwp/misc/lwp.tar.gz new file mode 100644 index 00000000..72e71fb6 Binary files /dev/null and b/src/lib/lwp/misc/lwp.tar.gz differ diff --git a/src/lib/lwp/misc/lwp.tex b/src/lib/lwp/misc/lwp.tex new file mode 100644 index 00000000..2cfb2b53 --- /dev/null +++ b/src/lib/lwp/misc/lwp.tex @@ -0,0 +1,189 @@ +\documentstyle[tgrind, a4]{article} +\title{The {\sc Rex} lightweight process library} +\author{Stephen Crane\\ (jsc@doc.ic.ac.uk)\thanks{Thanks to Mark Little +(m.c.little@ncl.ac.uk) for the Linux port}} +\begin{document} +\maketitle +This document describes the interface to and the behaviour underlying +my threads library for Rex.\footnote{Available as lwp.tar.gz by anonymous +ftp from gummo.doc.ic.ac.uk:/rex. Rex (Esprit project 2080) was +axed by Men in Suits.} It has been tested on Sun-3, Sun-4, +Mips, 386-BSD and Linux systems. Counting semi-colons, it is +260 lines long, including support for the different architectures (this +figure includes variable- but not function-declarations). + +A word from our sponsor: +\begin{quote} +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but {\sc WITHOUT ANY WARRANTY}; without even the implied warranty of +{\sc MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE}. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free +Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +\end{quote} + +(Note that while this library is protected by the GNU copyleft, it is not +supported by the Free Software Foundation.) + +\section{Threads} +Threads are prioritised and +non-preemptive. Operations supported on threads are: +\begin{tgrind} +\L{\LB{}\Tab{8}{\K{struct} pcb *initlp (\K{int} priority)}} +\L{\LB{}\Tab{8}{\K{struct} pcb *creatp (priority, entry, size, argc, argv, envp)}} +\L{\LB{}\Tab{8}{\K{void} readyp (\K{struct} pcb *p)}} +\L{\LB{}\Tab{8}{\K{void} yieldp (\K{void})}} +\L{\LB{}\Tab{8}{\K{void} *getenvp (\K{struct} pcb *p)}} +\L{\LB{}\Tab{8}{\K{void} setenvp (\K{struct} pcb *p, \K{void} *)}} +\L{\LB{}\Tab{8}{\K{void} suicidep (\K{void})}} +\L{\LB{}\Tab{8}{\K{void} destroyp (\K{struct} pcb *p)}} +\end{tgrind} +\begin{description} +\item[initlp] initialises the threads runtime, creating a thread with +specified priority for the invoker. +\item[creatp] creates a new thread with specified {\em priority}, {\em +entry} point, with a stack of {\em size}, {\em argc} arguments in {\em +argv} and a user-defined environment pointer. +\item[getenvp] returns the environment pointer associated with the given +thread. If the thread is null, the current thread is assumed. +\item[setenvp] reassigns the environment pointer associated with the +given thread. +\item[readyp] makes the specified thread ready to run, or the current +thread if null. +\item[yieldp] makes the current thread ready to run. If no thread of +higher priority is runnable, the current thread will run. +\item[suicidep] marks the invoking thread as dead. It will never be +rescheduled. +\item[destroyp] marks the specified thread as dead. It will be removed +at the next reschedule. If it is currently running, it will be +unaffected until the next reschedule. +\end{description} + +\section{Semaphores} +For synchronisation, counting semaphores are provided. Available +operations are: +\begin{tgrind} +\L{\LB{}\Tab{8}{\K{struct} sem *creats (\K{int} count)}} +\L{\LB{}\Tab{8}{\K{void} signals (\K{struct} sem *s)}} +\L{\LB{}\Tab{8}{\K{void} waits (\K{struct} sem *s)}} +\end{tgrind} +\begin{description} +\item[creats] allocates a new semaphore from the heap and initialises its +count. +\item[signals] increments the semaphore's count, makes a waiting process +ready if there is one. If the readied process's priority is greater than +that of the signaller, a reschedule is done. +\item[waits] decrements the semaphore's count. If it becomes negative, +the current process is suspended and a reschedule is done. +\end{description} + +\section{Signals} +The library is concerned with two types of signal, {\sc sigio} and {\sc +sigalrm}. These signals are normally blocked until the null process is +scheduled. It uses {\tt sigpause()} to reenable them and wait for one +to arrive. While awaiting a signal, the null process `runs' at maximum +priority. Thus users will not be able to cause a reschedule from +their handlers. When {\tt sigpause()} returns, the signal will have +been handled and the null process drops back down to the lowest priority +and yields to any thread which has been made ready to run from the +user-level handler. + +These semantics make the library rather unresponsive to signals in the +presence of busy processes. If a more responsive system is required, +the constant {\sc LCOUNT} may be changed. This value determines the +number of times the {\tt reschedp ()} function must be called before +signals are re-enabled. If given a value of {\tt 1}, it will affect +context-switching time by about 50\%. Its default value is {\tt -1}. + +\subsection{Input and output} +Input and output present a problem to threads, because they require +calls to the underlying {\sc Unix} system, which will block not only +the invoking thread, but also all others in the process. Thus, in +general, a thread must wait until the descriptor on which I/O is to +be done becomes ready for the operation. This is done by trapping +{\sc sigio}. Two routines are provided: +\begin{tgrind} +\L{\LB{}\Tab{8}{\K{int} sigioset (\K{int} fd, \K{void} (*han) (\K{void} +*, \K{int}), \K{void} *ctx)}} +\L{\LB{}\Tab{8}{\K{int} sigioclr (\K{int} fd)}} +\end{tgrind} +The general model adopted for processing {\sc sigio} is to install a +{\em handler} routine for the I/O descriptor using {\em sigioset} and +remove it using {\em sigioclr}. The user is responsible for setting up +the device correctly to generate {\sc sigio}. When {\sc sigio} arrives +for the descriptor, the handler will be called with a context pointer +as its argument. (In C++, this context is the instance pointer of the +invoking thread.) + +\subsection{The timer} +A single routine is provided to block the invoking thread for the +specified time: +\begin{tgrind} +\L{\LB{}\Tab{8}{\K{void} delayp (\K{int} n)}} +\end{tgrind} +This routine blocks the invoker for {\em at least\/} the time specified. +If this is zero, a reschedule is done. Delays are implemented as a +delta queue, using {\sc sigalrm}. $n$ specifies a microsecond delay +which is of limited utility in practice. + +\section{Performance} +\begin{figure}[htb] +\begin{center} +\begin{tabular}{||l|c|c|c||} \hline +Arch & ctxsw & creat & comment \\ \hline +sun3 & 308 & 778 & 3/240 \\ \hline +386bsd & 186 & 464 & 486/33 \\ \hline +sun4 & 96 & 436 & IPX \\ \hline +sun4 & 59 & 212 & Sparc-10 \\ \hline +linux & 56 & 382 & 486-DX2/50 \\ \hline +mips & 17 & 85 & Decstation \\ \hline +\end{tabular} +\caption{Performance with architecture (times in microseconds).} +\end{center} +\end{figure} +\begin{description} +\item[sun3] has very lightweight process initialisation, compared with +context switching. +\item[sun4] has a high context switch time as a result of {\tt setjmp ()} and +{\tt longjmp ()} implementations. Process initialisation is also relatively +heavyweight: it requires two calls to {\tt setjmp ()} and one to {\tt longjmp +()}. +\item[mips] provides its own context switching in assembly language. +\end{description} + +\section{Porting to another architecture} +Although the threads library is quite portable, a few guidelines should +be observed when moving to a new architecture. + +\begin{itemize} +\item Create two new files for your architecture/kernel (e.g. {\tt sun4.c} +and {\tt sun4.h}). +The `.c' file should contain any routines which your version of {\sc Unix} is +missing and a thread initialisation routine: +\begin{tgrind} +\L{\LB{}\Tab{8}{\K{void} initp (\K{struct} pcb *, \K{void} *)}} +\end{tgrind} +The `.h' file contains any machine-specific definitions. +\item If {\tt setjmp ()} and {\tt longjmp ()} don't work on your machine +(for example the {\sc Ultrix} {\tt longjmp ()} implementation checks that +the frame being jumped to is an ancestor of the current one), you will +have to write {\tt savep ()} and {\tt restorep ()} and put the following +define into your machine-specific header file: +\begin{tgrind} +\L{\LB{}\Tab{8}{\K{\#define} OWN\_CONTEXT\_SWITCH}} +\end{tgrind} +\item Compile and run the three test programs: {\tt producer.c}, {\tt +timer.c} and {\tt bm.c}. +\item Add the name of the architecture to `config'. +\item Send {\tt new-arch.[ch]}, any context diffs for the rest of the +library and the output of {\tt bm.c} to {\tt jsc@doc.ic.ac.uk}. Also +please let me know where you got the library from. +\end{itemize} +\end{document} diff --git a/src/lib/lwp/queue.c b/src/lib/lwp/queue.c new file mode 100644 index 00000000..1aa5ad48 --- /dev/null +++ b/src/lib/lwp/queue.c @@ -0,0 +1,51 @@ +/* + * queue.c -- queue manipulation routines. + * Copyright (C) 1991-3 Stephen Crane. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * author: Stephen Crane, (jsc@doc.ic.ac.uk), Department of Computing, + * Imperial College of Science, Technology and Medicine, 180 Queen's + * Gate, London SW7 2BZ, England. + */ +#include "lwp.h" +#include "lwpint.h" +#include "prototypes.h" + +#if defined(_EMPTH_LWP) + +struct lwpProc *lwpGetFirst(q) + struct lwpQueue *q; +{ + struct lwpProc *head; + + if ((head = q->head) && !(q->head = head->next)) + q->tail = 0; + return (head); +} + +void lwpAddTail(q, p) + register struct lwpQueue *q; + register struct lwpProc *p; +{ + if (!q->tail) + q->head = p; + else + q->tail->next = p; + q->tail = p; + p->next = 0; +} + +#endif diff --git a/src/lib/lwp/sel.c b/src/lib/lwp/sel.c new file mode 100644 index 00000000..af952694 --- /dev/null +++ b/src/lib/lwp/sel.c @@ -0,0 +1,250 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * sel.c: arrange to block on read/write file descriptors using lwp + * + * Known contributors to this file: + * Dave Pare, 1994 + */ + +#include +#include +#include +#include +#include +#include + +#ifdef hpux +#include +#endif + +#include "bit.h" +#include "lwp.h" +#include "lwpint.h" +#include "prototypes.h" + +#if defined(_EMPTH_LWP) + +struct lwpSelect { + int maxfd; + int nfds; + int nfile; + fd_set readmask; + fd_set writemask; + struct lwpProc **wait; + struct lwpQueue delayq; + struct lwpProc *proc; +}; + +struct lwpSelect LwpSelect; + +void lwpInitSelect(proc) + struct lwpProc *proc; +{ + LwpSelect.maxfd = 0; + LwpSelect.nfds = 0; +#ifdef hpux + LwpSelect.nfile = _NFILE; +#else + LwpSelect.nfile = getdtablesize(); +#endif + FD_ZERO(&LwpSelect.readmask); + FD_ZERO(&LwpSelect.writemask); + LwpSelect.wait = (struct lwpProc **) + calloc(LwpSelect.nfile, sizeof(char *)); + LwpSelect.delayq.head = 0; + LwpSelect.delayq.tail = 0; + LwpSelect.proc = proc; +} + +void lwpSleepFd(fd, mask) + int fd; + int mask; +{ + extern struct lwpProc *LwpCurrent; + + lwpStatus(LwpCurrent, "sleeping on fd %d", fd); + + if (LwpSelect.wait[fd] != 0) { + lwpStatus(LwpCurrent, + "multiple sleeps attempted on file descriptor %d", fd); + return; + } + if (mask & LWP_FD_READ) + FD_SET(fd, &LwpSelect.readmask); + if (mask & LWP_FD_WRITE) + FD_SET(fd, &LwpSelect.writemask); + + LwpSelect.nfds++; + + if (LwpSelect.maxfd == 0 && LwpSelect.delayq.head == 0) { + /* select process is sleeping until first waiter arrives */ + lwpStatus(LwpCurrent, "going to resched fd %d", fd); + lwpReady(LwpSelect.proc); + } + lwpStatus(LwpCurrent, "going to wait on fd %d", fd); + if (fd > LwpSelect.maxfd) + LwpSelect.maxfd = fd; + LwpSelect.wait[fd] = LwpCurrent; + LwpCurrent->fd = fd; + lwpReschedule(); +} + +void lwpWakeupFd(proc) + struct lwpProc *proc; +{ + if (proc->fd < 0) + return; + + lwpStatus(proc, "awakening; was sleeping on fd %d", proc->fd); + FD_CLR(proc->fd, &LwpSelect.readmask); + FD_CLR(proc->fd, &LwpSelect.writemask); + LwpSelect.nfds--; + LwpSelect.wait[proc->fd] = 0; + proc->fd = -1; + lwpReady(proc); +} + +void lwpSleepUntil(until) + long until; +{ + extern struct lwpProc *LwpCurrent; + + lwpStatus(LwpCurrent, "sleeping for %d sec", until - time(0)); + LwpCurrent->runtime = until; + if (LwpSelect.maxfd == 0 && LwpSelect.delayq.head == 0) { + /* select process is sleeping until first waiter arrives */ + lwpReady(LwpSelect.proc); + } + lwpAddTail(&LwpSelect.delayq, LwpCurrent); + lwpReschedule(); +} + +/*ARGSUSED*/ +void +lwpSelect(argc, argv) + int argc; + char **argv; +{ + extern struct lwpProc *LwpCurrent; + struct lwpProc *us = LwpCurrent; + fd_set readmask; + fd_set writemask; + int n; + int fd; + time_t now; + time_t delta; + struct lwpProc *proc; + struct timeval tv; + struct lwpQueue save; + + lwpStatus(us, "starting select loop"); + FD_ZERO(&readmask); + FD_ZERO(&writemask); + while (1) { + while (1) { + if (LwpSelect.nfds) + break; + if (LwpSelect.delayq.head) + break; + /* wait for someone to lwpSleepFd or lwpSleepUntil */ + LwpSelect.maxfd = 0; + lwpStatus(us, "no fds or sleepers, waiting"); + lwpReschedule(); + } + tv.tv_sec = 1000000; + tv.tv_usec = 0; + if (LwpSelect.delayq.head) { + time(&now); + proc = LwpSelect.delayq.head; + for ( ; proc != 0; proc = proc->next) { + delta = proc->runtime - now; + if (delta < tv.tv_sec) + tv.tv_sec = delta; + } + if (tv.tv_sec < 0) + tv.tv_sec = 0; + } + lwpStatus(us, "selecting; sleep %ld secs", (long)delta); + + bcopy((s_char *)&LwpSelect.readmask, (s_char *)&readmask, sizeof(fd_set)); + bcopy((s_char *)&LwpSelect.writemask, (s_char *)&writemask, sizeof(fd_set)); + n = select(LwpSelect.maxfd + 1, &readmask, &writemask, + (fd_set *)0, &tv); + + if (n < 0) { + if (errno == EINTR) { + /* go handle the signal */ + lwpReady(us); + lwpReschedule(); + continue; + } + lwpStatus(us, + "select failed (bad file descriptor?)"); + exit(-1); + } + + if (LwpSelect.delayq.head) { + /* sleeping proecss activity */ + time(&now); + save.tail = save.head = 0; + while (NULL != (proc = lwpGetFirst(&LwpSelect.delayq))) { + if (now >= proc->runtime) { + lwpStatus(proc, "sleep done"); + lwpReady(proc); + } else { + lwpAddTail(&save, proc); + } + } + LwpSelect.delayq = save; + } + if (n > 0) { + /* file descriptor activity */ + for(fd = 0; fd <= LwpSelect.maxfd; fd++) { + if (LwpSelect.wait[fd] == 0) + continue; + if (FD_ISSET(fd, &readmask)) { + lwpStatus(LwpSelect.wait[fd], + "input ready"); + lwpWakeupFd(LwpSelect.wait[fd]); + continue; + } + if (FD_ISSET(fd, &writemask)) { + lwpStatus(LwpSelect.wait[fd], + "output ready"); + lwpWakeupFd(LwpSelect.wait[fd]); + continue; + } + } + } + lwpStatus(us, "fd dispatch completed"); + lwpReady(LwpCurrent); + lwpReschedule(); + } + /*NOTREACHED*/ +} +#endif diff --git a/src/lib/lwp/sem.c b/src/lib/lwp/sem.c new file mode 100644 index 00000000..ee8199ac --- /dev/null +++ b/src/lib/lwp/sem.c @@ -0,0 +1,90 @@ +/* + * lwpSem.c -- lwpSemaphore manipulation. + * Copyright (C) 1991-3 Stephen Crane. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * author: Stephen Crane, (jsc@doc.ic.ac.uk), Department of Computing, + * Imperial College of Science, Technology and Medicine, 180 Queen's + * Gate, London SW7 2BZ, England. + */ +#include +#include + +#include "lwp.h" +#include "lwpint.h" +#include "prototypes.h" + +#if defined(_EMPTH_LWP) + +/* for systems without strdup */ +#ifdef NOSTRDUP +extern char *strdup(); +#endif /* NOSTRDUP */ + +/* + * create a lwpSemaphore. + */ +struct lwpSem *lwpCreateSem(name, count) + char *name; + int count; +{ + struct lwpSem *new; + + if (!(new = (struct lwpSem *)malloc(sizeof(struct lwpSem)))) + return (0); + new->name = strdup(name); + new->count = count; + new->q.head = new->q.tail = 0; + return (new); +} + +/* + * signal a lwpSemaphore. We only yield here if + * the blocked process has a higher priority than ours'. + */ +void lwpSignal(s) + struct lwpSem *s; +{ + extern struct lwpProc *LwpCurrent; + + lwpStatus(LwpCurrent, "done with semaphore %s", s->name); + if (s->count++ < 0) { + struct lwpProc *p = lwpGetFirst(&s->q); + lwpStatus(LwpCurrent, "activating first waiter"); + lwpReady(p); + if (LwpCurrent->pri < p->pri) { + lwpStatus(p, "priority is higher"); + lwpYield(); + } + } +} + +/* + * wait on a lwpSemaphore + */ +void lwpWait(s) + struct lwpSem *s; +{ + extern struct lwpProc *LwpCurrent; + + lwpStatus(LwpCurrent, "checking semaphore %s", s->name); + if (--s->count < 0) { + lwpStatus(LwpCurrent, "blocking"); + lwpAddTail(&s->q, LwpCurrent); + lwpReschedule(); + } +} +#endif diff --git a/src/lib/lwp/status.c b/src/lib/lwp/status.c new file mode 100644 index 00000000..045c3014 --- /dev/null +++ b/src/lib/lwp/status.c @@ -0,0 +1,69 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * status.c: Process and perhaps display status messages + * + * Known contributors to this file: + * Dave Pare, 1994 + */ + +#include +#ifdef BOUNDS_CHECK +#include +#endif +#include "lwp.h" +#include "prototypes.h" + +#if defined(_EMPTH_LWP) + +void lwpStatus(struct lwpProc *proc, char *format, ...) +{ + va_list ap; + static struct timeval startTime; + struct timeval tv; + char buf[1024]; + int sec, msec; + + va_start(ap,format); + if (proc->flags & LWP_PRINT) { + if (startTime.tv_sec == 0) + gettimeofday(&startTime, 0); + gettimeofday(&tv, 0); + sec = tv.tv_sec - startTime.tv_sec; + msec = (tv.tv_usec - startTime.tv_usec) / 1000; + if (msec < 0) { + sec++; + msec += 1000; + } + vsprintf(buf, format, ap); + printf("%d:%02d.%03d %17s[%d]: %s\n", sec/60, sec%60, msec/10, + proc->name, proc->pri, buf); + } + va_end(ap); +} + +#endif diff --git a/src/lib/player/Makefile b/src/lib/player/Makefile new file mode 100644 index 00000000..95bd786a --- /dev/null +++ b/src/lib/player/Makefile @@ -0,0 +1,62 @@ +# +# Empire - A multi-player, client/server Internet based war game. +# Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, +# Ken Stevens, Steve McClure +# +# 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 2 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, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# --- +# +# See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the +# related information and legal notices. It is expected that any future +# projects/authors will amend these files as needed. +# +# Makefile - Wolfpack, 1996 + +# Note that these could have been listed 1 per line, but I chose to just +# stick them all together this way to shorten the file. + +include ../../../build.conf +include ../../make.src +include ../../make.defs + +LIB = $(SRCDIR)/lib/libplayer.a +NTLIB = $(SRCDIR)\lib\libplayer.lib + +OBJS = accept.o dispatch.o empdis.o empmod.o init_nats.o login.o nat.o \ + player.o recvclient.o + +NTOBJS = accept.obj dispatch.obj empdis.obj empmod.obj init_nats.obj \ + login.obj nat.obj player.obj recvclient.obj + +all: $(LIB) + +nt: $(NTLIB) + +$(NTLIB): $(NTOBJS) + -del /q $@ + lib /OUT:$@ /DEBUGTYPE:CV $(NTOBJS) + +$(LIB): $(OBJS) + rm -f $(LIB) + ar cq $(LIB) $(OBJS) + $(RANLIB) $(LIB) + +clean: + -(rm -f $(OBJS)) + -(del /q $(NTOBJS)) + +include ../../make.rules +include Makedepend diff --git a/src/lib/player/accept.c b/src/lib/player/accept.c new file mode 100644 index 00000000..4c50a62d --- /dev/null +++ b/src/lib/player/accept.c @@ -0,0 +1,268 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * accept.c: Keep track of people logged in + * + * Known contributors to this file: + * Dave Pare, 1994 + */ + +#include "prototypes.h" +#include "misc.h" +#include "bit.h" +#include "proto.h" +#include "empthread.h" +#include "player.h" +#include "file.h" +#include "io_mask.h" +#include "empio.h" +#include "power.h" +#include "common.h" +#include "gen.h" +#include "optlist.h" + +#if !defined(_WIN32) +#include +#include +#include +#include +#include +#include +#include +#else +#include +#endif +#include +#include +#include +#include +#include + +struct emp_qelem Players; + +void +player_init(void) +{ + emp_initque(&Players); + init_player_commands(); +} + +struct player * +player_new(int s, struct sockaddr_in *sin) +{ + struct player *lp; + struct hostent *hostp; + + lp = (struct player *) calloc(1, sizeof(struct player)); + bzero((s_char *)lp, sizeof(struct player)); + if (sin) { + /* update uses dummy player */ + /* so does the market updater */ + emp_insque(&lp->queue, &Players); + strcpy(lp->hostaddr, inet_ntoa(sin->sin_addr)); +#ifdef RESOLVE_IPADDRESS + if (NULL != (hostp = gethostbyaddr((char *) &sin->sin_addr, sizeof(sin->sin_addr), AF_INET))) + strcpy(lp->hostname, hostp->h_name); +#endif /* RESOLVE_IPADDRESS */ + lp->cnum = 255; + lp->curid = -1; + time(&lp->curup); + lp->iop = io_open(s, IO_READ|IO_WRITE|IO_NBLOCK, + IO_BUFSIZE, 0, 0); + } + return lp; +} + +struct player * +player_delete(struct player *lp) +{ + struct player *back; + + back = (struct player *) lp->queue.q_back; + if (back) + emp_remque(&lp->queue); + if (lp->iop) { + /* it's a real player */ + io_close(lp->iop); + lp->iop = 0; + } + free((s_char *)lp); + /* XXX may need to free bigmap here */ + return back; +} + +struct player * +player_next(struct player *lp) +{ + if (lp == 0) + lp = (struct player *)Players.q_forw; + else + lp = (struct player *)lp->queue.q_forw; + if (&lp->queue == &Players) + return 0; + return lp; +} + +struct player * +player_prev(struct player *lp) +{ + if (lp == 0) + lp = (struct player *)Players.q_back; + else + lp = (struct player *)lp->queue.q_back; + if (&lp->queue == &Players) + return 0; + return lp; +} + +struct player * +getplayer(natid cnum) +{ + register struct emp_qelem *qp; + + for (qp = Players.q_forw; qp != &Players; qp = qp->q_forw) + if (((struct player *)qp)->cnum == cnum) + return (struct player *)qp; + + return 0; +} + +struct player * +player_find_other(struct player *us, register natid cnum) +{ + register struct emp_qelem *qp; + + for (qp = Players.q_forw; qp != &Players; qp = qp->q_forw) + if (((struct player *)qp)->cnum == cnum && + ((struct player *)qp != us) && + (((struct player *)qp)->state == PS_PLAYING)) + return (struct player *)qp; + + + return 0; +} + +void +player_wakeup_all(natid cnum) +{ + register struct player *lp; + + if (NULL != (lp = getplayer(cnum))) + player_wakeup(lp); +} + +void +player_wakeup(struct player *pl) +{ + if (pl->waiting) + empth_wakeup(pl->proc); +} + +/*ARGSUSED*/ +void +player_accept(void *argv) +{ + extern s_char *loginport; + extern int errno; + struct sockaddr_in sin; + struct servent *sp; + int s; + short port; + int val; + int maxfd; + struct player *np; + int len; + int ns; + int set = 1; + int stacksize; + char buf[128]; + + player_init(); + sp = getservbyname("empire", "tcp"); + if (sp == 0) + port = htons(atoi(loginport)); + else + port = sp->s_port; + sin.sin_addr.s_addr = INADDR_ANY; + sin.sin_port = port; + sin.sin_family = AF_INET; + if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) { + logerror("inet socket create"); + exit(1); + } + val = 1; +#if !(defined(__linux__) && defined(__alpha__)) + if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&val, sizeof(val)) < 0) { + logerror("inet socket setsockopt SO_REUSEADDR (%d)", errno); + exit(1); + } +#else + logerror("Alpha/Linux? You don't support SO_REUSEADDR yet, do you?\n"); +#endif + if (bind(s, (struct sockaddr *) &sin, sizeof(sin)) < 0) { + logerror("inet socket bind"); + exit(1); + } +#ifdef LISTENMAXCONN /* because someone in linux world didn't want to use + * SOMAXCONN as defined in the header files... */ + if (listen(s, LISTENMAXCONN) < 0) { + logerror("inet socket listen"); + exit(1); + } +#else + if (listen(s, SOMAXCONN) < 0) { + logerror("inet socket listen"); + exit(1); + } +#endif + maxfd = getfdtablesize() - 1; + while (1) { + empth_select(s, EMPTH_FD_READ); + len = sizeof(sin); + ns = accept(s, (struct sockaddr *) &sin, &len); + if (ns < 0) { + logerror("new socket accept"); + continue; + } + (void) setsockopt(ns, SOL_SOCKET, SO_KEEPALIVE, + (char *) &set, sizeof(set)); + if (ns >= maxfd) { + logerror("new fd %d, max %d, no fd's left for new user", + ns, maxfd); + close(ns); + continue; + } + np = player_new(ns, &sin); + /* XXX may not be big enough */ + stacksize = 100000 +/* budget */ + max(WORLD_X*WORLD_Y/2 * sizeof(int) * 7, +/* power */ MAXNOC * sizeof(struct powstr)); + sprintf(buf, "Player (fd #%d)", ns); + empth_create(PP_PLAYER, player_login, stacksize, + 0, buf, "Empire player", np); + } +} diff --git a/src/lib/player/dispatch.c b/src/lib/player/dispatch.c new file mode 100644 index 00000000..3e2ceecf --- /dev/null +++ b/src/lib/player/dispatch.c @@ -0,0 +1,114 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * dispatch.c: Actually execute the command given + * + * Known contributors to this file: + * Dave Pare, 1994 + * Steve McClure, 1998 + */ + +#include "prototypes.h" +#include "misc.h" +#include "player.h" +#include "com.h" +#include "user.h" +#include "match.h" +#include "nat.h" +#include "file.h" +#include "proto.h" +#include "empio.h" +#include "optlist.h" +#include "subs.h" +#include "common.h" + +int +dispatch(s_char *buf, s_char *redir) +{ + extern struct cmndstr player_coms[]; + extern int update_pending; + extern int max_btus; + struct natstr *np; + struct cmndstr *command; + int cmd; + + cmd = comtch(player->argp[0], player_coms, + player->ncomstat, player->god); + if (cmd < 0) { + if (cmd == M_NOTUNIQUE) + pr("\"%s\" is ambiguous -- ", buf); + else if (cmd == M_IGNORE) + return 0; + else { + pr("\"%s\" is not a legal command ", buf); + if (player->nstat != player->ncomstat) + pr("now "); + pr("\n"); + } + return -1; + } + command = &player_coms[cmd]; + np = getnatp(player->cnum); + if (np->nat_btu < command->c_cost && command->c_cost > 0) { + if (player->god || opt_BLITZ) + np->nat_btu = max_btus; + else { + pr("You don't have the BTU's, bozo\n"); + return 0; + } + } + if (command->c_addr == 0) { + pr("Command not implemented\n"); + return 0; + } + if (update_pending) { + pr("Update in progress...command failed\n"); + return 0; + } + if (redir) { + prredir(redir); + pr("%s\n", buf); + } + player->command = command; + switch (command->c_addr()) { + case RET_OK: + player->btused += command->c_cost; + break; + case RET_FAIL: + pr("command failed\n"); + player->btused += command->c_cost; + break; + case RET_SYN: + pr("Usage: %s\n", command->c_form); + break; + default: + logerror("%s: returned bad value", command->c_form); + break; + } + player->command = 0; + return 0; +} diff --git a/src/lib/player/empdis.c b/src/lib/player/empdis.c new file mode 100644 index 00000000..3c54dcdd --- /dev/null +++ b/src/lib/player/empdis.c @@ -0,0 +1,234 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * empdis.c: Empire dispatcher stuff + * + * Known contributors to this file: + * Dave Pare, 1994 + * Steve McClure, 2000 + */ + +#include "prototypes.h" +#include +#include "misc.h" +#include "player.h" +#include "nat.h" +#include "tel.h" +#include "proto.h" +#include "com.h" +#include "deity.h" +#include "keyword.h" +#include "file.h" +#include "empio.h" +#include "subs.h" +#include "common.h" + +#include +#ifdef Rel4 +#include +#endif /* Rel4 */ +#if !defined(_WIN32) +#include +#include +#endif +#include + +#define KEEP_COMMANDS 50 +s_char player_commands[KEEP_COMMANDS][1024 + 8]; +int player_commands_index = 0; + +int +getcommand(s_char *combufp) +{ + struct natstr *natp; + s_char buf[1024]; + +/* Note this now assumes a 1024 byte buffer is being passed in */ + natp = getnatp(player->cnum); + if (++player_commands_index >= KEEP_COMMANDS) + player_commands_index = 0; + sprintf(player_commands[player_commands_index], "%3d %3d [prompt]", + player_commands_index, player->cnum); + do { + prprompt(natp->nat_minused, natp->nat_btu); + buf[0] = 0; + if (recvclient(buf, 1024) < 0) { + return -1; + } + } while (buf[0] == 0); + if (++player_commands_index >= KEEP_COMMANDS) + player_commands_index = 0; + sprintf(player_commands[player_commands_index], "%3d %3d %s", + player_commands_index, player->cnum, buf); + copy(buf, combufp); + return (strlen(combufp)); +} + +void +init_player_commands(void) +{ + int i; + + for (i = 0; i < KEEP_COMMANDS; ++i) + *player_commands[i] = 0; +} + +void +log_last_commands(void) +{ + int i; + + logerror("Most recent player commands:"); + for (i = player_commands_index; i >=0; --i) + if (*player_commands[i]) + logerror("%s", player_commands[i]+4); + for (i = KEEP_COMMANDS - 1; i > player_commands_index; --i) + if (*player_commands[i]) + logerror("%s", player_commands[i]+4); +} + +int +explain(void) +{ + extern struct cmndstr player_coms[]; + register s_char *format; + register int i; + + pr("\t\tCurrent EMPIRE Command List\n"); + pr("\t\t------- ------ ------- ----\n"); + pr("Initial number is cost in B.T.U. units.\n"); + pr("Next 2 chars (if present) are:\n"); + pr("$ - must be non-broke\tc -- must have capital\n"); + pr("Args in [brackets] are optional.\n"); + if (player->nstat > 4) { + pr("All-caps args in "); + pr(" have the following meanings:\n"); + pr(" :: a number in unspecified units\n"); + pr(" :: a commodity such as `food', `guns', etc\n"); + pr(" :: a commodity such as `food', `guns', etc\n"); + pr(" :: an item type such as `ship', `plane', etc\n"); + } + for (i = 0; (format = player_coms[i].c_form) != 0; i++) { + if ((player_coms[i].c_permit & player->ncomstat) == player_coms[i].c_permit){ + pr("%2d ", player_coms[i].c_cost); + if ((player_coms[i].c_permit & MONEY) == MONEY) + pr("$"); + else + pr(" "); + if ((player_coms[i].c_permit & CAP) == CAP) + pr("c"); + else + pr(" "); + pr(" %s\n", format); + } + } + pr("For further info on command syntax see \"info Syntax\".\n"); + return RET_OK; +} + +/* + * returns true if down + */ +int +gamedown(void) +{ + extern s_char *downfil; + int downf; + struct telstr tgm; + s_char buf[1024]; + + if (player->god) + return 0; +#if !defined(_WIN32) + if ((downf = open(downfil, O_RDONLY, 0)) < 0) +#else + if ((downf = open(downfil, O_RDONLY|O_BINARY, 0)) < 0) +#endif + return 0; + if (read(downf, (s_char *) &tgm, sizeof(tgm)) != sizeof(tgm)) { + logerror("bad header on login message (downfil)"); + close(downf); + return 1; + } + if (read(downf, buf, tgm.tel_length) != tgm.tel_length) { + logerror("bad length %d on login message", tgm.tel_length); + close(downf); + return 1; + } + if (tgm.tel_length >= (long)sizeof(buf)) + tgm.tel_length = sizeof(buf)-1; + buf[tgm.tel_length] = 0; + pr(buf); + pr("\nThe game is down\n"); + (void) close(downf); + return 1; +} + +void +daychange(time_t now) +{ + struct natstr *natp; + struct tm *tm; + + natp = getnatp(player->cnum); + tm = localtime(&now); + if ((tm->tm_yday % 128) != natp->nat_dayno) { + natp->nat_dayno = tm->tm_yday % 128; + natp->nat_minused = 0; + } +} + +int +getminleft(time_t now, int *hour, int *mpd) +{ + s_char *bp; + struct tm *tm; + int nminleft; + int curtime; + struct natstr *natp; + int n; + + tm = localtime(&now); + curtime = tm->tm_min + tm->tm_hour * 60; + if (NULL != (bp = kw_find("minutes"))) + kw_parse(CF_VALUE, bp, mpd); + natp = getnatp(player->cnum); + nminleft = *mpd - natp->nat_minused; + if (NULL != (bp = kw_find("hours"))) { + /* + * assume hours has already been set; just verify + * that it is present + */ + n = hour[1] - curtime; + if (n < nminleft) + nminleft = n; + } + n = 60*24 - (tm->tm_min + tm->tm_hour*60); + if (n < nminleft) + nminleft = n; + return nminleft; +} diff --git a/src/lib/player/empmod.c b/src/lib/player/empmod.c new file mode 100644 index 00000000..24b28700 --- /dev/null +++ b/src/lib/player/empmod.c @@ -0,0 +1,433 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * empmod.c: List all commands for Empire + * + * Known contributors to this file: + * Dave Pare, 1986 + * Jeff Bailey + * Thomas Ruschak, 1992 + * Ken Stevens, 1995 + * Steve McClure, 1996-2000 + */ + +#include "misc.h" +#include "com.h" +#include "nat.h" +#include "file.h" + +extern int add(); +extern int anti(); +extern int assa(); +extern int atta(); +extern int boar(); +extern int bdes(); +extern int bomb(); +extern int buil(); +extern int chan(); +extern int coas(); +extern int comm(); +extern int coun(); +extern int decl(); +extern int deli(); +extern int show(); +extern int show_motd(void); +extern int desi(); +extern int diss(); +extern int drop(); +extern int echo(void); +extern int enli(); +extern int fire(); +extern int flee(); +extern int fly(); +extern int force(); +extern int info(); +extern int apro(); +extern int load(); +extern int look(); +extern int map(); +extern int mine(); +extern int move(); +extern int nati(); +extern int navi(); +extern int head(), news(); +extern int nuke(); +extern int offs(); +extern int para(); +extern int path(); +extern int payo(); +extern int powe(); +extern int rada(); +extern int rea(); +extern int real(); +extern int reco(); +extern int rout(); +extern int sona(); +extern int spy(); +extern int tele(); +extern int tend(); +extern int torp(); +extern int tran(); +extern int trea(); +extern int turn(); +extern int vers(); +/* + * new commands + */ +extern int repo(); +extern int laun(); +extern int new(); +extern int shoo(); +extern int thre(); +extern int dist(); +extern int sct(); +extern int plan(); +extern int arm(); +extern int hard(); +extern int upgr(); +extern int surv(); +extern int capi(); +extern int orig(); +extern int conv(); +extern int leve(); +extern int cuto(); +extern int prod(); +extern int wai(); +extern int carg(); +extern int terr(); +extern int sate(); +extern int give(); +extern int edit(); +extern int wipe(); +extern int dump(); +extern int ldump(); +extern int ndump(); +extern int pdump(); +extern int pboa(); +extern int sdump(); +extern int lost(); +extern int explore(); +extern int reso(); +extern int scra(); +extern int rela(); +extern int brea(); +extern int upda(); +extern int hidd(); +extern int orde(); +extern int qorde(); +extern int sorde(); +extern int reje(); +extern int acce(); +extern int sabo(); +extern int scut(); +extern int grin(); +extern int shar(); +extern int sail(); /* Forsman's hacks */ +extern int foll(); /**/ +extern int mobq(); /**/ +extern int name(); +extern int range(); +extern int zdon(); +extern int fuel(); +extern int multifire(); +extern int retr(); +extern int budg(); +extern int wire(); +extern int stop(); +extern int start(); + +extern int land(); +extern int supp(); +extern int lboa(); +extern int lcarg(); +extern int lload(); +extern int army(); +extern int lrange(); +extern int morale(); +extern int lretr(); +extern int landmine(); +extern int fort(); +extern int march(); +extern int llook(); +extern int mission(); +extern int work(); +extern int ltend(); +extern int cede(); +extern int best(); +extern int newe(); +extern int starve(); + +extern int setres(); +extern int setsector(); + +extern int disa(); +extern int enab(); + +/* + * Undeclared functions + */ +extern int quit(void); +extern int cens(); +extern int demo(); +extern int shi(); +extern int wing(); +extern int execute(void); +extern int explain(void); +extern int set(); +extern int flash(void); +extern int wall(); +extern int shut(); +extern int togg(); +extern int stre(); +extern int skyw(); +extern int play(); +extern int swaps(); + +extern int trad(); +extern int mark(); +extern int buy(); +extern int mult(); +extern int sell(); +extern int rese(); + +extern int repa(); +extern int fina(); +extern int coll(); +extern int cons(); +extern int ledg(); +extern int shark(); +extern int offe(); + +extern int mobupdate(); + +extern int sinfra(); +extern int improve(); +extern int lstats(); +extern int pstat(); +extern int sstat(); + +struct cmndstr player_coms[] = { +/* command form cost addr permit */ +{ "accept [as-COUNTRY]", 0, acce, C_MOD, NORM }, +{ "add ",0, add, C_MOD, GOD }, +{ "announce {message}", 0, tele, C_MOD, VIS }, +{ "anti ", 3, anti, C_MOD, NORM+MONEY+CAP }, +{ "apropos ", 0, apro, 0, VIS }, +{ "arm ", 3, arm, C_MOD, NORM+MONEY+CAP }, +{ "army ", 0, army, C_MOD, NORM }, +{ "assault [ ]",3,assa,C_MOD, NORM+MONEY+CAP }, +{ "attack [ ]",3,atta,C_MOD, NORM+MONEY+CAP }, +{ "bdes ", 0, bdes, C_MOD, NORM }, +{ "bestpath ", 0, best, 0, NORM }, +{ "bestdistpath ", 0, best, 0, NORM }, +{ "bmap [s|l|p|r|t*]", 0, map, C_MOD, NORM }, +{ "board [|]", 3, boar, C_MOD, NORM+MONEY+CAP }, +{ "bomb ",2,bomb,C_MOD, NORM+MONEY+CAP }, +{ "break {sanctuary}", 1, brea, C_MOD, SANCT }, +{ "budget [ ]",1,budg,0, NORM }, +{ "build [ ]",1, buil, C_MOD, NORM+MONEY+CAP }, +{ "buy ", 1, buy, C_MOD, CAP+NORM+MONEY }, +{ "bye {log-off}", 0, quit, 0, VIS }, +{ "capital ", 0, capi, C_MOD, NORM }, +{ "cargo ", 0, carg, 0, NORM }, +#ifdef CEDE_IS_ALLOWED +{ "cede [se|sh]", 639, cede, C_MOD, NORM }, +#endif /* CEDE_IS_ALLOWED */ +{ "census ", 0, cens, 0, VIS }, +{ "change ",0, chan, C_MOD, VIS }, +{ "coastwatch ", 1, coas, C_MOD, NORM+CAP }, +{ "collect ", 2, coll, C_MOD, NORM+MONEY+CAP }, +{ "commodity ", 0, comm, 0, VIS }, +{ "consider ",1,cons,C_MOD, NORM+CAP }, +{ "convert [sure?]", 2, conv, C_MOD, NORM+MONEY+CAP }, +{ "country ", 0, coun, 0, NORM }, +{ "cutoff ", 0, cuto, C_MOD, NORM }, +{ "declare ", 2, decl, C_MOD, NORM+CAP }, +{ "deliver [q|] [

]",1, deli, C_MOD, NORM }, +{ "demobilize [sure?]",1, demo, C_MOD, NORM+CAP }, +{ "designate [sure?]", 1, desi, C_MOD, NORM }, +{ "disable", 0, disa, C_MOD, GOD }, +{ "disarm ", 2, arm, C_MOD, NORM+MONEY+CAP }, +{ "dissolve ", 0, diss, C_MOD, GOD }, +{ "distribute ", 1, dist, C_MOD, NORM }, +{ "drop ",1,drop,C_MOD, NORM+MONEY+CAP }, +{ "dump []", 0, dump, 0, NORM }, +{ "echo []", 0, echo, 0, NORM }, +{ "edit ", 0, edit, C_MOD, GOD }, +{ "enable", 0, enab, C_MOD, GOD }, +{ "enlist ", 2, enli, C_MOD, NORM+MONEY+CAP }, +{ "execute ", 0, execute,0, VIS }, +{ "explore ",1,explore, C_MOD, NORM+MONEY+CAP }, +{ "financial", 0, fina, 0, NORM }, +{ "fire [TO-SECT | SHIP]",1,multifire,C_MOD, NORM+MONEY+CAP }, +{ "flash []", 0, flash, 0, VIS }, +{ "fleetadd ", 0, flee, C_MOD, NORM }, +{ "fly ",2,fly,C_MOD, NORM+MONEY+CAP }, +{ "follow ", 1, foll, C_MOD, NORM+CAP }, +{ "force ", 0, force, C_MOD, GOD }, +{ "fortify ", 1, fort, C_MOD, NORM }, +{ "fuel []", 1, fuel, C_MOD, NORM }, +{ "give ", 0, give, C_MOD, GOD }, +{ "grind ", 1, grin, C_MOD, NORM+MONEY+CAP }, +{ "harden ", 2, hard, C_MOD, NORM+MONEY+CAP }, +{ "help ", 0, info, 0, VIS }, +{ "headlines [days]", 0, head, C_MOD, VIS }, +{ "hidden ", 0, hidd, 0, GOD }, +{ "improve ",1, improve,C_MOD, NORM+MONEY+CAP }, +{ "info ", 0, info, 0, VIS }, +{ "land ", 0, land, C_MOD, NORM }, +{ "launch ", 3, laun, C_MOD, NORM+MONEY+CAP }, +{ "lboard []", 3, lboa, C_MOD, NORM+MONEY+CAP }, +{ "lcargo ", 0, lcarg, 0, NORM }, +{ "ledger ", 0, ledg, 0, NORM }, +{ "level ", 0, leve, 0, NORM }, +{ "list of commands", 0, explain,0, VIS }, +{ "lbmap [s|l|p|*]", 0, map, C_MOD, NORM }, +{ "ldump []", 0, ldump, 0, NORM }, +{ "lload ",1, lload, C_MOD, NORM+CAP }, +{ "llookout ", 1, llook, 0, NORM+CAP }, +{ "lmap [s|l|p|*]", 0, map, C_MOD, NORM }, +{ "lmine ", 2, landmine,C_MOD, NORM+MONEY+CAP }, +{ "load ",1,load,C_MOD, NORM+CAP }, +{ "lookout ", 1, look, 0, NORM+CAP }, +{ "lost", 0, lost, 0, NORM }, +{ "lradar ", 1, rada, 0, NORM+CAP }, +{ "lrange ", 1, lrange, C_MOD, NORM+CAP }, +{ "lretreat [i|h|b|c]", 1, lretr, C_MOD, NORM+CAP }, +{ "lstats ", 0, lstats, C_MOD, NORM }, +{ "ltend ",1, ltend, C_MOD, NORM+CAP }, +{ "lunload ",1,lload, C_MOD, NORM+CAP }, +{ "market [COMM]", 0, mark, 0, VIS }, +{ "map ", 0, map, C_MOD, VIS }, +{ "march ", 1, march, C_MOD, NORM+CAP }, +{ "mine ", 2, mine, C_MOD, NORM+MONEY+CAP }, +{ "mission []", 2,mission,C_MOD, NORM+CAP }, +{ "mobupdate ", 0, mobupdate, C_MOD, GOD }, +{ "morale ", 1, morale, C_MOD, NORM+CAP }, +{ "motd", 0, show_motd, C_MOD, VIS }, +{ "move ",1,move,C_MOD, NORM+CAP }, +{ "mquota ", 2, mobq, C_MOD, NORM+CAP }, +{ "mult [COUNTRY]", 1, mult, C_MOD, GOD }, +{ "name ", 0, name, C_MOD, NORM }, +{ "nation", 0, nati, 0, VIS }, +{ "navigate ", 1, navi, C_MOD, NORM+CAP }, +{ "ndump ", 0, ndump, 0, NORM }, +{ "newcap []", 0, new, C_MOD, GOD }, +{ "neweff ", 0, newe, C_MOD, NORM }, +{ "newspaper [days]", 0, news, 0, VIS }, +{ "nmap ", 0, map, C_MOD, VIS }, +{ "nuke ", 0, nuke, 0, NORM }, +{ "offer [ ]",1,offe,C_MOD, NORM+MONEY+CAP }, +{ "offset ", 0, offs, C_MOD, GOD }, +{ "order ", 1, orde, C_MOD, NORM+CAP }, +{ "origin ", 1, orig, C_MOD, NORM }, +{ "paradrop ",3,para,C_MOD, NORM+MONEY+CAP }, +{ "path ", 0, path, 0, NORM }, +{ "payoff ", 0, payo, C_MOD, NORM }, +{ "pbmap [s|l|p|*]", 0, map, C_MOD, NORM }, +{ "pboard ", 3, pboa, C_MOD, NORM+MONEY+CAP }, +{ "pdump []", 0, pdump, 0, NORM }, +{ "plane ", 0, plan, 0, NORM }, +{ "players", 0, play, 0, VIS }, +{ "pmap [s|l|p|*]", 0, map, C_MOD, NORM }, +{ "power [[\"new\" []] | [\"country\" ]]", 0, powe, C_MOD, VIS }, +{ "pray", 0, tele, C_MOD, NORM }, +{ "production ", 0, prod, 0, NORM }, +{ "pstat ", 0, pstat, 0, NORM }, +{ "qorder ", 0, qorde, C_MOD, NORM+CAP }, +{ "quit", 0, quit, 0, VIS }, +{ "radar ", 1, rada, 0, NORM+CAP }, +{ "range ", 1, range, C_MOD, NORM+CAP }, +{ "read", 0, rea, C_MOD, VIS }, +{ "realm []", 0, real, C_MOD, NORM }, +{ "recon ",3,reco,C_MOD, NORM+MONEY+CAP }, +{ "retreat [i|t|s|h|b|d|u|c]", 1,retr, C_MOD, NORM+CAP }, +{ "relations [as-COUNTRY]", 0, rela, 0, VIS }, +{ "reject ",2,reje,C_MOD, NORM }, +{ "repay ", 1, repa, C_MOD, NORM+MONEY+CAP }, +{ "report ", 0, repo, 0, VIS }, +{ "reset <0|price>", 1, rese, C_MOD, NORM+CAP }, +{ "resource ", 0, reso, 0, NORM }, +{ "route ", 1, rout, 0, NORM }, +{ "sabotage ", 1, sabo, C_MOD, NORM+MONEY+CAP }, +{ "sail ", 1, sail, C_MOD, NORM+CAP }, +{ "satellite [ [?cond&cond&...]]",1, sate, 0, NORM+MONEY+CAP }, +{ "sbmap [s|l|p|*]", 0, map, C_MOD, NORM }, +{ "scrap ", 2, scra, C_MOD, NORM+MONEY+CAP }, +{ "scuttle ", 5, scut, C_MOD, NORM+CAP }, +{ "sdump []", 0, sdump, 0, NORM }, +{ "sect ", 0, sct, 0, NORM }, +{ "sell ", 1, sell, C_MOD, NORM+CAP }, +{ "set ", 1, set, C_MOD, NORM+CAP }, +{ "setsector ", 0, setsector,C_MOD, GOD }, +{ "setresource ", 0, setres, C_MOD, GOD }, +{ "shark ", 25, shark, C_MOD, NORM+MONEY+CAP }, +{ "sharebmap []", 0, shar, C_MOD, NORM }, +{ "ship ", 0, shi, 0, NORM }, +{ "shoot ", 3, shoo, C_MOD, NORM+MONEY+CAP }, +{ "show <\"build\"|\"stats\"|\"cap\"> []", 0,show, 0, VIS }, +{ "shutdown [] ", 0, shut, 0, GOD }, +{ "sinfrastructure ", 0, sinfra, 0, VIS }, +{ "skywatch ", 1, skyw, C_MOD, NORM+CAP }, +{ "smap [s|l|p|*]", 0, map, C_MOD, NORM }, +{ "sonar ", 1, sona, C_MOD, NORM+CAP }, +{ "sorder ", 0, sorde, C_MOD, NORM+CAP }, +{ "spy ", 1, spy, C_MOD, NORM+CAP }, +{ "sstat ", 0, sstat, 0, NORM }, +{ "start ", 1, start, C_MOD, NORM+CAP }, +{ "starvation [|l |s ]", 0, starve, 0, NORM }, +{ "stop ", 1, stop, C_MOD, NORM+CAP }, +{ "strength ", 1, stre, C_MOD, NORM }, +{ "supply ", 1, supp, C_MOD, NORM+CAP }, +{ "survey ", 0, surv, 0, NORM+CAP }, +{ "swapsector ", 0, swaps, C_MOD, GOD }, +{ "sweep ",3,reco,C_MOD, NORM+MONEY+CAP }, +{ "telegram ", 0, tele, C_MOD, NORM }, +{ "tend ",1,tend, C_MOD, NORM+CAP }, +{ "territory []", 0, terr, C_MOD, NORM }, +{ "test ",1,move,0, NORM+CAP }, +{ "threshold ", 1, thre, C_MOD, NORM }, +{ "toggle [inform|flash|beep|coastwatch|sonar|techlists] [on|off]", 0, togg, C_MOD, VIS }, +{ "torpedo ",3, torp, C_MOD, NORM+MONEY+CAP }, +{ "trade", 1, trad, C_MOD, NORM+CAP+MONEY }, +{ "transport <\"nuke\"|\"plane\"> [ ] ",1,tran,C_MOD, NORM+CAP }, +{ "treaty ", 0, trea, 0, NORM+MONEY+CAP }, +{ "turn <\"on\"|\"off\"|\"mess\">", 0, turn, C_MOD, GOD }, +{ "unload ",1,load,C_MOD, NORM+CAP }, +{ "unsail ", 1, sail, C_MOD, NORM+CAP }, +{ "update", 0, upda, 0, VIS }, +{ "upgrade ", 1, upgr, C_MOD, NORM+MONEY+CAP }, +{ "version", 0, vers, 0, VIS }, +{ "wait", 0, wai, C_MOD, GOD }, +{ "wall []", 0, wall, C_MOD, NORM }, +{ "wingadd ", 1, wing, C_MOD, NORM }, +{ "wipe ", 1, wipe, C_MOD, NORM }, +{ "wire [yes|no|]", 0, rea, C_MOD, VIS }, +{ "work ", 1, work, C_MOD, NORM+MONEY+CAP }, +{ "zdone ", 0, zdon, C_MOD, NORM }, +{ 0, 0, 0, 0, 0 } +}; diff --git a/src/lib/player/init_nats.c b/src/lib/player/init_nats.c new file mode 100644 index 00000000..5f92b460 --- /dev/null +++ b/src/lib/player/init_nats.c @@ -0,0 +1,133 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * init_nats.c: Initialize country and nation file stuff + * + * Known contributors to this file: + * Dave Pare, 1994 + * Steve McClure, 2000 + */ + +#include "prototypes.h" +#include "misc.h" +#include "player.h" +#include "var.h" +#include "sect.h" +#include "nat.h" +#include "file.h" +#include "deity.h" +#include "optlist.h" +#include "common.h" +#include "gen.h" + +int +init_nats(void) +{ + struct natstr *np; + + if ((np = getnatp(player->cnum)) == 0) + return -1; + player->nstat = np->nat_stat; + player->god = np->nat_stat & STAT_GOD; + player->map = ef_ptr(EF_MAP, player->cnum); + player->bmap = ef_ptr(EF_BMAP, player->cnum); + if (opt_HIDDEN) { + putcontact(np, player->cnum, FOUND_SPY); + } + if (np->nat_money <= 0) + player->broke = 1; + else { + player->nstat |= MONEY; + player->broke = 0; + } + if (nat_cap(np->nat_btu) < 0) + return -1; + return 0; +} + +int +nat_cap(int btu) +{ + extern int s_p_etu; + extern int max_btus; + extern float btu_build_rate; + struct sctstr sect; + struct natstr *np; + double d; + double civ; + int delta; + + np = getnatp(player->cnum); + if (!getsect(np->nat_xcap, np->nat_ycap, §)) { + logerror("can't read %s's cap @ %d,%d", + np->nat_cnam, np->nat_xcap, np->nat_ycap); + return -1; + } + if ((player->nstat & NORM) == NORM) { + if (player->owner && (sect.sct_type == SCT_CAPIT || + sect.sct_type == SCT_MOUNT || + sect.sct_type == SCT_SANCT)) + player->nstat |= CAP; + else + player->nstat &= ~CAP; + /* Ok, has the country owner reset his capital yet after it was sacked? */ + if (np->nat_flags & NF_SACKED) + player->nstat &= ~CAP; /* No capital yet */ + } + delta = 0; + if ((player->nstat & CAP) || player->god) { + d = (double) (player->curup - np->nat_last_login) / s_p_etu; + if (d > 336.0) + d = 336.0; + civ = getvar(V_CIVIL, (caddr_t)§, EF_SECTOR); + if (civ > 999) + civ = 999; + if ((sect.sct_effic) && (sect.sct_type != SCT_MOUNT)) + delta=roundavg(d*civ*sect.sct_effic*btu_build_rate); + else /* Assume 1/2% efficiency minimum */ + delta=roundavg(d*civ*btu_build_rate/2.0); + if (player->god) + delta = max_btus - btu; + if (delta + btu > max_btus) + delta = max_btus - btu; + if (btu > max_btus) + delta = max_btus - btu; + if (opt_BLITZ) + delta = max_btus - btu; + + if (delta > 0) { + /* set date if BTUs made */ + np->nat_btu += delta; + } + if (btu > max_btus) + np->nat_btu = max_btus; + } + if (np->nat_stat == VIS) + np->nat_btu = max_btus; + putnat(np); + return 0; +} diff --git a/src/lib/player/login.c b/src/lib/player/login.c new file mode 100644 index 00000000..2bc15df1 --- /dev/null +++ b/src/lib/player/login.c @@ -0,0 +1,327 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * login.c: Allow the player to login + * + * Known contributors to this file: + * Dave Pare, 1994 + * Steve McClure, 2000 + */ + +#ifdef Rel4 +#include +#endif /* Rel4 */ +#include "prototypes.h" +#include "misc.h" +#include "proto.h" +#include "player.h" +#include "com.h" +#include "empthread.h" +#include "empio.h" +#include "nsc.h" +#include "nat.h" +#include "optlist.h" +#include "file.h" +#include "subs.h" +#include "common.h" +#include "gen.h" + +#ifdef aix +#include +#endif /* aix */ +#if !defined(_WIN32) +#include +#endif +#include + +struct cmndstr login_coms[]; + + +/*ARGSUSED*/ +void +player_login(void *ud) +{ + s_char buf[128]; + s_char space[512]; + s_char *av[64]; + int ac; + int cmd; + + player->proc = empth_self(); + + pr_id(player, C_INIT, "Empire server ready\n"); + + while (!io_eof(player->iop) && !io_error(player->iop)) { + io_output(player->iop, IO_WAIT); + if (io_gets(player->iop, buf, sizeof(buf)) < 0) { + io_input(player->iop, IO_WAIT); + continue; + } + ac = parse(buf, av, 0, space, 0); + cmd = comtch(av[0], login_coms, 0, 0); + if (cmd < 0) { + pr_id(player, C_BADCMD, "Command %s not found\n", av[0]); + continue; + } + switch (login_coms[cmd].c_addr(player, ac, av)) { + case RET_OK: + break; + case RET_FAIL: + break; + case RET_SYN: + pr_id(player, C_BADCMD, "Usage %s\n", login_coms[cmd].c_form); + break; + default: + break; + } + if (player->state >= PS_SHUTDOWN) + break; + } + player->state = PS_SHUTDOWN; + if (!io_eof(player->iop)) { + (void) pr_player(player, C_EXIT, "so long...\n"); + io_noblocking(player->iop, 0); + while (io_output(player->iop, IO_WAIT) > 0) + ; + } + player_delete(player); + empth_exit(); + /*NOTREACHED*/ +} + +int +client_cmd(struct player *player, int ac, char **av) +{ + int i; + + if (ac < 1 || av[1] == '\0') + return RET_SYN; + + for (i = 1; i < ac; ++i) { + if (i > 1) + (void) strncat(player->client, " ", sizeof(player->client)-1); + (void) strncat(player->client, av[i], sizeof(player->client)-1); + } + player->client[sizeof(player->client)-1] = '\0'; + pr_id(player, C_CMDOK, "talking to %s\n", player->client); + return RET_OK; +} + +int +user_cmd(struct player *player, int ac, char **av) +{ + if (ac < 1 || av[1] == '\0') + return RET_SYN; + (void) strncpy(player->userid, av[1], sizeof(player->userid)-1); + player->userid[sizeof(player->userid)-1] = '\0'; + pr_id(player, C_CMDOK, "hello %s\n", player->userid); + return RET_OK; +} + +int +sanc_cmd(struct player *player, int ac, char **av) +{ + struct nstr_item ni; + struct natstr nat; + int first = 1; + + if (!opt_BLITZ) { + pr_id(player, C_BADCMD, "Command %s not found\n", av[0]); + return RET_FAIL; + } + + snxtitem_all(&ni, EF_NATION); + while (nxtitem(&ni, (s_char *)&nat)) { + if (nat.nat_stat != (STAT_INUSE|STAT_SANCT)) + continue; + if (first) { + pr_id(player, C_DATA, "The following countries are still in sanctuary:\n"); + first = 0; + } + pr_id(player, C_DATA, "%s\n", nat.nat_cnam); + } + if (first) + pr_id(player, C_CMDOK, "There are no countries in sanctuary\n"); + else + pr_id(player, C_CMDOK, "\n"); + return RET_OK; +} + +int +coun_cmd(struct player *player, int ac, char **av) +{ + natid cnum; + + if (ac < 1 || av[1] == '\0') + return RET_SYN; + if (natbyname(av[1], &cnum) < 0) { + pr_id(player, C_CMDERR, "country %s does not exist\n",av[1]); + return 0; + } + player->cnum = cnum; + player->validated = 0; + pr_id(player, C_CMDOK, "country name %s\n", av[1]); + return 0; +} + +int +pass_cmd(struct player *player, int ac, char **av) +{ + if (ac < 1 || av[1] == '\0') + return RET_SYN; + if (player->cnum == 255) { + pr_id(player, C_CMDERR, "need country first\n"); + return RET_FAIL; + } + if (!natpass(player->cnum, av[1])) { + pr_id(player, C_CMDERR, "password bad, logging entry\n"); + logerror("%s tried country #%d with %s", + praddr(player), player->cnum, av[1]); + return RET_FAIL; + } + player->validated++; + pr_id(player, C_CMDOK, "password ok\n"); + logerror("%s using country #%d", praddr(player), player->cnum); + return RET_OK; +} + +/*ARGSUSED*/ +int +play_cmd(struct player *player, int ac, char **av) +{ + extern char *banfil; + struct player *other; + natid cnum; + struct natstr *natp; + + if (ac == 4) { + (void) strncpy(player->userid, av[1], sizeof(player->userid)-1); + player->userid[sizeof(player->userid)-1] = '\0'; + player->validated = 0; + if (natbyname(av[2], &cnum) < 0) { + pr_id(player, C_CMDERR, "country %s does not exist\n", av[2]); + return 0; + } + if (!natpass(cnum, av[3])) { + pr_id(player, C_CMDERR, "password bad, logging entry\n"); + logerror("%s tried country #%d with %s", + praddr(player), cnum, av[3]); + return RET_FAIL; + } + player->cnum = cnum; + player->validated++; + } + if (player->cnum == 255 || !player->validated) { + pr_id(player, C_CMDERR, "need country and password\n"); + return RET_FAIL; + } + if ((other = player_find_other(player, (natid)player->cnum)) != 0) { + natp = getnatp(player->cnum); + if (natp->nat_stat != VIS) { + pr_id(player, C_EXIT, "country in use by %s\n", + praddr(other)); + } else { + pr_id(player, C_EXIT, "country in use\n"); + } + return RET_FAIL; + } + if (match_user(banfil, player)) { + logerror("Attempted login by BANNED host %s", + praddr(player)); + pr("Your login has been banned from this game\n"); + io_shutdown(player->iop, IO_READ); + return RET_FAIL; + } + player_main(player); + player->state = PS_SHUTDOWN; + return RET_OK; +} + +/*ARGSUSED*/ +int +kill_cmd(struct player *player, int ac, char **av) +{ + struct player *other; + + if (player->cnum == 255 || !player->validated) { + pr_id(player, C_CMDERR, "need country and password\n"); + return RET_FAIL; + } + /* XXX find cnum other than us */ + if ((other = player_find_other(player, player->cnum)) == 0) { + pr_id(player, C_EXIT, "country not in use\n"); + return RET_FAIL; + } + io_shutdown(other->iop, IO_READ|IO_WRITE); + pr_id(player, C_EXIT, "closed socket of offending job\n"); + return RET_OK; +} + +/*ARGSUSED*/ +int +list_cmd(struct player *player, int ac, char **av) +{ + struct player *lp; + int first = 1; + + if (player->cnum != 0 || !player->validated) { + pr_id(player, C_CMDERR, "Permission denied\n"); + return 0; + } + for (lp = player_next(0); lp != 0; lp = player_next(lp)) { + if (first) { + pr_id(player, C_DATA, "user@host\tcountry\tpid\n"); + first = 0; + } + pr_id(player, C_DATA, "%s\t%d\n", praddr(lp), lp->cnum); + } + if (first == 0) + pr_id(player, C_DATA, "\n"); + return 0; +} + +/*ARGSUSED*/ +int +quit_cmd(struct player *player, int ac, char **av) +{ + pr_id(player, C_EXIT, "so long\n"); + io_shutdown(player->iop, IO_READ); + return RET_OK; +} + +struct cmndstr login_coms[] = { + { "list", 0, list_cmd, 0, 0 }, + { "client clientname [version info]", 0, client_cmd, 0, 0 }, + { "user username", 0, user_cmd, 0, 0 }, + { "sanc", 0, sanc_cmd, 0, 0 }, + { "coun countryname", 0, coun_cmd, 0, 0 }, + { "pass password", 0, pass_cmd, 0, 0 }, + { "play [user country pass]", 0, play_cmd, 0, 0 }, + { "quit ", 0, quit_cmd, 0, 0 }, + { "kill {self}", 0, kill_cmd, 0, 0 }, + { 0, 0, 0, 0, 0 } +}; diff --git a/src/lib/player/nat.c b/src/lib/player/nat.c new file mode 100644 index 00000000..73005d6f --- /dev/null +++ b/src/lib/player/nat.c @@ -0,0 +1,68 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * nat.c: Get nation stuff + * + * Known contributors to this file: + * Dave Pare, 1994 + */ + +#include "prototypes.h" +#include "misc.h" +#include "nat.h" +#include "file.h" +#include "player.h" +#include + +int +natbyname(s_char *name, natid *result) +{ + struct natstr *np; + int i; + + for (i=0; NULL != (np = getnatp(i)); i++) { + if (strcmp(np->nat_cnam, name) == 0) { + *result = i; + return 0; + } + } + *result = 255; + return -1; +} + +int +natpass(int cn, s_char *pass) +{ + struct natstr *np; + + np = getnatp((natid)cn); + if (np->nat_stat == VIS) + return 1; + if (strcmp(np->nat_pnam, pass) == 0) + return 1; + return 0; +} diff --git a/src/lib/player/player.c b/src/lib/player/player.c new file mode 100644 index 00000000..b175279b --- /dev/null +++ b/src/lib/player/player.c @@ -0,0 +1,426 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * player.c: Main command loop for a player + * + * Known contributors to this file: + * Steve McClure, 2000 + * + */ + +#include "prototypes.h" +#include +#include "gamesdef.h" +#include "misc.h" +#include "player.h" +#include "proto.h" +#include "var.h" +#include "com.h" +#include "nat.h" +#include "sect.h" +#include "deity.h" +#include "file.h" +#include "proto.h" +#include "empio.h" +#include "empthread.h" +#include "tel.h" +#include "gen.h" +#include "subs.h" +#include "common.h" + +#if !defined(_WIN32) +#include +#include +#endif +#include +#include + +struct player *player; +extern int m_m_p_d; + +void +player_main(struct player *p) +{ + extern s_char *authfil; + struct natstr *natp; + int hour[2]; + int secs; + s_char buf[128]; + + p->state = PS_PLAYING; + player = p; + time(&player->lasttime); + (void) time(&player->curup); + showvers(CLIENTPROTO); + show_motd(); + if (init_nats() < 0) + return; + natp = getnatp(player->cnum); + if (player->god && + !match_user(authfil, player)) { + logerror("NON-AUTHed Login attempted by %s", + praddr(player)); + pr("You're not a deity!\n"); + return; + } + if (!gamehours(player->curup, hour)) { + pr("Empire hours restriction in force\n"); + if ((natp->nat_stat & STAT_GOD) == 0) + return; + } + daychange(player->curup); + if ((player->minleft = getminleft(player->curup, hour, &m_m_p_d)) <= 0){ + pr("Time exceeded today\n"); + return; + } + if ((*natp->nat_hostaddr && + *player->hostaddr && + strcmp(natp->nat_hostaddr, player->hostaddr)) || + (*natp->nat_userid && + *player->userid && + strcmp(natp->nat_userid, player->userid))) { + if (natp->nat_stat != VIS) { + pr("Last connection from: %s", ctime(&natp->nat_last_login)); + pr(" to: %s", natp->nat_last_login < + natp->nat_last_logout ? ctime(&natp->nat_last_logout):"?"); + pr(" by: %s@%s\n", + *natp->nat_userid?natp->nat_userid : (s_char *)"nobody", + *natp->nat_hostname?natp->nat_hostname: + *natp->nat_hostaddr?natp->nat_hostaddr:(s_char *)"nowhere"); + } + } + if (*player->userid) + strcpy(natp->nat_userid, player->userid); + else + strcpy(natp->nat_userid, "nobody"); + + if (*player->hostname) + strcpy(natp->nat_hostname, player->hostname); + else + strcpy(natp->nat_hostname, "nowhere"); + + if (*player->hostaddr) + strcpy(natp->nat_hostaddr, player->hostaddr); + + time(&natp->nat_last_login); + natp->nat_connected = 1; + putnat(natp); + if (natp->nat_flags & NF_INFORM && + natp->nat_tgms > 0) { + if (natp->nat_tgms == 1) + pr("You have a new telegram waiting ...\n"); + else + pr("You have %s new telegrams waiting ...\n", + numstr(buf, natp->nat_tgms)); + natp->nat_tgms = 0; + } + + while (status()) { + if (command() == 0 && !player->aborted) + break; + player->aborted = 0; + } + /* #*# I put the following line in to prevent server crash -KHS */ + natp = getnatp(player->cnum); + /* + * randomly round up to the nearest minute, + * charging at least 15 seconds. + */ + time(&natp->nat_last_logout); + secs = max(natp->nat_last_logout - player->lasttime, 15); + natp->nat_minused += secs / 60; + secs = secs % 60; + if (chance(secs / 60.0)) + natp->nat_minused += 1; + natp->nat_connected = 0; + putnat(natp); + pr("Bye-bye\n"); +} + +int +command(void) +{ + register unsigned int x; + s_char *redir; + int kill_player(); + s_char scanspace[1024]; + + if (getcommand(player->combuf) < 0) + return 0; + if (parse(player->combuf, player->argp, &player->condarg, + scanspace, &redir) < 0) { + pr("See \"info Syntax\"?\n"); + } else { + /* XXX don't use alarm; use a scavenger thread */ + /* DONT USE IT!!!! alarm and sleep may and dont work + together -- Sasha */ + /* alarm((unsigned int)60*60); 1 hour */ + if (player->condarg != (s_char *)0) + for(x=0;xcondarg);x++) + if (isupper(*(player->condarg+x))) + *(player->condarg+x) = tolower(*(player->condarg+x)); + if (dispatch(player->combuf, redir) < 0) + pr("Try \"list of commands\" or \"info\"\n"); + } + return 1; +} + +int +status(void) +{ + struct natstr *natp; + int minute; + struct sctstr sect; + int hour[2]; + s_char buf[128]; + + if (player->state == PS_SHUTDOWN) + return 0; + natp = getnatp(player->cnum); + if (io_error(player->iop) || io_eof(player->iop)) { + putnat(natp); + return 0; + } + player->visitor = (natp->nat_stat & (STAT_NORM|STAT_GOD)) == 0; + if (player->dolcost != 0.0) { + if (player->dolcost > 100.0) + pr("That just cost you $%.2f\n", player->dolcost); + else if (player->dolcost < -100.0) + pr("You just made $%.2f\n", -player->dolcost); + if (natp->nat_money < player->dolcost && !player->broke) { + player->broke = 1; + player->nstat &= ~MONEY; + pr("You are now broke; industries are on strike.\n"); + } else if (player->broke && natp->nat_money - player->dolcost > 0) { + player->broke = 0; + player->nstat |= MONEY; + pr("You are no longer broke!\n"); + } + natp->nat_money -= roundavg(player->dolcost); + player->dolcost = 0.0; + } else { + if (natp->nat_money < 0.0 && !player->broke) { + player->broke = 1; + player->nstat &= ~MONEY; + pr("You are now broke; industries are on strike.\n"); + } + if (player->broke && natp->nat_money > 0) { + player->broke = 0; + player->nstat |= MONEY; + pr("You are no longer broke!\n"); + } + } + getsect(natp->nat_xcap, natp->nat_ycap, §); + if ((sect.sct_type == SCT_CAPIT || sect.sct_type == SCT_MOUNT || + sect.sct_type == SCT_SANCT) && + sect.sct_own == player->cnum) + player->nstat |= CAP; + else + player->nstat &= ~CAP; + /* Ok, has the country owner reset his capital yet after it was sacked? */ + if (natp->nat_flags & NF_SACKED) + player->nstat &= ~CAP; /* No capital yet */ + player->ncomstat = player->nstat; + (void) time(&player->curup); + minute = (player->curup - player->lasttime) / 60; + if (minute > 0) { + player->minleft -= minute; + if (player->minleft <= 0) { + /* + * countdown timer "player->minleft" has expired. + * either day change, or hours restriction + */ + daychange(player->curup); + if (!gamehours(player->curup, hour)) { + pr("Empire hours restriction in force\n"); + if ((natp->nat_stat & STAT_GOD) == 0) { + putnat(natp); + return 0; + } + } + player->minleft = getminleft(player->curup, hour, &m_m_p_d); + } + player->lasttime += minute * 60; + natp->nat_minused += minute; + } + if ((player->nstat & NORM) && natp->nat_minused > m_m_p_d) { + pr("Max minutes per day limit exceeded.\n"); + player->ncomstat = VIS; + } + if (player->btused) { + natp->nat_btu -= player->btused; + player->btused = 0; + } + if (natp->nat_tgms > 0) { + if (!(natp->nat_flags & NF_INFORM)) { + if (natp->nat_tgms == 1) + pr("You have a new telegram waiting ...\n"); + else + pr("You have %s new telegrams waiting ...\n", + numstr(buf, natp->nat_tgms)); + natp->nat_tgms = 0; + } + } + if (natp->nat_ann > 0) { + if (natp->nat_ann == 1) + pr("You have a new announcement waiting ...\n"); + else + pr("You have %s new announcements waiting ...\n", + numstr(buf, natp->nat_ann)); + natp->nat_ann = 0; + } + if (!player->visitor && !player->god && (player->nstat & CAP) == 0) + pr("You lost your capital... better designate one\n"); + putnat(natp); + if (gamedown() && !player->god) { + pr("gamedown\n"); + return 0; + } + return 1; +} + +/* + * actually a command; redirection and piping ignored. + * XXX This whole mess should be redone; execute block should + * start with "exec start", and should end with "exec end". + * We'll wait until 1.2 I guess. + */ +int +execute(void) +{ + s_char buf[512]; + int abort; + s_char *p; + s_char *redir; + s_char scanspace[1024]; + + abort = 0; + redir = 0; + + p = getstarg (player->argp[1], "File? ", buf); + + if (p == (s_char *) 0 || p == '\0') + return RET_SYN; + + prexec(player->argp[1]); + while (!abort && status()) { + if (recvclient(buf, sizeof(buf)) < 0) + break; + if (parse(buf, player->argp, &player->condarg, + scanspace, &redir) < 0) { + abort = 1; + continue; + } + if (redir == 0) + pr("\nExecute : %s\n", buf); + if (dispatch(buf, redir) < 0) + abort = 1; + } + if (abort) { + while (recvclient(buf, sizeof(buf)) >= 0) + ; + } + if (redir == 0) + pr("Execute : %s\n", abort ? "aborted" : "terminated"); + return RET_OK; +} + +int +show_motd(void) +{ + extern s_char *upfil; + int upf; + struct telstr tgm; + s_char buf[MAXTELSIZE]; + +#if !defined(_WIN32) + if ((upf = open(upfil, O_RDONLY, 0)) < 0) +#else + if ((upf = open(upfil, O_RDONLY|O_BINARY, 0)) < 0) +#endif + return RET_FAIL; + if (read(upf, (s_char *) &tgm, sizeof(tgm)) != sizeof(tgm)) { + logerror("bad header on login message (upfil)"); + close(upf); + return RET_FAIL; + } + if (read(upf, buf, tgm.tel_length) != tgm.tel_length) { + logerror("bad length %d on login message", tgm.tel_length); + close(upf); + return RET_FAIL; + } + if (tgm.tel_length >= (long)sizeof(buf)) + tgm.tel_length = sizeof(buf)-1; + buf[tgm.tel_length] = 0; + pr(buf); + (void) close(upf); + return RET_OK; +} + +int match_user(char *file, struct player *player) +{ + FILE *fp; + int match = 0; + s_char host[256]; + s_char user[256]; + + if ((fp = fopen(file, "r")) == NULL) { + /*logerror("Cannot find file %s", file);*/ + return 0; + } + match = 0; + while (!feof(fp) && !match) { + if (fgets(host, sizeof(host)-1, fp) == NULL) + break; + if (host[0] == '#') continue; + if (fgets(user, sizeof(user)-1, fp) == NULL) + break; + host[strlen(host)-1] = '\0'; + user[strlen(user)-1] = '\0'; + if (strstr(player->userid, user) && + (strstr(player->hostaddr, host) || + strstr(player->hostname, host))) + ++match; + } + fclose(fp); + return match; +} + +int +quit(void) +{ + player->state = PS_SHUTDOWN; + return RET_OK; +} + +s_char * +praddr(struct player *player) +{ + return prbuf("%s@%s", player->userid, + *player->hostname?player->hostname:player->hostaddr); +} + diff --git a/src/lib/player/recvclient.c b/src/lib/player/recvclient.c new file mode 100644 index 00000000..fa8baa53 --- /dev/null +++ b/src/lib/player/recvclient.c @@ -0,0 +1,72 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * recvclient.c: Send and receive commands from the client + * + * Known contributors to this file: + * Dave Pare, 1986 + */ + +#include "prototypes.h" +#include +#include "misc.h" +#include "bit.h" +#include "empio.h" +#include "player.h" +#include "empthread.h" + +#include + +int +recvclient(s_char *cmd, int size) +{ + extern int errno; + int count; + + if (player->aborted) + return -2; + count = io_gets(player->iop, cmd, size); + while (!player->aborted && count < 0) { + io_output_all(player->iop); + io_input(player->iop, IO_WAIT); + if (io_error(player->iop)) + player->aborted++; + else if (io_eof(player->iop)) + return -1; + else + count = io_gets(player->iop, cmd, size); + } + if (count > 0) { + if (strcmp(cmd, "ctld") == 0) + return -1; + if (strcmp(cmd, "aborted") == 0) + player->aborted = 1; + } + if (player->aborted) + return -2; + return count; +} diff --git a/src/lib/subs/Makefile b/src/lib/subs/Makefile new file mode 100644 index 00000000..828b8439 --- /dev/null +++ b/src/lib/subs/Makefile @@ -0,0 +1,76 @@ +# +# Empire - A multi-player, client/server Internet based war game. +# Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, +# Ken Stevens, Steve McClure +# +# 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 2 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, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# --- +# +# See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the +# related information and legal notices. It is expected that any future +# projects/authors will amend these files as needed. +# +# Makefile - Wolfpack, 1996 + +# Note that these could have been listed 1 per line, but I chose to just +# stick them all together this way to shorten the file. + +include ../../../build.conf +include ../../make.src +include ../../make.defs + +LIB = $(SRCDIR)/lib/libsubs.a +NTLIB = $(SRCDIR)\lib\libsubs.lib + +OBJS = aircombat.o askyn.o aswplnsubs.o attsub.o bigmap.o border.o bsanct.o \ + caploss.o chkmoney.o cnumb.o comsub.o control.o detonate.o disloan.o \ + distrea.o fileinit.o fortdef.o getbit.o getele.o land.o landgun.o \ + list.o lndsub.o lostsub.o mission.o move.o mslsub.o mtch.o natarg.o \ + neigh.o nreport.o nstr.o nuke.o nxtitem.o nxtsct.o paths.o plane.o \ + plnsub.o pr.o radmap.o rej.o retreat.o sarg.o satmap.o \ + sect.o ship.o show.o shpsub.o snxtitem.o snxtsct.o supply.o \ + takeover.o trdsub.o trechk.o whatitem.o wire.o wu.o + +NTOBJS = aircombat.obj askyn.obj aswplnsubs.obj attsub.obj bigmap.obj \ + border.obj bsanct.obj caploss.obj chkmoney.obj cnumb.obj comsub.obj \ + control.obj detonate.obj disloan.obj distrea.obj fileinit.obj fortdef.obj \ + getbit.obj getele.obj land.obj landgun.obj list.obj lndsub.obj \ + lostsub.obj mission.obj move.obj mslsub.obj mtch.obj natarg.obj neigh.obj \ + nreport.obj nstr.obj nuke.obj nxtitem.obj nxtsct.obj paths.obj plane.obj \ + plnsub.obj pr.obj radmap.obj rej.obj retreat.obj sarg.obj satmap.obj \ + sect.obj ship.obj show.obj shpsub.obj snxtitem.obj \ + snxtsct.obj supply.obj takeover.obj trdsub.obj trechk.obj whatitem.obj \ + wire.obj wu.obj + +all: $(LIB) + +nt: $(NTLIB) + +$(NTLIB): $(NTOBJS) + -del /q $@ + lib /OUT:$@ /DEBUGTYPE:CV $(NTOBJS) + +$(LIB): $(OBJS) + rm -f $(LIB) + ar cq $(LIB) $(OBJS) + $(RANLIB) $(LIB) + +clean: + -(rm -f $(OBJS)) + -(del /q $(NTOBJS)) + +include ../../make.rules +include Makedepend diff --git a/src/lib/subs/aircombat.c b/src/lib/subs/aircombat.c new file mode 100644 index 00000000..cff1e388 --- /dev/null +++ b/src/lib/subs/aircombat.c @@ -0,0 +1,1196 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * aircombat.c: Deal with air to air combat + * + * Known contributors to this file: + * Dave Pare, 1986 + * Thomas Ruschak, 1992 + * Steve McClure, 1996 + */ + +#include + +#include "misc.h" +#include "player.h" +#include "var.h" +#include "news.h" +#include "land.h" +#include "sect.h" +#include "nuke.h" +#include "plane.h" +#include "ship.h" +#include "nat.h" +#include "file.h" +#include "xy.h" +#include "nsc.h" +#include "path.h" +#include "prototypes.h" +#include "optlist.h" + +extern int update_pending; + +#ifndef MIN +#define MIN(x,y) ((x) < (y) ? (x) : (y)) +#endif +#ifndef MAX +#define MAX(x,y) ((x) < (y) ? (y) : (x)) +#endif + +static void getilist(struct emp_qelem *list, natid own, + struct emp_qelem *a, struct emp_qelem *b, + struct emp_qelem *c, struct emp_qelem *d); +static void ac_dog(register struct plist *ap, register struct plist *dp); + +#define DOG_MAX 15 +#define FLAK_MAX 15 + + /* -7 -6 -5 -4 -3 -2 -1 0 */ +float flaktable[16] = { 0.20, 0.20, 0.25, 0.30, 0.35, 0.40, 0.45, 0.50, + 0.50, 0.55, 0.60, 0.65, 0.70, 0.75, 0.80, 0.85, }; + +void +ac_encounter(struct emp_qelem *bomb_list, struct emp_qelem *esc_list, coord x, coord y, s_char *path, int mission_flags, int no_air_defense, struct emp_qelem *obomb, struct emp_qelem *oesc) +{ + int val, non_missiles; + int rel; + int dir; + int nats[MAXNOC]; + int lnats[MAXNOC]; + int gotilist[MAXNOC]; + int unfriendly[MAXNOC]; + int overfly[MAXNOC]; + struct emp_qelem ilist[MAXNOC], *qp; + s_char mypath[1024]; + int myp; + int civ, mil; + natid plane_owner; + struct sctstr sect; + struct shpstr ship; + struct lndstr land; + struct nstr_item ni; + natid cn; + struct natstr *over, *mynatp; + struct plist *plp; + int evaded; + struct shiplook head; + struct shiplook *s,*s2; + int changed = 0; + int intx, inty; /* Last sector planes intercepted over */ + int intown = 0; /* Last owner to intercept */ +/* We want to only intercept once per sector per owner. So, if we overfly + a sector, and then overfly some land units or ships, we don't want to + potentially intercept 3 times. */ + + bzero((s_char *)&head,sizeof(struct shiplook)); + head.uid = -1; + + plp = (struct plist *) bomb_list->q_forw; + plane_owner = plp->plane.pln_own; + + bzero((s_char *)mypath, 1024); + bcopy(path,mypath,strlen(path)); + myp = 0; + + bzero((s_char *)overfly, sizeof(overfly)); + bzero((s_char *)gotilist, sizeof(gotilist)); + bzero((s_char *)unfriendly, sizeof(unfriendly)); + for (cn=1; cn HOSTILE) + continue; + if (plane_owner == cn) + continue; + unfriendly[cn]++; + } + if (mission_flags & PM_R) { + if (mission_flags & P_S) { + PR(plane_owner,"\nSPY Plane report\n"); + PRdate(plane_owner); + sathead(); + } else if (mission_flags & P_A){ + PR(plane_owner,"\nAnti-Sub Patrol report\n"); + } else { + PR(plane_owner,"\nReconnaissance report\n"); + PRdate(plane_owner); + } + } + + pln_removedupes(bomb_list, esc_list); + while ((dir = mypath[myp++]) && !QEMPTY(bomb_list)) { + if ((val = chkdir(dir, DIR_STOP, DIR_LAST)) == 0) + break; + /* XXX using xnorm is probably bad */ + x = xnorm(x + diroff[val][0]); + y = ynorm(y + diroff[val][1]); + getsect(x, y, §); + over = getnatp(sect.sct_own); + if (opt_HIDDEN) { + setcont(plane_owner,sect.sct_own, FOUND_FLY); + } + + if (mission_flags & PM_R) { + if (sect.sct_type == SCT_WATER){ + PR(plane_owner,"flying over %s at %s\n", + dchr[sect.sct_type].d_name, + xyas(x, y, plane_owner)); + if (mission_flags & PM_S) + plane_sweep(bomb_list,x,y); + if (mission_flags & P_A){ + plane_sona(bomb_list,x,y,&head); + } + changed += map_set(plane_owner, + sect.sct_x, sect.sct_y, + dchr[sect.sct_type].d_mnem, + 0); + } else if (mission_flags & P_S) { + satdisp(§, (mission_flags&P_I)?10:50, 1); + } else { + /* This is borrowed from lookout */ + if (sect.sct_own == plane_owner) + PR(plane_owner,"Your "); + else + PR(plane_owner, + "%s (#%d) ", + cname(sect.sct_own), + sect.sct_own); + PR(plane_owner,dchr[sect.sct_type].d_name); + changed += map_set(plane_owner, + sect.sct_x, sect.sct_y, + dchr[sect.sct_type].d_mnem, + 0); + PR(plane_owner," %d%% efficient ", + (sect.sct_own == plane_owner) ? + sect.sct_effic : + roundintby((int)sect.sct_effic,25)); + civ = getvar(V_CIVIL, (s_char *)§, EF_SECTOR); + mil = getvar(V_MILIT, (s_char *)§, EF_SECTOR); + if (civ) + PR(plane_owner,"with %s%d civ ", + (sect.sct_own == plane_owner) ? + "" : "approx ", + (sect.sct_own == plane_owner) ? + civ : roundintby(civ, 25)); + if (mil) + PR(plane_owner,"with %s%d mil ", + (sect.sct_own == plane_owner) ? + "" : "approx ", + (sect.sct_own == plane_owner) ? + mil : roundintby(mil, 25)); + PR(plane_owner,"@ %s\n", xyas(x, y, plane_owner)); + } + } else { + PR(plane_owner,"flying over %s at %s\n", + dchr[sect.sct_type].d_name, + xyas(x, y, plane_owner)); + changed += map_set(plane_owner, sect.sct_x, + sect.sct_y, + dchr[sect.sct_type].d_mnem, 0); + } + if ((rel = getrel(over, plane_owner)) == ALLIED) + continue; + + evaded = do_evade(bomb_list,esc_list); + + if (sect.sct_own != 0 && sect.sct_own != plane_owner && + (!evaded)) { + /* We only show planes overhead if they didn't + * evade radar */ + overfly[sect.sct_own]++; + PR(sect.sct_own, "%s planes spotted over %s\n", + cname(plane_owner), xyas(x, y, sect.sct_own)); + } + + if (!evaded) { + /* Fire flak */ + if (unfriendly[sect.sct_own]) + ac_doflak(bomb_list, §); + /* If bombers left, fire flak from units and ships */ + if (!QEMPTY(bomb_list)) + ac_landflak(bomb_list, x, y); + if (!QEMPTY(bomb_list)) + ac_shipflak(bomb_list, x, y); + } + /* mission planes aborted due to flak -- don't send escorts */ + if (QEMPTY(bomb_list)) + break; + if ((!no_air_defense) && (!evaded)) + air_defense(x,y,plane_owner,bomb_list, esc_list); + + if (sect.sct_own == 0 || sect.sct_own == plane_owner) + continue; + + if (evaded) + continue; + + non_missiles = 0; + for (qp = bomb_list->q_forw; qp != bomb_list; qp = qp->q_forw){ + struct plist *ip = (struct plist *) qp; + if (!(plchr[(int)ip->plane.pln_type].pl_flags & P_M)) + non_missiles = 1; + } + + if (!non_missiles) + continue; + + if (unfriendly[sect.sct_own] && !gotilist[sect.sct_own]) { + getilist(&ilist[sect.sct_own], sect.sct_own, + bomb_list, esc_list, obomb, oesc); + gotilist[sect.sct_own]++; + } + if (rel > HOSTILE) + continue; + ac_intercept(bomb_list, esc_list, &ilist[sect.sct_own], + sect.sct_own, x, y); + intx = x; + inty = y; + intown = sect.sct_own; + } + + /* Let's report all of the overflights even if aborted */ + for (cn = 1; cn < MAXNOC; cn++) { + if (plane_owner == cn) + continue; + if (overfly[cn] > 0) + nreport(plane_owner, N_OVFLY_SECT, cn, overfly[cn]); + } + /* If the map changed, update it */ + if (changed) + if (!update_pending && plane_owner == player->cnum) + writemap(player->cnum); + /* Now, if the bomber and escort lists are empty, we are done */ + if (QEMPTY(bomb_list) && QEMPTY(esc_list)) { + if (mission_flags & P_A){ + s=head.next; + while (s != (struct shiplook *)0){ + s2=s; + s=s->next; + free(s2); + } + } + return; + } + + /* Something made it through */ + /* Go figure out if there are ships in this sector, and who's they are */ + bzero((s_char *)nats, sizeof(nats)); + snxtitem_xy(&ni, EF_SHIP, x, y); + while (nxtitem(&ni, (s_char *)&ship)) { + if (mchr[(int)ship.shp_type].m_flags & M_SUB) + continue; + nats[ship.shp_own]++; + } + /* Go figure out if there are units in this sector, and who's they are */ + bzero((s_char *)lnats, sizeof(lnats)); + snxtitem_xy(&ni, EF_LAND, x, y); + while (nxtitem(&ni, (s_char *)&land)) { + lnats[land.lnd_own]++; + } + + /* Now, let's make life a little rougher. */ + for (cn = 1; cn < MAXNOC && !QEMPTY(bomb_list); cn++) { + if (plane_owner == cn) + continue; + intown = -1; + /* Are there ships owned by this country? */ + if (nats[cn] != 0) { + /* Yes. */ + if (cn != 0) + PR(cn, "%s planes spotted over ships in %s\n", + cname(plane_owner), xyas(x, y, cn)); + if (unfriendly[cn]) { + /* They are unfriendly too */ + if (!gotilist[cn]) { + getilist(&ilist[cn], cn, bomb_list, esc_list, obomb, oesc); + gotilist[cn]++; + } + PR(plane_owner, "Flying over %s ships in %s\n", cname(cn), xyas(x, y, plane_owner)); + /* This makes going for ships in harbors tough */ + if (!evaded) { + /* We already fired flak up above. Now we intercept again if we haven't already */ + /* Flag that we intercepted */ + intown = 1; + /* And now intercept again */ + ac_intercept(bomb_list, esc_list, &ilist[cn], cn, x, y); + } + } + } + /* Are there units owned by this country? */ + if (lnats[cn] != 0) { + /* Yes. */ + if (cn != 0) + PR(cn, "%s planes spotted over land units in %s\n", + cname(plane_owner), xyas(x, y, cn)); + if (unfriendly[cn]) { + /* They are unfriendly too */ + if (!gotilist[cn]) { + getilist(&ilist[cn], cn, bomb_list, esc_list, obomb, oesc); + gotilist[cn]++; + } + PR(plane_owner,"Flying over %s land units in %s\n", cname(cn), xyas(x, y, plane_owner)); + if (!evaded) { + if (intown == -1) { + /* We haven't intercepted yet, so intercept */ + ac_intercept(bomb_list, esc_list, &ilist[cn], cn, x, y); + } + } + } + } + } + + if ((mission_flags & P_A) && (head.uid != -1)) { + s=head.next; + while (s != (struct shiplook *)0){ + s2=s; + s=s->next; + free(s2); + } + } +} + +static int +count_non_missiles(struct emp_qelem *list) +{ + struct emp_qelem *qp; + struct plist *plp; + int att_count = 0; + + /* don't intercept missiles */ + for (qp = list->q_forw; qp != list; qp = qp->q_forw){ + plp = (struct plist *)qp; + if (!(plp->pcp->pl_flags & P_M)) + att_count++; + } + return att_count; +} + +void +sam_intercept(struct emp_qelem *att_list, struct emp_qelem *def_list, natid def_own, natid plane_owner, coord x, coord y, int delete_missiles) +{ + struct emp_qelem *aqp; + struct emp_qelem *anext; + struct emp_qelem *dqp; + struct emp_qelem *dnext; + struct plist *aplp; + struct plist *dplp; + int first = 1; + + for (aqp = att_list->q_forw, + dqp = def_list->q_forw; + aqp != att_list && + dqp != def_list; + aqp = anext) { + anext = aqp->q_forw; + aplp = (struct plist *)aqp; + if (aplp->pcp->pl_flags & P_M) + continue; + if (aplp->pcp->pl_cost < 1000) + continue; + for (;dqp != def_list; dqp = dnext) { + dnext = dqp->q_forw; + dplp = (struct plist *)dqp; + if (!(dplp->pcp->pl_flags & P_M)) + continue; + + if (dplp->plane.pln_range < mapdist(x, y, dplp->plane.pln_x, dplp->plane.pln_y)) { + emp_remque(dqp); + free((s_char *)dqp); + continue; + } + if (mission_pln_equip(dplp, 0, P_F, 0) < 0) { + emp_remque(dqp); + free((s_char *)dqp); + continue; + } + if (first) { + first = 0; + PR(plane_owner,"%s launches SAMs!\n", cname(def_own)); + PR(def_own, "Launching SAMs at %s planes!\n", cname(plane_owner)); + ac_combat_headers(plane_owner, def_own); + } + ac_dog(aplp, dplp); + dqp = dnext; + break; + } + } + if (!first) { + PR(plane_owner, "\n"); + PR(def_own, "\n"); + } + if (delete_missiles) { + for (;dqp != def_list; dqp = dnext) { + dnext = dqp->q_forw; + dplp = (struct plist *)dqp; + if (!(dplp->pcp->pl_flags & P_M)) + continue; + emp_remque(dqp); + free((s_char *)dqp); + continue; + } + } +} + +void +ac_intercept(struct emp_qelem *bomb_list, struct emp_qelem *esc_list, struct emp_qelem *def_list, natid def_own, coord x, coord y) +{ + register struct plnstr *pp; + struct plist *plp; + int icount; + struct emp_qelem *next; + struct emp_qelem *qp; + struct emp_qelem int_list; + int att_count; + natid plane_owner; + int dist; + + plp = (struct plist *)bomb_list->q_forw; + plane_owner = plp->plane.pln_own; + + icount = 0; + + sam_intercept(bomb_list, def_list, def_own, plane_owner, x, y, 0); + sam_intercept(esc_list, def_list, def_own, plane_owner, x, y, 1); + if (!(att_count = count_non_missiles(bomb_list) + + count_non_missiles(esc_list))) + return; + + emp_initque(&int_list); + for (qp = def_list->q_forw; qp != def_list; qp = next) { + next = qp->q_forw; + plp = (struct plist *) qp; + pp = &plp->plane; + /* SAMs interdict separately */ + if (plp->pcp->pl_flags & P_M) + continue; + dist = mapdist(x, y, pp->pln_x, pp->pln_y) * 2; + if (pp->pln_range < dist) + continue; + if (mission_pln_equip(plp, 0, P_F, 0) < 0) { + emp_remque(qp); + free((s_char *)qp); + continue; + } + /* got one; delete from def_list, add to int_list */ + emp_remque(qp); + emp_insque(qp, &int_list); + pp->pln_mobil -= pln_mobcost(dist,pp,P_F); + putplane(pp->pln_uid, pp); + icount++; + if (icount > att_count) + break; + } + if (icount == 0) + return; + PR(plane_owner,"%d %s fighter%s rising to intercept!\n", icount, + cname(def_own), icount == 1 ? " is" : "s are"); + PR(def_own,"%d fighter%s intercepting %s planes!\n", icount, + icount == 1 ? " is" : "s are", cname(plane_owner)); + ac_combat_headers(plane_owner, def_own); + ac_airtoair(esc_list, &int_list, def_own); + ac_airtoair(bomb_list, &int_list, def_own); + PR(plane_owner, "\n"); + PR(def_own, "\n"); +} + +void +ac_combat_headers(natid plane_owner, natid def_own) +{ + PR(plane_owner," %-10.10s %-10.10s strength int odds damage results\n", cname(plane_owner), cname(def_own)); + PR(def_own," %-10.10s %-10.10s strength int odds damage results\n", cname(def_own), cname(plane_owner)); +} + +/* + * air-to-air combat. + */ +void +ac_airtoair(struct emp_qelem *att_list, struct emp_qelem *int_list, natid def_own) +{ + register struct plist *attacker; + register struct plist *interceptor; + struct emp_qelem *att; + struct emp_qelem *in; + int nplanes; + int more_att; + int more_int; + struct emp_qelem *att_next; + struct emp_qelem *in_next; + natid att_own; + + att = att_list->q_forw; + in = int_list->q_forw; + more_att = 1; + more_int = 1; + if (QEMPTY(att_list) || QEMPTY(int_list)) { + more_att = 0; + more_int = 0; + } + while (more_att || more_int) { + in_next = in->q_forw; + att_next = att->q_forw; + attacker = (struct plist *) att; + + /* skip missiles. If only missiles left, we're done */ + if (plchr[(int)attacker->plane.pln_type].pl_flags & P_M){ + att = att_next; + if (att == att_list) { + more_att = 0; + if (QEMPTY(att_list)) + more_int = 0; + else + att = att->q_forw; + } + if (all_missiles(att_list)) + more_att = 0; + continue; + } + interceptor = (struct plist *) in; + att_own = attacker->plane.pln_own; + def_own = interceptor->plane.pln_own; + nplanes = attacker->plane.pln_effic; + if (nplanes > interceptor->plane.pln_effic) + nplanes = interceptor->plane.pln_effic; + ac_dog(attacker, interceptor); + in = in_next; + att = att_next; + if (att == att_list) { + more_att = 0; + if (QEMPTY(att_list)) + more_int = 0; + else + att = att->q_forw; + } + if (in == int_list) { + more_int = 0; + if (QEMPTY(int_list)) + more_att = 0; + else + in = in->q_forw; + } + } +} + +int +all_missiles(struct emp_qelem *att_list) +{ + struct emp_qelem *qp; + struct plist *p; + + qp = att_list->q_forw; + while (qp != att_list){ + p = (struct plist *)qp; + if (!(plchr[(int)p->plane.pln_type].pl_flags & P_M)) + return 0; + + qp = qp->q_forw; + } + return 1; +} + +static void +ac_dog(register struct plist *ap, register struct plist *dp) +{ + int att, def; + double odds; + int intensity; + natid att_own, def_own; + int adam, ddam; + s_char mesg[1024]; + s_char temp[14]; + + att_own = ap->plane.pln_own; + def_own = dp->plane.pln_own; + + PR(att_own," %3.3s #%-4d %3.3s #%-4d", + ap->pcp->pl_name, + ap->plane.pln_uid, + dp->pcp->pl_name, + dp->plane.pln_uid); + if (def_own) + PR(def_own," %3.3s #%-4d %3.3s #%-4d", + dp->pcp->pl_name, + dp->plane.pln_uid, + ap->pcp->pl_name, + ap->plane.pln_uid); + if (ap->plane.pln_att == 0){ + att = ap->plane.pln_def * ap->plane.pln_effic / 100; + att = MAX(att,ap->pcp->pl_def/2); + }else{ + att = ap->plane.pln_att * ap->plane.pln_effic / 100; + att = MAX(att,ap->pcp->pl_att/2); + } + + def = dp->plane.pln_def * dp->plane.pln_effic / 100; + def = MAX(def,dp->pcp->pl_def/2); + + if ((ap->pcp->pl_flags & P_F) && ap->bombs != 0) + att -= 2; + if ((dp->pcp->pl_flags & P_F) && dp->bombs != 0) + def -= 2; + att += ((float)ap->pcp->pl_stealth/25.0); + def += ((float)dp->pcp->pl_stealth/25.0); + if (att < 1) { + def += 1 - att; + att = 1; + } + if (def < 1) { + att += 1 - def; + def = 1; + } + odds = ((double)att/((double)def+(double)att)); + if (odds <= 0.05) + odds = 0.05; + intensity = roll(20)+roll(20)+roll(20)+roll(20)+1; + + PR(att_own," %3d/%-3d %3d %3.2f ",att,def,intensity,odds); + PR(def_own," %3d/%-3d %3d %3.2f ",def,att,intensity,odds); + + adam = 0; ddam = 0; + while ((intensity--)>0){ + + if (chance(odds)) { + ddam += 1; + if ((dp->plane.pln_effic-ddam) < PLANE_MINEFF) + intensity=0; + } else { + adam += 1; + if ((ap->plane.pln_effic-adam) < PLANE_MINEFF) + intensity=0; + } + } + + if (dp->pcp->pl_flags & P_M) + ddam = 100; + + PR(att_own,"%3d/%-3d", adam, ddam); + PR(def_own,"%3d/%-3d", ddam, adam); + ac_planedamage(ap, dp->plane.pln_own, + adam, def_own, 1, 0, mesg); + strncpy(temp,mesg,14); + ac_planedamage(dp, ap->plane.pln_own, + ddam, att_own, 1, 0, mesg); + PR(att_own, "%-13.13s %-13.13s\n", temp, mesg); + PR(def_own, "%-13.13s %-13.13s\n", mesg, temp); +} + +/* + * zap plane associated with plp. + * Damaging country is "from", damage is "dam". + * def_own is the country on the other side of the conflict from the plane + * owner. The only time def_own != from is when the interceptor is getting + * damaged. + * + * NOTE: This routine removes the appropriate plane element from the + * queue if it gets destroyed. That means that the caller must assume + * that the current queue pointer is invalid on return from the ac_planedamage + * call. (this has caused bugs in the past) + */ +void +ac_planedamage(struct plist *plp, natid from, int dam, natid other, int checkabort, int show, s_char *mesg) +{ + register struct plnstr *pp; + int disp; + s_char dmess[255]; + int eff; + struct shpstr ship; + struct lndstr land; + /* s_char *sprintf(); already in misc.h [JFW] */ + natid plane_owner; + + disp = 0; + pp = &plp->plane; + plane_owner = pp->pln_own; + eff = pp->pln_effic; + sprintf(dmess," no damage"); + if (dam <= 0) { + strcpy(mesg, dmess); + return; + } + bzero(dmess,255); + eff -= dam; + if (eff < 0) + eff = 0; + if (eff < PLANE_MINEFF) { + sprintf(dmess," shot down"); + disp = 1; + } else if (eff < 80 && chance((100-eff)/100.0) && checkabort){ + sprintf(dmess," aborted @%2d%%", eff); + disp = 2; + } else if (show == 0) { + sprintf(dmess," cleared"); + } + + if ((plp->pcp->pl_flags & P_M) == 0) { + if (show) { + PR(plane_owner, " %s %s takes %d%s.\n", + cname(pp->pln_own), + prplane(pp), dam, dmess); + if (other) + PR(other, " %s %s takes %d%s.\n", + cname(pp->pln_own), + prplane(pp), dam, dmess); + } + } + if (show && checkabort == 1) { + PR(plane_owner,"\n"); + if (other) + PR(other,"\n"); + } + + pp->pln_effic = eff; + pp->pln_mobil -= min(32 + pp->pln_mobil, dam/2); + if (disp == 1) { + if (from != 0 && (plp->pcp->pl_flags & P_M) == 0) + nreport(from, N_DOWN_PLANE, pp->pln_own, 1); + if (pp->pln_ship >= 0) { + getship(pp->pln_ship,&ship); + take_plane_off_ship(pp,&ship); + } + if (pp->pln_land >= 0) { + getland(pp->pln_land,&land); + take_plane_off_land(pp,&land); + } + makelost(EF_PLANE, pp->pln_own, pp->pln_uid, pp->pln_x, pp->pln_y); + pp->pln_own = 0; + putplane(pp->pln_uid, pp); + emp_remque(&plp->queue); + free((s_char *)plp); + } else if (disp == 2) { + putplane(pp->pln_uid, pp); + emp_remque(&plp->queue); + free((s_char *)plp); + } else + putplane(pp->pln_uid, pp); + strcpy(mesg, dmess); +} + +void +ac_doflak(struct emp_qelem *list, struct sctstr *from) +{ + int shell, add; + int gun; + natid plane_owner; + struct plist *plp; + + plp = (struct plist *)list->q_forw; + plane_owner = plp->plane.pln_own; + + gun = getvar(V_GUN, (s_char *)from, EF_SECTOR); + shell = getvar(V_SHELL, (s_char *)from, EF_SECTOR); + add = 0; + if (shell < (gun/2)) + add = supply_commod(from->sct_own,from->sct_x,from->sct_y, + I_SHELL,ldround(((double)gun/2.0),1)-shell); + shell += add; + if (gun == 0 || shell == 0) + return; + if (gun > shell*2) + gun = shell*2; + if (gun > 14) + gun = 14; + + putvar(V_SHELL, shell, (s_char *)from, EF_SECTOR); + putsect(from); + gun = 2.0 * tfact(from->sct_own, (double) gun); + if (gun > 0) { + PR(plane_owner,"firing %d flak guns in %s...\n", + gun, xyas(from->sct_x, from->sct_y, plane_owner)); + if(from->sct_own != 0) + PR(from->sct_own, "firing %d flak guns in %s...\n", + gun, xyas(from->sct_x, from->sct_y, from->sct_own)); + ac_fireflak(list, from->sct_own, 0, gun); + } +} + +void +ac_shipflak(struct emp_qelem *list, coord x, coord y) +{ + struct nstr_item ni; + struct shpstr ship; + struct mchrstr *mcp; + int firing; + int guns; + int gun; + int shell; + int rel; + struct plist *plp; + natid plane_owner; + natid from; + int nats[MAXNOC]; + + plp = (struct plist *)list->q_forw; + plane_owner = plp->plane.pln_own; + + bzero((s_char *)nats, sizeof(nats)); + guns = 0; + snxtitem_xy(&ni, EF_SHIP, x, y); + while (!QEMPTY(list) && nxtitem(&ni, (s_char *)&ship)) { + if (ship.shp_own == 0 || ship.shp_own == plane_owner) + continue; + if (guns >= 14) + break; + mcp = &mchr[(int)ship.shp_type]; + if (mcp->m_flags & M_SUB) + continue; + rel = getrel(getnatp(ship.shp_own), plane_owner); + if (rel > HOSTILE) + continue; + shell = gun = 0; + gun = min(getvar(V_GUN, (s_char *)&ship, EF_SHIP), ship.shp_glim); + if (gun) { + shell = getvar(V_SHELL, (s_char *)&ship, EF_SHIP); + if (shell <= 0) + shell = supply_commod(ship.shp_own, ship.shp_x, + ship.shp_y, I_SHELL, 1); + } + if (gun == 0 || shell == 0) + continue; + firing = (int) (techfact(ship.shp_tech, (double)gun) * 2.0); + guns += firing; + + if (!nats[ship.shp_own]) { + /* First time here, print the message */ + PR(ship.shp_own, "%s planes spotted over ships in %s\n", + cname(plane_owner), xyas(x, y, ship.shp_own)); + PR(plane_owner, "Flying over %s ships in %s\n", cname(ship.shp_own), + xyas(x, y, plane_owner)); + nats[ship.shp_own] = 1; + } + PR(ship.shp_own, "firing %d flak guns from %s...\n", + firing, prship(&ship)); + putvar(V_SHELL, shell, (s_char *)&ship, EF_SHIP); + putship(ship.shp_uid, &ship); + from = ship.shp_own; + } + if (guns > 0) { + if (guns > 14) + guns = 14; + guns = 2.0 * tfact(from, (double)guns); + PR(plane_owner, "Flak! Ships firing %d flak guns...\n", guns); + ac_fireflak(list, from, 0, guns); + } +} + +void +ac_landflak(struct emp_qelem *list, coord x, coord y) +{ + struct nstr_item ni; + struct lndstr land; + struct lchrstr *lcp; + int firing; + int guns; + int rel; + natid from; + struct plist *plp; + natid plane_owner; + int nats[MAXNOC]; + + plp = (struct plist *)list->q_forw; + plane_owner = plp->plane.pln_own; + + bzero((s_char *)nats, sizeof(nats)); + guns = 0; + snxtitem_xy(&ni, EF_LAND, x, y); + while (!QEMPTY(list) && nxtitem(&ni, (s_char *)&land)) { + if (land.lnd_own == 0 || land.lnd_own == plane_owner) + continue; + if (guns >= 14) + break; + lcp = &lchr[(int)land.lnd_type]; + + if ((lcp->l_flags & L_FLAK) == 0) + continue; + + if (land.lnd_aaf == 0) + continue; + + rel = getrel(getnatp(land.lnd_own), plane_owner); + if (rel > HOSTILE) + continue; + firing = (int)(techfact(land.lnd_tech, (double)land.lnd_aaf) * 3.0); + guns += firing; + + if (!nats[land.lnd_own]) { + /* First time here, print the message */ + PR(land.lnd_own, "%s planes spotted over land units in %s\n", + cname(plane_owner), xyas(x, y, land.lnd_own)); + PR(plane_owner, "Flying over %s land units in %s\n", cname(land.lnd_own), + xyas(x, y, plane_owner)); + nats[land.lnd_own] = 1; + } + PR(land.lnd_own, "firing flak guns from unit %s (aa rating %d)\n", + prland(&land), land.lnd_aaf); + + from = land.lnd_own; /* We always use the last owner as the from */ + } + if (guns > 0) { + if (guns > 14) + guns = 14; + guns = 2.0 * tfact(from, (double)guns); + PR(plane_owner, "Flak! Land units firing %d flak guns...\n", guns); + ac_fireflak(list, from, 0, guns); + } +} + +/* + * Called from shipflak, landflak, and doflak. + */ +void +ac_fireflak(struct emp_qelem *list, natid from, natid other, int guns) +{ + extern double flakscale; + register struct plnstr *pp; + struct plist *plp; + int n; + float mult; + int diff; + struct emp_qelem *qp; + struct emp_qelem *next; + s_char msg[255]; + + plp = (struct plist *)list->q_forw; + + for (qp = list->q_forw; qp != list; qp = next) { + /* + * fighters don't get shot at by flak + * non-tactical bombers are harder to hit with flak. + * ('Cause they're not dive-bombing?) + */ + next = qp->q_forw; + plp = (struct plist *) qp; + pp = &plp->plane; + diff = guns - pp->pln_def; + if ((plp->pcp->pl_flags & P_T) == 0) + diff--; + if (plp->pcp->pl_flags & P_X) + diff -= 2; + if (plp->pcp->pl_flags & P_H) + diff -= 1; + if (diff > 8) + mult = flaktable[FLAK_MAX] * 1.33; + else if (diff < -7) + mult = flaktable[0] * 0.66; + else { + diff += 7; + mult = flaktable[diff]; + } + mult *= flakscale; + n = (int) ((roll(8) + 2) * mult); + if (n > 100) + n = 100; + ac_planedamage(plp, from, n, other, 2, 1, msg); + } +} + +/* + * See if this plane is flying in this list + */ +int +ac_isflying(struct plnstr *plane, struct emp_qelem *list) +{ + struct emp_qelem *qp; + struct emp_qelem *next; + struct plnstr *pp; + struct plist *plp; + + if (!list) + return 0; + for (qp = list->q_forw; qp != list; qp = next) { + next = qp->q_forw; + plp = (struct plist *) qp; + pp = &plp->plane; + if (plane->pln_uid == pp->pln_uid) + return 1; + } + return 0; +} + + +/* + * Get a list of planes available for interception duties. + */ +static void +getilist(struct emp_qelem *list, natid own, struct emp_qelem *a, struct emp_qelem *b, struct emp_qelem *c, struct emp_qelem *d) +{ + register struct plchrstr *pcp; + struct plnstr plane; + struct shpstr ship; + struct lndstr land; + struct sctstr sect; + struct nstr_item ni; + int type; + s_char *ptr; + struct plist *ip; + + emp_initque(list); + snxtitem_all(&ni, EF_PLANE); + while (nxtitem(&ni, (s_char *)&plane)) { + if (plane.pln_own != own) + continue; + pcp = &plchr[(int)plane.pln_type]; + if ((pcp->pl_flags & P_F) == 0) + continue; + if (plane.pln_mission != 0) + continue; + if (plane.pln_mobil <= 0) + continue; + if (plane.pln_effic < 40) + continue; + if (plane.pln_ship >= 0) { + if (!can_fly(plane.pln_uid)) + continue; + getship(plane.pln_ship,&ship); + ptr = (s_char *)&ship; + type = EF_SHIP; + } else + if (plane.pln_land >= 0) { + if (!can_fly(plane.pln_uid)) + continue; + getland(plane.pln_land,&land); + ptr = (s_char *)&land; + type = EF_LAND; + } else { + getsect(plane.pln_x, plane.pln_y, §); + ptr = (s_char *)§ + type = EF_SECTOR; +#if 0 + if (sect.sct_effic < 60 && (pcp->pl_flags & P_V) == 0) + continue; +#else + if ((sect.sct_effic < 60 || sect.sct_type != SCT_AIRPT) + && (pcp->pl_flags & P_V) == 0) + continue; +#endif + } + if (((float)getvar(V_PETROL, ptr, type)) < + (((float)pcp->pl_fuel)/2.0)) + continue; + /* Finally, is it in the list of planes already in + flight? */ + if (ac_isflying(&plane, a)) + continue; + if (ac_isflying(&plane, b)) + continue; + if (ac_isflying(&plane, c)) + continue; + if (ac_isflying(&plane, d)) + continue; + /* got one! */ + ip = (struct plist *) malloc(sizeof(*ip)); + ip->state = P_OK; + ip->bombs = 0; + ip->misc = 0; + ip->pcp = &plchr[(int)plane.pln_type]; + bcopy((s_char *)&plane, (s_char *)&ip->plane, sizeof(plane)); + emp_insque(&ip->queue, list); + } +} + + + +int +can_fly(int p) /* Can this plane fly from the ship or land unit it is on? */ + +{ + struct plnstr plane; + struct shpstr ship; + struct lndstr land; + struct plchrstr *pcp; + struct mchrstr *scp; + struct lchrstr *lcp; + + getplane(p,&plane); + pcp = &plchr[(int)plane.pln_type]; + + if (plane.pln_ship >= 0){ + if ( + !(pcp->pl_flags & P_L) && !(pcp->pl_flags & P_M) + && !(pcp->pl_flags & P_K) + && !(pcp->pl_flags & P_E) + ) + return 0; + + getship(plane.pln_ship,&ship); + scp = & mchr[(int)ship.shp_type]; + + if ((pcp->pl_flags & P_L) && (scp->m_flags & M_FLY)){ + return 1; + } + + if ((pcp->pl_flags & P_M) && (scp->m_flags & M_MSL)){ + return 1; + } + + if ((pcp->pl_flags & P_K) && (scp->m_flags & M_CHOPPER)){ + return 1; + } + + if ((pcp->pl_flags & P_E) && (scp->m_flags & M_XLIGHT)){ + return 1; + } + } + + if (plane.pln_land >= 0){ + if (!(pcp->pl_flags & P_E)) + return 0; + + getland(plane.pln_land,&land); + lcp = & lchr[(int)land.lnd_type]; + + if ((pcp->pl_flags & P_E) && (lcp->l_flags & L_XLIGHT)){ + return 1; + } + } + + return 0; +} + +int +do_evade(struct emp_qelem *bomb_list, struct emp_qelem *esc_list) +{ + struct emp_qelem *qp; + double evade; + struct plist *plp; + + evade=100.0; + for (qp = bomb_list->q_forw; qp != bomb_list; qp = qp->q_forw){ + plp = (struct plist *) qp; + if (evade > ((float)plp->pcp->pl_stealth/100.0)) + evade = (plp->pcp->pl_stealth/100.0); + } + for (qp = esc_list->q_forw; qp != esc_list; qp = qp->q_forw){ + plp = (struct plist *) qp; + if (evade > plp->pcp->pl_stealth/100.0) + evade = (plp->pcp->pl_stealth/100.0); + } + + if (chance(evade)) + return 1; + + return 0; +} diff --git a/src/lib/subs/askyn.c b/src/lib/subs/askyn.c new file mode 100644 index 00000000..f4ed15cb --- /dev/null +++ b/src/lib/subs/askyn.c @@ -0,0 +1,83 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * askyn.c: The oldest routines in the book... ask questions of the user + * + * Known contributors to this file: + * Thomas Ruschak, 1993 + * Doug Hay, 1998 + */ + +#include "misc.h" +#include +#if !defined(_WIN32) +#include +#endif +#include "nat.h" +#include "tel.h" +#include "file.h" +#include "var.h" +#include "prototypes.h" + +/* + * If they don't answer 'y' or 'Y', return 0 + */ +int +confirm(s_char *promptstring) +{ + s_char y_or_n[1024]; + char c; + + if (getstring(promptstring, y_or_n) == 0) + return 0; + c = *y_or_n; + if (c == 'y' || c == 'Y') + return 1; + return 0; +} + +/* + * Make them answer 'y', 'Y', 'n', or 'N', and + * return 1 for y or Y, and 0 for n or N + */ +int +askyn(s_char *promptstring) +{ + s_char y_or_n[1024]; + char c; + + while (getstring(promptstring, y_or_n)) { + c = *y_or_n; + if (c == 'y' || c == 'Y') + return 1; + if (c == 'n' || c == 'N') + return 0; + pr("You must answer either yes or no!\n"); + } + /* assume no if aborted */ + return 0; +} diff --git a/src/lib/subs/aswplnsubs.c b/src/lib/subs/aswplnsubs.c new file mode 100644 index 00000000..1b6d9d9f --- /dev/null +++ b/src/lib/subs/aswplnsubs.c @@ -0,0 +1,176 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * aswplnsubs.c: Various subroutines used for ASW planes + * + * Known contributors to this file: + * + */ + +#include "misc.h" +#include "player.h" +#include "var.h" +#include "xy.h" +#include "sect.h" +#include "ship.h" +#include "nsc.h" +#include "nat.h" +#include "path.h" +#include "file.h" +#include "queue.h" +#include "plane.h" +#include +#include +#include "prototypes.h" + +int +have_looked(u_char uid, struct shiplook *head) +{ + struct shiplook *s; + + s=head; + if (s->uid == -1) + return 0; + + while (s != ((struct shiplook *)0)){ + if (s->uid == uid) + return s->looked; + s=s->next; + } + + return 0; +} + +int +have_found(u_char uid, struct shiplook *head) +{ + struct shiplook *s; + + s=head; + if (s->uid == -1) + return 0; + + while (s != ((struct shiplook *)0)){ + if (s->uid == uid) + return s->found; + s=s->next; + } + + return 0; +} + +void +set_have_looked(u_char uid, struct shiplook *head) +{ + struct shiplook *s,*s2; + + s=head; + if (s->uid == -1){ + s->uid=uid; + s->looked=1; + s->found=0; + s->next=(struct shiplook *)0; + } + + while (s != ((struct shiplook *)0)){ + if (s->uid == uid){ + s->looked=1; + return; + } + s2=s; + s=s->next; + } + + s=(struct shiplook *)malloc(sizeof(struct shiplook)); + bzero((s_char *)s,sizeof(struct shiplook)); + s2->next = s; + s->uid = uid; + s->looked = 1; + s->next = (struct shiplook *)0; +} + +void +set_have_found(u_char uid, struct shiplook *head) +{ + struct shiplook *s,*s2; + + s=head; + if (s->uid == -1){ + s->uid=uid; + s->looked=0; + s->found=1; + s->next=(struct shiplook *)0; + } + + + while (s != ((struct shiplook *)0)){ + if (s->uid == uid){ + s->found=1; + return; + } + s2=s; + s=s->next; + } + + s=(struct shiplook *)malloc(sizeof(struct shiplook)); + bzero((s_char *)s,sizeof(struct shiplook)); + s2->next = s; + s->uid = uid; + s->found = 1; + s->next = (struct shiplook *)0; +} + +int +print_found(struct shiplook *head) +{ + struct shiplook *s; + extern s_char *effadv(int); + int first; + struct mchrstr *mp; + struct shpstr ship; + + s=head; + first = 1; + if (s->uid == -1) + return 0; + + while (s != ((struct shiplook *)0)){ + getship(s->uid,&ship); + mp = &mchr[(int)ship.shp_type]; + if (first) { + pr(" # player->owner eff type\n"); + first = 0; + } + pr("(#%3d) %10.10s %12.12s %s\n", ship.shp_uid, + cname(ship.shp_own), + effadv(ship.shp_effic), + prship(&ship)); + s=s->next; + } + + return 1; +} diff --git a/src/lib/subs/attsub.c b/src/lib/subs/attsub.c new file mode 100644 index 00000000..39bef2c3 --- /dev/null +++ b/src/lib/subs/attsub.c @@ -0,0 +1,2647 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * attsub.c: Attack subroutines + * + * Known contributors to this file: + * Ken Stevens, 1995 + * Steve McClure, 1996-2000 + */ + +#include +#include "misc.h" +#include "player.h" +#include "file.h" +#include "var.h" +#include "sect.h" +#include "ship.h" +#include "path.h" +#include "news.h" +#include "treaty.h" +#include "nat.h" +#include "xy.h" +#include "land.h" +#include "nsc.h" +#include "mission.h" +#include "combat.h" +#include "item.h" +#include "optlist.h" +#include "prototypes.h" + +#define CASUALTY_LUMP 1 /* How big casualty chunks should be */ + +static void ask_olist(int combat_mode, struct combat *off, struct combat *def, struct emp_qelem *olist, s_char *land_answer, int *a_spyp, int *a_engineerp); +static void take_move_in_mob(int combat_mode, struct llist *llp, struct combat *off, struct combat *def); +static void move_in_land(int combat_mode, struct combat *off, struct emp_qelem *olist, struct combat *def); +static void ask_move_in(struct combat *off, struct emp_qelem *olist, struct combat *def); +static void ask_move_in_off(struct combat *off, struct combat *def); + +static int board_abort(struct combat *off, struct combat *def); +static int land_board_abort(struct combat *off, struct combat *def); +static int ask_off(int combat_mode, struct combat *off, struct combat *def); +static int get_dlist(struct combat *def, struct emp_qelem *list, int a_spy, int *d_spyp); +static int get_ototal(int combat_mode, struct combat *off, struct emp_qelem *olist, double osupport, int check); +static int get_dtotal(struct combat *def, struct emp_qelem *list, double dsupport, int check); +static int take_casualty(int combat_mode, struct combat *off, struct emp_qelem *olist); + +static void send_reacting_units_home(struct combat *def, struct emp_qelem *list); +static int take_def(int combat_mode, struct emp_qelem *list, struct combat *off, struct combat *def); + +void att_move_in_off(int combat_mode, struct combat *off, struct emp_qelem *olist, struct combat *def); +static int get_land(int combat_mode, struct combat *def, int uid, struct llist *llp, int victim_land); + +/* + * The principal object in this code is the "combat" object. A combat object + * is either a sector or ship. There are + * usually two instances of this, the "def" or defense combat object, and + * the array of "off" or offense objects. The number of offense objects is + * determined by the value of off->last (e.g. more than one attacking sector). + * the type of the object is determined by combat->type which can take the + * values EF_SECTOR, EF_SHIP, EF_PLANE, or EF_BAD. Another important parameter + * which is often passed to these functions is combat_mode. This can take + * the value A_DEFENSE, A_ATTACK, A_ASSAULT, A_PARA, A_BOARD and A_LBOARD. + * As these six modes of being in combat affect things like mobcost and combat + * value, there are often switches made on combat_mode. Note that in all cases + * no mobility is taken from sectors, ships, or land units until the player + * has committed to a fight. Instead, the cost is temporarily placed in + * combat->mobcost, or llp->mobil as the case may be, and then when the object + * is "put" back onto disk, then the amounts in these variables are subtracted + * from the object's mobility. It needs to be done this way as the objects + * are constantly being re-read from disk, and we don't want to take any mob + * unless a fight actually occurrs. + * -Ken Stevens + */ + +/* initialize combat object */ + +int +att_combat_init(struct combat *com, int type) +{ + bzero((s_char *)com, sizeof(*com)); + com->type = type; + return type; +} + +/* print a combat object with optional preposition */ + +static s_char * +pr_com(int inon, struct combat *com, natid who) +{ + if (com->type == EF_SECTOR) { + return prbuf("%s%s", + inon?inon==1?"in ":"into ":"", + xyas(com->x, com->y, who)); + } else if (com->type == EF_SHIP) { + if (opt_SHIPNAMES) { + return prbuf("%s%s %s(#%d)", + inon?inon==1?"on ":"onto ":"", + com->shp_mcp->m_name, com->shp_name, com->shp_uid); + } else { + return prbuf("%s%s #%d", + inon?inon==1?"on ":"onto ":"", + com->shp_mcp->m_name, com->shp_uid); + } + } else if (com->type == EF_LAND) { + return prbuf("%s%s #%d", + inon?inon==1?"on ":"onto ":"", + com->lnd_lcp->l_name, com->lnd_uid); + } else { + return "your forces"; + } +} + +static s_char * +prcom(int inon, struct combat *com) +{ + return pr_com(inon, com, player->cnum); +} + +/* Doing a sneak attack */ +static void +do_sneak(def, success) + struct combat *def; + int success; +{ + struct sctstr sect; + struct natstr *natp = getnatp(player->cnum); + int issneak = getrel(natp, def->own); + + if (def->type != EF_SECTOR) + return; + + getsect(def->x, def->y, §); + + if (issneak == AT_WAR || + !def->own || + sect.sct_oldown == player->cnum) + return; + + if (success) + pr("Your sneak attack was successful\nBut "); + else + pr("Your sneak attack was unsuccessful\nAnd "); + + pr("it will cost you $5000\n"); + pr("War has been declared!!!!\n"); + wu(0,def->own, "Country %s (#%d) has Sneak Attacked!!\n", + cname(player->cnum), player->cnum); + wu(0,def->own,"Country %s (#%d) has Declared WAR on you!!\n", + cname(player->cnum), player->cnum); + player->dolcost += 5000; + issneak = min(issneak, MOBILIZATION); + nreport(player->cnum, N_DECL_WAR, def->own, 1); + setrel(player->cnum,def->own,issneak); +} + +/* + * This is the combat object "type" based integrity check. It basically + * splits along three divisions: ship/sector, attacker/defender, + * first time/not first time. + */ + +int +att_get_combat(struct combat *com, int isdef) +{ + struct sctstr sect; + struct shpstr ship; + struct lndstr land; + s_char *thing; + natid owner; + int mil; + int eff; + int mob; + coord x, y; + + switch (com->type) { + case EF_SECTOR: + if (!getsect(com->x, com->y, §)) { + pr("Bad sector: %s\n", + xyas(com->x, com->y, player->cnum)); + return att_combat_init(com, EF_BAD); + } + com->sct_type = sect.sct_type; + com->sct_dcp = &dchr[sect.sct_type]; + thing = (s_char *)§ + owner = sect.sct_own; + eff = sect.sct_effic; + mob = sect.sct_mobil; + x = com->x; + y = com->y; + break; + case EF_LAND: + if (!getland(com->lnd_uid, &land)) { + if (isdef) + pr("Land unit #%d is not in the same sector!\n", com->lnd_uid); + return att_combat_init(com, EF_BAD); + } + if (isdef && player->owner) { + pr("Boarding yourself? Try using the 'load' command.\n"); + return att_combat_init(com, EF_BAD); + } + com->lnd_lcp = &lchr[(int)land.lnd_type]; + thing = (s_char *)&land; + owner = land.lnd_own; + eff = land.lnd_effic; + mob = land.lnd_mobil; + x = land.lnd_x; + y = land.lnd_y; + break; + case EF_SHIP: + if (!getship(com->shp_uid, &ship) || !ship.shp_own) { + if (isdef) + pr("Ship #%d is not in the same sector!\n", com->shp_uid); + else + pr("Ship #%d is not your ship!\n", com->shp_uid); + return att_combat_init(com, EF_BAD); + } + if (opt_MARKET) { + if (isdef && player->owner && + ontradingblock(EF_SHIP, (int *)&ship)) { + pr("%s is on the trading block.\n", prcom(0, com)); + return att_combat_init(com, EF_BAD); + } + } + if (isdef && player->owner) { + pr("Boarding yourself? Try using the 'tend' command.\n"); + return att_combat_init(com, EF_BAD); + } + com->shp_mcp = &mchr[(int)ship.shp_type]; + if (opt_SHIPNAMES) + strncpy(com->shp_name, ship.shp_name, MAXSHPNAMLEN); + if (!isdef && !player->owner) { + if (com->set) + pr("%s was just sunk!\n", prcom(0, com)); + else + pr("Ship #%d is not your ship!\n", com->shp_uid); + return att_combat_init(com, EF_BAD); + } + thing = (s_char *)&ship; + owner = ship.shp_own; + eff = ship.shp_effic; + mob = ship.shp_mobil; + x = ship.shp_x; + y = ship.shp_y; + break; + case EF_PLANE: + return com->mil; + case EF_BAD: + return EF_BAD; + default: + return att_combat_init(com, EF_BAD); + } + + mil = getvar(V_MILIT, thing, com->type); + if (!com->set) { /* first time */ + if (isdef) { /* defender */ + com->troops = mil; + } else { /* attacker */ + if (!mil) + pr("No mil %s\n", prcom(1, com)); + else if (mil == 1) + pr("Only 1 mil %s\n", prcom(1, com)); + /* don't abandon attacking sectors or ships */ + com->troops = max(0, mil-1); + } + com->plague = (getvar(V_PSTAGE, thing, com->type)) == + PLG_INFECT; + } else { /* not first time */ + if (isdef) { /* defender */ + if (com->x != x || com->y != y) { + pr("%s has moved!\n", prcom(0, com)); + return att_combat_init(com, EF_BAD); + } + if (owner != com->own) { + if (owner) { + pr("WARNING: The ownership of %s just changed from %s to %s!\n", prcom(0, com), cname(com->own), cname(owner)); + } else if (com->type == EF_SECTOR) { + pr("WARNING: %s just abandoned sector %s!\n", cname(com->own), xyas(com->x,com->y,player->cnum)); + } + } + if (com->mil != mil) + pr("WARNING: The enemy mil %s just %s from %d to %d!\n", prcom(1, com), + com->mil < mil?"increased":"decreased", + com->mil, mil); + com->troops = mil; + } else { /* attacker */ + if (owner != player->cnum && + getrel(getnatp(owner), player->cnum) != ALLIED) { /* must be EF_SECTOR */ + if (com->mil) + pr("WARNING: Your %d mil in %s were destroyed because %s just took the sector!\n", com->mil, xyas(com->x,com->y,player->cnum), cname(owner)); + else + pr("You no longer own %s\n", + xyas(com->x,com->y,player->cnum)); + return att_combat_init(com, EF_BAD); + } + if (com->troops && com->troops + 1 > mil) { + if (com->own == owner && + player->cnum == owner) /* not a takeover */ + pr("WARNING: Your mil %s has been reduced from %d to %d!\n", prcom(1, com), com->troops, max(0,mil-1)); + com->troops = max(0,mil-1); + } + } + } + com->set = 1; + com->mil = mil; + com->own = owner; + com->x = x; + com->y = y; + com->eff = eff; + com->mob = mob; + return com->troops; +} + +/* + * In the course of the fight, the combat object may have lost mil, eff, or + * mobility. This is the place where the data in the object gets flushed to + * disk to make it "real". + */ + +static void +put_combat(struct combat *com) +{ + struct sctstr sect; + struct shpstr ship; + struct lndstr land; + int deff; + + switch (com->type) { + case EF_SECTOR: + getsect(com->x, com->y, §); + sect.sct_type = com->sct_type; + deff = sect.sct_effic - com->eff; + if (deff > 0) { + sect.sct_road -= (sect.sct_road * deff / 100.0); + sect.sct_rail -= (sect.sct_rail * deff / 100.0); + sect.sct_defense -= (sect.sct_defense * deff / 100.0); + if (sect.sct_road <= 0) + sect.sct_road = 0; + if (sect.sct_rail <= 0) + sect.sct_rail = 0; + if (sect.sct_defense <= 0) + sect.sct_defense = 0; + } + sect.sct_effic = com->eff; + if (!opt_DEFENSE_INFRA) + sect.sct_defense = sect.sct_effic; + if (com->mobcost) { + if (opt_MOB_ACCESS) { + if ((com->mob - com->mobcost) < -127) + sect.sct_mobil = -127; + else + sect.sct_mobil = (short)(com->mob - com->mobcost); + } else { + if ((com->mob - com->mobcost) < 0) + sect.sct_mobil = 0; + else + sect.sct_mobil = (short)(com->mob - com->mobcost); + } + } + makelost(EF_SECTOR, sect.sct_own, 0, sect.sct_x, sect.sct_y); + makenotlost(EF_SECTOR, com->own, 0, sect.sct_x, sect.sct_y); + sect.sct_own = com->own; + if (com->plague) { + if (getvar(V_PSTAGE, (s_char *)§, EF_SECTOR) == PLG_HEALTHY) + putvar(V_PSTAGE, PLG_EXPOSED, (s_char *)§, EF_SECTOR); + } + putvar(V_MILIT, com->mil, (s_char *)§, EF_SECTOR); + putsect(§); + com->own = sect.sct_own; /* avoid WARNING if sector reverts */ + break; + case EF_LAND: + getland(com->lnd_uid, &land); + land.lnd_effic = com->eff; + if (com->mobcost) { + if (com->mob - com->mobcost < -127) + land.lnd_mobil = -127; + else + land.lnd_mobil = (s_char)(com->mob - com->mobcost); + } + makelost(EF_LAND, land.lnd_own, land.lnd_uid, land.lnd_x, land.lnd_y); + land.lnd_own = com->own; + makenotlost(EF_LAND, land.lnd_own, land.lnd_uid, land.lnd_x, land.lnd_y); + if (com->plague) { + if (getvar(V_PSTAGE, (s_char *)&land, EF_LAND) == PLG_HEALTHY) + putvar(V_PSTAGE, PLG_EXPOSED, (s_char *)&land, EF_LAND); + } + if (!(com->lnd_lcp->l_flags & L_SPY)) + putvar(V_MILIT, com->mil, (s_char *)&land, EF_LAND); + lnd_count_units(&land); + if (com->own == player->cnum) { + land.lnd_mission = 0; + land.lnd_rflags = 0; + bzero(land.lnd_rpath, RET_LEN); + } + putland(com->lnd_uid, &land); + break; + case EF_SHIP: + getship(com->shp_uid, &ship); + ship.shp_effic = com->eff; + if (com->mobcost) { + if (com->mob - com->mobcost < -127) + ship.shp_mobil = -127; + else + ship.shp_mobil = + (s_char)(com->mob - com->mobcost); + } + makelost(EF_SHIP, ship.shp_own, ship.shp_uid, ship.shp_x, ship.shp_y); + ship.shp_own = com->own; + makenotlost(EF_SHIP, ship.shp_own, ship.shp_uid, ship.shp_x, ship.shp_y); + if (com->plague) { + if (getvar(V_PSTAGE, (s_char *)&ship, EF_SHIP) == PLG_HEALTHY) + putvar(V_PSTAGE, PLG_EXPOSED, (s_char *)&ship, EF_SHIP); + } + putvar(V_MILIT, com->mil, (s_char *)&ship, EF_SHIP); + count_units(&ship); + if (com->own == player->cnum) { + ship.shp_mission = 0; + ship.shp_rflags = 0; + bzero(ship.shp_rpath,RET_LEN); + } + putship(com->shp_uid, &ship); + } + com->mobcost = 0; + att_get_combat(com, com->own != player->cnum); +} + +/* If pre-attack, abort fight. If post-attack, don't move anything in */ + +static int +abort_attack(void) +{ + return player->aborted = 1; +} + +/* + * This is the combat_mode based integrity check. It splits among two main + * divisions: first time/not first time, and attack/assault/para/board. + */ + +int +att_abort(int combat_mode, struct combat *off, struct combat *def) +{ + struct sctstr sect; + int issneak; + s_char y_or_n[512]; + struct natstr *natp; + + if (player->aborted) + return 1; + if (att_get_combat(def, 1) < 0) + return abort_attack(); + + if (off && combat_mode != A_ATTACK) { + if (att_get_combat(off, 0) < 0) + return abort_attack(); + if (off->type == EF_SHIP && + (!getsect(off->x, off->y, §) || + sect.sct_type != SCT_WATER)) { + pr("%s can not %s from that far inland!\n", + prcom(0, off), + att_mode[combat_mode]); + return abort_attack(); + } + } + switch (combat_mode) { + case A_ATTACK: + if (!neigh(def->x, def->y, player->cnum) && + !adj_units(def->x, def->y, player->cnum)) { + pr("You are not adjacent to %s\n", xyas(def->x, def->y, player->cnum)); + return abort_attack(); + } + if (def->own == player->cnum) { + pr("You can't attack your own sector.\n"); + return abort_attack(); + } + break; + case A_ASSAULT: + if (off && mapdist(off->x, off->y, def->x, def->y) > 1) { + pr("You'll have to get there first...\n"); + return abort_attack(); + } + if (off && def->sct_type == SCT_MOUNT) { + pr("You can't assault a %s sector!\n", def->sct_dcp->d_name); + return abort_attack(); + } + break; + case A_PARA: + if (def->own == player->cnum) { + pr("You can't air-assault your own sector.\n"); + return abort_attack(); + } + if (off && (def->sct_type == SCT_MOUNT || + def->sct_type == SCT_WATER || + def->sct_type == SCT_CAPIT || + def->sct_type == SCT_FORTR || + def->sct_type == SCT_WASTE)) { + pr("You can't air-assault a %s sector!\n", + def->sct_dcp->d_name); + return abort_attack(); + } + break; + case A_BOARD: + return board_abort(off, def); + case A_LBOARD: + return land_board_abort(off, def); + } + + if (off && def->sct_dcp->d_mcst <= 0) { + pr("You can't %s a %s sector!\n", att_mode[combat_mode], + def->sct_dcp->d_name); + return abort_attack(); + } + if (!off || off->relations_checked) + return 0; + off->relations_checked = 1; + + if (opt_HIDDEN) { + setcont(player->cnum, def->own, FOUND_SPY); + setcont(def->own, player->cnum, FOUND_SPY); + } + if (opt_SLOW_WAR && def->own != player->cnum) { + natp = getnatp(player->cnum); + issneak = getrel(natp, def->own); + + if (issneak == ALLIED){ + sprintf(y_or_n,"Sector is owned by %s, your ally, %s [yn]? ",cname(def->own), att_mode[combat_mode]); + if (!confirm(y_or_n)) + return abort_attack(); + + } + if (opt_SNEAK_ATTACK) { + getsect(def->x, def->y, §); + if ((issneak != AT_WAR) && (def->own) && (def->own != player->cnum) && + (sect.sct_oldown != player->cnum) && (issneak != SITZKRIEG) && + (issneak != MOBILIZATION)) { + pr("You're not at war with them!\n"); + if (!confirm("Do you really want to sneak attack (it will cost you $5000) [yn]? ")){ + pr("Sneak attack cancelled!\n"); + return abort_attack(); + } + } + if ((issneak != AT_WAR) && (def->own) && (def->own != player->cnum) && + (sect.sct_oldown != player->cnum) && ((issneak == MOBILIZATION) || + (issneak == SITZKRIEG))) { + pr("You're not at war with them!\n"); + return abort_attack(); + } + } else { + if ((issneak != AT_WAR) && (def->own) && + (sect.sct_oldown != player->cnum)) { + pr("You're not at war with them!\n"); + return abort_attack(); + } + } + } + return 0; +} + +/* + * Lots of special things need to be checked for boarding, so I put it in + * it's own function. + */ + +static int +board_abort(struct combat *off, struct combat *def) +{ + struct shpstr aship, dship; /* for tech levels */ + struct sctstr sect; + + if (att_get_combat(def, 1) < 0) + return abort_attack(); + + if (!off) + return 0; + + if (att_get_combat(off, 0) < 0) + return abort_attack(); + + if (off->x != def->x || off->y != def->y) { + pr("Ship #%d is not in the same sector!\n", def->shp_uid); + return abort_attack(); + } + if (off->type == EF_SHIP) { + if (off->mob <= 0) { + pr("%s has no mobility!\n", prcom(0, off)); + return abort_attack(); + } + getship(off->shp_uid, &aship); + getship(def->shp_uid, &dship); + if (techfact(aship.shp_tech, 1.0) * + aship.shp_speed * off->eff <= + techfact(dship.shp_tech, 1.0) * + dship.shp_speed * def->eff) { + pr("Victim ship moves faster than you do!\n"); + if (def->own) + wu(0, def->own, + "%s (#%d) %s failed to catch %s\n", + cname(aship.shp_own), aship.shp_own, + pr_com(0, off, def->own), + pr_com(0, def, def->own)); + return abort_attack(); + } + } else if (off->type != EF_SECTOR) { + pr("Please tell the deity that you got the 'banana boat' error\n"); + return abort_attack(); + } + if (def->shp_mcp->m_flags & M_SUB) { + getsect(def->x, def->y, §); + if (sect.sct_type == SCT_WATER) { + pr("You can't board a submarine!\n"); + return abort_attack(); + } + } + return 0; +} + +/* + * Lots of special things need to be checked for boarding, so I put it in + * it's own function. + * STM - I copied it for land unit boarding. :) + */ + +static int +land_board_abort(struct combat *off, struct combat *def) +{ + if (att_get_combat(def, 1) < 0) + return abort_attack(); + + if (!off) + return 0; + + if (att_get_combat(off, 0) < 0) + return abort_attack(); + + if (off->x != def->x || off->y != def->y) { + pr("Land unit #%d is not in the same sector!\n", def->lnd_uid); + return abort_attack(); + } + + return 0; +} + +/* If we are boarding, then the defending ship gets a chance to fire back */ +int +att_approach(struct combat *off, struct combat *def) +{ + int dam; + struct sctstr sect; + struct shpstr ship; + + pr("Approaching %s...\n", prcom(0, def)); + if (def->own) + wu(0, def->own, + "%s is being approached by %s...\n", + pr_com(0, def, def->own), + pr_com(0, off, def->own)); + if (!(dam = shipdef(player->cnum, def->own, def->x, def->y))) + return 0; + + pr("They're firing at us sir!\n"); + if (def->own) { + wu(0, def->own, + "Your fleet at %s does %d damage to %s\n", + xyas(def->x, def->y, def->own), + dam, + pr_com(0, off, def->own)); + } + if (off->type == EF_SECTOR) { + getsect(off->x, off->y, §); + sectdamage(§, dam, 0); + putsect(§); + pr("Enemy fleet at %s does %d damage to %s\n", + xyas(def->x, def->y, player->cnum), + dam, prcom(0, off)); + } else if (off->type == EF_SHIP) { + getship(off->shp_uid, &ship); + shipdamage(&ship, dam); + putship(off->shp_uid, &ship); + if (def->own && ship.shp_effic < SHIP_MINEFF) { + wu(0, def->own, + "%s sunk!\n", pr_com(0, off, def->own)); + nreport(player->cnum, N_SHP_LOSE, def->own, 1); + } + } + if (att_get_combat(off, 0) < 0) + return abort_attack(); + return 0; +} + +/* The attack is valid. Tell the attacker about what they're going to hit */ + +int +att_show(struct combat *def) +{ + /* Note that we tell the player about the treaty BEFORE we tell them + about the item. If we didn't, then they gain free information */ + if (def->type == EF_SECTOR) { + if (!trechk(player->cnum, def->own, LANATT)) + return abort_attack(); + pr("%s is a %d%% %s %s with approximately %d military.\n", + xyas(def->x, def->y, player->cnum), + roundintby((int)def->eff, 10), + cname(def->own), def->sct_dcp->d_name, + roundintby(def->troops, 10)); + if (map_set(player->cnum, def->x, def->y, def->sct_dcp->d_mnem, 0)) + writemap(player->cnum); + } else if (def->type == EF_SHIP || def->type == EF_LAND) { + if (def->type == EF_SHIP) { + if (!trechk(player->cnum, def->own, SEAATT)) + return abort_attack(); + } else { + if (!trechk(player->cnum, def->own, LNDATT)) + return abort_attack(); + } + pr("%s is about %d%% efficient and has approximately %d mil on board.\n", + prcom(0, def), + roundintby((int)def->eff, 10), + roundintby(def->troops, 10)); + } + /* Ok, everything is fine */ + return 0; +} + +/* Attack and assault ask the user which kind of support they want */ + +int +att_ask_support(int offset, int *fortp, int *shipp, int *landp, int *planep) +{ + s_char buf[1024]; + s_char *p; + *fortp = *shipp = *landp = *planep = 1; + + if (player->argp[offset] != (s_char *)0){ + if ((player->argp[offset+1] == (s_char *)0) || + (player->argp[offset+2] == (s_char *)0) || + (player->argp[offset+3] == (s_char *)0)){ + pr("If any support arguments are used, all must be!\n"); + return RET_SYN; + } + + *fortp=*shipp=0; + *landp=*planep=0; + + if (!(p = getstarg(player->argp[offset], "Use fort support? ", buf))) + return RET_SYN; + + if ((*p == 'y') || (*p == 'Y')) + *fortp = 1; + + if (!(p = getstarg(player->argp[offset+1], "Use ship support? ", buf))) + return RET_SYN; + + if ((*p == 'y') || (*p == 'Y')) + *shipp = 1; + + if (!(p = getstarg(player->argp[offset+2], "Use land support? ", buf))) + return RET_SYN; + + if ((*p == 'y') || (*p == 'Y')) + *landp = 1; + + if (!(p = getstarg(player->argp[offset+3], "Use plane support? ", buf))) + return RET_SYN; + + if ((*p == 'y') || (*p == 'Y')) + *planep = 1; + } + return RET_OK; +} + +/* + * Attack, assault, and board ask the attacker what they'd like to attack + * with. This includes mil and land units from each "off" object. Note that + * after each sub-prompt, we check to make sure that the attack is still + * valid, and if it's not, then we abort the attack. + */ + +int +att_ask_offense(int combat_mode, struct combat *off, struct combat *def, struct emp_qelem *olist, int *a_spyp, int *a_engineerp) +{ + int n; + s_char land_answer[1024]; + + emp_initque(olist); + if (att_abort(combat_mode, off, def)) + return 0; + bzero(land_answer, sizeof(land_answer)); + for (n = 0; n <= off->last; ++n) { + off[n].troops = ask_off(combat_mode, off + n, def); + if (att_abort(combat_mode, off, def)) + return 0; + ask_olist(combat_mode, off + n, def, olist, land_answer, + a_spyp, a_engineerp); + if (att_abort(combat_mode, off, def)) + return 0; + } + return 0; +} + +/* How many mil is off allowed to attack with when it attacks def? */ + +static int +get_mob_support(int combat_mode, struct combat *off, struct combat *def) +{ + int mob_support; + + switch (combat_mode) { + case A_ATTACK: + mob_support = off->mob / sector_mcost(getsectp(def->x, def->y), + MOB_ROAD); + if (mob_support < 0) + mob_support = 0; +/* mob_support = off->mob / sector_mcost(def->sct_type, def->eff);*/ + if (mob_support < off->troops) + pr("Sector %s has %d mobility which can only support %d mil,\n", + xyas(off->x, off->y, player->cnum), + off->mob, + mob_support); + else + mob_support = off->troops; + return mob_support; + case A_ASSAULT: + if (def->own != player->cnum && def->mil) { + if (off->shp_mcp->m_flags & M_SEMILAND) + return off->troops/4; + else if (!(off->shp_mcp->m_flags & M_LAND)) + return off->troops/10; + } + break; + case A_BOARD: + if (off->type == EF_SECTOR && off->mob <= 0) + return 0; + mob_support = vl_find(V_MILIT, def->shp_mcp->m_vtype, + def->shp_mcp->m_vamt,def->shp_mcp->m_nv); + if (mob_support < off->troops) + pr("The size of the ship you are trying to board limits your party to %d mil,\n", mob_support); + else + mob_support = off->troops; + return mob_support; + case A_LBOARD: + if (off->mob <= 0) + return 0; + if (def->lnd_lcp->l_flags & L_SPY) + return 1; + mob_support = vl_find(V_MILIT, def->lnd_lcp->l_vtype, + def->lnd_lcp->l_vamt,def->lnd_lcp->l_nv); + if (mob_support < off->troops) + pr("The size of the unit you are trying to board limits your party to %d mil,\n", mob_support); + else + mob_support = off->troops; + return mob_support; + } + return off->troops; +} + +/* + * If the attacker decides to go through with the attack, then the + * sectors/ships they are attacking with may be charged some mobility. + * This is where that amount of mobility is calculated. It is actually + * subtracted "for real" from the object's mobility in put_combat(). + */ + +static void +calc_mobcost(int combat_mode, struct combat *off, struct combat *def, int attacking_mil) +{ + struct shpstr ship; + + if (!attacking_mil) + return; + switch (combat_mode) { + case A_ATTACK: + off->mobcost += + max(1, (int)(attacking_mil * sector_mcost(getsectp(def->x, def->y), MOB_ROAD))); + break; + case A_LBOARD: + off->mobcost += max(1, attacking_mil / 5); + break; + case A_BOARD: + switch (off->type) { + case EF_SECTOR: + off->mobcost += max(1, attacking_mil / 5); + break; + case EF_SHIP: + /* the 2 in the formula below is a fudge factor */ + getship(def->shp_uid, &ship); + off->mobcost += (def->eff / 100) * + (ship.shp_speed / 2); + } + } +} + +/* How many mil to we want to attack from off against def? */ + +static int +ask_off(int combat_mode, struct combat *off, struct combat *def) +{ + int attacking_mil; + int mob_support; + s_char prompt[512]; + + if (att_get_combat(off, 0) <= 0) + return 0; + if ((off->type == EF_SECTOR) && (off->own != player->cnum)) + return 0; + if ((mob_support = get_mob_support(combat_mode, off, def)) <= 0) + return 0; + if (off->type == EF_SECTOR) { + if (off->own != player->cnum) + return 0; + sprintf(prompt, "Number of mil from %s at %s (max %d) : ", + off->sct_dcp->d_name, + xyas(off->x, off->y, player->cnum), mob_support); + } else { + sprintf(prompt, "Number of mil from %s (max %d) : ", + prcom(0, off), mob_support); + } + if ((attacking_mil = onearg(0, prompt)) < 0) + abort_attack(); + if (att_abort(combat_mode, off, def)) + return 0; + if (att_get_combat(off, 0) <= 0) + return 0; + if ((attacking_mil = min(attacking_mil, min(mob_support, off->troops))) <= 0) + return 0; + + calc_mobcost(combat_mode, off, def, attacking_mil); + return attacking_mil; +} + +/* + * Which units would you like to attack with or move in with [ynYNq?] + */ + +static s_char +att_prompt(s_char *prompt, s_char army) +{ + s_char buf[1024]; + s_char *p = buf; + + if (army == ' ') + army = '~'; + *buf = -2; + while (!p || + (*p != 'y' && + *p != 'n' && + *p != 'Y' && + *p != 'N')) { + if (p && *p == 'q') { + abort_attack(); + return 'N'; + } + if (!p || !*p) + return 'n'; + if (p && *p != -2) + pr("y - yes this unit\nn - no this unit\nY - yes to all units in army '%c'\nN - no to all units in army '%c'\nq - quit\n? - this help message\n\n", army, army); + p = getstring(prompt, buf); + if (player->aborted) { + buf[0] = 'N'; + p = buf; + } + } + return *p; +} + +/* Ask the attacker which units they want to attack/assault/board with */ + +static void +ask_olist(int combat_mode, struct combat *off, struct combat *def, struct emp_qelem *olist, s_char *land_answer, int *a_spyp, int *a_engineerp) +{ + struct nstr_item ni; + struct lndstr land; + double mobcost; + struct llist *llp; + struct lchrstr *lcp; + int att_val; + int count = 0; + int maxland = 0; + int first_time = 1; + s_char prompt[512]; + + if (def->type == EF_LAND) + return; + if (def->type == EF_SHIP) + maxland = def->shp_mcp->m_nland; + + snxtitem_xy(&ni,EF_LAND,off->x,off->y); + while(nxtitem(&ni,(s_char *)&land)){ + if (land.lnd_own != player->cnum) + continue; + if (land.lnd_effic < LAND_MINEFF) + continue; + if (land_answer[(int)land.lnd_army] == 'N') + continue; + if (!lnd_can_attack(&land)) + continue; + lcp = &lchr[(int)land.lnd_type]; + + if (def->type == EF_SHIP && !maxland) { + pr("Land units are not able to board this kind of ship\n"); + return; + } + if (land.lnd_mobil <= 0) { + pr("%s is out of mobility, and cannot %s\n", + prland(&land), + att_mode[combat_mode]); + continue; + } + + if (opt_MARKET) { + if (ontradingblock(EF_LAND, (int *)&land)) { + pr("%s is on the trading block, and cannot %s\n", + prland(&land), att_mode[combat_mode]); + continue; + } + } + + if (off->type == EF_SECTOR && land.lnd_ship >= 0) { + pr("%s is on ship #%d, and cannot %s\n", + prland(&land), land.lnd_ship, + att_mode[combat_mode]); + continue; + } else if (off->type == EF_SHIP) { + if (land.lnd_ship != off->shp_uid) + continue; + } else if (land.lnd_land >= 0) { + pr("%s is on unit #%d, and cannot %s\n", + prland(&land), land.lnd_land, att_mode[combat_mode]); + continue; + } + switch (combat_mode) { + case A_ATTACK: + mobcost = lnd_mobcost(&land, getsectp(def->x, def->y), MOB_NONE); + if (land.lnd_mobil < mobcost) { + pr("%s does not have enough mobility (%d needed)\n", + prland(&land), + (int)mobcost + 1); + continue; + } + break; + case A_ASSAULT: + case A_BOARD: + mobcost = 0; + if (!(lcp->l_flags & L_ASSAULT)) + continue; + } + att_val = attack_val(combat_mode, &land); + if (!att_val) { + pr("%s has no offensive strength\n", + prland(&land)); + continue; + } + resupply_all(&land); + putland(land.lnd_uid,&land); + if (!has_supply(&land)){ + pr("%s is out of supply, and cannot %s\n", + prland(&land), att_mode[combat_mode]); + continue; + } + if (def->type == EF_SHIP && first_time) { + first_time = 0; + pr("You may board with a maximum of %d land units\n", maxland); + } + pr("%s has a base %s value of %d\n", + prland(&land), + att_mode[combat_mode], + att_val); + if (land_answer[(int)land.lnd_army] != 'Y') { + sprintf(prompt, + "%s with %s %s (%c %d%%) [ynYNq?] ", + att_mode[combat_mode], + prland(&land), + prcom(1, off), + land.lnd_army==' '?'~':land.lnd_army, + land.lnd_effic); + land_answer[(int)land.lnd_army] = + att_prompt(prompt, land.lnd_army); + if (att_abort(combat_mode, off, def)) + return; + if (land_answer[(int)land.lnd_army] != 'y' && + land_answer[(int)land.lnd_army] != 'Y') + continue; + } + if (!(llp = (struct llist *)malloc(sizeof(struct llist)))) { + logerror("Malloc failed in attack!\n"); + abort_attack(); + return; + } + bzero((s_char *)llp,sizeof(struct llist)); + emp_insque(&llp->queue,olist); + llp->mobil = mobcost; + if (!get_land(combat_mode, def, land.lnd_uid, llp, 0)) + continue; + if (lnd_spyval(&land) > *a_spyp) + *a_spyp = lnd_spyval(&land); + if (llp->lcp->l_flags & L_ENGINEER) + ++(*a_engineerp); + if (def->type == EF_SHIP && ++count >= maxland) + break; + } +} + +/* What's the offense or defense multiplier? */ + +double +att_combat_eff(struct combat *com) +{ + double eff = 1.0; + double str; + double sector_strength(struct sctstr *sp); + struct shpstr ship; + + if (com->type == EF_SECTOR) { + eff = com->eff / 100.0; + if (com->own == player->cnum) { + str = com->sct_dcp->d_ostr; + eff = 1.0 + ((str - 1.0) * eff); + } else + eff = sector_strength(getsectp(com->x, com->y)); +/* str = com->sct_dcp->d_dstr;*/ + } else if (com->type == EF_SHIP && com->own != player->cnum) { + getship(com->shp_uid, &ship); + eff = (1.0 + ship.shp_armor / 100.0); + } + return eff; +} + +/* + * Estimate the defense strength and give the attacker a chance to abort + * if the odds are less than 50% + */ + +int +att_estimate_defense(int combat_mode, struct combat *off, struct emp_qelem *olist, struct combat *def, int a_spy) +{ + int ototal; + int estimate; + int odds; + + /* + * Get the attacker units & mil again in case they changed while the + * attacker was answering sub-prompts. + */ + + ototal = get_ototal(combat_mode, off, olist, 1.0, 1); + if (att_empty_attack(combat_mode, ototal, def)) + return abort_attack(); + if (combat_mode == A_PARA) + return ototal; + pr("\n Initial attack strength: %8d\n", ototal); + + estimate = att_combat_eff(def) * roundintby(def->troops, 10); + estimate += att_combat_eff(def) * get_dlist(def, 0, a_spy, 0); + + /* + * Calculate the initial (pre-support) attack odds. If they're less + * than 50%, ask for a confirmation. + */ + + odds = (int)(att_calcodds(ototal,estimate) * 100); + +/* + if (odds < 50) { + pr(" Estimated defense strength: %8d\n", estimate); + pr(" Estimated odds: %8d%%\n\n",odds); + sprintf(prompt, "Are you sure you want to %s [yn]? ", + att_mode[combat_mode]); + if (!confirm(prompt)) + return abort_attack(); + ototal = get_ototal(combat_mode, off, olist,1.0,1); + if (att_empty_attack(combat_mode, ototal, def)) + return abort_attack(); + } + */ + return ototal; +} + +/* Get the defensive units and reacting units */ +int +att_get_defense(struct emp_qelem *olist, struct combat *def, struct emp_qelem *dlist, int a_spy, int ototal) +{ + int d_spy = 0; + struct emp_qelem *qp; + struct llist *llp; + int dtotal; + int old_dtotal; + + emp_initque(dlist); + get_dlist(def, dlist, 0, &d_spy); + dtotal = get_dtotal(def,dlist,1.0,0); + + /* + * Call in reacting units + */ + + if (def->type == EF_SECTOR && def->sct_type != SCT_MOUNT) + att_reacting_units(def, dlist, a_spy, &d_spy, ototal); + + for (qp = olist->q_forw; qp != olist; qp = qp->q_forw) { + llp = (struct llist *)qp; + intelligence_report(def->own, &llp->land, d_spy, + "Scouts report attacking unit:"); + } + + old_dtotal = dtotal; + dtotal = get_dtotal(def,dlist,1.0,0); + if (dtotal != old_dtotal) + pr("Defense strength with reacting units: %8d\n", dtotal); + + return dtotal; +} + +/* Get the defensive land units in the sector or on the ship */ + +static int +get_dlist(struct combat *def, struct emp_qelem *list, int a_spy, int *d_spyp) +{ + struct nstr_item ni; + struct llist *llp; + struct lndstr land; + int estimate = 0; + +/* In here is where you need to take out spies and trains from the defending + lists. Spies try to hide, trains get trapped and can be boarded. */ + + snxtitem_xy(&ni,EF_LAND,def->x,def->y); + while(nxtitem(&ni,(s_char *)&land)){ + if (!land.lnd_own) + continue; + if (land.lnd_own != def->own) + continue; + if (def->type == EF_SECTOR && land.lnd_ship >= 0) + continue; + if (def->type == EF_SECTOR && land.lnd_land >= 0) + continue; + if (def->type == EF_SHIP && land.lnd_ship != def->shp_uid) + continue; + if (def->type == EF_LAND && land.lnd_land != def->lnd_uid) + continue; + if (!list) { /* Just estimating the enemy strength */ + estimate += intelligence_report(player->cnum, + &land,a_spy, + "Scouts report defending unit:"); + continue; + } + if (!(llp = (struct llist *)malloc(sizeof(struct llist)))) { + logerror("Malloc failed in attack!\n"); + abort_attack(); + return 0; + } + bzero((s_char *)llp,sizeof(struct llist)); + emp_insque(&llp->queue,list); + llp->supplied = has_supply(&land); + if (!get_land(A_DEFEND,def,land.lnd_uid, llp, 1)) + continue; + if (lnd_spyval(&land) > *d_spyp) + *d_spyp = lnd_spyval(&land); + } + return estimate; +} + +/* Calculate the total offensive strength */ + +static int +get_ototal(int combat_mode, struct combat *off, struct emp_qelem *olist, double osupport, int check) +{ + double ototal=0.0; + struct emp_qelem *qp, *next; + struct llist *llp; + int n,w; + + /* + * first, total the attacking mil + */ + + for (n = 0; n <= off->last; ++n) { + if (off[n].type == EF_BAD || (check && + att_get_combat(&off[n], 0) <= 0)) + continue; + ototal += off[n].troops * att_combat_eff(off + n); + } + + /* + * next, add in the attack_values of all + * the attacking units + */ + + for (qp = olist->q_forw; qp != olist; qp = next) { + next = qp->q_forw; + llp = (struct llist *)qp; + if (check && !get_land(combat_mode,0,llp->land.lnd_uid, llp, 0)) + continue; + if (combat_mode == A_ATTACK) { + w=-1; + for(n = 0;n <= off->last; ++n) { + if (off[n].type == EF_BAD) + continue; + if ((off[n].x == llp->land.lnd_x) && + (off[n].y == llp->land.lnd_y)) + w = n; + } + if (w < 0) { + lnd_delete(llp, "is in a sector not owned by you"); + continue; + } + ototal += attack_val(combat_mode, &llp->land) * + att_combat_eff(off + w); + } else { + ototal += attack_val(combat_mode, &llp->land); + } + } + ototal *= osupport; + + return ldround(ototal, 1); +} + +/* Calculate the total defensive strength */ + +static int +get_dtotal(struct combat *def, struct emp_qelem *list, double dsupport, int check) +{ + double dtotal=0.0, eff = 1.0, d_unit; + struct emp_qelem *qp, *next; + struct llist *llp; + + if (check && att_get_combat(def, 1) < 0) + return 0; + eff = att_combat_eff(def); + dtotal = def->troops * eff; + + /* + * next, add in the defense_values of all + * the defending non-retreating units + */ + + for (qp = list->q_forw; qp != list; qp = next) { + next = qp->q_forw; + llp = (struct llist *)qp; + d_unit = 0.0; + if (check && !get_land(A_DEFEND,def,llp->land.lnd_uid, llp, 1)) + continue; + d_unit = defense_val(&llp->land); + if (!llp->supplied) + d_unit = ((double)defense_val(&llp->land)/2.0); + dtotal += d_unit * eff; + } + + dtotal *= dsupport; + + return ldround(dtotal,1); +} + +/* + * This is the land unit integrity check. Note that we don't print + * warnings about victim land units because the attacker may not have seen them + */ + +static int +get_land(int combat_mode, struct combat *def, int uid, struct llist *llp, int victim_land) +{ + struct lndstr *lp = &llp->land; + s_char buf[512]; + + getland(uid, lp); + + if (!llp->lcp) { /* first time */ + llp->x = llp->land.lnd_x; + llp->y = llp->land.lnd_y; + llp->lcp = &lchr[(int)llp->land.lnd_type]; + } else { /* not first time */ + if (lp->lnd_effic < LAND_MINEFF) { + sprintf(buf, "was destroyed and is no longer a part of the %s", att_mode[combat_mode]); + lnd_delete(llp, buf); + return 0; + } + if (victim_land) { + if (lp->lnd_x != def->x || lp->lnd_y != def->y) { + lnd_delete(llp, "left to go fight another battle and is no longer a part of the defense"); + return 0; + } + } else { + if (lp->lnd_own != player->cnum) { + sprintf(buf, "was destroyed and is no longer a part of the %s", att_mode[combat_mode]); + lnd_delete(llp, buf); + return 0; + } + if (lp->lnd_x != llp->x || lp->lnd_y != llp->y) { + sprintf(buf, "left to fight another battle and is no longer a part of the %s", att_mode[combat_mode]); + lnd_delete(llp, buf); + return 0; + } + if (lp->lnd_effic < llp->eff) { + sprintf(buf, "damaged from %d%% to %d%%", + llp->eff, lp->lnd_effic); + lnd_print(llp, buf); + } + } + } + llp->eff = llp->land.lnd_effic; + + return 1; +} + +/* + * Put the land unit on the disk. If there was some mobility cost, then + * subtract it from the units mobility. Note that this works the same way + * as sectors & ships in that no mobility is actually taken until the attacker + * has committed to attacking. + */ + +static void +kill_land(struct emp_qelem *list) +{ + struct emp_qelem *qp, *next; + struct llist *llp; + + for (qp = list->q_forw; qp != list; qp = next) { + next = qp->q_forw; + llp = (struct llist *)qp; + if (llp->land.lnd_ship >= 0) { + llp->land.lnd_effic=0; + lnd_delete(llp, "cannot return to the ship, and dies!"); + } + } +} + +static void +att_infect_units(struct emp_qelem *list, int plague) +{ + struct emp_qelem *qp, *next; + struct llist *llp; + + if (!plague) + return; + for (qp = list->q_forw; qp != list; qp = next) { + next = qp->q_forw; + llp = (struct llist *)qp; + if (getvar(V_PSTAGE, (s_char *)&(llp->land), EF_LAND) == PLG_HEALTHY) + putvar(V_PSTAGE, PLG_EXPOSED, (s_char *)&(llp->land), EF_LAND); + } +} + +static void +put_land(struct emp_qelem *list) +{ + struct emp_qelem *qp, *next; + struct llist *llp; + + for (qp = list->q_forw; qp != list; qp = next) { + next = qp->q_forw; + llp = (struct llist *)qp; + llp->land.lnd_mission=0; + llp->land.lnd_harden=0; + llp->land.lnd_mobil -= (int)llp->mobil; + llp->mobil = 0.0; + putland(llp->land.lnd_uid, &llp->land); + if (llp->land.lnd_own != player->cnum) { + emp_remque((struct emp_qelem *)llp); + free((s_char *)llp); + } else + get_land(A_ATTACK,0, llp->land.lnd_uid, llp, 0); + } +} + +/* + * Keep sending in reinforcements until it looks like we're going to win. + * Note that the "strength" command also calls this routine. + */ + +int +att_reacting_units(struct combat *def, struct emp_qelem *list, int a_spy, int *d_spyp, int ototal) +{ + struct nstr_item ni; + struct lndstr land; + struct sctstr sect, dsect; + struct llist *llp; + int dtotal; + int new_land = 0; + double mobcost; + double move_cost; + int supply_state; + int dist; + int radius; + int origx, origy; + double eff = att_combat_eff(def); + s_char *p; + s_char buf[1024]; + + /* + * + * All units that are within their reaction radius and not damaged + * below their morale value now get to react to the threatened sect. + * Once we've sent enough to counter the threat, stop sending them. + * + * Not anymore. All units get to react. :) + */ + + if (list) + dtotal = get_dtotal(def, list, 1.0, 1); + else + dtotal = 0; + snxtitem_all(&ni,EF_LAND); + while(nxtitem(&ni,(s_char *)&land) && + (dtotal + new_land * eff < (int)(1.2*(float)ototal))){ + if (!land.lnd_own) + continue; + if (!land.lnd_rad_max) + continue; + if ((land.lnd_x == def->x) && (land.lnd_y == def->y)) + continue; + if (land.lnd_own != def->own) + continue; + if (land.lnd_ship >= 0) + continue; + if (!defense_val(&land)) + continue; +/* + if (land.lnd_effic <= land.lnd_retreat) + continue; + */ + if (!lnd_can_attack(&land)) + continue; + + /* Only supplied units can react */ + if (!(supply_state=has_supply(&land))) + continue; + + dist = mapdist(land.lnd_x,land.lnd_y,def->x,def->y); + + getsect(land.lnd_x, land.lnd_y, §); + /* Units on efficient headquarters can react 1 farther */ + if ((sect.sct_type == SCT_HEADQ) && (sect.sct_effic >= 60)) + radius=land.lnd_rad_max+1; + else + radius=land.lnd_rad_max; + + if (land.lnd_mission == MI_RESERVE) + radius += 2; + + if (dist > radius) + continue; + + getsect(def->x, def->y, &dsect); + if (!(p = (s_char *)BestLandPath(buf, §, &dsect, &move_cost, MOB_ROAD))) + continue; + + mobcost = land.lnd_effic * 0.01*lchr[(int)land.lnd_type].l_spd; + if (mobcost < 0.01) + mobcost = 0.01; + mobcost = 480.0 / (mobcost + techfact(land.lnd_tech, mobcost)); + mobcost *= (move_cost * 5.0); + + if (land.lnd_mobil < mobcost) + continue; + + new_land += defense_val(&land); + + if (!list) /* we are in the "strength" command */ + continue; + + /* move to defending sector */ + land.lnd_mobil -= ldround(mobcost,1); + origx = land.lnd_x; + origy = land.lnd_y; + land.lnd_x = def->x; + land.lnd_y = def->y; + putland(land.lnd_uid,&land); + wu(0,land.lnd_own,"%s reacts to %s.\n", + prland(&land), + xyas(land.lnd_x,land.lnd_y,land.lnd_own)); + + llp = (struct llist *) + malloc(sizeof(struct llist)); + + bzero((s_char *)llp,sizeof(struct llist)); + llp->supplied = supply_state; + llp->x = origx; + llp->y = origy; + llp->lcp = &lchr[(int)land.lnd_type]; + bcopy((s_char *)&land,(s_char *)&llp->land,sizeof(struct lndstr)); + emp_insque(&llp->queue, list); + if (lnd_spyval(&land) > *d_spyp) + *d_spyp = lnd_spyval(&land); + + intelligence_report(player->cnum,&land,a_spy, + "Scouts sight reacting enemy unit:"); + } + return new_land; +} + +/* Pop off shells and fly bombing missions to get your attack multiplier up */ + +static double +get_osupport(s_char *outs, struct combat *def, int fort_sup, int ship_sup, int land_sup, int plane_sup) +{ + double osupport = 1.0; + int dam; + double af, as, au, ap; + + af = as = au = ap = 0.0; + if (fort_sup) { + dam = dd(def->own, player->cnum, def->x, def->y, 0, 0); + af = ((double)dam/100.0); + osupport += af; + } + if (ship_sup){ + dam = sd(def->own, player->cnum, def->x, def->y, 0, 0, 0); + + as = ((double)dam/100.0); + osupport += as; + } + + if (land_sup){ + dam = lnd_support(def->own, player->cnum, def->x, def->y); + au = ((double)dam/100.0); + osupport += au; + } + + if (plane_sup){ + dam = off_support(def->x,def->y,def->own,player->cnum); + ap = (((double)dam)/100.0); + osupport += ap; + } + sprintf(outs,"attacker\t%1.2f\t%1.2f\t%1.2f\t%1.2f\n",af,as,au,ap); + return osupport; +} + +/* Pop off shells and fly bombing missions to get your defense multiplier up */ + +static double +get_dsupport(s_char *outs, struct emp_qelem *list, struct combat *def, int ototal, int dtotal) +{ + double dsupport = 1.0; + int dam; + double df, ds, du, dp; + int good = 0; + + df = ds = du = dp = 0.0; + if (dtotal < 0.1 * ototal) { + good = -1; + } else if (dtotal >= 1.2 * ototal) { + good = 1; + } else { + dam = dd(player->cnum, def->own, def->x, def->y, 0, 1); + df = ((double)dam/100.0); + dsupport += df; + + dtotal = get_dtotal(def,list,dsupport,0); + if ( dtotal < 1.2 * ototal) { + dam = sd(player->cnum, def->own, def->x, def->y, 0, 1, 0); + ds = ((double)dam/100.0); + dsupport += ds; + dtotal = get_dtotal(def,list,dsupport,0); + } + if ( dtotal < 1.2 * ototal) { + dam = lnd_support(player->cnum, def->own, def->x, def->y); + du = ((double)dam/100.0); + dsupport += du; + dtotal = get_dtotal(def,list,dsupport,1); + } + if ( dtotal < 1.2 * ototal) { + dam = def_support(def->x,def->y,player->cnum,def->own); + dp = (((double)dam)/100.0); + dsupport += dp; + } + } + if (good) + *outs = '\0'; + else + sprintf(outs,"defender\t%1.2f\t%1.2f\t%1.2f\t%1.2f\n\n",df,ds,du,dp); + if (def->own) { + if (good < 0) + wu(0,def->own,"\nOdds are bad for us...support cancelled.\n\n"); + else if (good > 0) + wu(0,def->own,"\nOdds are good for us...support cancelled.\n\n"); + } + return dsupport; +} + +/* + * Land mines add to the defense multiplier. If the attacker has engineers + * then this multipluer is cut in half. + */ + +static double +get_mine_dsupport(struct combat *def, int a_engineer) +{ + int mines; + struct sctstr sect; + + getsect(def->x, def->y, §); + + if (sect.sct_oldown != player->cnum){ + mines = getvar(V_MINE, (s_char *)§, EF_SECTOR); + mines = min(mines,20); + if (a_engineer) + mines = ldround(((double)mines/2.0),1); + if (mines > 0){ + if (def->own) + wu(0,def->own,"Defending mines add %1.2f\n", mines * 0.02); + pr("Defending mines add %1.2f\n", mines * 0.02); + return mines * 0.02; + } + } + return 0.0; +} + +/* Get the offensive and defensive support */ +int +att_get_support(int combat_mode, int ofort, int oship, int oland, int oplane, struct emp_qelem *olist, struct combat *off, struct emp_qelem *dlist, struct combat *def, double *osupportp, double *dsupportp, int a_engineer) +{ + int ototal, dtotal; + s_char osupports[512]; + s_char dsupports[512]; + + if (combat_mode == A_PARA) + *osupports = '\0'; + else + *osupportp = get_osupport(osupports, def, + ofort, oship, oland, oplane); + + /* + * I need to put a 1 at the end of the next four total_stren calls + * becauase units & mil may have been damaged by collateral damage or + * neclear warheads from the offensive & defensive support. + */ + + ototal = get_ototal(combat_mode,off,olist,*osupportp,1); + if (att_empty_attack(combat_mode, ototal, def)) + return abort_attack(); + dtotal = get_dtotal(def,dlist,*dsupportp,1); + + /* + * Calculate defensive support. If odds are too good or too bad + * then don't call in support. + */ + + *dsupportp = get_dsupport(dsupports, dlist, def, ototal, dtotal); + ototal = get_ototal(combat_mode,off,olist,*osupportp,1); + if (att_empty_attack(combat_mode, ototal, def)) + return abort_attack(); + + if ((*osupports || *dsupports) && + (*osupportp != 1.0 || *dsupportp != 1.0)) { + pr("\n\t\tsupport values\n"); + pr("\t\tforts\tships\tunits\tplanes\n"); + if (*osupportp != 1.0) + pr("%s", osupports); + if (*dsupportp != 1.0) + pr("%s", dsupports); + if (def->own) { + wu(0,def->own,"\n\t\tsupport values\n"); + wu(0,def->own,"\t\tforts\tships\tunits\tplanes\n"); + if (*osupportp != 1.0) + wu(0, def->own, "%s", osupports); + if (*dsupportp != 1.0) + wu(0, def->own, "%s", dsupports); + } + } + + dtotal = get_dtotal(def,dlist,*dsupportp,1); + if (dtotal && def->type == EF_SECTOR) + *dsupportp += get_mine_dsupport(def, a_engineer); + return 0; +} + +/* How many two-legged bipeds are in this combat force? */ + +static int +count_bodies(struct combat *off, struct emp_qelem *list) +{ + int n; + int bodies = 0; + struct emp_qelem *qp; + struct llist *llp; + + for (n = 0; n <= off->last; ++n) + bodies += off[n].troops; + for (qp=list->q_forw;qp!=list;qp=qp->q_forw) { + llp = (struct llist *)qp; + bodies += total_mil(&llp->land); + } + return bodies; +} + +/* This is where the fighting actually occurs. */ + +int +att_fight(int combat_mode, struct combat *off, struct emp_qelem *olist, double osupport, struct combat *def, struct emp_qelem *dlist, double dsupport) +{ + int success = 0; + int a_cas = 0; /* Casualty counts */ + int d_cas = 0; + int ototal; /* total attacking strength */ + int dtotal; /* total defending strength */ + int a_bodies; /* total attacking mil (incl. mil in units) */ + int d_bodies; /* total defending mil (incl. mil in units) */ + int d_mil; + int a_troops[6]; + int n; + int news_item; + int recalctime; + double odds; + s_char *action; + + ototal = get_ototal(combat_mode,off,olist,osupport, + combat_mode != A_PARA); + dtotal = get_dtotal(def,dlist,dsupport,0); + if (!dtotal) + success = 1; + + a_bodies = count_bodies(off, olist); + d_bodies = count_bodies(def, dlist); + d_mil = def->troops; + for (n=0; n <= off->last; ++n) + if (off[n].type == EF_BAD) + a_troops[n] = 0; + else + a_troops[n] = off[n].troops; + + /* This switch is required to get the spacing right */ + switch (combat_mode) { + case A_ATTACK: + pr(" Final attack strength: %8d\n", ototal); + break; + case A_ASSAULT: + pr(" Final assault strength: %8d\n", ototal); + break; + case A_PARA: + if (def->sct_type == SCT_MOUNT || + def->sct_type == SCT_WATER || + def->sct_type == SCT_CAPIT || + def->sct_type == SCT_FORTR || + def->sct_type == SCT_WASTE) { + pr("You can't air-assault a %s sector!\n", + def->sct_dcp->d_name); + a_cas = a_bodies; + off[0].troops = 0; + ototal = get_ototal(A_PARA,off,olist,osupport, 0); + } + pr(" Final air-assault strength: %8d\n", ototal); + break; + case A_BOARD: + case A_LBOARD: + pr(" Final board strength: %8d\n", ototal); + } + + + pr(" Final defense strength: %8d\n",dtotal); + odds = att_calcodds(ototal,dtotal); + pr(" Final odds: %8d%%\n",(int)(odds*100)); + + /* spread the plague */ + if (combat_mode != A_PARA) { + if (!def->plague) + for (n = 0; n <= off->last; ++n) + if (off[n].type != EF_BAD) + def->plague |= off[n].plague; + for (n = 0; n <= off->last; ++n) + if (off[n].type != EF_BAD) + off[n].plague |= def->plague; + } + att_infect_units(olist, off->plague); + att_infect_units(dlist, def->plague); + + /* Fighting is slightly random. There is always that last little + * effort you see people put in. Or the stray bullet that takes out + * an officer and the rest go into chaos. Things like that. + * Thus, we have added a very slight random factor that will sometimes + * allow the little guy to win. We modify the odds a little + * (either +- 5%) to account for this randomness. We also only + * recalculate the odds every 8-50 casualties, not every cacsualty, + * since a single dead guy normally wouldn't cause a commander to + * rethink his strategies, but 50 dead guys might. */ + odds = odds + (double)((double)((random() % 11) - 5) / 100.0); + if (odds < 0.0) + odds = 0.1; + if (odds > 1.0) + odds = 1.0; + recalctime = 8 + (random() % 43); + while (!success && ototal){ + if (chance(odds)) { + pr("!"); + d_cas += take_casualty(A_DEFEND,def,dlist); + dtotal = get_dtotal(def,dlist,dsupport,0); + if (!dtotal) + ++success; + } else { + pr("@"); + a_cas += take_casualty(combat_mode,off,olist); + ototal = get_ototal(combat_mode,off,olist,osupport,0); + } + if (((a_cas + d_cas) % 70) == 69) + pr("\n"); + if (recalctime-- <= 0) { + recalctime = 8 + (random() % 43); + odds = att_calcodds(ototal,dtotal); + odds = odds + (double)((double)((random() % 11) - 5) / 100.0); + if (odds < 0.0) + odds = 0.1; + if (odds > 1.0) + odds = 1.0; + } + } + pr("\n"); + /* update defense mobility & mil */ + if (success) + def->mil = 0; + else { + if (def->type == EF_SECTOR && d_mil && d_cas) { + int tmob; + + /* Make sure we use a positive mobility here */ + tmob = ((def->mob < 0) ? -(def->mob) : (def->mob)); + def->mobcost = min(20, min(1, tmob - damage(tmob, 100 * d_cas / d_mil))); + } + def->mil = def->troops; + } + + /* update attack mobility & mil */ + for (n=0; n <= off->last; ++n) + if (off[n].type != EF_BAD && off[n].troops < a_troops[n]) { + if (off[n].type == EF_SECTOR && off[n].mil) + off[n].mobcost += min(20,min(1, off[n].mob - damage(off[n].mob, 100 * (a_troops[n] - off[n].troops) / off[n].mil))); + off[n].mil -= a_troops[n] - off[n].troops; + } + + /* update land unit mobility */ + if (d_bodies && d_cas) + lnd_takemob(dlist, (double)d_cas / d_bodies); + if (a_bodies && a_cas) + lnd_takemob(olist, (double)a_cas / a_bodies); + + /* damage attacked sector */ + def->eff = effdamage(def->eff, (d_cas + a_cas)/10); + + pr("- Casualties -\n Yours: %d\n", a_cas); + pr(" Theirs: %d\n", d_cas); + pr("Papershuffling ... %.1f B.T.U\n", (d_cas + a_cas) * 0.15); + player->btused += (int) ((d_cas + a_cas) * 0.015 + 0.5); + + if (success) { + switch (combat_mode) { + case A_ATTACK: + news_item = def->own?N_WON_SECT:N_TOOK_UNOCC; + pr("We have captured %s, sir!\n", prcom(0, def)); + action = "taking"; break; + case A_ASSAULT: + news_item = def->own?N_AWON_SECT:N_START_COL; + pr("We have secured a beachhead at %s, sir!\n", prcom(0, def)); + action = "assaulting and taking"; break; + case A_PARA: + news_item = def->own?N_PWON_SECT:N_PARA_UNOCC; + pr("We have captured %s, sir!\n", prcom(0, def)); + action = "air-assaulting and taking"; break; + case A_BOARD: + news_item = N_BOARD_SHIP; + pr("We have boarded %s, sir!\n", prcom(0, def)); + action = "boarding"; break; + case A_LBOARD: + news_item = N_BOARD_LAND; + pr("We have boarded %s, sir!\n", prcom(0, def)); + action = "boarding"; break; + } + } else { + switch (combat_mode) { + case A_ATTACK: + news_item = N_SCT_LOSE; + pr("You have been defeated!\n"); + action = "attacking"; + break; + case A_ASSAULT: + news_item = N_ALOSE_SCT; + pr("You have been defeated!\n"); + kill_land(olist); + action = "trying to assault"; + break; + case A_PARA: + news_item = N_PLOSE_SCT; + pr("All of your troops were destroyed\n"); + action = "trying to air-assault"; + break; + case A_BOARD: + news_item = N_SHP_LOSE; + pr("You have been repelled\n"); + kill_land(olist); + action = "trying to board"; + break; + case A_LBOARD: + news_item = N_LND_LOSE; + pr("You have been repelled\n"); + kill_land(olist); + action = "trying to board"; + break; + } + } + nreport(player->cnum, news_item, def->own, 1); + if (def->own) { + wu(0, def->own, + "%s (#%d) lost %d troops %s %s\nWe lost %d troops defending\n", + cname(player->cnum), player->cnum, a_cas, + action, + pr_com(0, def, def->own), + d_cas); + } + + if (opt_SNEAK_ATTACK) { + do_sneak(def, success); + } + + send_reacting_units_home(def, dlist); + + /* putland the defending land */ + lnd_put(dlist, 0); + + /* putland the attacking land */ + put_land(olist); + + /* put the victim sector/ship/land */ + if (!success || !take_def(combat_mode, olist, off, def)) + put_combat(def); + + /* put the attacking sectors/ship */ + for (n = 0; n <= off->last; ++n) + if (off[n].type != EF_BAD) + put_combat(&off[n]); + + if (!success) + return 0; + + switch (combat_mode) { + case A_ATTACK: + ask_move_in(off, olist, def); + + /* put sectors again to get abandon warnings */ + for (n = 0; n <= off->last; ++n) + if (off[n].type != EF_BAD) + put_combat(&off[n]); + break; + default: + att_move_in_off(combat_mode, off, olist, def); + } + if (def->mil > 0) + pr("%d of your troops now occupy %s\n", def->mil, prcom(0, def)); + return 1; +} + +/* What percentage of the combat forces going head-to-head are we? */ + +double +att_calcodds(int ototal, int dtotal) +{ + double odds; + + /* calculate odds */ + if (ototal <= 0) + odds = 0.0; + else if (dtotal <=0) + odds = 1.0; + else + odds = ((double)ototal) / (dtotal + ototal); + + return odds; +} + +/* Here's where the dead soldiers get dragged off the battlefield */ + +static int +take_casualty(int combat_mode, struct combat *off, struct emp_qelem *olist) +{ + int to_take = CASUALTY_LUMP; + int biggest_troops = 0, index = -1; + int n, tot_troops = 0, biggest_mil, cas; + struct emp_qelem *qp, *biggest; + struct llist *llp; + + for (n = 0; n <= off->last; ++n) { + if (off[n].type != EF_BAD) { + tot_troops += off[n].troops; + if (off[n].troops > biggest_troops) { + biggest_troops = off[n].troops; + index = n; + } + } + } + + if (tot_troops) + to_take -= tot_troops; + + if (to_take >= 0) { + for(n = 0; n <= off->last; ++n) + if (off[n].type != EF_BAD) + off[n].troops=0; + } else { + /* + * They can all come off mil. We rotate the casualties, + * starting with the sector containing the most mil. + */ + to_take = CASUALTY_LUMP; + if (index < 0) { + pr("ERROR: Tell the deity that you got the 'green librarian' error\n"); + index = 0; + } + while (to_take > 0) { + for (n = index; n <= off->last && to_take; ++n) { + if (off[n].type != EF_BAD && + off[n].troops > 0) { + --to_take; + --off[n].troops; + } + } + for (n = 0; n < index && to_take; ++n) { + if (off[n].type != EF_BAD && + off[n].troops > 0) { + --to_take; + --off[n].troops; + } + } + } + return CASUALTY_LUMP; + } + + if (QEMPTY(olist)) + return (CASUALTY_LUMP - to_take); + + /* + * Need to take some casualties from attacking units + * Procedure: find the biggest unit remaining (in + * terms of mil) and give it the casualties. + */ + biggest = (struct emp_qelem *)0; + biggest_mil = -1; + for (qp = olist->q_forw; qp != olist; qp = qp->q_forw){ + llp = (struct llist *)qp; + + if (total_mil(&llp->land) > biggest_mil){ + biggest_mil = total_mil(&llp->land); + biggest = qp; + } + } + if (biggest == (struct emp_qelem *)0) + return (CASUALTY_LUMP-to_take); + + llp = (struct llist *)biggest; + cas = lnd_take_casualty(combat_mode,llp,to_take); + return (CASUALTY_LUMP-(to_take-cas)); +} + +/* Send reacting defense units back to where they came from (at no mob cost) */ + +static void +send_reacting_units_home(struct combat *def, struct emp_qelem *list) +{ + struct emp_qelem *qp, *next; + struct llist *llp; + s_char buf[1024]; + + for (qp = list->q_forw; qp != list; qp = next) { + next = qp->q_forw; + llp = (struct llist *)qp; + if ((llp->land.lnd_x != llp->x) || + (llp->land.lnd_y != llp->y)) { + sprintf(buf, "returns to %s", + xyas(llp->x, llp->y, llp->land.lnd_own)); + llp->land.lnd_x = llp->x; + llp->land.lnd_y = llp->y; + lnd_delete(llp, buf); + } + } +} + +/* Check for 0 offense strength. This call will always preceed an abort */ + +int +att_empty_attack(int combat_mode, int ototal, struct combat *def) +{ + if (ototal <= 0) { + if (def->own && player->cnum != def->own) { + wu(0, def->own, + "%s (#%d) considered %sing you @%s\n", + cname(player->cnum), player->cnum, + att_mode[combat_mode], + xyas(def->x, def->y, def->own)); + } + pr("No troops for %s...\n", att_mode[combat_mode]); + return 1; + } + return 0; +} + +/* + * Take the defending sector or ship from the defender and give it to the + * attacker. + */ + +static int +take_def(int combat_mode, struct emp_qelem *list, struct combat *off, struct combat *def) +{ + int n; + int occuppied = 0; + struct llist *llp, *delete_me = 0; + s_char buf[1024]; + struct sctstr sect; + struct shpstr ship; + struct lndstr land; + + for (n = 0; n <= off->last && !occuppied; ++n) { + if (off[n].type != EF_BAD && + off[n].troops > 0 && + (off[n].type != EF_SECTOR || off[n].mob)) { + ++occuppied; + if (def->type == EF_LAND) { + if (def->lnd_lcp->l_flags & L_SPY) { + continue; + } + } + --(off[n].troops); + --(off[n].mil); + ++def->mil; + pr("1 mil from %s moves %s\n", + prcom(0, off + n), prcom(2, def)); + } + } + if (!occuppied) { + if (QEMPTY(list)) { + pr("%s left unoccupied\n", prcom(0, def)); + if (def->own) + wu(0, def->own, + "No enemy troops moved %s so you still own it!\n", pr_com(2, def, def->own)); + return 0; + } else { + llp = (struct llist *)list->q_forw; + llp->land.lnd_x = def->x; + llp->land.lnd_y = def->y; + take_move_in_mob(combat_mode, llp, off, def); + if (def->type == EF_SHIP) { + llp->land.lnd_ship = def->shp_uid; + sprintf(buf, "boards %s", prcom(0, def)); + delete_me = llp; + } else { + llp->land.lnd_ship = -1; + sprintf(buf, "moves in to occupy %s", + xyas(def->x, def->y, player->cnum)); + lnd_delete(llp, buf); + } + } + } + put_combat(def); + if (def->type == EF_SECTOR) { + getsect(def->x, def->y, §); + takeover(§, player->cnum); + if (sect.sct_type == SCT_CAPIT || sect.sct_type == SCT_MOUNT) + caploss(§, def->own, + "* We have captured %s's capital, sir! *\n"); + putsect(§); + } else if (def->type == EF_SHIP) { + getship(def->shp_uid, &ship); + takeover_ship(&ship, player->cnum, 1); + putship(ship.shp_uid, &ship); + } else if (def->type == EF_LAND) { + getland(def->lnd_uid, &land); + takeover_land(&land, player->cnum, 1); + putland(land.lnd_uid, &land); + } + if (delete_me) + lnd_delete(delete_me, buf); + att_get_combat(def, 0); + return 1; +} + +/* + * Ask the attacker which mil & land units they'd like to move into the + * conquered sector. + */ + +static void +ask_move_in(struct combat *off, struct emp_qelem *olist, struct combat *def) +{ + int n; + struct emp_qelem *qp, *next; + struct llist *llp; + s_char buf[512]; + s_char prompt[512]; + s_char land_answer[1024]; + s_char *answerp; + + for (n = 0; n <= off->last; ++n) + if (off[n].type != EF_BAD && off[n].troops > 0) + if (off[n].mob) { + ask_move_in_off(&off[n], def); + if (player->aborted) + break; + } + + if (QEMPTY(olist)) + return; + bzero(land_answer, sizeof(land_answer)); + for (qp = olist->q_forw; qp != olist; qp = next) { + next = qp->q_forw; + llp = (struct llist *)qp; + answerp = &land_answer[(int)llp->land.lnd_army]; + if (player->aborted || + att_get_combat(def, 0) < 0) + *answerp = 'N'; + if (*answerp == 'Y') + continue; + if (*answerp != 'N') { + if (!get_land(A_ATTACK, def,llp->land.lnd_uid, llp, 0)) + continue; + sprintf(prompt, "Move in with %s (%c %d%%) [ynYNq?] ", + prland(&llp->land), + llp->land.lnd_army==' '?'~':llp->land.lnd_army, + llp->land.lnd_effic); + *answerp = att_prompt(prompt, llp->land.lnd_army); + if (player->aborted || + att_get_combat(def, 0) < 0) + *answerp = 'N'; + if (!get_land(A_ATTACK,def, llp->land.lnd_uid, llp, 0)) + continue; + } + if (*answerp == 'y' || *answerp == 'Y') + continue; + sprintf(buf, "stays in %s", + xyas(llp->land.lnd_x, llp->land.lnd_y, player->cnum)); + lnd_delete(llp, buf); + } + if (QEMPTY(olist)) + return; + if (att_get_combat(def, 0) < 0) { + for (qp = olist->q_forw; qp != olist; qp = next) { + next = qp->q_forw; + llp = (struct llist *)qp; + if (!get_land(A_ATTACK,def,llp->land.lnd_uid, llp, 0)) + continue; + sprintf(buf, "stays in %s", + xyas(llp->land.lnd_x, llp->land.lnd_y, player->cnum)); + lnd_delete(llp, buf); + } + return; + } + if (opt_INTERDICT_ATT) + lnd_interdict(olist, def->x, def->y, player->cnum); + move_in_land(A_ATTACK, off, olist, def); +} + +/* Move offensive land units to the conquered sector or ship */ + +static void +move_in_land(int combat_mode, struct combat *off, struct emp_qelem *olist, struct combat *def) +{ + struct emp_qelem *qp, *next; + struct llist *llp; + s_char buf[512]; + + if (QEMPTY(olist)) + return; + for (qp = olist->q_forw; qp != olist; qp = next) { + next = qp->q_forw; + llp = (struct llist *)qp; + if (!get_land(combat_mode, def,llp->land.lnd_uid, llp, 0)) + continue; + take_move_in_mob(combat_mode, llp, off, def); + llp->land.lnd_x = def->x; + llp->land.lnd_y = def->y; + if (def->type == EF_SHIP) + llp->land.lnd_ship = def->shp_uid; + else + llp->land.lnd_ship = -1; + } + if (QEMPTY(olist)) + return; + if (def->type == EF_SECTOR) { + if (opt_INTERDICT_ATT) { + lnd_sweep(olist, 0, 0, def->own); + lnd_check_mines(olist); + } + sprintf(buf, "now occupies %s", prcom(0, def)); + } else { + sprintf(buf, "boards %s", prcom(0, def)); + } + if (QEMPTY(olist)) + return; + for (qp = olist->q_forw; qp != olist; qp = next) { + next = qp->q_forw; + llp = (struct llist *)qp; + lnd_print(llp, buf); + } + if (QEMPTY(olist)) + return; + lnd_put(olist, 0); +} + +/* + * Move assaulting, paradropping, or boarding mil & units into def + * If the mil are coming from a ship, then pack a lunch. + */ + +void +att_move_in_off(int combat_mode, struct combat *off, struct emp_qelem *olist, struct combat *def) +{ + struct sctstr sect; + struct shpstr ship; + struct lndstr land; + int defvec[I_MAX+1]; + int shipvec[I_MAX+1]; + int troops; + int n, lunchbox = 0; + s_char *thing; + + move_in_land(combat_mode, off, olist, def); + + for (n = 0; n <= off->last; ++n) { + if (off[n].type == EF_BAD || !off[n].troops) + continue; + troops = off[n].troops; + off[n].troops = 0; + off[n].mil -= troops; + def->mil += troops; + put_combat(off + n); + if (combat_mode == A_ASSAULT) { + getship(off[n].shp_uid, &ship); + getvec(VT_ITEM, shipvec, (s_char *)&ship, EF_SHIP); + lunchbox += (int)((troops + 1) * shipvec[I_FOOD] / + (shipvec[I_MILIT] + troops + shipvec[I_CIVIL] + 0.5)); + shipvec[I_FOOD] -= lunchbox; + putvec(VT_ITEM, shipvec, (s_char *)&ship, EF_SHIP); + putship(ship.shp_uid, &ship); + } + } + put_combat(def); + if (!lunchbox) + return; + + if (def->type == EF_SECTOR) { + getsect(def->x, def->y, §); + thing = (s_char *)§ + } else if (def->type == EF_SHIP) { + getship(def->shp_uid, &ship); + thing = (s_char *)&ship; + } else if (def->type == EF_LAND) { + getship(def->lnd_uid, &land); + thing = (s_char *)&land; + } else { + pr("Please tell the deity that you got the 'hungry mole' error\n"); + return; + } + getvec(VT_ITEM, defvec, thing, def->type); + defvec[I_FOOD] += lunchbox; + putvec(VT_ITEM, defvec, thing, def->type); + if (def->type == EF_SECTOR) + putsect(§); + else if (def->type == EF_SHIP) + putship(ship.shp_uid, &ship); + else + putland(land.lnd_uid, &land); +} + + +/* Ask how many mil to move in from each sector */ + +static void +ask_move_in_off(struct combat *off, struct combat *def) +{ + int mob_support; + int num_mil, dam = 0, left; + double d, weight; + s_char prompt[512]; + s_char buf[1024]; + s_char *p; + + if (att_get_combat(off, 0) <= 0) + return; + if (att_get_combat(def, 0) < 0) + return; + if (off->own != player->cnum) + return; + d = sector_mcost(getsectp(def->x, def->y), MOB_ROAD); + if ((mob_support = min(off->troops, (int)(off->mob / d))) <= 0) + return; + sprintf(prompt,"How many mil to move in from %s (%d max)? ", xyas(off->x, off->y, player->cnum), mob_support); + if (!(p = getstring(prompt, buf)) || + !*p || + (num_mil = atoi(p)) <= 0) { + num_mil = 0; + return; + } +/* Make sure we don't move in more than we can support mobility-wise */ + if (num_mil > mob_support) + num_mil = mob_support; + if (att_get_combat(off, 0) <= 0) + return; + if (att_get_combat(def, 0) < 0) + return; + if ((num_mil = min(off->troops, num_mil)) <= 0) { + pr("No mil moved in from %s\n", + xyas(off->x, off->y, player->cnum)); + return; + } + mob_support = max(1,(int)(num_mil * d)); + off->mob -= min(off->mob, mob_support); + off->mil -= num_mil; + off->troops -= num_mil; + put_combat(off); + left = num_mil; + weight = num_mil * ichr[I_MILIT].i_lbs; + if (opt_INTERDICT_ATT && chance(weight / 200.0)) { + if (chance(weight/100.0)) + dam += ground_interdict(def->x, def->y, player->cnum, "military"); + dam += check_lmines(def->x, def->y, weight); + } + + if (dam) { + left = commdamage(num_mil, dam, V_MILIT); + if (left < num_mil) { + if (left) { + pr("%d of the mil you were moving were destroyed!\nOnly %d mil made it to %s\n", + num_mil - left, + left, + xyas(def->x, def->y, player->cnum)); + } else { + pr("All of the mil you were moving were destroyed!\n"); + } + } + /* maybe got nuked */ + if (att_get_combat(def, 0) < 0) + return; + } + def->mil += left; + put_combat(def); +} + + +/* Charge land units for moving into a sector or onto a ship */ + +static void +take_move_in_mob(int combat_mode, struct llist *llp, struct combat *off, struct combat *def) +{ + extern int etu_per_update; + extern float land_mob_scale; + int mobcost; + int new; + + switch (combat_mode) { + case A_ATTACK: + mobcost = lnd_mobcost(&llp->land, getsectp(def->x, def->y), MOB_NONE); + new = llp->land.lnd_mobil - mobcost; + if (new < -127) + new = -127; + llp->land.lnd_mobil = new; + break; + case A_ASSAULT: + if (off->shp_mcp->m_flags & M_LAND) { + if (llp->lcp->l_flags & L_MARINE) + llp->land.lnd_mobil -= ((float)etu_per_update *land_mob_scale*0.5); + else + llp->land.lnd_mobil -= ((float)etu_per_update + *land_mob_scale); + } else { + if (llp->lcp->l_flags & L_MARINE) + llp->land.lnd_mobil = 0; + else + llp->land.lnd_mobil = (((float)etu_per_update + *land_mob_scale)*(-1)); + } + break; + case A_BOARD: + /* I arbitrarily chose the numbers 10 and 40 below -KHS */ + if (llp->lcp->l_flags & L_MARINE) + llp->land.lnd_mobil -= 10; + else + llp->land.lnd_mobil -= 40; + break; + } +} + +static void +free_list(struct emp_qelem *list) +{ + register struct emp_qelem *qp, *next; + + if (!list || QEMPTY(list)) + return; + + qp = list->q_forw; + while(qp != list) { + next = qp->q_forw; + emp_remque(qp); + free(qp); + qp = next; + } +} + +int +att_free_lists(struct emp_qelem *olist, struct emp_qelem *dlist) +{ + free_list(olist); + free_list(dlist); + return RET_OK; +} + +/* + * sector_strength - Everyone starts at 1. You can get up to a max + * of d_dstr, depending on how much you build up the + * defenses of the sector. + */ + +double +sector_strength(struct sctstr *sp) +{ + double d; + + d = 1.0; + + if (sp->sct_type == SCT_MOUNT) + d = 2.0; + + d = d + ((double)(dchr[sp->sct_type].d_dstr - d) * + ((double)sp->sct_defense / 100.0)); + + if (d > dchr[sp->sct_type].d_dstr) + d = dchr[sp->sct_type].d_dstr; + if (d < 0.1) + d = 0.1; + return d; +} diff --git a/src/lib/subs/bigmap.c b/src/lib/subs/bigmap.c new file mode 100644 index 00000000..ea3b5553 --- /dev/null +++ b/src/lib/subs/bigmap.c @@ -0,0 +1,105 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * bigmap.c: Updates a player's sector map using sector offsets and + * simple overwrite rules. + * + * Known contributors to this file: + * + */ + +#include "misc.h" +#include "player.h" +#include "file.h" +#include "prototypes.h" + +/* values of only_bmap: + * 0 = update both maps + * 1 = update only bmap + * 2 = update only bmap with force + */ + +static int +do_map_set(natid cnum, s_char *map, coord x, coord y, s_char t, int force, int sync); + +int +map_set(natid cnum, coord x, coord y, s_char t, int only_bmap) +{ + int set = 0; + + if (!t) + return 0; + if (!only_bmap) + set |= do_map_set(cnum, ef_ptr(EF_MAP,cnum), x,y, t, 0, 0); + set |= do_map_set(cnum, ef_ptr(EF_BMAP,cnum),x,y, t, only_bmap > 1, 1); + + return set; +} + + +static int +do_map_set(natid cnum, s_char *map, coord x, coord y, s_char t, int force, int sync) +{ + int id; + s_char ot; + + if ((id = sctoff(x, y)) < 0) + return 0; + + if (((map[id] == 'x') || (map[id] == 'X')) && !force) + return 0; + + ot = map[id]; + if (t == '?') { + switch (map[id]) { + case '.': + case '-': + case ' ': + case 0: + map[id] = t; + break; + default: + break; + } + } else { + map[id] = t; + } + return 1; +} + +void +writebmap(natid cnum) +{ + ef_write(EF_BMAP, cnum, ef_ptr(EF_BMAP,cnum)); +} + +void +writemap(natid cnum) +{ + ef_write(EF_MAP, cnum, ef_ptr(EF_MAP,cnum)); + ef_write(EF_BMAP, cnum, ef_ptr(EF_BMAP,cnum)); +} diff --git a/src/lib/subs/border.c b/src/lib/subs/border.c new file mode 100644 index 00000000..4dbb2b47 --- /dev/null +++ b/src/lib/subs/border.c @@ -0,0 +1,98 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * border.c: Create a border around a map + * + * Known contributors to this file: + * + */ + +#include "misc.h" +#include "nat.h" +#include "file.h" +#include "xy.h" +#include "prototypes.h" +#include "optlist.h" + +void +border(struct range *rp, s_char *prefstr, s_char *sep) + + /* prefixes each line */ + /* separates the numbers */ +{ + register int posi; + register int n; + register int x; + + if ((WORLD_X / 2) >= 100) { + if (rp->lx + rp->width > 99 || rp->hx - rp->width < -99) { + /* + * hundreds + */ + pr(prefstr); + for (x=rp->lx, n=0; n < rp->width; n++, x++) { + if (x >= WORLD_X/2) + x -= WORLD_X; + pr(sep); + if (x < 0 && x > -100) { + pr("-"); + } else { + posi = (x < 0 ? -x : x) / 100; + pr("%d", posi % 10); + } + } + pr("\n"); + } + } + /* + * tens + */ + pr(prefstr); + for (x=rp->lx, n=0; n < rp->width; n++, x++) { + if (x >= WORLD_X/2) + x -= WORLD_X; + pr(sep); + if (x < 0 && x > -10) { + pr("-"); + } else { + posi = (x < 0 ? -x : x) / 10; + pr("%d", posi % 10); + } + } + pr("\n"); + /* + * units... + */ + pr(prefstr); + for (x=rp->lx, n=0; n < rp->width; n++, x++) { + if (x >= WORLD_X/2) + x -= WORLD_X; + posi = (x < 0 ? -x : x); + pr("%s%d", sep, posi % 10); + } + pr("\n"); +} diff --git a/src/lib/subs/bsanct.c b/src/lib/subs/bsanct.c new file mode 100644 index 00000000..f784091b --- /dev/null +++ b/src/lib/subs/bsanct.c @@ -0,0 +1,78 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * bsanct.c: Break Sanctuary subroutines + * + * Known contributors to this file: + * + */ + +#include "misc.h" +#include "player.h" +#include "var.h" +#include "xy.h" +#include "sect.h" +#include "nsc.h" +#include "nat.h" +#include "news.h" +#include "path.h" +#include "file.h" +#include "deity.h" +#include "prototypes.h" + +void +bsanct(void) +{ + register int count; + struct sctstr s; + struct nstr_sect nstr; + + if (player->god) + return; + count = 0; + snxtsct(&nstr, "*"); + while (nxtsct(&nstr, &s)) { + if (!player->owner) + continue; + if (s.sct_type != SCT_SANCT) + continue; + pr("%s is no longer a sanctuary.\n", + xyas(s.sct_x, s.sct_y, player->cnum)); + if (s.sct_effic == 100) { + s.sct_type = SCT_CAPIT; + s.sct_newtype = SCT_CAPIT; + } else { + s.sct_type = SCT_HIWAY; + s.sct_newtype = SCT_HIWAY; + } + time(&s.sct_access); + (void) putsect(&s); + count++; + } + if (count > 0) + nreport(player->cnum, N_BROKE_SANCT, 0, 1); +} diff --git a/src/lib/subs/caploss.c b/src/lib/subs/caploss.c new file mode 100644 index 00000000..9f8d2e80 --- /dev/null +++ b/src/lib/subs/caploss.c @@ -0,0 +1,129 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * caploss.c: Lose your capital (kiss of death) + * + * Known contributors to this file: + * Steve McClure, 2000 + * + */ + +#include "misc.h" +#include "player.h" +#include "nat.h" +#include "var.h" +#include "sect.h" +#include "file.h" +#include "xy.h" +#include "news.h" +#include "path.h" +#include "loan.h" +#include "commodity.h" +#include "prototypes.h" +#include "optlist.h" + +void +caploss(struct sctstr *sp, natid coun, s_char *msg) +{ + struct natstr *natp; + struct lonstr loan; + struct comstr comm; + long lose; + long gain; + struct sctstr sect; + int n; + int loan_num = 0; + int comm_num = 0; + + if (coun == 0) return; + natp = getnatp(coun); + if ((xrel(natp,natp->nat_xcap) != xrel(natp,sp->sct_x)) || + (yrel(natp,natp->nat_ycap) != yrel(natp,sp->sct_y))) + return; + if (coun == player->cnum) { + player->nstat &= ~CAP; + return; + } + /* Ok, has the country owner reset their capital yet after it was last sacked? */ + if (natp->nat_flags & NF_SACKED) + return; /* No, so not really the capital yet, so return */ + pr(msg, natp->nat_cnam); + gain = lose = natp->nat_money / 2; + if (lose < 3000) + lose = 3000; + n = roll(6); + getsect(sp->sct_x + diroff[n][0], + sp->sct_y + diroff[n][1], + §); + natp->nat_xcap = sect.sct_x; + natp->nat_ycap = sect.sct_y; + natp->nat_money -= lose; + /* Your capital has now been sacked, no more sacking until you reset it */ + natp->nat_flags |= NF_SACKED; + putnat(natp); + wu(0, coun, + "* %s just sacked your capital! *\n", + cname(player->cnum)); + + if (gain >= 0) { + gain = (0.2 + 0.8 * (sp->sct_effic/100.0)) * gain; + player->dolcost -= gain; + } else + gain = 0; + wu(0, coun, + "You lost $%d and they gained $%d\n", + lose, gain); + wu(0, coun, + "Your capital has been moved to %s. You must use 'capital' to reset it.\n", + xyas(natp->nat_xcap, natp->nat_ycap, coun)); + wu(0, 0, "%s just took %s's capital and gained $%d\n", + cname(player->cnum), cname(coun), + -(int)(player->dolcost)); + if (opt_LOANS) { + for (loan_num = 0; getloan(loan_num, &loan); loan_num++) { + if (loan.l_ldur != 0 && loan.l_loner == coun) { + loan.l_loner = player->cnum; + putloan(loan_num, &loan); + pr("Loan %d has been transfered over to you\n", + loan_num); + } + } + } + if (opt_MARKET) { + for (comm_num = 0; getcomm(comm_num, &comm); comm_num++) { + if (comm.com_owner == coun) { + if (comm.com_owner == comm.com_maxbidder) + comm.com_maxbidder = player->cnum; + comm.com_owner = player->cnum; + putcomm(comm_num, &comm); + pr("You now own commodity #%d.\n", + comm_num); + } + } + } + nreport(player->cnum, N_SACK_CAP, coun, 1); +} diff --git a/src/lib/subs/chkmoney.c b/src/lib/subs/chkmoney.c new file mode 100644 index 00000000..fa8bb820 --- /dev/null +++ b/src/lib/subs/chkmoney.c @@ -0,0 +1,76 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * chkmoney.c: Some routines to check if a country will go broke + * + * Known contributors to this file: + * Ken Stevens, 1995 + */ + +#include "misc.h" +#include "player.h" +#include "prototypes.h" + +int +chkmoney(long int cost, long int cash, s_char *argp) +{ + s_char buf[1024]; + s_char *p; + + if (cash > 0 && cost > cash/2) { + pr("This operation will cost you $%d, and you only have $%d.\n", cost, cash); + if (cost > cash) { + pr("You will be broke with $%d if you proceed with this command.\n", cash - cost); + } + p = getstarg(argp, "Are you sure that you want to do this? ", buf); + if (p == 0 || *p != 'y') + return RET_SYN; + } + return 0; +} + +int +check_cost(int looping, int cost, long int cash, int *warnedp, s_char *argp) +{ + s_char buf[1024]; + s_char *p; + + if (looping && cash > 0 && player->dolcost + cost > cash && *warnedp < 2) { + *warnedp = 2; + pr("You will go broke! (it will cost $%d and you only have $%d)\n", cost, cash - (long)player->dolcost); + p = getstarg(argp, "Are you sure you wish to continue? ", buf); + if (p == 0 || *p != 'y') + return 1; + } + player->dolcost += cost; + if (looping && cash > 0 && player->dolcost > cash/2 && *warnedp < 1) { + *warnedp = 1; + pr("WARNING. You have just spent over half of your money.\n"); + pr("You started with $%d and now you only have $%d left\n", cash, cash - (long)player->dolcost); + } + return 0; +} diff --git a/src/lib/subs/cnumb.c b/src/lib/subs/cnumb.c new file mode 100644 index 00000000..044e4adb --- /dev/null +++ b/src/lib/subs/cnumb.c @@ -0,0 +1,66 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * cnumb.c: Return country number give country name + * + * Known contributors to this file: + * + */ + +#include "misc.h" +#include "player.h" +#include "nat.h" +#include "file.h" +#include "prototypes.h" + +int +cnumb(s_char *cntry) +{ + register s_char *ncp; + register s_char *cp; + register struct natstr *natp; + int bcount; + natid best; + natid cn; + + bcount = 0; + for (cn = 0; cn < MAXNOC; cn++) { + if ((natp = getnatp(cn)) == 0) + break; + ncp = natp->nat_cnam; + for (cp=cntry; *cp == *ncp; cp++, ncp++) { + if (*cp == 0) + return cn; + } + if (cp > cntry && *cp == 0) { + best = cn; + bcount++; + } + } + /* can only have 1 match or not successful */ + return bcount == 1 ? (int) best : -1; +} diff --git a/src/lib/subs/comsub.c b/src/lib/subs/comsub.c new file mode 100644 index 00000000..ba35fe11 --- /dev/null +++ b/src/lib/subs/comsub.c @@ -0,0 +1,173 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * comsub.c: Commodity read/write stuff + * + * Known contributors to this file: + * Dave Pare, 1986 + * Steve McClure, 1998 + */ + +#include "misc.h" +#include "player.h" +#include "var.h" +#include "nat.h" +#include "prototypes.h" + +#if !defined(_WIN32) +#include +#endif + +int commf; + +int c_comm[MAXNOC][I_MAX+1]; +float c_price[MAXNOC][I_MAX+1]; +float c_mult[MAXNOC][MAXNOC]; + +#if !defined(_WIN32) +static struct iovec commvec[3] = { + { (caddr_t)c_comm, sizeof(c_comm) }, + { (caddr_t)c_price, sizeof(c_price) }, + { (caddr_t)c_mult, sizeof(c_mult) } +}; +static int nvec = sizeof(commvec)/sizeof(struct iovec); +#endif + +/* + * comm file is the list of "deity commodities" + * lying around. Perhaps a better way of doing this + * might be at each update seeing what is on sale, + * then buying it, then distributing things amongst the + * people wanting the items. + * + * Of course that would be a gigantic pain... + */ + +int +commread(void) +{ + int n; + + (void) lseek(commf, (off_t) 0, 0); +#if !defined(_WIN32) + if ((n = readv(commf, commvec, nvec)) != + sizeof(c_comm) + sizeof(c_price) + sizeof(c_mult)) { + logerror("commread: readv returns %d", n); + return -1; + } +#else + if ((n = read(commf, c_comm, sizeof(c_comm))) != sizeof(c_comm)) { + logerror("commread: read returns %d, not %d", n, sizeof(c_comm)); + return -1; + } + if ((n = read(commf, c_price, sizeof(c_price))) != sizeof(c_price)) { + logerror("commread: read returns %d, not %d", n, sizeof(c_price)); + return -1; + } + if ((n = read(commf, c_mult, sizeof(c_mult))) != sizeof(c_mult)) { + logerror("commread: read returns %d, not %d", n, sizeof(c_mult)); + return -1; + } +#endif + return 0; +} + +int +commwrite(void) +{ +#if defined(_WIN32) + int n; +#endif + (void) lseek(commf, (off_t) 0, 0); +#if !defined(_WIN32) + if (writev(commf, commvec, nvec) != + sizeof(c_comm) + sizeof(c_price) + sizeof(c_mult)) { + logerror("commwrite: writev failed"); + return -1; + } +#else + if ((n = write(commf, c_comm, sizeof(c_comm))) != sizeof(c_comm)) { + logerror("commwrite: write returns %d, not %d", n, sizeof(c_comm)); + return -1; + } + if ((n = write(commf, c_price, sizeof(c_price))) != sizeof(c_price)) { + logerror("commwrite: write returns %d, not %d", n, sizeof(c_price)); + return -1; + } + if ((n = write(commf, c_mult, sizeof(c_mult))) != sizeof(c_mult)) { + logerror("commwrite: write returns %d, not %d", n, sizeof(c_mult)); + return -1; + } +#endif + return 0; +} + +int +commlock(void) +{ + return file_lock(commf); +} + +int +communlock(void) +{ + return file_unlock(commf); +} + +/* + * returns amount of commodity, and price to the user + */ +int +commamt(natid trader, int product, float *priceval) +{ + *priceval = c_price[trader][product] * c_mult[trader][player->cnum]; + return c_comm[trader][product]; +} + +void +commset(natid trader, int product, int amt) +{ + c_comm[trader][product] += amt; +} + +double +multread(natid trader, natid tradee) +{ + return c_mult[trader][tradee]; +} + +void +multset(natid tradee, float newmult) +{ + c_mult[player->cnum][tradee] = newmult; +} + +void +commprice(int product, float *newprice) +{ + c_price[player->cnum][product] = *newprice; +} diff --git a/src/lib/subs/control.c b/src/lib/subs/control.c new file mode 100644 index 00000000..5edb9ba2 --- /dev/null +++ b/src/lib/subs/control.c @@ -0,0 +1,72 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * control.c: Military control functions + * + * Known contributors to this file: + * Dave Pare, 1986 + */ + +#include "misc.h" +#include "player.h" +#include "var.h" +#include "sect.h" +#include "nat.h" +#include "var.h" +#include "file.h" +#include "path.h" +#include "xy.h" +#include "land.h" +#include "nsc.h" +#include "item.h" +#include "deity.h" +#include "prototypes.h" + +/* + * Does the player->owner have military control of this sector? + * + */ +int +military_control(struct sctstr *sp) +{ + int tot_mil=0; + struct nstr_item ni; + struct lndstr land; + + if (sp->sct_oldown != sp->sct_own){ + snxtitem_xy(&ni, EF_LAND, sp->sct_x, sp->sct_y); + while (nxtitem(&ni, (s_char *)&land)){ + if (land.lnd_own == sp->sct_own) + tot_mil += total_mil(&land); + } + if ((getvar(V_MILIT, (s_char *)sp, EF_SECTOR)+tot_mil) * 10 + < getvar(V_CIVIL, (s_char *)sp, EF_SECTOR)) + return 0; + } + + return 1; +} diff --git a/src/lib/subs/detonate.c b/src/lib/subs/detonate.c new file mode 100644 index 00000000..4c58387e --- /dev/null +++ b/src/lib/subs/detonate.c @@ -0,0 +1,332 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * detonate.c: Detonate a nuclear device in a sector. + * + * Known contributors to this file: + * Steve McClure, 1998-2000 + */ + +#include "misc.h" +#include "player.h" +#include "xy.h" +#include "nat.h" +#include "file.h" +#include "sect.h" +#include "nuke.h" +#include "ship.h" +#include "land.h" +#include "news.h" +#include "plane.h" +#include "nsc.h" +#include "var.h" +#include "optlist.h" +#include "prototypes.h" + +void kaboom(int x, int y, int rad, natid cn); + +int +detonate(struct plnstr *pp, int x, int y) +{ + int nuketype = pp->pln_nuketype; + natid bombown = pp->pln_own; + int airburst = (pp->pln_flags & PLN_AIRBURST); + struct nchrstr *ncp; + struct plnstr plane; + struct sctstr sect; + struct shpstr ship; + struct lndstr land; + struct nukstr nuke; + s_char *bp; + s_char buf[128]; + s_char buf2[128]; + natid own; + int type; + int damage; + int fallout; + int rad; + struct nstr_sect ns; + struct nstr_item ni; + int issea = 0; + int retval; + + pp->pln_nuketype = -1; + getsect(x,y,§); + if (sect.sct_type == SCT_WATER) + issea = 1; + ncp = &nchr[nuketype]; + kaboom(x, y, ncp->n_blast, bombown); + rad = ncp->n_blast; + if (!airburst) + rad = rad * 2 / 3; + snxtsct_dist(&ns, x, y, rad); + while (nxtsct(&ns, §)) { + /* Nukes falling on water affect only 1 sector */ + if ((sect.sct_x != x) && issea) + continue; + if ((sect.sct_y != y) && issea) + continue; + own = sect.sct_own; + type = sect.sct_type; + if ((damage = nukedamage(ncp, ns.curdist, airburst)) <= 0) + continue; + if (type == SCT_SANCT) { + mpr(bombown,"bounced off %s\n", xyas(ns.x, ns.y, bombown)); + if(own != 0) + mpr(own, "%s nuclear device bounced off %s\n", + cname(bombown), xyas(ns.x, ns.y, bombown)); + nreport(bombown, N_NUKE, own, 1); + continue; + } + if (opt_FALLOUT) + fallout = getvar(V_FALLOUT,(s_char *)§,EF_SECTOR); + sect_damage(§, damage, 0); + if (sect.sct_x == x && sect.sct_y == y) + retval = damage; + if (opt_FALLOUT) { + if (opt_NEUTRON && (ncp->n_flags & N_NEUT)) + fallout += damage*30; + else + fallout += damage*3; + putvar(V_FALLOUT,fallout,(s_char *)§,EF_SECTOR); + } + if (damage > 100) { + makelost(EF_SECTOR, sect.sct_own, 0, sect.sct_x, sect.sct_y); + sect.sct_oldown = 0; + sect.sct_own = 0; + if (type == SCT_WATER || type == SCT_BSPAN || + type == SCT_BTOWER) { + bp = "left nothing but water in %s\n"; + if (type != SCT_WATER) { + sect.sct_newtype = SCT_WATER; + sect.sct_type = SCT_WATER; + } + } else { + sect.sct_newtype = SCT_WASTE; + sect.sct_type = SCT_WASTE; + bp = "turned %s into a radioactive wasteland\n"; + } + } else { + sprintf(buf, "did %d%%%% damage in %%s\n", damage); + bp = buf; + } + if ((type == SCT_CAPIT || type == SCT_MOUNT) && damage >= 100) + caploss(§, own, "\n%s lost its capital!\n\n"); + (void) putsect(§); + if (type != SCT_WATER) + nreport(bombown, N_NUKE, own, 1); + mpr(bombown,bp, xyas(ns.x, ns.y, bombown)); + if (own != bombown && own != 0) { + (void) sprintf(buf2, bp, xyas(ns.x, ns.y, own)); + mpr(own, "%s nuclear device %s\n", + cname(bombown), buf2); + } + } + snxtitem_dist(&ni, EF_PLANE, x, y, rad); + while (nxtitem(&ni, (caddr_t)&plane)) { + /* Nukes falling on water affect only 1 sector */ + if ((plane.pln_x != x) && issea) + continue; + if ((plane.pln_y != y) && issea) + continue; + if ((own = plane.pln_own) == 0) + continue; + if ((plane.pln_flags & PLN_LAUNCHED) && (airburst != 2)) + continue; + damage = nukedamage(ncp, ni.curdist, airburst) - plane.pln_harden; + if (damage <= 0) + continue; + if (plane.pln_ship >= 0) { + /* Are we on a sub? */ + getship(plane.pln_ship, &ship); + + if (mchr[(int)ship.shp_type].m_flags & M_SUB) { + struct sctstr sect1; + + /* Should we damage this sub? */ + getsect(ship.shp_x,ship.shp_y,§1); + + if (sect1.sct_type == SCT_BSPAN || + sect1.sct_type == SCT_BTOWER || + sect1.sct_type == SCT_WATER) { + /* Ok, we're not in a harbor or trapped + inland. Now, did we get pasted + directly? */ + if (ship.shp_x != x || ship.shp_y != y) { + /* Nope, so don't mess with it */ + continue; + } + } + } + } + planedamage(&plane, damage); + if (own == bombown) { + mpr(bombown,"%s at %s reports %d%% damage\n", + prplane(&plane), + xyas(plane.pln_x, plane.pln_y, own), + damage); + } else { + if(own != 0) + mpr(own, + "%s nuclear device did %d%% damage to %s at %s\n", + cname(bombown), damage, + prplane(&plane), + xyas(plane.pln_x, plane.pln_y, own)); + } + putplane(ni.cur, &plane); + } + snxtitem_dist(&ni, EF_LAND, x, y, rad); + while (nxtitem(&ni, (caddr_t)&land)) { + /* Nukes falling on water affect only 1 sector */ + if ((land.lnd_x != x) && issea) + continue; + if ((land.lnd_y != y) && issea) + continue; + if ((own = land.lnd_own) == 0) + continue; + if ((damage = nukedamage(ncp, ni.curdist, airburst)) <= 0) + continue; + + if (land.lnd_ship >= 0) { + /* Are we on a sub? */ + getship(land.lnd_ship, &ship); + + if (mchr[(int)ship.shp_type].m_flags & M_SUB) { + struct sctstr sect1; + + /* Should we damage this sub? */ + getsect(ship.shp_x,ship.shp_y,§1); + + if (sect1.sct_type == SCT_BSPAN || + sect1.sct_type == SCT_BTOWER || + sect1.sct_type == SCT_WATER) { + /* Ok, we're not in a harbor or trapped + inland. Now, did we get pasted + directly? */ + if (ship.shp_x != x || ship.shp_y != y) { + /* Nope, so don't mess with it */ + continue; + } + } + } + } + land_damage(&land, damage); + if (own == bombown) { + mpr(bombown,"%s at %s reports %d%% damage\n", + prland(&land), + xyas(land.lnd_x, land.lnd_y, own), damage); + } else { + if(own != 0) + mpr(own, "%s nuclear device did %d%% damage to %s at %s\n", + cname(bombown), damage, + prland(&land), + xyas(land.lnd_x, land.lnd_y, own)); + } + putland(land.lnd_uid, &land); + } + snxtitem_dist(&ni, EF_SHIP, x, y, rad); + while (nxtitem(&ni, (caddr_t)&ship)) { + /* Nukes falling on water affect only 1 sector */ + if ((ship.shp_x != x) && issea) + continue; + if ((ship.shp_y != y) && issea) + continue; + if ((own = ship.shp_own) == 0) + continue; + if ((damage = nukedamage(ncp, ni.curdist, airburst)) <= 0) + continue; + if (mchr[(int)ship.shp_type].m_flags & M_SUB) { + struct sctstr sect1; + + /* Should we damage this sub? */ + getsect(ship.shp_x,ship.shp_y,§1); + + if (sect1.sct_type == SCT_BSPAN || + sect1.sct_type == SCT_BTOWER || + sect1.sct_type == SCT_WATER) { + /* Ok, we're not in a harbor or trapped + inland. Now, did we get pasted + directly? */ + if (ship.shp_x != x || ship.shp_y != y) { + /* Nope, so don't mess with it */ + continue; + } + } + } + ship_damage(&ship, damage); + if (own == bombown) { + mpr(bombown,"%s at %s reports %d%% damage\n", + prship(&ship), + xyas(ship.shp_x, ship.shp_y, own), damage); + } else { + if(own != 0) + mpr(own, "%s nuclear device did %d%% damage to %s at %s\n", + cname(bombown), damage, prship(&ship), + xyas(ship.shp_x, ship.shp_y, own)); + } + putship(ship.shp_uid, &ship); + } + snxtitem_dist(&ni, EF_NUKE, x, y, rad); + while (nxtitem(&ni, (caddr_t)&nuke)) { + /* Nukes falling on water affect only 1 sector */ + if ((nuke.nuk_x != x) && issea) + continue; + if ((nuke.nuk_y != y) && issea) + continue; + if ((own = nuke.nuk_own) == 0) + continue; + if ((damage = nukedamage(ncp, ni.curdist, airburst)) <= 0) + continue; + if (roll(100) >= damage) + continue; + makelost(EF_NUKE, nuke.nuk_own, nuke.nuk_uid, nuke.nuk_x, nuke.nuk_y); + nuke.nuk_own = 0; + if (own == bombown) { + mpr(bombown,"nuclear stockpile #%d at %s destroyed\n", + ni.cur, xyas(nuke.nuk_x, nuke.nuk_y, own)); + } else { + if(own != 0) + mpr(own, "nuclear stockpile #%d at %s destroyed\n", + ni.cur, xyas(nuke.nuk_x, nuke.nuk_y, own)); + } + putnuke(ni.cur, &nuke); + } + return retval; +} + + +/* + * silly to be sure. + */ +void +kaboom(int x, int y, int rad, natid cn) +{ + mpr(cn,"\n\nK A B "); + while (rad-- > 0) + mpr(cn,"O O "); + mpr(cn,"M ! in %s\n\n", xyas(x, y, cn)); +} diff --git a/src/lib/subs/disloan.c b/src/lib/subs/disloan.c new file mode 100644 index 00000000..62d90c54 --- /dev/null +++ b/src/lib/subs/disloan.c @@ -0,0 +1,115 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * disloan.c: Display a loan + * + * Known contributors to this file: + * Pat Loney, 1992 + * Steve McClure, 1996 + */ +/* + * Display a loan; there's a lot of stuff going + * on here to figure out how much people owe. + * It would be nice to change loans to work on + * some kind of payment plan...like house payments + * and such, where the bucks just get paid up each + * update or so. + * + * I'd have made this more like treaty if I weren't + * so disgusted with how it works. + */ + +#include "misc.h" +#include "player.h" +#include "loan.h" +#include "nat.h" +#include "file.h" +#include "prototypes.h" + +int +disloan(int n, register struct lonstr *loan) +{ + time_t now; + time_t due; + time_t lastpaydate; + time_t normaltime; + time_t doubletime; + time_t accept; + double rate; + double owe; + + if (loan->l_status == LS_FREE) + return 0; + if (loan->l_ldur == 0) + return 0; + if (loan->l_loner != player->cnum && loan->l_lonee != player->cnum) + return 0; + (void) time(&now); + pr("\nLoan #%d from %s to", n, cname(loan->l_loner)); + pr(" %s\n", cname(loan->l_lonee)); + if (loan->l_status == LS_PROPOSED) { + pr("(proposed) principal=$%d interest rate=%d%%", + loan->l_amtdue, loan->l_irate); + pr(" duration(days)=%d\n", loan->l_ldur); + if (loan->l_duedate < now) { + loan->l_status = LS_FREE; + putloan(n, loan); + pr("This offer has expired\n"); + return 0; + } + accept = loan->l_lastpay + loan->l_ldur * SECS_PER_DAY; + pr("Loan must be accepted by %s", ctime(&accept)); + return 1; + } + due = loan->l_duedate; + lastpaydate = loan->l_lastpay; + if (now < due) { + normaltime = now - lastpaydate; + doubletime = 0; + } + if (lastpaydate < due && due < now) { + normaltime = due - lastpaydate; + doubletime = now - due; + } + if (due < lastpaydate) { + normaltime = 0; + doubletime = now - lastpaydate; + } + rate = ((double)loan->l_irate / 100.0) / (loan->l_ldur * SECS_PER_DAY); + owe = ((double) loan->l_amtdue * + (((double) normaltime * rate + 1.0) + + ((double) doubletime * rate * 2.0))) + 0.5; + pr("Amount paid to date $%d\n", loan->l_amtpaid); + pr("Amount due (if paid now) $%.2f", owe); + if (doubletime == 0) { + pr(" (if paid on due date) $%.2f\n", + loan->l_amtdue * ((due - lastpaydate) * rate + 1.0)); + pr("Due date is %s", ctime(&loan->l_duedate)); + } else + pr(" ** In Arrears **\n"); + return 1; +} diff --git a/src/lib/subs/distrea.c b/src/lib/subs/distrea.c new file mode 100644 index 00000000..87489a45 --- /dev/null +++ b/src/lib/subs/distrea.c @@ -0,0 +1,94 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * distrea.c: Display treaty information + * + * Known contributors to this file: + * + */ + +#include "misc.h" +#include "player.h" +#include "treaty.h" +#include "nat.h" +#include "deity.h" +#include "file.h" +#include "prototypes.h" + +int +distrea(int n, register struct trtstr *tp) +{ + register int i; + int acond; + int bcond; + int cond; + time_t now; + + if (tp->trt_status == TS_FREE) + return 0; + if (tp->trt_cna != player->cnum && + tp->trt_cnb != player->cnum && !player->god) + return 0; + (void) time(&now); + if (now > tp->trt_exp) { + if (!ef_lock(EF_TREATY)) { + pr("Can't lock treaty file; get help!\n"); + return 0; + } + tp->trt_status = TS_FREE; + if (!puttre(n, tp)) { + pr("Couldn't save treaty; get help!\n"); + (void) ef_unlock(EF_TREATY); + return 0; + } + (void) ef_unlock(EF_TREATY); + pr("Treaty #%d expired %s", n, ctime(&tp->trt_exp)); + return 0; + } + pr("\n * * * Empire Treaty #%d * * *\n", n); + if (tp->trt_status == TS_PROPOSED) + pr("(proposed)\n"); + pr("between %s and ", cname(tp->trt_cna)); + pr("%s expires %s", cname(tp->trt_cnb), ctime(&tp->trt_exp)); + pr("%24.24s terms", cname(tp->trt_cna)); + pr(" - %s terms\n", cname(tp->trt_cnb)); + for (i = 0; 0 != (cond = tchr[i].t_cond); i++) { + acond = tp->trt_acond & cond; + bcond = tp->trt_bcond & cond; + if (acond | bcond) { + if (acond) + pr("%30s", tchr[i].t_name); + else + pr("%30s", ""); + if (bcond) + pr(" - %s\n", tchr[i].t_name); + else + pr(" -\n"); + } + } + return 1; +} diff --git a/src/lib/subs/fileinit.c b/src/lib/subs/fileinit.c new file mode 100644 index 00000000..1477b04d --- /dev/null +++ b/src/lib/subs/fileinit.c @@ -0,0 +1,94 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * fileinit.c: Stuff that ef_init uses to initialize the ca pointers and + * the pre/post i/o calls. + * + * Known contributors to this file: + * + */ + +#include +#include "misc.h" +#include "xy.h" +#include "nsc.h" +#include "file.h" +#include "loan.h" +#include "lost.h" +#include "commodity.h" +#include "prototypes.h" +#include "optlist.h" + +extern struct castr sect_ca[]; +extern struct castr news_ca[]; +extern struct castr loan_ca[]; +extern struct castr ship_ca[]; +extern struct castr plane_ca[]; +extern struct castr treaty_ca[]; +extern struct castr nuke_ca[]; +extern struct castr trade_ca[]; +extern struct castr commodity_ca[]; +extern struct castr lost_ca[]; + +struct fileinit fileinit[EF_MAX] = { + { (ef_fileinit) sct_init, sct_postread, sct_prewrite, sect_ca }, + { shp_init, shp_postread, shp_prewrite, ship_ca }, + { pln_init, pln_postread, pln_prewrite, plane_ca }, + { lnd_init, lnd_postread, lnd_prewrite, land_ca }, + { nuk_init, nuk_postread, nuk_prewrite, nuke_ca }, + { 0, 0, 0, news_ca }, + { 0, 0, 0, treaty_ca }, + { 0, 0, 0, trade_ca }, + { 0, 0, 0, 0 }, /* power */ + { 0, 0, 0, 0 }, /* nation */ + { 0, 0, 0, loan_ca }, + { 0, 0, 0, 0 }, /* map */ + { 0, 0, 0, 0 }, /* map */ + { 0, 0, 0, commodity_ca }, + { 0, 0, 0, lost_ca } +}; + +void +ef_init(void) +{ + int i; + struct empfile *ef; + struct fileinit *fi; + + ef = empfile; + fi = fileinit; + for (i=0; iinit = fi->init; + ef->postread = fi->postread; + ef->prewrite = fi->prewrite; + ef->cadef = fi->cadef; + /* We have to set the size for the map and bmap files at + runtime. */ + if (i == EF_MAP || i == EF_BMAP) + ef->size = (WORLD_X * WORLD_Y) / 2; + } +} diff --git a/src/lib/subs/fortdef.c b/src/lib/subs/fortdef.c new file mode 100644 index 00000000..e4bab65f --- /dev/null +++ b/src/lib/subs/fortdef.c @@ -0,0 +1,281 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * fortdef.c: Fort defends an area. + * + * Known contributors to this file: + * + */ +/* + * The base routines can also be used for general purposes. + * Noisy tells whther to send teles, print things, etc. + * Defending tells whether they are being defensive, or offensive. + */ + +#include "misc.h" +#include "var.h" +#include "xy.h" +#include "nat.h" +#include "sect.h" +#include "ship.h" +#include "land.h" +#include "news.h" +#include "nsc.h" +#include "file.h" +#include "options.h" +#include "optlist.h" +#include "prototypes.h" + +#define QUIET 0 +#define NOISY 1 + +extern double tfactfire(natid, double); + +/* + * See if any nearby ships will open up on the attacker + * Return damage done to attacker, if any. + * Subtracts shells used for firing. Responding ships + * require military, shells, and guns. + */ +int +shipdef(natid att, natid own, coord x, coord y) +{ + return sd(att, own, x, y, NOISY, 1, 1); +} + +int +sd(natid att, natid own, coord x, coord y, int noisy, int defending, int usesubs) +{ + int nshot; + double range; + double eff; + struct shpstr ship; + struct nstr_item ni; + int vec[I_MAX+1]; + int dam, rel, rel2; + + if (own == 0) + return 0; + if (att == own) + return 0; + eff = 1.0; + snxtitem_dist(&ni, EF_SHIP, x, y, 8); + while (nxtitem(&ni, (caddr_t)&ship) && eff > 0.30) { + if (ship.shp_own == att) + continue; + if (ship.shp_own == 0) + continue; + + rel = getrel(getnatp(ship.shp_own),own); + rel2 = getrel(getnatp(ship.shp_own),att); + if ((ship.shp_own != own) && + ((rel != ALLIED) || (rel2 != AT_WAR))) + continue; + if (ship.shp_effic < 60) + continue; + if ((mchr[(int)ship.shp_type].m_flags & M_SUB) && (!usesubs)) + continue; + range = techfact(ship.shp_tech, + ship.shp_frnge * ship.shp_effic / 200.0); + range = (double)roundrange(range); + if (range < ni.curdist) + continue; + /* must have gun, shell, and milit to fire */ + if (getvec(VT_ITEM, vec, (caddr_t)&ship, EF_SHIP) < 3) + continue; + if (vec[I_SHELL] < ship.shp_glim) + vec[I_SHELL] += supply_commod(ship.shp_own,ship.shp_x, + ship.shp_y,I_SHELL, + vec[I_SHELL]-ship.shp_glim); + nshot = min(min(vec[I_GUN], vec[I_SHELL]), vec[I_MILIT]); + nshot = min(nshot, ship.shp_glim); + if (nshot <= 0) + continue; + (void)putvar(V_SHELL,vec[I_SHELL]-nshot,(caddr_t)&ship,EF_SHIP); + putship(ship.shp_uid, &ship); + if (defending) + nreport(ship.shp_own, N_FIRE_BACK, att, 1); + else + nreport(ship.shp_own, N_FIRE_S_ATTACK, att, 1); + dam = seagun(ship.shp_effic, nshot); + eff *= (1.0 - (0.01 * dam)); + if (noisy) { + pr_beep(); + pr("Incoming shell%s %d damage!\n", + nshot == 1 ? " does" : "s do", dam); + } + if (noisy || (ship.shp_own != own)){ + if (ship.shp_own == own) + wu(0, own, "%s fired on %s at %s doing %d damage.\n", prship(&ship), + cname(att), xyas(x, y,own),dam); + else{ + if (defending) + wu(0, ship.shp_own, "%s fired on %s at %s in defense of %s, doing %d damage.\n", prship(&ship), + cname(att), + xyas(x, y, ship.shp_own), + cname(own),dam); + else + wu(0, ship.shp_own,"%s supported %s attacks against %s at %s, doing %d damage.\n", prship(&ship), + cname(own), + cname(att), + xyas(x, y, ship.shp_own), dam); + } + } + } + return (int) 100 - (eff * 100); +} + +/* + * Determine if any nearby gun-equipped sectors are within + * range and able to fire at an attacker. Firing sectors + * need to have guns, shells, and military. Sector being + * attacked is x,y -- attacker is at ax,ay. + */ +#if 0 +/* defdef isn't called anywhere, and uses wrong + * number of arguments for dd */ +int +defdef(att, def_own, defval, ax, ay) + natid att; + natid def_own; + int defval; + coord ax; + coord ay; +{ + return dd(att, def_own, defval, ax, ay, NOISY, 1); +} +#endif + +int +dd(natid att, natid def_own, coord ax, coord ay, int noisy, int defending) +{ + int dam, rel, rel2; + double tech; + double range; + struct sctstr firing; + struct nstr_sect ns; + int vec[I_MAX+1]; + + if (opt_NO_FORT_FIRE) /* Forts can't fire! */ + return 0; + if (def_own == 0) + return 0; + if (att == def_own) + return 0; + tech = tfactfire(def_own, 1.0); + dam = 0; + snxtsct_dist(&ns, ax, ay, 8); + while (nxtsct(&ns, &firing) && dam < 80) { + if (firing.sct_own == att) + continue; + if (firing.sct_own == 0) + continue; + if (firing.sct_effic < (u_char)FORTEFF ) + continue; + rel = getrel(getnatp(firing.sct_own),def_own); + rel2 = getrel(getnatp(firing.sct_own),att); + if ((firing.sct_own != def_own) && + ((rel != ALLIED) || (rel2 != AT_WAR))) + continue; + if (getvec(VT_ITEM, vec, (caddr_t)&firing, EF_SECTOR) < 0) + continue; + + range = tfactfire(def_own, 7.0); + if (firing.sct_effic > 59) + range++; + /* Here we round down the range, and then add 1 to it + to determine if we could possibly hit the sector. If + we do, we call sb where the range is re-calculated and + the percentages are checked. */ + range = (double)((int)(range) + 1); + if (range < ns.curdist) + continue; + /* XXX defdef damage is additive, but ship or land unit damage isn't */ + dam += sb(att, def_own, &firing, + ax, ay, noisy, defending); + } + return dam; +} + +/* Shoot back + * + * See if the sector being fired at will defend itself. + */ +int +sb(natid att, natid def, struct sctstr *sp, coord tx, coord ty, int noisy, int defending) +{ + register int damage; + natid own; + int shell; + double range; + int range2, gun; + + if (sp->sct_type != SCT_FORTR) { + /* XXX I don't like this restriction */ + return 0; + } + + if (sp->sct_effic < (u_char)FORTEFF) + return 0; + + own = sp->sct_own; + if (own == 0) + return 0; + if (att == own) + return 0; + range = tfactfire(own, 7.0); + if (sp->sct_effic > 59) + range++; + range = (double)roundrange(range); + range2 = mapdist((int)sp->sct_x, (int)sp->sct_y, tx, ty); + if (range < range2) + return 0; + gun = getvar(V_GUN, (caddr_t)sp, EF_SECTOR); + if (gun == 0) + return 0; + shell = getvar(V_SHELL, (caddr_t)sp, EF_SECTOR); + if (shell <= 0) + shell += supply_commod(sp->sct_own,sp->sct_x,sp->sct_y,I_SHELL, + 1); + if (shell <= 0) + return 0; + putvar(V_SHELL, shell - 1, (caddr_t)sp, EF_SECTOR); + putsect(sp); + damage = landgun((int)sp->sct_effic,gun); + if (sp->sct_own != def) + wu(0,sp->sct_own, "%s fired on %s in %s in defense of %s, doing %d damage!\n", + xyas(sp->sct_x,sp->sct_y,sp->sct_own), + cname(att), xyas(tx,ty,sp->sct_own), + cname(def), damage); + if (defending) + nreport(sp->sct_own, N_FIRE_BACK, att, 1); + else + nreport(sp->sct_own, N_FIRE_F_ATTACK, att, 1); + if (noisy) + pr("Incoming shell! %d damage done.\007\n", damage); + return damage; +} diff --git a/src/lib/subs/getbit.c b/src/lib/subs/getbit.c new file mode 100644 index 00000000..263a0c4f --- /dev/null +++ b/src/lib/subs/getbit.c @@ -0,0 +1,175 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * getbit.c: Replaces old bitmap code + * + * Known contributors to this file: + * Dave Pare, 1989 + */ + +#include "misc.h" +#include "player.h" +#include "xy.h" +#include "nsc.h" +#include "sect.h" +#include "nat.h" +#include "prototypes.h" +#include "optlist.h" + +#define GCFx(x) ((x + WORLD_X) % WORLD_X) +#define GCFy(y) ((y + WORLD_Y) % WORLD_Y) + +int +emp_getbit(int x, int y, u_char *bitmap) +{ + int id; + + id = (GCFy(y)) * WORLD_X/2 + GCFx(x)/2; + return bitmap[id / 8] & bit(id & 07); +} + +void +emp_setbit(int x, int y, u_char *bitmap) +{ + register int id; + + id = (GCFy(y)) * WORLD_X/2 + GCFx(x)/2; + bitmap[id / 8] |= bit(id & 07); +} + +void +emp_setbitmap(register int x, register int y, register u_char *bitmap, int *bitmaps) +{ + register int *mp; + register int id; + register int dx, dy; + + for (mp = bitmaps; *mp != 9999; ) { + dx = x + *mp++; + dy = y + *mp++; + id = (GCFy(dy)) * WORLD_X/2 + GCFx(dx)/2; + bitmap[id / 8] |= bit(id & 07); + } +} + + +/* + * if we're not player->god, we have to set up the bitmaps + * correctly for the owned sectors. If we are player->god, + * forego all this (expensive) nonsense! + */ +void +emp_bitinit(struct nstr_sect *np, u_char *bitmap) +{ + extern int *bitmaps[]; + struct sctstr sect; + int eff; + + while (nxtsct(np, §)) { + if (!player->owner) + continue; + eff = sect.sct_effic / 20; + if (eff > 4) + eff = 4; + emp_setbitmap(np->x, np->y, bitmap, bitmaps[eff]); + } + snxtsct_rewind(np); +} + +/* + * + * the bit offsets for each bit pattern based on the efficiency of + * the sector. + * + * bitmap0: 0-20% + * bitmap1: 21-40% + * bitmap2: 41-60% + * bitmap3: 61-80% + * bitmap4: 81-100% + */ + +#define bitoff(x, y) x, y + +int bitmap0[] = { + bitoff(-1,-1), bitoff(1,-1), + bitoff(-2,0), bitoff(0,0), bitoff(2,0), + bitoff(-1,1), bitoff(1,1), + bitoff(9999,9999), +}; + +int bitmap1[] = { + bitoff(0,-2), + bitoff(-3,-1), bitoff(-1,-1), bitoff(1,-1), bitoff(3,-1), + bitoff(-2,0), bitoff(0,0), bitoff(2,0), + bitoff(-3,1), bitoff(-1,1), bitoff(1,1), bitoff(3,1), + bitoff(0,2), + bitoff(9999,9999), +}; + +int bitmap2[] = { + bitoff(-2,-2), bitoff(0,-2), bitoff(2,-2), + bitoff(-3,-1), bitoff(-1,-1), bitoff(1,-1), bitoff(3,-1), + bitoff(-4,0), bitoff(-2,0), bitoff(0,0), bitoff(2,0), bitoff(4,0), + bitoff(-3,1), bitoff(-1,1), bitoff(1,1), bitoff(3,1), + bitoff(-2,2), bitoff(0,2), bitoff(2,2), + bitoff(9999,9999), +}; + +int bitmap3[] = { + bitoff(-1,-3), bitoff(1,-3), + bitoff(-4,-2), bitoff(-2,-2), bitoff(0,-2), bitoff(2,-2), bitoff(4,-2), + bitoff(-5,-1), bitoff(-3,-1), bitoff(-1,-1), bitoff(1,-1), + bitoff(3,-1), bitoff(5,-1), + bitoff(-4,0), bitoff(-2,0), bitoff(0,0), bitoff(2,0), bitoff(4,0), + bitoff(-5,1), bitoff(-3,1), bitoff(-1,1), bitoff(1,1), + bitoff(3,1), bitoff(5,1), + bitoff(-4,2), bitoff(-2,2), bitoff(0,2), bitoff(2,2), bitoff(4,2), + bitoff(-1,3), bitoff(1,3), + bitoff(9999,9999), +}; + +int bitmap4[] = { + bitoff(-3,-3), bitoff(-1,-3), bitoff(1,-3), bitoff(3,-3), + bitoff(-4,-2), bitoff(-2,-2), bitoff(0,-2), bitoff(2,-2), bitoff(4,-2), + bitoff(-5,-1), bitoff(-3,-1), bitoff(-1,-1), bitoff(1,-1), + bitoff(3,-1), bitoff(5,-1), + bitoff(-6,0), bitoff(-4,0), bitoff(-2,0), bitoff(0,0), bitoff(2,0), + bitoff(4,0), bitoff(6,0), + bitoff(-5,1), bitoff(-3,1), bitoff(-1,1), bitoff(1,1), + bitoff(3,1), bitoff(5,1), + bitoff(-4,2), bitoff(-2,2), bitoff(0,2), bitoff(2,2), bitoff(4,2), + bitoff(-3,3), bitoff(-1,3), bitoff(1,3), bitoff(3, 3), + bitoff(9999,9999), +}; + +int *bitmaps[5] = { + bitmap0, + bitmap1, + bitmap2, + bitmap3, + bitmap4, +}; diff --git a/src/lib/subs/getele.c b/src/lib/subs/getele.c new file mode 100644 index 00000000..4041980a --- /dev/null +++ b/src/lib/subs/getele.c @@ -0,0 +1,115 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * getele.c: Read a telegram from a file or stdin and send it to a country + * + * Known contributors to this file: + * + */ + +#include +#include "misc.h" +#include "player.h" +#include "tel.h" +#include "prototypes.h" + +static int tilde_escape(s_char *s, s_char c); + +int +getele(s_char *nation, s_char *buf) +{ + register s_char *bp; + register int len; + register int c; + s_char buffer[MAXTELSIZE + 2]; + s_char left[MAXTELSIZE + 2]; + + pr("Enter telegram for %s\n", nation); + pr("undo last line with ~u, print with ~p, abort with ~q, end with ^D or .\n"); + bp = buf; + while (!player->aborted) { + sprintf(left, "%4d left: ", (int)(buf + MAXTELSIZE - bp)); + buffer[0] = 0; + if (prmptrd(left, buffer, MAXTELSIZE-2) <= 0) + break; + if (tilde_escape(buffer, 'q')) + return -1; + if (tilde_escape(buffer, 'u')) { + if (bp == buf) { + pr("No more lines to undo\n"); + continue; + } + pr("Last line deleted.\n"); + for (bp -= 2; bp > buf && *bp != '\n'; --bp); + if (bp > buf) + *(++bp) = 0; + else + bp = buf; + continue; + } + if (tilde_escape(buffer, 'p')) { + pr("This is what you have written so far:\n"); + pr("%s", buf); + continue; + } + if (buffer[0] == '.' && ((buffer[1] == 0) || + (buffer[1] == '\n') || (buffer[1] == '\r'))) + break; + len = strlen(buffer); + buffer[len++] = '\n'; + buffer[len] = 0; + if (len + (bp - buf) > MAXTELSIZE) + pr("Too long. Try that last line again...\n"); + else { + if (buffer[0] == '>') /* forgery attempt? */ + buffer[0] = '?'; /* foil it */ + (void) strcpy(bp, buffer); + bp += len; + } + } + if (player->aborted) + return -1; + len = bp - buf; + buf[len] = 0; + /* Get rid of non-ASCII and control characters. */ + for (bp = buf; 0 != (c = *bp); bp++) { + if (isascii(c) && (isprint(c) || isspace(c))) + continue; + *bp = '?'; + } + return len; +} + +static int +tilde_escape(s_char *s, s_char c) +{ + if (s[0] == '~' && s[1] == c && + ((s[2] == 0) || (s[2] == '\n') || (s[2] == '\r'))) + return 1; + return 0; +} + diff --git a/src/lib/subs/land.c b/src/lib/subs/land.c new file mode 100644 index 00000000..2d5a06af --- /dev/null +++ b/src/lib/subs/land.c @@ -0,0 +1,173 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * land.c: Land unit post-read and pre-write + * + * Known contributors to this file: + * Steve McClure, 1996 + */ + +#include "misc.h" +#include "player.h" +#include "var.h" +#include "file.h" +#include "land.h" +#include "ship.h" +#include "xy.h" +#include "nat.h" +#include "deity.h" +#include "nsc.h" +#include "plane.h" +#include "prototypes.h" +#include "optlist.h" + +int +lnd_postread(int n, s_char *ptr) +{ + struct lndstr *llp = (struct lndstr *) ptr; + struct shpstr theship; + struct lndstr theland; + + if (llp->lnd_uid != n) { + logerror("lnd_postread: Error - %d != %d, zeroing.\n", llp->lnd_uid, n); + bzero(ptr, sizeof(struct lndstr)); + } + if (llp->lnd_ship >= 0 && llp->lnd_own && llp->lnd_effic >= LAND_MINEFF) { + if (getship(llp->lnd_ship, &theship) && + (theship.shp_effic >= SHIP_MINEFF)) { + /* wooof! Carriers are a pain */ + if (llp->lnd_mission){ + /* + * If the unit is on a mission centered + * on it's loc, the op-area travels with + * the unit. + */ + if ((llp->lnd_opx == llp->lnd_x) && + (llp->lnd_opy == llp->lnd_y)) { + llp->lnd_opx = theship.shp_x; + llp->lnd_opy = theship.shp_y; + } + } + if (llp->lnd_x != theship.shp_x || llp->lnd_y != theship.shp_y) + time(&llp->lnd_timestamp); + llp->lnd_x = theship.shp_x; + llp->lnd_y = theship.shp_y; + } + } + if (llp->lnd_land >= 0 && llp->lnd_own && llp->lnd_effic >= LAND_MINEFF) { + if (getland(llp->lnd_land, &theland) && + (theland.lnd_effic >= LAND_MINEFF)) { + /* wooof! Carriers are a pain */ + if (llp->lnd_mission){ + /* + * If the unit is on a mission centered + * on it's loc, the op-area travels with + * the unit. + */ + if ((llp->lnd_opx == llp->lnd_x) && + (llp->lnd_opy == llp->lnd_y)){ + llp->lnd_opx = theland.lnd_x; + llp->lnd_opy = theland.lnd_y; + } + } + if (llp->lnd_x != theland.lnd_x || llp->lnd_y != theland.lnd_y) + time(&llp->lnd_timestamp); + llp->lnd_x = theland.lnd_x; + llp->lnd_y = theland.lnd_y; + } + } + if (opt_MOB_ACCESS) + lnd_do_upd_mob(llp); + + player->owner = (player->god || llp->lnd_own == player->cnum); + return 1; +} + +/*ARGSUSED*/ +int +lnd_prewrite(int n, s_char *ptr) +{ + struct lndstr *llp = (struct lndstr *) ptr; + struct lndstr land; + struct lndstr *lp; + struct plnstr *pp; + int i; + + llp->ef_type = EF_LAND; + llp->lnd_uid = n; + + time(&llp->lnd_timestamp); + + if (llp->lnd_own && llp->lnd_effic < LAND_MINEFF) { + makelost(EF_LAND, llp->lnd_own, llp->lnd_uid, llp->lnd_x, llp->lnd_y); + llp->lnd_own = 0; + + getland(n, &land); + + for (i = 0; NULL != (lp = getlandp(i)); i++) { + if (lp->lnd_own && lp->lnd_land == n) { + mpr(lp->lnd_own, "%s MIA!\n", prland(lp)); + makelost(EF_LAND, lp->lnd_own, lp->lnd_uid, lp->lnd_x, lp->lnd_y); + lp->lnd_own = 0; + lp->lnd_effic = 0; + lp->lnd_ship = -1; + lp->lnd_land = -1; + putland(lp->lnd_uid, lp); + } + } + for (i = 0; NULL != (pp = getplanep(i)); i++) { + if (pp->pln_own && pp->pln_land == n) { + mpr(pp->pln_own, "%s MIA!\n", prplane(pp)); + makelost(EF_PLANE, pp->pln_own, pp->pln_uid, pp->pln_x, pp->pln_y); + pp->pln_own = 0; + pp->pln_effic = 0; + pp->pln_ship = -1; + pp->pln_land = -1; + putplane(pp->pln_uid, pp); + } + } + } else + getland(n, &land); + + return 1; +} + +void +lnd_init(int n, s_char *ptr) +{ + struct lndstr *lp = (struct lndstr *) ptr; + + lp->ef_type = EF_LAND; + lp->lnd_uid = n; + lp->lnd_own = 0; +} + +s_char * +prland(struct lndstr *lp) +{ + return prbuf("%s #%d", lchr[(int)lp->lnd_type].l_name, lp->lnd_uid); +} diff --git a/src/lib/subs/landgun.c b/src/lib/subs/landgun.c new file mode 100644 index 00000000..afad0b56 --- /dev/null +++ b/src/lib/subs/landgun.c @@ -0,0 +1,88 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * landgun.c: Return values for land and ship gun firing damages + * + * Known contributors to this file: + * + */ + +#include "misc.h" +#include "ship.h" +#include "land.h" +#include "sect.h" +#include "prototypes.h" + +double +landgun(int effic, int guns) +{ + double d; + double g = (double)min(guns,7); + + d = ((double)(random() % 30) + 20.0) * ((double)g / 7.0); + d *= ((double)effic); + d /= 100.0; + return d; +} + +double +seagun(int effic, int guns) +{ + double d; + + d = 0.0; + while (guns--) + d += 10.0 + (double)(random() % 6); + d *= ((double)effic) * 0.01; + return d; +} + +double +landunitgun(int effic, int shots, int guns, int ammo, int shells) +{ + double d = 0.0; + + shots = min(shots, guns); + while (shots-- > 0) + d += 5.0 + (double)(random() % 6); + d *= ((double)effic) * 0.01; + if (shells < ammo && ammo != 0) + d *= (double)((double)shells / (double)ammo); + return d; +} + +int +roundrange(double r) +{ + double f; + + f = r - ((int)r); + if (chance(f)) + return (((int)r) + 1); + else + return ((int)r); +} diff --git a/src/lib/subs/list.c b/src/lib/subs/list.c new file mode 100644 index 00000000..defb1f6e --- /dev/null +++ b/src/lib/subs/list.c @@ -0,0 +1,314 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * list.c: List ships, planes, units at a given x,y + * + * Known contributors to this file: + * Dave Pare, 1986 + */ + +#include "misc.h" +#include "player.h" +#include "var.h" +#include "news.h" +#include "ship.h" +#include "land.h" +#include "sect.h" +#include "nuke.h" +#include "plane.h" +#include "nat.h" +#include "item.h" +#include "xy.h" +#include "nsc.h" +#include "file.h" +#include "prototypes.h" + +extern s_char *effadv(int); + +int +shipsatxy(coord x, coord y, int wantflags, int nowantflags) +{ + int first; + int ships; + struct nstr_item ni; + struct mchrstr *mp; + struct shpstr ship; + + first = 1; + ships = 0; + snxtitem_xy(&ni, EF_SHIP, x, y); + while (nxtitem(&ni, (s_char *)&ship)) { + if (player->owner) + continue; + if (ship.shp_effic < SHIP_MINEFF || ship.shp_own == 0) + continue; + mp = &mchr[(int)ship.shp_type]; + if (wantflags) { + if ((mp->m_flags & wantflags) == 0) + continue; + } + if (nowantflags) { + if (mp->m_flags & nowantflags) + continue; + } + if (first) { + pr(" # owner eff type\n"); + first = 0; + } + pr("(#%3d) %10.10s %12.12s %s\n", ni.cur, + cname(ship.shp_own), + effadv(ship.shp_effic), prship(&ship)); + ships++; + } + return ships; +} + +/* This one only shows owned or allied ships */ + +int +carriersatxy(coord x, coord y, int wantflags, int nowantflags, natid own) +{ + int first; + int ships; + struct nstr_item ni; + struct mchrstr *mp; + struct shpstr ship; + int allied; + + first = 1; + ships = 0; + snxtitem_xy(&ni, EF_SHIP, x, y); + while (nxtitem(&ni, (s_char *)&ship)) { + if (ship.shp_effic < SHIP_MINEFF || ship.shp_own == 0) + continue; + allied = (getrel(getnatp(ship.shp_own), own) == ALLIED); + if ((ship.shp_own != own) & !allied) + continue; + mp = &mchr[(int)ship.shp_type]; + if (wantflags) { + if ((mp->m_flags & wantflags) == 0) + continue; + } + if (nowantflags) { + if (mp->m_flags & nowantflags) + continue; + } + if (first) { + pr(" # owner eff type\n"); + first = 0; + } + pr("(#%3d) %10.10s %12.12s %s\n", ni.cur, + cname(ship.shp_own), + effadv(ship.shp_effic), + prship(&ship)); + ships++; + } + return ships; +} + +int +unitsatxy(coord x, coord y, int wantflags, int nowantflags) +{ + int first; + int units; + struct nstr_item ni; + struct lchrstr *lp; + struct lndstr land; + double odds; + + first = 1; + units = 0; + snxtitem_xy(&ni, EF_LAND, x, y); + while (nxtitem(&ni, (s_char *)&land)) { + if (land.lnd_effic < LAND_MINEFF || land.lnd_own == 0) + continue; + /* Can't bomb units on ships or other units */ + if (land.lnd_ship >= 0 || land.lnd_land >= 0) + continue; + lp = &lchr[(int)land.lnd_type]; + + if (wantflags) { + if ((lp->l_flags & wantflags) == 0) + continue; + } + if (nowantflags) { + if (lp->l_flags & nowantflags) + continue; + } + + if (lp->l_flags & L_SPY) { + odds = (double)(100 - land.lnd_effic) + 0.10; + if (!(chance(odds))) + continue; + } + + if (first) { + pr(" # owner eff type\n"); + first = 0; + } + pr("(#%3d) %10.10s %12.12s %s\n", ni.cur, + cname(land.lnd_own), + effadv(land.lnd_effic), prland(&land)); + units++; + } + return units; +} + +int +planesatxy(coord x, coord y, int wantflags, int nowantflags, struct emp_qelem *list) +{ + int first; + int planes; + struct plnstr plane; + struct nstr_item ni; + struct plchrstr *plp; + + planes = 0; + first = 1; + snxtitem_xy(&ni, EF_PLANE, x, y); + while (nxtitem(&ni, (s_char *)&plane)) { + if (plane.pln_effic < PLANE_MINEFF || plane.pln_own == 0) + continue; + if (plane.pln_flags & PLN_LAUNCHED) + continue; + /* Is this plane one of the ones flying somewhere? */ + if (ac_isflying(&plane, list)) + continue; + plp = &plchr[(int)plane.pln_type]; + if (first) { + pr(" # owner eff type\n"); + first = 0; + } + if (wantflags) { + if ((plp->pl_flags & wantflags) == 0) + continue; + } + if (nowantflags) { + if (plp->pl_flags & nowantflags) + continue; + } + pr("(#%3d) %10.10s %12.12s %s\n", ni.cur, + cname(plane.pln_own), + effadv(plane.pln_effic), prplane(&plane)); + planes++; + } + return planes; +} + +int +asw_shipsatxy(coord x, coord y, int wantflags, int nowantflags, struct plnstr *pp, struct shiplook *head) +{ + int first; + int ships; + struct nstr_item ni; + struct mchrstr *mp; + struct shpstr ship; + + first = 1; + ships = 0; + snxtitem_xy(&ni, EF_SHIP, x, y); + while (nxtitem(&ni, (s_char *)&ship)) { + if (player->owner) + continue; + if (ship.shp_effic < SHIP_MINEFF || ship.shp_own == 0) + continue; + mp = &mchr[(int)ship.shp_type]; + if (wantflags) { + if ((mp->m_flags & wantflags) == 0) + continue; + } + if (nowantflags) { + if (mp->m_flags & nowantflags) + continue; + } + if (mp->m_flags & M_SUB){ + if (roll(100) > pln_hitchance(pp, + shp_hardtarget(&ship), + EF_SHIP)) + continue; + } + set_have_found(ship.shp_uid,head); + if (first) { + pr(" # owner eff type\n"); + first = 0; + } + pr("(#%3d) %10.10s %12.12s %s\n", ni.cur, + cname(ship.shp_own), + effadv(ship.shp_effic), prship(&ship)); + ships++; + } + return ships; +} + +int +num_shipsatxy(coord x, coord y, int wantflags, int nowantflags) +{ + int ships; + struct nstr_item ni; + struct mchrstr *mp; + struct shpstr ship; + + ships = 0; + snxtitem_xy(&ni, EF_SHIP, x, y); + while (nxtitem(&ni, (s_char *)&ship)) { + if (ship.shp_effic < SHIP_MINEFF || ship.shp_own == 0) + continue; + mp = &mchr[(int)ship.shp_type]; + if (wantflags) { + if ((mp->m_flags & wantflags) == 0) + continue; + } + if (nowantflags) { + if (mp->m_flags & nowantflags) + continue; + } + ships++; + } + return ships; +} + +/* + * is p a list of ships/planes/units? + * + */ + +int +islist(s_char *p) +{ + register int x; + + x=0; + + while(*(p+x)){ + if (!isdigit(*(p+x)) && (*(p+x) != '/')) + return 0; + + x++; + } + + return 1; +} diff --git a/src/lib/subs/lndsub.c b/src/lib/subs/lndsub.c new file mode 100644 index 00000000..5311c7de --- /dev/null +++ b/src/lib/subs/lndsub.c @@ -0,0 +1,1341 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * lndsub.c: Land unit subroutines + * + * Known contributors to this file: + * Ken Stevens, 1995 + * Steve McClure, 1998-2000 + */ + +#include +#include "misc.h" +#include "player.h" +#include "file.h" +#include "var.h" +#include "sect.h" +#include "path.h" +#include "news.h" +#include "treaty.h" +#include "nat.h" +#include "xy.h" +#include "land.h" +#include "ship.h" +#include "nsc.h" +#include "mission.h" +#include "plane.h" +#include "combat.h" +#include "damage.h" +#include "optlist.h" +#include "prototypes.h" + +extern int etu_per_update; + +int +attack_val(int combat_mode, struct lndstr *lp) +{ + extern double assault_penalty; + int men; + int value; + struct lchrstr *lcp; + + if (((int)lp->lnd_effic) < LAND_MINEFF){ + makelost(EF_LAND, lp->lnd_own, lp->lnd_uid, lp->lnd_x, lp->lnd_y); + lp->lnd_own=0; + putland(lp->lnd_uid,lp); + return 0; + } + + lcp = &lchr[(int)lp->lnd_type]; + +/* Spies always count as 1 during assaults. If they are the only ones + in the assault, they get to sneak on anyway. */ + + if (lcp->l_flags & L_SPY && combat_mode == A_ASSAULT) + return 1; + + men = total_mil(lp); + + value = ldround(((double)men*(double)lp->lnd_att),1); + + value = (int)((double)value * ((double)lp->lnd_effic / 100.0)); + + switch (combat_mode) { + case A_ATTACK: + return value; + case A_ASSAULT: + if (!(lcp->l_flags & L_MARINE)) + return (int)(assault_penalty * value); + break; + case A_BOARD: + if (!(lcp->l_flags & L_MARINE)) + return (int)(assault_penalty * men); + } + + return value; +} +int +defense_val(struct lndstr *lp) +{ + extern int land_mob_max; + int men; + double value; + struct lchrstr *lcp; + + if (((int)lp->lnd_effic) < LAND_MINEFF){ + makelost(EF_LAND, lp->lnd_own, lp->lnd_uid, lp->lnd_x, lp->lnd_y); + lp->lnd_own=0; + putland(lp->lnd_uid,lp); + return 0; + } + + lcp = &lchr[(int)lp->lnd_type]; + + men = total_mil(lp); + + if (men < 0) + men = 0; + if ((lp->lnd_ship >= 0 || lp->lnd_land >= 0) && + !(lcp->l_flags & L_MARINE)) + return men; + + value = men * lp->lnd_def; + + value *= ((double)land_mob_max + lp->lnd_harden) / (double)land_mob_max; + value = (int)((double)value * ((double)lp->lnd_effic / 100.0)); + value = (int)ldround(value, 1); + + /* If there are military on the unit, you get at least a 1 + man defensive unit, except for spies */ + if (value < 1.0 && men > 0 && !(lcp->l_flags & L_SPY)) + return 1; + + return (int)(value); +} +int +total_mil(struct lndstr *lp) +{ + struct lchrstr *lcp; + double men; + + lcp = &lchr[(int)lp->lnd_type]; + + men = lnd_getmil(lp); +/* men *= ((double)lp->lnd_effic)/100.0;*/ + + return ldround(men,1); +} + +void +lnd_print(struct llist *llp, s_char *s) +{ + if (llp->land.lnd_own == player->cnum) + pr("%s %s\n",prland(&llp->land), s); + else + wu(0, llp->land.lnd_own, + "%s %s\n",prland(&llp->land),s); +} + +void +lnd_delete(struct llist *llp, s_char *s) +{ + if (s) + lnd_print(llp, s); + putland(llp->land.lnd_uid, &llp->land); + emp_remque((struct emp_qelem *)llp); + free((s_char *)llp); +} +int +lnd_take_casualty(int combat_mode, struct llist *llp, int cas) + /* attacking or assaulting or paratrooping? */ + + /* number of casualties to take */ +{ + int eff_eq; + int n; + int biggest; + int civs; + int nowned; + coord ret_x, ret_y; + coord bx, by; + struct sctstr sect; + int ret_chance; + s_char buf[1024]; + int taken; + int nowhere_to_go = 0; + struct sctstr rsect; + double mobcost; + s_char orig; + int mob; + + + + taken = lnd_getmil(&(llp->land)); + /* Spies always die */ + if (llp->lcp->l_flags & L_SPY) { + eff_eq = 100; + llp->land.lnd_effic = 0; + } else { + eff_eq = ldround((((double)cas*100.0) / (double)llp->lcp->l_mil),1); + llp->land.lnd_effic -= eff_eq; + lnd_submil(&(llp->land), cas); + } + + if (llp->land.lnd_effic < LAND_MINEFF) { + sprintf(buf, "dies %s %s!", + combat_mode?att_mode[combat_mode]:(s_char*) "defending", + xyas(llp->land.lnd_x, llp->land.lnd_y, llp->land.lnd_own)); + lnd_delete(llp, buf); + /* Since we killed the unit, we killed all the mil on it */ + return taken; + } else { + /* Ok, now, how many did we take off? (sould be the diff) */ + taken = taken - lnd_getmil(&(llp->land)); + } + + if (llp->land.lnd_effic >= llp->land.lnd_retreat) + return taken; + + /* we're being boarded */ + if (llp->land.lnd_ship >= 0 && combat_mode == A_DEFEND) + return taken; + + /* we're being boarded */ + if (llp->land.lnd_land >= 0 && combat_mode == A_DEFEND) + return taken; + + /* Have to make a retreat check */ + + ret_chance = llp->land.lnd_retreat - llp->land.lnd_effic; + if (roll(100) < ret_chance) { + pr("\n"); + lnd_print(llp, "fails morale check!"); + llp->land.lnd_mission = 0; + llp->land.lnd_harden = 0; + if (llp->land.lnd_ship >= 0 || llp->land.lnd_land >= 0) + nowhere_to_go = 1; + else if (combat_mode == A_DEFEND) { + /* + * defending unit.. find a place to send it + * strategy: look for the most-populated + * adjacent sector that is owned by the unit + * player->owner. Charge mob.. + */ + biggest = -1; + nowned = 0; + for(n = 1; n <= 6; ++n) { + ret_x = llp->land.lnd_x + diroff[n][0]; + ret_y = llp->land.lnd_y + diroff[n][1]; + getsect(ret_x, ret_y, §); + if (sect.sct_own != llp->land.lnd_own) + continue; + if (sect.sct_type == SCT_MOUNT) + continue; + ++nowned; + civs = getvar(V_CIVIL, (s_char *)§, EF_SECTOR); + if (civs > biggest){ + biggest = civs; + bx = sect.sct_x; + by = sect.sct_y; + } + } + if (!nowned) + nowhere_to_go = 1; + else { + /* retreat to bx,by */ + llp->land.lnd_x = bx; + llp->land.lnd_y = by; + getsect(bx,by,&rsect); + mobcost = lnd_mobcost(&llp->land, &rsect, MOB_ROAD); + mob = llp->land.lnd_mobil-(int)mobcost; + if (mob < -127) + mob = -127; + orig = llp->land.lnd_mobil; + llp->land.lnd_mobil = (s_char)mob; + if (llp->land.lnd_mobil > orig) + llp->land.lnd_mobil = (-127); + sprintf(buf, "retreats at %d%% efficiency to %s!", + llp->land.lnd_effic, + xyas(bx,by,llp->land.lnd_own)); + lnd_delete(llp, buf); + } + } else { /* attacking from a sector */ + sprintf(buf, "leaves the battlefield at %d%% efficiency", + llp->land.lnd_effic); + if ((llp->land.lnd_mobil - (int)llp->mobil) < -127) + llp->land.lnd_mobil = -127; + else + llp->land.lnd_mobil -= (int)llp->mobil; + llp->mobil = 0.0; + lnd_delete(llp, buf); + } + } + if (nowhere_to_go) { + /* nowhere to go.. take more casualties */ + llp->land.lnd_effic -= 10; + lnd_submil(&llp->land, llp->lcp->l_mil / 10); + if (llp->land.lnd_effic < LAND_MINEFF) + lnd_delete(llp, "has nowhere to retreat, and dies!"); + else + lnd_print(llp, "has nowhere to retreat and takes extra losses!"); + } + + return taken; +} + +void +lnd_takemob(struct emp_qelem *list, double loss) +{ + extern double combat_mob; + struct emp_qelem *qp, *next; + struct llist *llp; + int new; + int mcost = ldround(combat_mob * loss, 1); + + for (qp = list->q_forw; qp != list; qp = next) { + next = qp->q_forw; + llp = (struct llist *)qp; +/* + if (chance(loss)) + use_supply(&llp->land); + if (llp->land.lnd_mission == MI_RESERVE) + new = llp->land.lnd_mobil - mcost/2; + else + */ + new = llp->land.lnd_mobil - mcost; + if (new < -127) + new = -127; + llp->land.lnd_mobil = (s_char)new; + } +} +int +lnd_getmil(struct lndstr *lp) +{ + int vec[I_MAX+1]; + + getvec(VT_ITEM, vec, (s_char *)lp, EF_LAND); + return vec[I_MILIT]; +} + +void +lnd_submil(struct lndstr *lp, int num) +{ + int vec[I_MAX+1]; + + getvec(VT_ITEM, vec, (s_char *)lp, EF_LAND); + vec[I_MILIT] -= num; + if (vec[I_MILIT] < 0) + vec[I_MILIT] = 0; + putvec(VT_ITEM, vec, (s_char *)lp, EF_LAND); +} +int +lnd_spyval(struct lndstr *lp) +{ + if (lchr[(int)lp->lnd_type].l_flags & L_RECON) + return (lp->lnd_spy * (lp->lnd_effic/100.0))+2; + else + return (lp->lnd_spy * (lp->lnd_effic/100.0)); +} + +int +intelligence_report(int destination, struct lndstr *lp, int spy, s_char *mess) +{ + struct lchrstr *lcp; + s_char buf1[80],buf2[80],buf3[80]; + double estimate = 0.0; /* estimated defense value */ + + if (destination == 0) + return 0; + + if (lp->lnd_own == 0) + return 0; + + lcp = &lchr[(int)lp->lnd_type]; + + bzero(buf1,80); + bzero(buf2,80); + bzero(buf3,80); + if (chance((double)(spy+lp->lnd_vis)/10.0)){ + if (destination == player->cnum) + pr("%s %s", mess, prland(lp)); + else + sprintf(buf1,"%s %s", mess, prland(lp)); + + estimate = lnd_getmil(lp); + + if (chance((double)(spy+lp->lnd_vis)/20.0)){ + + if (destination == player->cnum) + pr(" (eff %d, mil %d", roundintby(lp->lnd_effic,5), roundintby(lnd_getmil(lp),10)); + else + sprintf(buf2," (eff %d, mil %d", roundintby(lp->lnd_effic,5), roundintby(lnd_getmil(lp),10)); + estimate = lnd_getmil(lp) * lp->lnd_effic / 100.0; + + if (chance((double)(spy+lp->lnd_vis)/20.0)){ + int t; + t = lp->lnd_tech - 20 + roll(40); + t = max(t,0); + if (destination == player->cnum) + pr(", tech %d)\n",t); + else + sprintf(buf3,", tech %d)\n",t); + }else{ + if (destination == player->cnum) + pr(")\n"); + else + sprintf(buf3,")\n"); + } + }else{ + if (destination == player->cnum) + pr("\n"); + else + sprintf(buf2,"\n"); + } + } + + if (destination != player->cnum){ + wu(0, destination, "%s%s%s",buf1,buf2,buf3); + } + + if (lp->lnd_ship < 0 || lcp->l_flags & L_MARINE) + estimate *= lp->lnd_def; + + return (int)estimate; +} + +/* Used by the spy command to count land units in a sector. If used + for anything else, you may want to reconsider, because this doesn't + always count spies. :) */ +int +count_sect_units(struct sctstr *sp) +{ + int count = 0; + double odds; + struct nstr_item ni; + struct lndstr land; + + snxtitem_all(&ni, EF_LAND); + while (nxtitem(&ni, (s_char *)&land)) { + if (!land.lnd_own) + continue; + if (land.lnd_x != sp->sct_x || land.lnd_y != sp->sct_y) + continue; + /* Don't always see spies */ + if (lchr[(int)land.lnd_type].l_flags & L_SPY) { + odds = (double)(100 - land.lnd_effic) + 0.10; + if (!(chance(odds))) + continue; + } + /* Got here, report it */ + ++count; + } + + return count; +} + +void +count_units(struct shpstr *sp) +{ + struct nstr_item ni; + struct lndstr land; + int nland = 0; + + if (sp->shp_effic < SHIP_MINEFF) + return; + + snxtitem_xy(&ni, EF_LAND, sp->shp_x, sp->shp_y); + while (nxtitem(&ni, (s_char *)&land)){ + if (land.lnd_own == 0) + continue; + if (land.lnd_ship == sp->shp_uid) + nland++; + } + + if (sp->shp_nland != nland) { + sp->shp_nland = nland; + putship(sp->shp_uid,sp); + } +} + +void +lnd_count_units(struct lndstr *lp) +{ + struct nstr_item ni; + struct lndstr land; + int nland = 0; + + if (lp->lnd_effic < LAND_MINEFF) + return; + + snxtitem_xy(&ni, EF_LAND, lp->lnd_x, lp->lnd_y); + while (nxtitem(&ni, (s_char *)&land)){ + if (land.lnd_own == 0) + continue; + if (land.lnd_land == lp->lnd_uid) + nland++; + } + + if (lp->lnd_nland != nland) { + lp->lnd_nland = nland; + putland(lp->lnd_uid,lp); + } +} + +void +lnd_sel(struct nstr_item *ni, struct emp_qelem *list) + + +/* int wantflags; + int nowantflags; +*/ +{ + struct lndstr land; + struct lchrstr *lcp; + struct llist *llp; + + emp_initque(list); + while (nxtitem(ni, (s_char *)&land)) { + if (!player->owner) + continue; + if (opt_MARKET) { + if (ontradingblock(EF_LAND, (int *)&land)) { + pr("unit #%d inelligible - it's for sale.\n", land.lnd_uid); + continue; + } + } + lcp = &lchr[(int)land.lnd_type]; +/* if (wantflags && (lcp->m_flags & wantflags) != wantflags) + continue; + if (nowantflags && lcp->m_flags & nowantflags) + continue; +*/ + /* This abuse is better fixed by building a unit with the normal negative + mobility that everything else is built with */ +/* Just so that the player can't build a bunch of land units, and them + march them a few minutes later... */ +/* + if (opt_MOB_ACCESS) { + if (land.lnd_effic < 11 && + land.lnd_mobil < etu_per_update) { + pr("Land unit #%d needs at least %d mob to march.\n", + land.lnd_uid, etu_per_update); + continue; + } + } +*/ + land.lnd_mission = 0; + land.lnd_rflags = 0; + land.lnd_harden = 0; + bzero(land.lnd_rpath,RET_LEN); + putland(land.lnd_uid, &land); + llp = (struct llist *) malloc(sizeof(struct llist)); + llp->lcp = lcp; + bcopy((s_char *)&land, (s_char *)&llp->land, + sizeof(struct lndstr)); + llp->mobil = (double)land.lnd_mobil; + emp_insque(&llp->queue, list); + } +} + +/* This function assumes that the list was created by lnd_sel */ +void +lnd_mar(struct emp_qelem *list, double *minmobp, double *maxmobp, int *togetherp, natid actor) +{ + struct emp_qelem *qp; + struct emp_qelem *next; + struct llist *llp; + struct sctstr sect; + struct lndstr land; + coord allx; + coord ally; + int first=1; + s_char mess[128]; + int rel; + + *minmobp = 9876.0; + *maxmobp = -9876.0; + *togetherp = 1; + for (qp = list->q_back; qp != list; qp = next) { + next = qp->q_back; + llp = (struct llist *) qp; + getland(llp->land.lnd_uid, &land); + if (land.lnd_own != actor) { + mpr(actor, "%s was disbanded at %s\n", + prland(&land), + xyas(land.lnd_x, land.lnd_y, land.lnd_own)); + emp_remque((struct emp_qelem *)llp); + free((s_char *)llp); + continue; + } + if (land.lnd_ship >= 0) { + lnd_mess("is on a ship", llp); + continue; + } + if (land.lnd_land >= 0) { + lnd_mess("is on a unit", llp); + continue; + } + if (!getsect(land.lnd_x, land.lnd_y, §)) { + lnd_mess("was sucked into the sky by a strange looking spaceland", llp); /* heh -KHS */ + continue; + } + if (!(lchr[(int)llp->land.lnd_type].l_flags & L_SPY) && + !(lchr[(int)llp->land.lnd_type].l_flags & L_TRAIN) && + lnd_getmil(&llp->land) == 0) { + lnd_mess("has no mil on it to guide it", llp); + continue; + } + rel = getrel(getnatp(sect.sct_own), player->cnum); + if (sect.sct_own != land.lnd_own && rel != ALLIED && + !(lchr[(int)llp->land.lnd_type].l_flags & L_SPY) && + sect.sct_own) { + sprintf(mess, "has been kidnapped by %s", cname(sect.sct_own)); + lnd_mess(mess, llp); + continue; + } + if (first){ + allx = land.lnd_x; + ally = land.lnd_y; + first = 0; + } + if (land.lnd_x != allx || + land.lnd_y != ally) + *togetherp = 0; + if (land.lnd_mobil + 1 < (int)llp->mobil) { + llp->mobil = (double)land.lnd_mobil; + } + if (llp->mobil < *minmobp) + *minmobp = llp->mobil; + if (llp->mobil > *maxmobp) + *maxmobp = llp->mobil; + bcopy((s_char *)&land, (s_char *)&llp->land, + sizeof(struct lndstr)); + } +} + +void +lnd_put(struct emp_qelem *list, natid actor) +{ + register struct emp_qelem *qp; + register struct emp_qelem *newqp; + struct llist *llp; + + qp = list->q_back; + while (qp != list) { + llp = (struct llist *) qp; + if (actor) { + mpr(actor, "%s stopped at %s\n", prland(&llp->land), + xyas(llp->land.lnd_x, llp->land.lnd_y, llp->land.lnd_own)); + if (llp->mobil < -127) + llp->mobil = -127; + llp->land.lnd_mobil = llp->mobil; + } + putland(llp->land.lnd_uid, &llp->land); + newqp = qp->q_back; + emp_remque(qp); + free((s_char *)qp); + qp = newqp; + } +} + +void +lnd_sweep(struct emp_qelem *land_list, int verbose, int takemob, natid actor) +{ + struct emp_qelem *qp; + struct emp_qelem *next; + struct llist *llp; + struct sctstr sect; + int mines, m, max, sshells, lshells; + double mobcost; + + for (qp=land_list->q_back;qp!=land_list;qp=next) { + next = qp->q_back; + llp = (struct llist *) qp; + if (!(llp->lcp->l_flags & L_ENGINEER)) { + if (verbose) + mpr(actor, "%s is not an engineer!\n", + prland(&llp->land)); + continue; + } + if (takemob && llp->mobil < 0.0) { + if (verbose) + lnd_mess("is out of mobility", llp); + continue; + } + getsect(llp->land.lnd_x,llp->land.lnd_y,§); + if (sect.sct_oldown == llp->land.lnd_own) { + if (verbose) + mpr(actor, "%s is in a sector completely owned by you. Don't bother digging up mines there!\n", + prland(&llp->land)); + continue; + } + if (sect.sct_type == SCT_BSPAN) { + if (verbose) + mpr(actor, "%s is on a bridge. No mines there!\n", prland(&llp->land)); + continue; + } + if (takemob) { +/* mobcost = llp->land.lnd_effic * 0.01 * llp->lcp->l_spd;*/ + mobcost = llp->land.lnd_spd; + mobcost = 480.0 / (mobcost + + techfact(llp->land.lnd_tech,mobcost)); + llp->mobil -= mobcost; + llp->land.lnd_mobil = (int)llp->mobil; + } + putland(llp->land.lnd_uid, &llp->land); + if (!(mines=getvar(V_MINE,(s_char *)§,EF_SECTOR))) + continue; + max = vl_find(V_SHELL, llp->lcp->l_vtype, + llp->lcp->l_vamt, (int)llp->lcp->l_nv); + lshells = getvar(V_SHELL, (s_char *)&llp->land, EF_LAND); + sshells = getvar(V_SHELL, (s_char *)§, EF_SECTOR); + for (m=0; mines > 0 && m < max * 2; m++) { + if (chance(0.5 * llp->lcp->l_att)) { + mpr(actor, "Sweep...\n"); + mines--; + if (lshells < max) + ++lshells; + else + ++sshells; + } + } + putvar(V_MINE, mines, (s_char *)§, EF_SECTOR); + putvar(V_SHELL, lshells, (s_char *)&llp->land, EF_LAND); + putvar(V_SHELL, sshells, (s_char *)§, EF_SECTOR); + putland(llp->land.lnd_uid, &llp->land); + putsect(§); + } +} + +static int +contains_engineer(struct emp_qelem *list) +{ + struct emp_qelem *qp; + struct emp_qelem *next; + struct llist *llp; + + for (qp=list->q_back;qp!=list;qp=next) { + next = qp->q_back; + llp = (struct llist *) qp; + if (llp->lcp->l_flags & L_ENGINEER) + return 1; + } + return 0; +} + +int +lnd_check_mines(struct emp_qelem *land_list) +{ + struct emp_qelem *qp; + struct emp_qelem *next; + struct llist *llp; + struct sctstr sect; + int mines; + int stopping = 0; + int has_engineers = contains_engineer(land_list); + + for (qp=land_list->q_back;qp!=land_list;qp=next) { + next = qp->q_back; + llp = (struct llist *) qp; + getsect(llp->land.lnd_x,llp->land.lnd_y,§); + if (sect.sct_oldown == llp->land.lnd_own) + continue; + if (sect.sct_type == SCT_BSPAN) + continue; + if (!(mines=getvar(V_MINE,(s_char *)§,EF_SECTOR))) + continue; + if (chance(DMINE_LHITCHANCE(mines)/(1 + 2*has_engineers))) { + lnd_hit_mine(&llp->land, llp->lcp); + mines--; + putvar(V_MINE,mines,(s_char *)§,EF_SECTOR); + putsect(§); + putland(llp->land.lnd_uid, (s_char *)&llp->land); + if (!llp->land.lnd_own) { + stopping = 1; + emp_remque(qp); + free((s_char *)qp); + } + } + } + return stopping; +} + +void +lnd_list(struct emp_qelem *land_list) +{ + struct emp_qelem *qp; + struct emp_qelem *next; + struct llist *llp; + struct lndstr *lnd; + int vec[I_MAX+1]; + + pr("lnd# land type x,y a eff sh gun xl mu tech retr fuel\n"); + + for (qp=land_list->q_back;qp!=land_list;qp=next) { + next = qp->q_back; + llp = (struct llist *) qp; + lnd = &llp->land; + pr("%4d ", lnd->lnd_uid); + pr("%-16.16s ", llp->lcp->l_name); + prxy("%4d,%-4d ", lnd->lnd_x, lnd->lnd_y, llp->land.lnd_own); + pr("%1c", lnd->lnd_army); + pr("%4d%%", lnd->lnd_effic); + getvec(VT_ITEM, vec, (s_char *)lnd, EF_LAND); + pr("%4d", vec[I_SHELL]); + pr("%4d", vec[I_GUN]); + count_land_planes(lnd); + pr("%3d",lnd->lnd_nxlight); + pr("%4d", lnd->lnd_mobil); + pr("%4d", lnd->lnd_tech); + pr("%4d%%", lnd->lnd_retreat); + pr("%5d\n", lnd->lnd_fuel); + } +} + +void +lnd_mess(s_char *str, struct llist *llp) +{ + mpr(llp->land.lnd_own, "%s %s & stays in %s\n", + prland(&llp->land), + str, xyas(llp->land.lnd_x, llp->land.lnd_y, llp->land.lnd_own)); + if (llp->mobil < -127) + llp->mobil = -127; + llp->land.lnd_mobil = llp->mobil; + putland(llp->land.lnd_uid, &llp->land); + emp_remque((struct emp_qelem *)llp); + free((s_char *)llp); +} + +static int +lnd_count(struct emp_qelem *list) +{ + struct emp_qelem *qp; + struct emp_qelem *next; + struct llist *llp; + int count = 0; + + for (qp = list->q_back; qp != list; qp = next) { + next = qp->q_back; + llp = (struct llist *) qp; + ++count; + } + return count; +} + +static int +lnd_damage(struct emp_qelem *list, int totdam) +{ + struct emp_qelem *qp; + struct emp_qelem *next; + struct llist *llp; + int dam; + int count; + + if (!totdam || !(count = lnd_count(list))) + return 0; + dam = ldround(((double)totdam/(double)count),1); + for (qp = list->q_back; qp != list; qp = next) { + next = qp->q_back; + llp = (struct llist *) qp; + /* have to get it again because of collateral damage */ + getland(llp->land.lnd_uid, &llp->land); + landdamage(&llp->land, dam); + putland(llp->land.lnd_uid, &llp->land); + if (!llp->land.lnd_own) { + emp_remque(qp); + free((s_char *)qp); + } + } + return dam; +} + +static int lnd_easiest_target(struct emp_qelem *list) +{ + struct emp_qelem *qp; + struct emp_qelem *next; + struct llist *llp; + int hard; + int easiest = 9876; /* things start great for victim */ + int count = 0; + + for (qp = list->q_back; qp != list; qp = next) { + next = qp->q_back; + llp = (struct llist *) qp; + hard = lnd_hardtarget(&llp->land); + if (hard < easiest) + easiest = hard; /* things get worse for victim */ + ++count; + } + return easiest - count; +} + +static int +lnd_missile_interdiction(struct emp_qelem *list, coord newx, coord newy, natid victim) +{ + int dam; + struct emp_qelem msl_list, *qp, *newqp; + + msl_sel(&msl_list, newx, newy, victim, P_T, P_MAR, MI_INTERDICT); + + dam = msl_launch_mindam(&msl_list, newx, newy, + lnd_easiest_target(list), EF_LAND, + lnd_count(list) * 20, "troops", victim, + MI_INTERDICT); + if (dam) { + mpr(victim, "missile interdiction mission does %d damage!\n", dam); + collateral_damage(newx, newy, dam, 0); + } + qp = msl_list.q_forw; + while(qp != msl_list.q_forw) { + newqp=qp->q_forw; + emp_remque(qp); + free(qp); + qp = newqp; + } + return dam; +} + +#if 0 +/* Steve M. - commented out for now until abuse is decided upon */ +/* risner: allow forts to interdict land units. */ +static int +lnd_fort_interdiction(struct emp_qelem *list, + coord newx, coord newy, natid victim) +{ + extern int fort_max_interdiction_range; + struct nstr_sect ns; + struct sctstr fsect; + int trange; + double range, range2, guneff; + int shell, gun; + int dam; + int totdam = 0; + int i; + + snxtsct_dist(&ns, newx, newy, fort_max_interdiction_range); + while (nxtsct(&ns,&fsect)) { + if (fsect.sct_own == 0) + continue; + if (fsect.sct_own == victim) + continue; + if (fsect.sct_type != SCT_FORTR) + continue; + if (getrel(getnatp(fsect.sct_own), victim) >= NEUTRAL) + continue; + gun = getvar(V_GUN,(s_char *)&fsect,EF_SECTOR); + if (gun < 1) + continue; + range = tfactfire(fsect.sct_own,(double)min(gun,7)); + if (fsect.sct_effic > 59) + range++; + range2 = roundrange(range); + trange = mapdist(newx, newy, + fsect.sct_x, fsect.sct_y); + if (trange > range2) + continue; + if (getvar(V_MILIT,(s_char *)&fsect,EF_SECTOR)<5) + continue; + shell = getvar(V_SHELL,(s_char *)&fsect,EF_SECTOR); + if (shell < 1) + shell += supply_commod(fsect.sct_own, + fsect.sct_x,fsect.sct_y,I_SHELL, + 1); + if (shell < 1) + continue; + shell--; + putvar(V_SHELL, shell, (s_char *)&fsect, EF_SECTOR); + putsect(&fsect); + if (gun > 7) + gun = 7; + guneff = landgun((int)fsect.sct_effic, gun); + dam = (int)guneff; + totdam += dam; + mpr(victim, "Incoming fire does %d damage!\n", dam); + wu(0,fsect.sct_own, + "%s fires at %s land units in %s for %d!\n", + xyas(fsect.sct_x,fsect.sct_y, + fsect.sct_own), + cname(victim), + xyas(newx,newy,fsect.sct_own), dam); + nreport(fsect.sct_own, N_SCT_SHELL, victim, 1); + } + if (totdam > 0) + return lnd_damage(list, totdam); + return 0; +} +#endif + +int +lnd_interdict(struct emp_qelem *list, coord newx, coord newy, natid victim) +{ + int stopping = 0; + +#if 0 + if (!opt_NO_FORT_FIRE) +/* Steve M. - commented out for now until abuse is decided upon */ + stopping |= lnd_fort_interdiction(list, newx, newy, victim); +#endif + + stopping |= lnd_damage(list, unit_interdict(newx,newy,victim,"land units", lnd_easiest_target(list), MI_INTERDICT)); + + stopping |= lnd_damage(list, lnd_missile_interdiction(list,newx,newy,victim)); + return stopping; +} + +/* high value of hardtarget is harder to hit */ +int +lnd_hardtarget(struct lndstr *lp) +{ + struct sctstr sect; + + getsect(lp->lnd_x, lp->lnd_y, §); + return (int)(((double)lp->lnd_effic/100.0) * + (10 + dchr[sect.sct_type].d_dstr * 2 + + (double)lp->lnd_spd/2.0 - lp->lnd_vis)); +} + +int +lnd_hit_mine(struct lndstr *lp, struct lchrstr *lcp) +{ + double m; + + mpr(lp->lnd_own, "Blammo! Landmines detected in %s! ", + xyas(lp->lnd_x, lp->lnd_y, lp->lnd_own)); + + nreport(lp->lnd_own, N_LHIT_MINE, 0, 1); + + m = roll(20) + 10; + if (lcp->l_flags & L_ENGINEER) + m /= 2.0; + + landdamage(lp, ldround(m,1)); + + return (int)m; +} + +double +lnd_mobcost(struct lndstr *lp, struct sctstr *sp, int mobtype) +{ + double mobcost; + double smobcost; + + /* supply unit's speed depends on their eff, since + that is their purpose */ + if (lchr[(int)lp->lnd_type].l_flags & L_SUPPLY) + mobcost = lp->lnd_effic * 0.01 * lp->lnd_spd; + else + mobcost = lp->lnd_spd; + if (mobcost < 0.01) + mobcost = 0.01; + +/* sector_mcost now takes 2 different arguments, a sector pointer, and + whether or not to figure in the highway bonus, rail bonus or none. + bridge heads, bridges and highways have built-in highways bonus + because they are a 1, and this will discount that. */ + + smobcost = (double)sector_mcost(sp, mobtype); + if (smobcost < 0.01) + smobcost = 0.01; + +/* marching through 0 mobility conquered sectors takes lots of mobility, + unless you are a train. Capturing railways is a good thing. */ + + if (sp->sct_own != sp->sct_oldown && sp->sct_mobil <= 0 && + smobcost < LND_MINMOBCOST && mobtype != MOB_RAIL) + smobcost = LND_MINMOBCOST; + + mobcost = smobcost * 5.0 * 480.0 / + (mobcost + techfact(lp->lnd_tech, mobcost)); + + return mobcost; +} + +int +lnd_mar_one_sector(struct emp_qelem *list, int dir, natid actor, int together) +{ + struct sctstr sect, osect; + struct emp_qelem *qp; + struct emp_qelem *qp2; + struct emp_qelem *next; + struct llist *llp; + coord dx; + coord dy; + coord newx; + coord newy; + int stopping = 0; + int visible = 0; + int stop; + s_char dp[80]; + int rel; + double odds; + int oldown; + + if (dir <= DIR_STOP || dir >= DIR_VIEW) { + lnd_put(list, actor); + return 1; + } + dx = diroff[dir][0]; + dy = diroff[dir][1]; + for (qp=list->q_back;qp!=list;qp=next) { + next = qp->q_back; + llp = (struct llist *)qp; + getsect(llp->land.lnd_x, llp->land.lnd_y, &osect); + oldown = osect.sct_own; + newx = xnorm(llp->land.lnd_x + dx); + newy = ynorm(llp->land.lnd_y + dy); + getsect(newx, newy, §); + rel = getrel(getnatp(sect.sct_own), player->cnum); + if ((sect.sct_own != actor && rel != ALLIED && + !(lchr[(int)llp->land.lnd_type].l_flags & L_SPY) && + sect.sct_own) || (sect.sct_type == SCT_WATER || + sect.sct_type == SCT_SANCT || + sect.sct_type == SCT_WASTE)) { + if (together) { + pr("can't go to %s\n",xyas(newx, newy, actor)); + return 1; + } else { + sprintf(dp, "can't go to %s", + xyas(newx, newy, actor)); + lnd_mess(dp, llp); + continue; + } + } + + if (!(lchr[(int)llp->land.lnd_type].l_flags & L_SPY)) visible = 1; + if (sect.sct_rail == 0 && + lchr[(int)llp->land.lnd_type].l_flags & L_TRAIN) { + if (together) { + pr("no rail system in %s\n",xyas(newx, newy, actor)); + return 1; + } else { + sprintf(dp, "has no rail system in %s", + xyas(newx, newy, actor)); + lnd_mess(dp, llp); + continue; + } + } + /* Note we check would_abandon first because we don't want + to always have to do these checks */ + if (would_abandon(&osect, V_CIVIL, 0, &(llp->land))) { + stop = 0; + if (!want_to_abandon(&osect, V_CIVIL, 0, &(llp->land))) { + stop = 1; + } + /* now check stuff */ + if (!check_sect_ok(§)) + return 1; + if (!check_sect_ok(&osect)) + return 1; + for (qp2 = list->q_back; qp2 != list; qp2 = qp2->q_back) { + if (!check_land_ok(&(((struct llist *)qp2)->land))) + return 1; + } + if (stop) { + lnd_mess("stops", llp); + continue; + } + } + if (llp->mobil <= 0.0) { + lnd_mess("is out of mobility", llp); + continue; + } + llp->land.lnd_x = newx; + llp->land.lnd_y = newy; + if (lchr[(int)llp->land.lnd_type].l_flags & L_TRAIN) { + llp->mobil -= lnd_mobcost(&llp->land, §, MOB_RAIL); + } else { + llp->mobil -= lnd_mobcost(&llp->land, §, MOB_ROAD); + } + llp->land.lnd_mobil = (int)llp->mobil; + putland(llp->land.lnd_uid, &llp->land); + putsect(&osect); + getsect(osect.sct_x, osect.sct_y, &osect); + if (osect.sct_own != oldown && oldown == player->cnum) { + /* It was your sector, now it's not. Simple :) */ + pr("You no longer own %s\n", + xyas(osect.sct_x, osect.sct_y, player->cnum)); + } + if (rel != ALLIED && sect.sct_own != actor && sect.sct_own) { /* must be a spy */ + /* Always a 10% chance of getting caught. */ + odds = (100 - llp->land.lnd_effic) + .10; + if (chance(odds)) { + if (rel == NEUTRAL || rel == FRIENDLY) { + wu(0, sect.sct_own, + "%s unit spotted in %s\n", cname(player->cnum), + xyas(sect.sct_x, sect.sct_y, sect.sct_own)); + setrel(sect.sct_own, llp->land.lnd_own, HOSTILE); + } else if (rel == HOSTILE || rel == AT_WAR || + rel == SITZKRIEG || rel == MOBILIZATION) { + wu(0, sect.sct_own, + "%s spy shot in %s\n", cname(player->cnum), + xyas(sect.sct_x, sect.sct_y, sect.sct_own)); + pr("%s was shot and killed.\n", prland(&llp->land)); + llp->land.lnd_effic = 0; + putland(llp->land.lnd_uid, &llp->land); + lnd_delete(llp, 0); + } + } + } + } + if (QEMPTY(list)) + return stopping; + lnd_sweep(list, 0, 1, actor); + stopping |= lnd_check_mines(list); + if (QEMPTY(list)) + return stopping; + if (visible) stopping |= lnd_interdict(list, newx, newy, actor); + return stopping; +} + +/* + * find all artillery units belonging + * to the attacker or defender that can fire. + * Each arty unit adds +1%/damage point + * + */ +int +lnd_support(natid victim, natid attacker, coord x, coord y) +{ + struct nstr_item ni; + struct lndstr land; + int rel, rel2; + double dam = 0.0; + int dist; + int shell; + int gun; + double range, range2; + + snxtitem_all(&ni,EF_LAND); + while(nxtitem(&ni,(s_char *)&land)){ + if (land.lnd_frg == 0) + continue; + if ((land.lnd_x == x) && (land.lnd_y == y)) + continue; + if (land.lnd_ship >= 0) + continue; + if (land.lnd_land >= 0) + continue; + if (land.lnd_mission > 0) + continue; + if (land.lnd_effic < LAND_MINFIREEFF) + continue; + /* Do we have mil? */ + if (getvar(V_MILIT, (s_char *)&land, EF_LAND) <= 0) + continue; + rel = getrel(getnatp(land.lnd_own),attacker); + rel2 = getrel(getnatp(land.lnd_own),victim); + if ((land.lnd_own != attacker) && + ((rel != ALLIED) || (rel2 != AT_WAR))) + continue; + + /* do we have supplies? */ + if (!has_supply(&land)) + continue; + + /* are we in range? */ + dist=mapdist(land.lnd_x,land.lnd_y,x,y); + + range=techfact((int)land.lnd_tech, + (double)land.lnd_frg / 2.0); + + range2=roundrange(range); + if (dist>range2) + continue; + + shell = getvar(V_SHELL, (s_char *)&land, EF_LAND); + gun = getvar(V_GUN, (s_char *)&land, EF_LAND); + + if (shell == 0 || gun == 0) + continue; + + use_supply(&land); + nreport(land.lnd_own,N_FIRE_L_ATTACK,victim,1); + if (roll(100) < land.lnd_acc){ + dam += landunitgun(land.lnd_effic, land.lnd_dam, gun, + land.lnd_ammo, shell) / 2; + } else { + dam += landunitgun(land.lnd_effic, land.lnd_dam, gun, + land.lnd_ammo, shell); + } + if (land.lnd_own != attacker) + wu(0,land.lnd_own, + "%s supported %s at %s\n", + prland(&land), + cname(attacker),xyas(x,y,land.lnd_own)); + } + return (int)dam; +} + +s_char * +lnd_path(int together, struct lndstr *lp, s_char *buf) +{ + coord destx; + coord desty; + struct sctstr d_sect, sect; + s_char *cp; + double dummy; + + if (!sarg_xy(buf, &destx, &desty)) + return 0; + if (!together){ + pr("Cannot go to a destination sector if not all starting in the same sector\n"); + return 0; + } + if (!getsect(destx, desty, &d_sect)) { + pr("%d,%d is not a sector\n", destx, desty); + return 0; + } + getsect(lp->lnd_x, lp->lnd_y, §); + if (lchr[(int)lp->lnd_type].l_flags & L_TRAIN) + cp = (s_char *)BestLandPath(buf, §, &d_sect, &dummy, MOB_RAIL); + else + cp = (s_char *)BestLandPath(buf, §, &d_sect, &dummy, MOB_ROAD); + if (!cp) { + pr("No owned path from %s to %s!\n", + xyas(lp->lnd_x,lp->lnd_y,player->cnum), + xyas(d_sect.sct_x,d_sect.sct_y,player->cnum)); + return 0; + } + pr("Using path '%s'\n",cp); + return cp; +} + +int +lnd_can_attack(struct lndstr *lp) +{ + struct lchrstr *lcp = &lchr[(int)lp->lnd_type]; + +/* if (lcp->l_flags & L_SUPPLY || + lcp->l_flags & L_SECURITY || + lcp->l_flags & L_FLAK || + lcp->l_frg) + return 0; */ + if (lcp->l_flags & L_SUPPLY) + return 0; + + return 1; +} diff --git a/src/lib/subs/lostsub.c b/src/lib/subs/lostsub.c new file mode 100644 index 00000000..ce875f85 --- /dev/null +++ b/src/lib/subs/lostsub.c @@ -0,0 +1,118 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * lostsub.c: Subroutines for lost items + * + * Known contributors to this file: + * Steve McClure, 1997 + */ + +#include "misc.h" +#include "player.h" +#include "var.h" +#include "file.h" +#include "land.h" +#include "ship.h" +#include "xy.h" +#include "nat.h" +#include "deity.h" +#include "nsc.h" +#include "plane.h" +#include "lost.h" +#include "prototypes.h" + +void +makelost(char type, natid owner, short int id, coord x, coord y) +{ + struct loststr lost; + int n; + + n = findlost(type, owner, id, x, y, 1); + if (n < 0) { + ef_extend(EF_LOST, 25); + n = findlost(type, owner, id, x, y, 1); + if (n < 0) + return; + } + + getlost(n, &lost); + lost.lost_type = type; + lost.lost_owner = owner; + lost.lost_id = id; + lost.lost_x = x; + lost.lost_y = y; + lost.lost_uid = n; + time(&lost.lost_timestamp); + putlost(n, &lost); +} + +void +makenotlost(char type, natid owner, short int id, coord x, coord y) +{ + struct loststr lost; + int n; + + n = findlost(type, owner, id, x, y, 0); + if (n < 0) + return; + getlost(n, &lost); + lost.lost_owner = 0; + lost.lost_timestamp = 0; + putlost(n, &lost); +} + +int +findlost(char type, natid owner, short int id, coord x, coord y, int free) + + + + + + /* Give me the item of a free slot */ +{ + struct loststr lost; + int n; + int freeslot = -1; + +/* Find a free slot, or find this item again */ + for (n = 0; getlost(n, &lost); n++) { + if (!lost.lost_owner && freeslot == -1 && free == 1) + freeslot = n; + if (!lost.lost_owner) + continue; + if (lost.lost_owner == owner && type == lost.lost_type) { + if (type == EF_SECTOR && lost.lost_x == x && lost.lost_y == y) { + freeslot = n; + break; + } else if (lost.lost_id == id) { + freeslot = n; + break; + } + } + } + return freeslot; +} diff --git a/src/lib/subs/mission.c b/src/lib/subs/mission.c new file mode 100644 index 00000000..c92f9cdb --- /dev/null +++ b/src/lib/subs/mission.c @@ -0,0 +1,1712 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * mission.c: Mission subroutines for planes/ships/units + * + * Known contributors to this file: + * Ken Stevens, 1995 + * Steve McClure, 1996-2000 + */ + +#include "options.h" +#include "misc.h" +#include "player.h" +#include "var.h" +#include "xy.h" +#include "sect.h" +#include "retreat.h" +#include "ship.h" +#include "land.h" +#include "plane.h" +#include "nat.h" +#include "nsc.h" +#include "deity.h" +#include "file.h" +#include "path.h" +#include "mission.h" +#include "genitem.h" +#include "nuke.h" +#include "news.h" +#include "item.h" +#include +#include "damage.h" +#include "prototypes.h" +#include "optlist.h" + +struct airport{ + struct emp_qelem queue; + coord x,y; + natid own; +}; + +s_char *mission_name(short int mission); +s_char *nameofitem(s_char *buf, struct genitem *gp, int type); + +/* + * Interdict commodities & transported planes + */ +int +ground_interdict(coord x, coord y, natid victim, s_char *s) +{ + register int cn; + int dam=0, newdam, rel; + struct genlist mi[MAXNOC]; + int z; + + bzero((s_char *)mi,sizeof(mi)); + for(z=1;z HOSTILE) + continue; + + if (QEMPTY(&mi[cn].queue)) + continue; + + newdam = perform_mission(x,y,victim,&mi[cn].queue, + MI_INTERDICT,s,SECT_HARDTARGET); + dam += newdam; + if (newdam) + mpr(victim, "%s interdiction mission does %d damage!\n", + cname(cn), newdam); + } + if (dam) { + collateral_damage(x,y,dam, 0); + } + return dam; +} + +int +collateral_damage(coord x, coord y, int dam, struct emp_qelem *list) +{ + extern double collateral_dam; + int coll; + struct sctstr sect; + + if (!dam) + return 0; + + getsect(x,y,§); + if (sect.sct_own) { + coll = ldround((double)dam * collateral_dam, 1); + if (coll == 0) + return 0; + mpr(sect.sct_own, "%s takes %d%% collateral damage\n", + xyas(x,y,sect.sct_own), coll); + sectdamage(§, coll, list); + putsect(§); + return coll; + } + return 0; +} + +int +only_subs(struct emp_qelem *list) +{ + struct emp_qelem *qp; + struct genlist *glp; + struct genitem *gp; + struct mchrstr *mcp; + + for(qp = list->q_forw; qp != list; qp = qp->q_forw) { + glp = (struct genlist *)qp; + gp = (struct genitem *)glp->thing; + + if (glp->type != EF_SHIP) + return 0; + mcp = (struct mchrstr *)glp->cp; + if (!(mcp->m_flags & M_SUB)) + return 0; + /* It's a sub! */ + } + /* They were all subs! */ + return 1; +} + + +/* + * Interdict ships & land units + * + */ +int +unit_interdict(coord x, coord y, natid victim, s_char *s, int hardtarget, int mission) +{ + register int cn; + int dam=0, newdam; + struct genlist mi[MAXNOC]; + int z; + int osubs; + + bzero((s_char *)mi,sizeof(mi)); + for(z=1;z= FRIENDLY) + continue; + } else if (getrel(getnatp(cn),victim) > HOSTILE) + continue; + + if (QEMPTY(&mi[cn].queue)) + continue; + + osubs = only_subs(&mi[cn].queue); + newdam = perform_mission(x,y,victim,&mi[cn].queue, + mission,s,hardtarget); + dam += newdam; + if (newdam) { + /* If only subs responded, then we don't know who's + subs they are */ + if (osubs) { + mpr(victim, + "Enemy interdiction mission does %d damage!\n", + newdam); + } else { + mpr(victim, + "%s interdiction mission does %d damage!\n", + cname(cn), newdam); + } + } + } + if (dam) { + collateral_damage(x,y,dam, 0); + } + return dam; +} + +/* + * Perform a mission against victim, on behalf of actee + */ +int +off_support(coord x, coord y, natid victim, natid actee) +{ + int dam=0; + struct genlist mi[MAXNOC]; + int z; + + bzero((s_char *)mi,sizeof(mi)); + for(z=1;zown == 0) + continue; + + if (gp->mobil < 1) + continue; + + if ((gp->mission != mission) && (mission != MI_SINTERDICT)) + continue; + + if ((gp->mission != mission) && (mission == MI_SINTERDICT) && + (gp->mission != MI_INTERDICT)) + continue; + + relat = getrel(getnatp(gp->own), victim); + if (mission == MI_SINTERDICT) { + if (relat >= FRIENDLY) + continue; + else if (type != EF_PLANE && relat > HOSTILE) + continue; + } else if (relat > HOSTILE) + continue; + + dist = mapdist(x, y, gp->opx, gp->opy); + + radius = gp->radius; + if (mission != MI_RESERVE) /* XXX */ + oprange(gp,type,&radius); + + if (dist > radius) + continue; + + /* Ok, it is within the operations range. */ + /* Now check from where the object actually is */ + dist = mapdist(x, y, gp->x, gp->y); + radius = 999; + oprange(gp, type, &radius); + if (dist > radius) + continue; + /* Ok, the object can get to where the x,y is */ + + if (opt_SLOW_WAR) { + if (mission != MI_AIR_DEFENSE) { + getsect(x,y,(s_char *)§); + if (getrel(getnatp(gp->own), sect.sct_own) > AT_WAR) { + + /* + * If the player->owner of the unit isn't at war + * with the victim, and doesn't own the + * sect being acted upon, and isn't the + * old player->owner of that sect, bounce them. + */ + if (sect.sct_type != SCT_WATER && + sect.sct_own != gp->own && + sect.sct_oldown != gp->own) + continue; + } + } + } + + glp = (struct genlist *) malloc(sizeof(struct genlist)); + bzero((s_char *)glp,sizeof(struct genlist)); + glp->x = gp->x; + glp->y = gp->y; + glp->type = type; + switch(type){ + case EF_LAND: glp->cp = (s_char *)&lchr[(int)gp->type]; + break; + case EF_SHIP: glp->cp = (s_char *)&mchr[(int)gp->type]; + break; + case EF_PLANE: glp->cp = (s_char *)&plchr[(int)gp->type]; + break; + } + glp->thing = (s_char *)malloc(size); + bcopy(block,glp->thing,size); + emp_insque(&glp->queue, &mi[gp->own].queue); + } +} + +void +find_escorts(coord x, coord y, natid cn, struct emp_qelem *escorts) +{ + struct nstr_item ni; + struct plist *plp; + struct plnstr plane; + int dist; + + snxtitem_all(&ni,EF_PLANE); + while(nxtitem(&ni, (s_char *)&plane)){ + if (plane.pln_own != cn) + continue; + + if (plane.pln_mission != MI_ESCORT) + continue; + + dist = mapdist(x,y,plane.pln_x,plane.pln_y); + + if (dist > ((int)((float)plane.pln_range/2.0)) ) + continue; + + plp = (struct plist *) malloc(sizeof(struct plist)); + bzero((s_char *)plp,sizeof(struct plist)); + plp->pcp = &plchr[(int)plane.pln_type]; + bcopy((s_char *)&plane,(s_char *)&plp->plane,sizeof(struct plnstr)); + emp_insque(&plp->queue, escorts); + } +} + +int +perform_mission(coord x, coord y, natid victim, struct emp_qelem *list, int mission, s_char *s, int hardtarget) +{ + extern int land_max_interdiction_range; + extern int ship_max_interdiction_range; + s_char *mission_name(short int mission), *nameofitem(s_char *buf, struct genitem *gp, int type); + struct emp_qelem *qp, missiles, bombers, escorts, airp, b, e; + struct emp_qelem *newqp; + struct genlist *glp; + struct plist *plp; + struct genitem *gp; + struct lndstr *lp; + struct shpstr *sp; + struct sctstr sect; + struct lchrstr *lcp; + struct mchrstr *mcp; + struct plchrstr *pcp; + int dam=0,dam2, mission_flags, tech; + natid plane_owner = 0; + int gun,shell,md, air_dam=0; + double range2, prb, range, mobcost, hitchance; + extern int torpedo_damage; + + getsect(x,y,§); + + emp_initque(&missiles); + emp_initque(&bombers); + emp_initque(&escorts); + emp_initque(&airp); + + for(qp = list->q_forw; qp != list; qp = qp->q_forw){ + glp = (struct genlist *)qp; + gp = (struct genitem *)glp->thing; + + md = mapdist(x,y,gp->x,gp->y); + + if (glp->type == EF_LAND){ + lp = (struct lndstr *)glp->thing; + lcp = (struct lchrstr *)glp->cp; + + if (lp->lnd_effic < LAND_MINFIREEFF) + continue; + + if (mission == MI_SINTERDICT) + continue; + + if ((mission == MI_INTERDICT) && + (md > land_max_interdiction_range)) + continue; + + if (md > (lp->lnd_frg / 2)) + continue; + + if (lnd_getmil(lp) < 1) + continue; + + range = techfact((int)lp->lnd_tech, + (double)lp->lnd_frg / 2.0); + range2 = (double)roundrange(range); + + if (md > range2) + continue; + + shell = getvar(V_SHELL, (s_char *)lp, EF_LAND); + gun = getvar(V_GUN, (s_char *)lp, EF_LAND); + if (shell == 0 || gun == 0) + continue; + + if (has_supply(lp)){ + use_supply(lp); + putland(lp->lnd_uid, lp); + dam2 = ldround(landunitgun(lp->lnd_effic, lp->lnd_dam, gun, + lp->lnd_ammo, shell),1); + if (sect.sct_type == SCT_WATER){ + double dam3 = (double)dam2; + if (chance(((double)lp->lnd_acc)/100.0)) + dam2=ldround((dam3/2.0),1); + } + dam += dam2; + if (sect.sct_type == SCT_WATER) + nreport(lp->lnd_own,N_SHP_SHELL,victim,1); + else + nreport(lp->lnd_own,N_SCT_SHELL,victim,1); + wu(0,lp->lnd_own, + "%s fires at %s %s at %s\n", + prland(lp), cname(victim), + s, xyas(x,y,lp->lnd_own)); + + mpr(victim, "%s %s fires at you at %s\n", + cname(lp->lnd_own), prland(lp), + xyas(x,y,victim)); + } + }else if (glp->type == EF_SHIP){ + sp = (struct shpstr *)glp->thing; + mcp = (struct mchrstr *)glp->cp; + + if (sp->shp_effic < 60) + continue; + if (sp->shp_frnge == 0) + continue; + if (((mission == MI_INTERDICT) || + (mission == MI_SINTERDICT)) && + (md > ship_max_interdiction_range)) + continue; + if (getvar(V_MILIT, (s_char *)sp, EF_SHIP) < 1) + continue; +/* + if ((mcp->m_flags & M_SUB) && + (sect.sct_type != SCT_WATER)) + continue; +*/ + if (mission == MI_SINTERDICT){ + if (!(mcp->m_flags & M_SONAR)) + continue; + if (!(mcp->m_flags & M_DCH) && + !(mcp->m_flags & M_SUBT)) + continue; + range2 = techfact(sp->shp_tech, + (double)mcp->m_vrnge); + range2 *= (double)sp->shp_effic / 200.0; + if (md > range2) + continue; + /* can't look all the time */ + if (chance(0.5)) + continue; + } + if (mcp->m_flags & M_SUB){ +/* If we aren't shooting at "subs" or "ships" don't fire at all from + a sub. */ + if (*s != 's') + continue; + if (sp->shp_mobil < (s_char)0) + continue; + gun = getvar(V_GUN,(s_char *)sp,EF_SHIP); + if (gun < 1) + continue; + shell = getvar(V_SHELL,(s_char *)sp,EF_SHIP); + if (shell < 3) + shell += supply_commod(sp->shp_own, + sp->shp_x,sp->shp_y,I_SHELL, + 3-shell); + if (shell < 3) + continue; + + range = sp->shp_effic* techfact(sp->shp_tech, + ((double)sp->shp_frnge)) / 100.0; + + range2 = (double)roundrange(range); + if (md > range) + continue; + + if (!line_of_sight((s_char **)0, x, y, + gp->x, gp->y)) + continue; + putvar(V_SHELL,shell-3,(s_char *)sp,EF_SHIP); + mobcost = sp->shp_effic * 0.01 * sp->shp_speed; + mobcost = (480.0/(mobcost + + techfact(sp->shp_tech, mobcost))); + sp->shp_mobil -= mobcost; + putship(sp->shp_uid,sp); + hitchance = DTORP_HITCHANCE(md, sp->shp_visib); + + wu(0,sp->shp_own, + "%s locking on %s %s in %s\n", + prship(sp),cname(victim),s, + xyas(x,y,sp->shp_own)); + wu(0,sp->shp_own, + "\tEffective torpedo range is %.1f\n", range); + wu(0,sp->shp_own, + "\tWhooosh... Hitchance = %d%%\n", + (int)(hitchance*100)); + + if (hitchance < 1.0 && !chance(hitchance)) { + wu(0,sp->shp_own, + "\tMissed\n"); + mpr(victim, "Incoming torpedo sighted @ %s missed (whew)!\n", + xyas(x,y,victim)); + continue; + } + wu(0,sp->shp_own, + "\tBOOM!...\n"); + dam2 = TORP_DAMAGE(); + + dam += dam2; + nreport(victim,N_TORP_SHIP,sp->shp_own,1); + wu(0,sp->shp_own, + "\tTorpedo hit %s %s for %d damage\n", + cname(victim),s,dam2); + + mpr(victim, + "Incoming torpedo sighted @ %s hits and does %d damage!\n", + xyas(x,y,victim), dam2); + }else{ + range = techfact(sp->shp_tech, + (double)mcp->m_frnge/2.0); + range2 = (double)roundrange(range); + if (md > range2) + continue; + gun = getvar(V_GUN, (s_char *)sp, EF_SHIP); + gun = min(gun, sp->shp_glim); + shell = getvar(V_SHELL, (s_char *)sp, EF_SHIP); + if (shell < gun) + shell += supply_commod(sp->shp_own, + sp->shp_x,sp->shp_y,I_SHELL, + gun-shell); + gun = min(gun, shell); + gun = min(gun,(int)((float)getvar(V_MILIT, + (s_char *)sp,EF_SHIP)/2.0)); + if (gun ==0) + continue; + gun = max(gun,1); + dam2 = seagun(sp->shp_effic,gun); + if ( range2 == 0.0 ) + prb = 1.0; + else + prb = ((double)md) / range2; + prb *= prb; + if (chance(prb)) + dam2 = (int)((float)dam2/2.0); + dam += dam2; + if (sect.sct_type == SCT_WATER) + nreport(sp->shp_own,N_SHP_SHELL,victim,1); + else + nreport(sp->shp_own,N_SCT_SHELL,victim,1); + wu(0,sp->shp_own, + "%s fires at %s %s at %s\n", + prship(sp), + cname(victim), s, + xyas(x,y,sp->shp_own)); + + mpr(victim, "%s fires at you at %s\n", + cname(sp->shp_own), prship(sp), + xyas(x,y,victim)); + + putvar(V_SHELL,shell-gun,(s_char *)sp, EF_SHIP); + putship(sp->shp_uid,sp); + } + }else if (glp->type == EF_PLANE) { + pcp = (struct plchrstr *)glp->cp; + if (pcp->pl_flags & P_M) + /* units have their own missile interdiction */ + if (hardtarget != SECT_HARDTARGET || + pcp->pl_flags & P_MAR) + continue; + + /* save planes for later */ + plp = (struct plist *)malloc(sizeof(struct plist)); + + bzero((s_char *)plp,sizeof(struct plist)); + plp->pcp = pcp; + bcopy(glp->thing, (s_char *)&plp->plane, + sizeof(struct plnstr)); + if (plp->pcp->pl_flags & P_M) + emp_insque(&plp->queue, &missiles); + else + emp_insque(&plp->queue, &bombers); + plane_owner = plp->plane.pln_own; + } + } + if (!QEMPTY(&missiles)) { + /* I arbitrarily chose 100 mindam -KHS */ + dam += msl_launch_mindam(&missiles, x, y, hardtarget, EF_SECTOR, 100, "sector", victim, mission); + qp=missiles.q_forw; + while(qp != (&missiles)){ + qp=qp->q_forw; + free(qp); + } + } + + if (QEMPTY(&bombers)) { + qp=list->q_forw; + while(qp != list){ + glp = (struct genlist *)qp; + qp=qp->q_forw; + + free(glp->thing); + free((s_char *)glp); + } + return dam; + } + /* + * If there are planes performing an + * interdict or support mission, find + * some escorts for them, if possible. + * Up to 2 per bomber, if possible. + */ + find_escorts(x,y,plane_owner,&escorts); + + if (mission == MI_SINTERDICT) + mission_pln_sel(&bombers,P_T|P_A,0,hardtarget); + else + mission_pln_sel(&bombers,P_T,P_A,SECT_HARDTARGET); + + mission_pln_sel(&escorts,P_ESC|P_F,0,SECT_HARDTARGET); + + for(qp = bombers.q_forw; qp != (&bombers); qp = qp->q_forw){ + plp = (struct plist *)qp; + if (!find_airport(&airp,plp->plane.pln_x,plp->plane.pln_y)) + add_airport(&airp,plp->plane.pln_x, + plp->plane.pln_y); + } + + for(qp = airp.q_forw; qp != (&airp); qp = qp->q_forw){ + struct airport *air; + s_char pp[512]; + + air = (struct airport *)qp; + md = mapdist(x,y,air->x,air->y); + + emp_initque(&b); + emp_initque(&e); + + /* Split off the bombers at this base into b */ + divide(&bombers,&b,air->x,air->y); + + /* Split off the escorts at this base into e */ + divide(&escorts,&e,air->x,air->y); + + tech = 0; + mission_flags = 0; + mission_flags |= P_X; /* stealth (shhh) */ + mission_flags |= P_H; /* gets turned off if not all choppers */ + + mission_flags = mission_pln_arm(&b,air->x,air->y,2*md,'p',0, + 0,mission_flags,&tech); + + if (QEMPTY(&b)){ + continue; + } + + mission_flags = mission_pln_arm(&e,air->x,air->y,2*md,'p',0, + P_F|P_ESC,mission_flags,&tech); + + BestAirPath(pp, air->x, air->y, x, y); + wu(0, plane_owner, "Flying %s mission from %s\n", + mission_name(mission), xyas(air->x, air->y, plane_owner)); + if (air->own && (air->own != plane_owner)) { + wu(0, air->own, "%s is flying %s mission from %s\n", + cname(plane_owner), mission_name(mission), + xyas(air->x, air->y, air->own)); + } + + ac_encounter(&b,&e,air->x,air->y,pp,mission_flags,0, 0, 0); + + if (!QEMPTY(&b)) + air_dam += air_damage(&b,x,y,mission,victim,s,hardtarget); + + pln_put(&b); + pln_put(&e); + } + + if (air_dam > 0){ + dam += air_dam; + if (sect.sct_type == SCT_WATER) + nreport(plane_owner,N_SHP_BOMB,victim,1); + else + nreport(plane_owner,N_SCT_BOMB,victim,1); + } + + /* free up all this memory */ + qp=list->q_forw; + while(qp != list){ + glp = (struct genlist *)qp; + qp=qp->q_forw; + + free(glp->thing); + free((s_char *)glp); + } + + qp = escorts.q_forw; + while(qp != (&escorts)){ + newqp = qp->q_forw; + emp_remque(qp); + free((s_char *)qp); + qp = newqp; + } + + qp=bombers.q_forw; + while(qp != (&bombers)){ + newqp = qp->q_forw; + emp_remque(qp); + free((s_char *)qp); + qp = newqp; + } + + return dam; +} + +int +cando(int mission, int type) +{ + switch (mission){ + case MI_ESCORT: + if (type == EF_PLANE) + return 1; + return 0; + case MI_AIR_DEFENSE: + if (type == EF_PLANE) + return 1; + return 0; + case MI_SINTERDICT: + if ((type == EF_PLANE) || (type == EF_SHIP)) + return 1; + return 0; + case MI_INTERDICT: + return 1; + case MI_SUPPORT: + case MI_OSUPPORT: + case MI_DSUPPORT: + if (type == EF_PLANE) + return 1; + return 0; + case MI_RESERVE: + if (type == EF_LAND) + return 1; + return 0; + } + + return 0; +} + +s_char *nameofitem(s_char *buf, struct genitem *gp, int type) +{ + switch(type){ + case EF_SHIP: + return prship((struct shpstr *)gp); + break; + case EF_PLANE: + return prplane((struct plnstr *)gp); + break; + case EF_LAND: + return prland((struct lndstr *)gp); + } + return NULL; +} + +s_char *mission_short_name(int mission) +{ + switch (mission){ + case MI_INTERDICT: return "interdict"; + case MI_SUPPORT: return "support "; + case MI_OSUPPORT: return "offensive"; + case MI_DSUPPORT: return "defensive"; + case MI_RESERVE: return "reserve "; + case MI_ESCORT: return "escort "; + case MI_SINTERDICT: return "interdict"; + case MI_AIR_DEFENSE: return "air def "; + default: return " "; + } +} + +s_char *mission_name(short int mission) +{ + switch (mission){ + case MI_INTERDICT: return "an interdiction"; + case MI_SUPPORT: return "a support"; + case MI_OSUPPORT: return "a offensive support"; + case MI_DSUPPORT: return "a defensive support"; + case MI_RESERVE: return "a reserve"; + case MI_ESCORT: return "an escort"; + case MI_SINTERDICT: return "a sub interdiction"; + case MI_AIR_DEFENSE: return "an air defense"; + } + return "a mysterious"; +} + +void +show_mission(int type, struct nstr_item *np) +{ + int size, first=1, radius; + s_char *block; + struct genitem *gp; + s_char buf[128]; + + size = max(sizeof(struct lndstr),sizeof(struct plnstr)); + size = max(size,sizeof(struct shpstr)); + block = (s_char *)malloc(size); + + while (nxtitem(np, block)) { + gp = (struct genitem *)block; + if (!player->owner || gp->own == 0) + continue; + + if (first){ + pr("Thing x,y op-sect rad mission\n"); + first=0; + } + pr("%-25s", nameofitem(buf, gp,type)); + pr(" %7s", xyas(gp->x,gp->y,player->cnum)); + if (gp->mission == MI_INTERDICT || gp->mission == MI_SUPPORT || + gp->mission == MI_OSUPPORT || + gp->mission == MI_DSUPPORT || + gp->mission == MI_AIR_DEFENSE){ + radius = 999; + oprange(gp,type,&radius); + pr(" %7s", xyas(gp->opx,gp->opy,player->cnum)); + if (radius < gp->radius) + pr(" %4d", radius); + else + pr(" %4d", gp->radius); + }else if (gp->mission == MI_RESERVE){ + struct sctstr sect; + int plus=2; + + getsect(gp->x,gp->y,§); + if ((sect.sct_type == SCT_HEADQ) && + (sect.sct_effic >= 60)) + plus++; + + if (((struct lndstr *)block)->lnd_rad_max == 0) + plus = 0; + else + plus += ((struct lndstr *)block)->lnd_rad_max; + pr(" %7s", xyas(gp->x,gp->y,player->cnum)); + pr(" %4d", plus); + }else if (gp->mission == MI_ESCORT){ + pr(" "); + pr(" %4d", (int) + ((float)((struct plnstr *)block)->pln_range/2.0) + ); + }else + pr(" "); + if (gp->mission) + pr(" is on %s mission\n", + mission_name(gp->mission)); + else + pr(" has no mission.\n"); + } +} + +int +oprange(struct genitem *gp, int type, int *radius) +{ + double techfact(int, double); + int range; + struct shpstr ship; + struct lndstr land; + struct plnstr plane; + + switch (type){ + case EF_SHIP: + getship(gp->uid,&ship); + range = ldround(techfact(gp->tech, + (double)ship.shp_frnge / 2.0),1); + break; + case EF_LAND: + getland(gp->uid,&land); + range = ldround(techfact((int)land.lnd_tech, + (double)land.lnd_frg / 2.0),1); + break; + case EF_PLANE: + getplane(gp->uid,&plane); + /* missiles go one way, so we can use all the range */ + if (plchr[(int)plane.pln_type].pl_flags & P_M) + range = plane.pln_range; + else + range = ldround((double)plane.pln_range/2.0,1);; + break; + } + + if ((*radius) > range) + *radius = range; + + return range; +} + +/* + * Remove all planes who cannot go on + * the mission from the plane list. + */ +void +mission_pln_sel(struct emp_qelem *list, int wantflags, int nowantflags, int hardtarget) +{ + struct emp_qelem *qp, *next; + struct plnstr *pp; + struct shpstr ship; + struct lndstr land; + struct sctstr sect; + struct plchrstr *pcp; + struct plist *plp; + register int y, bad, bad1; + unsigned int x; + + for (qp = list->q_forw; qp != list; qp = next) { + next = qp->q_forw; + plp = (struct plist *)qp; + pp = &plp->plane; + pcp = plp->pcp; + + if (pp->pln_effic < 40){ + emp_remque(qp); + free((s_char *)qp); + continue; + } + + if (pp->pln_mobil < 1) { + emp_remque(qp); + free((s_char *)qp); + continue; + } + + if (opt_MARKET) { + if (ontradingblock(EF_PLANE, (int *)pp)) { + emp_remque(qp); + free((s_char *)qp); + continue; + } + } + + bad=0; + bad1=0; + if (wantflags) { + for(x=0;xpl_flags & y) != y){ + switch(y){ + case P_F: + case P_ESC: bad1=2; + break; + case P_E: + case P_L: + case P_K: bad1=1; + break; + default: bad=1; + } + } + } + if (bad){ + emp_remque(qp); + free((s_char *)qp); + continue; + } + if (bad1 == 2){ + if ((pcp->pl_flags & P_ESC) || + (pcp->pl_flags & P_F)) + bad1=0; + } + if (bad1 == 1){ + if ((pcp->pl_flags & P_E) || + (pcp->pl_flags & P_K) || + (pcp->pl_flags & P_L)) + bad1=0; + } + if (bad1){ + emp_remque(qp); + free((s_char *)qp); + continue; + } + } + bad=0; + bad1=0; + if (nowantflags) { + for(x=0;xpl_flags & y) == y) + bad=1; + } + if (bad){ + emp_remque(qp); + free((s_char *)qp); + continue; + } + } + if (pp->pln_ship >= 0) { + if (!getship(pp->pln_ship, &ship)){ + shipsunk: + pp->pln_effic = 0; + putplane(pp->pln_uid, pp); + emp_remque(qp); + free((s_char *)qp); + continue; + } + if (!can_be_on_ship(pp->pln_uid,ship.shp_uid)) { + goto shipsunk; + } + if (ship.shp_effic < SHIP_MINEFF){ + goto shipsunk; + } + /* Can't fly off of ships < 50%, or non-owned or non-allied ships */ + if ((ship.shp_effic < 50) || + ((ship.shp_own != pp->pln_own) && + (getrel(getnatp(ship.shp_own), pp->pln_own) != ALLIED))) { + emp_remque(qp); + free((s_char *)qp); + continue; + } + } + if (pp->pln_land >= 0) { + if (!getland(pp->pln_land, &land)){ + landdead: + pp->pln_effic = 0; + putplane(pp->pln_uid, pp); + emp_remque(qp); + free((s_char *)qp); + continue; + } + if (!(pcp->pl_flags & P_E)) + goto landdead; + if (land.lnd_effic < LAND_MINEFF) + goto landdead; + + /* Can't fly off of units < 50%, or non-owned or non-allied units */ + if ((land.lnd_effic < 50) || + ((land.lnd_own != pp->pln_own) && + (getrel(getnatp(land.lnd_own), pp->pln_own) != ALLIED))) { + emp_remque(qp); + free((s_char *)qp); + continue; + } + + /* Can't fly off units in ships or other units */ + if ((land.lnd_ship >= 0) || (land.lnd_land >= 0)) { + emp_remque(qp); + free((s_char *)qp); + continue; + } + } + /* Now, check the sector status if not on a plane or unit */ + if ((pp->pln_ship < 0) && (pp->pln_land < 0)) { + /* If we can't get the sector, we can't check it, and can't fly */ + if (!getsect(pp->pln_x, pp->pln_y, §)) { + emp_remque(qp); + free((s_char *)qp); + continue; + } + /* First, check allied status */ + /* Can't fly from non-owned sectors or non-allied sectors */ + if ((sect.sct_own != pp->pln_own) && + (getrel(getnatp(sect.sct_own), pp->pln_own) != ALLIED)) { + emp_remque(qp); + free((s_char *)qp); + continue; + } + /* non-vtol plane */ + if ((pcp->pl_flags & P_V) == 0) { + if ((sect.sct_type != SCT_AIRPT) || (sect.sct_effic < 40)) { + emp_remque(qp); + free((s_char *)qp); + continue; + } + } + } + if (pcp->pl_flags & P_A) { + if (roll(100) > pln_identchance(pp, hardtarget, EF_SHIP)) { + emp_remque(qp); + free((s_char *)qp); + continue; + } + } + + putplane(pp->pln_uid, pp); + } +} + +/* + * Arm only the planes at x,y + * + */ +int +mission_pln_arm(struct emp_qelem *list, coord x, coord y, int dist, int mission, struct ichrstr *ip, int flags, int mission_flags, int *tech) +{ + struct emp_qelem *qp; + struct emp_qelem *next; + struct plist *plp; + + if (*tech == 0) + *tech = 9999; + for (qp = list->q_forw; qp != list; qp = next) { + next = qp->q_forw; + plp = (struct plist *) qp; + + if (plp->plane.pln_x != x) + continue; + if (plp->plane.pln_y != y) + continue; + + if (mission_pln_equip(plp, ip, flags, mission) < 0) { + emp_remque(qp); + free((s_char *)qp); + continue; + } + if (flags & (P_S|P_I)) { + if(plp->pcp->pl_flags & P_S) + mission_flags |= P_S; + if(plp->pcp->pl_flags & P_I) + mission_flags |= P_I; + } + if (*tech > plp->plane.pln_tech) + *tech = plp->plane.pln_tech; + if (!(plp->pcp->pl_flags & P_H)) + /* no stealth on this mission */ + mission_flags &= ~P_H; + if (!(plp->pcp->pl_flags & P_X)) + /* no stealth on this mission */ + mission_flags &= ~P_X; + if (!(plp->pcp->pl_flags & P_A)) { + /* no asw on this mission */ + mission_flags &= ~P_A; + } + if (!(plp->pcp->pl_flags & P_MINE)) { + /* no asw on this mission */ + mission_flags &= ~P_MINE; + } + + /* + * Mob costs for missions are 1/2 normal + * Not anymore. :) + */ +/* plp->plane.pln_mobil -= pln_mobcost(dist,&plp->plane,flags)/2;*/ + plp->plane.pln_mobil -= pln_mobcost(dist,&plp->plane,flags); + + } + return mission_flags; +} + +int +mission_pln_equip(struct plist *plp, struct ichrstr *ip, int flags, s_char mission) +{ + register struct plchrstr *pcp; + struct plnstr *pp; + int needed; + struct lndstr land; + struct shpstr ship; + struct sctstr sect; + int type; + s_char *ptr; + int item; + int rval; + int vec[I_MAX+1]; + + pp = &plp->plane; + pcp = plp->pcp; + if (pp->pln_ship >= 0) { + getship(pp->pln_ship, &ship); + type = EF_SHIP; + ptr = (s_char *) &ship; + } else + if (pp->pln_land >= 0) { + getland(pp->pln_land, &land); + type = EF_LAND; + ptr = (s_char *) &land; + } else { + getsect(pp->pln_x, pp->pln_y, §); + type = EF_SECTOR; + ptr = (s_char *) § + } + getvec(VT_ITEM, vec, ptr, type); + if (pcp->pl_fuel > vec[I_PETROL]) { + return -1; + } + vec[I_PETROL] -= pcp->pl_fuel; + rval = 0; + if (!(flags & P_F)) { + item = 0; + needed = 0; + switch (mission) { + case 's': + case 'p': + if (pp->pln_nuketype == -1) { + item = I_SHELL; + needed = pp->pln_load; + } + break; + case 't': + if ((pcp->pl_flags & P_C) == 0 || ip == 0) + break; + item = ip - ichr; + needed = (pp->pln_load * 2) / ip->i_lbs; + break; + case 'd': + if ((pcp->pl_flags & P_C) == 0 || ip == 0) + break; + item = ip - ichr; + needed = (pp->pln_load * 2) / ip->i_lbs; + break; + case 'a': + if ((pcp->pl_flags & (P_V|P_C)) == 0) + break; + item = I_MILIT; + needed = pp->pln_load / ip->i_lbs; + break; + case 'n': + if (pp->pln_nuketype == -1) + rval = -1; + break; + case 'i': /* missile interception */ + if (pp->pln_load) { + item = I_SHELL; + needed = pp->pln_load; + } + break; + default: + break; + } + if (rval < 0 || (item && needed <= 0)) { + return -1; + } + if ((vec[item] < needed) && (item == I_SHELL)) + vec[item] += supply_commod(plp->plane.pln_own, + plp->plane.pln_x,plp->plane.pln_y, + I_SHELL,needed); + if (vec[item] < needed) { + return -1; + } else { + vec[item] -= needed; + } + if (item == I_SHELL && (mission == 's' || mission == 'p')) + plp->bombs = needed; + else + plp->misc = needed; + } + putvec(VT_ITEM, vec, ptr, type); + if (type == EF_SHIP) + putship(ship.shp_uid,&ship); + else if (type == EF_LAND) + putland(land.lnd_uid,&land); + else + putsect(§); + return rval; +} + +/* + * Return 1 if this x,y pair is in the list + */ +int +find_airport(struct emp_qelem *airp, coord x, coord y) +{ + struct emp_qelem *qp; + struct airport *a; + + for (qp = airp->q_forw; qp != airp; qp = qp->q_forw){ + a = (struct airport *)qp; + if ((a->x == x) && (a->y == y)) + return 1; + } + + return 0; +} + +/* #*# This needs to be changed to include acc's -KHS */ +void +add_airport(struct emp_qelem *airp, coord x, coord y) +{ + struct airport *a; + struct sctstr sect; + + a = (struct airport *)malloc(sizeof(struct airport)); + + a->x = x; + a->y = y; + getsect(x,y,§); + a->own = sect.sct_own; + + emp_insque((struct emp_qelem *)a,airp); +} + +/* + * Take all the planes in list 1 that + * are at x,y, and put them into list 2. + */ +void +divide(struct emp_qelem *l1, struct emp_qelem *l2, coord x, coord y) +{ + struct emp_qelem *qp, *next; + struct plist *plp; + + for (qp = l1->q_forw; qp != l1; qp = next){ + next = qp->q_forw; + plp = (struct plist *)qp; + + if (plp->plane.pln_x != x) + continue; + if (plp->plane.pln_y != y) + continue; + + emp_remque(qp); + emp_insque(qp,l2); + } +} + +int +air_damage(struct emp_qelem *bombers, coord x, coord y, int mission, natid victim, s_char *s, int hardtarget) +{ + struct emp_qelem *qp; + struct plist *plp; + struct plnstr *pp; + int newdam,dam=0; + int hitchance; + int nukedam; + + for(qp = bombers->q_forw; qp != bombers; qp = qp->q_forw){ + plp = (struct plist *)qp; + pp = &plp->plane; + + if ((mission == MI_SINTERDICT) && !(plp->pcp->pl_flags & P_A)) + continue; + + if (!plp->bombs) + continue; + + newdam = 0; + if (plp->pcp->pl_flags & P_A) { + if (roll(100) > pln_identchance(pp, hardtarget, EF_SHIP)) { + wu(0,pp->pln_own, + "\t%s detects sub movement in %s\n", + prplane(pp), xyas(x,y,pp->pln_own)); + continue; + } + if (getrel(getnatp(pp->pln_own),victim) > HOSTILE) { + wu(0,pp->pln_own, + "\t%s tracks %s %s at %s\n", + prplane(pp), + cname(victim), s, xyas(x,y,pp->pln_own)); + continue; + } + wu(0,pp->pln_own, + "\t%s depth-charging %s %s in %s\n", + prplane(pp), + cname(victim), + s, + xyas(x,y,pp->pln_own)); + } else { + wu(0,pp->pln_own, + "\t%s pinbombing %s %s in %s\n", + prplane(pp), + cname(victim), + s, + xyas(x,y,pp->pln_own)); + } + hitchance = pln_hitchance(pp, hardtarget, EF_SHIP); + if (plp->plane.pln_nuketype != -1) + hitchance = 100; + else if (hardtarget != SECT_HARDTARGET) + wu(0,pp->pln_own,"\t\t%d%% hitchance...", hitchance); + /* Always calculate damage */ + if (roll(100) <= hitchance) { + newdam = pln_damage(&plp->plane,x,y,'p',&nukedam, 1); + if (nukedam) { + if (mission == MI_INTERDICT) { + wu(0,pp->pln_own, + "\t\tnuclear warhead does %d damage to %s %s\n", + prplane(pp), + nukedam, cname(victim), s); + dam += nukedam; + } + } else { + wu(0,pp->pln_own, + "\t\thit %s %s for %d damage\n", + cname(victim), s, newdam); + dam += newdam; + } + } else { + newdam = pln_damage(&plp->plane,x,y,'p',&nukedam, 0); + wu(0,pp->pln_own,"missed\n"); + if (mission == MI_SINTERDICT) { + mpr(victim, + "RUMBLE... your sub in %s hears a depth-charge explode nearby\n", + xyas(x,y,victim)); + } else if (*s == 's') { + mpr(victim, + "SPLASH! Bombs miss your %s in %s\n", + s, xyas(x,y,victim)); + } else { + mpr(victim, "SPLAT! Bombs miss your %s in %s\n", + s, xyas(x, y, victim)); + } + /* Now, even though we missed, the bombs + land somewhere. */ + collateral_damage(x, y, newdam, bombers); + } + + /* use up missiles */ + if (plp->pcp->pl_flags & P_M) { + makelost(EF_PLANE, pp->pln_own, pp->pln_uid, pp->pln_x, pp->pln_y); + pp->pln_own = 0; + } + } + + return dam; +} + +/* + * Check to see if anyone hostile to the victim + * is running an air defense mission on this + * sector. If so, do air combat + */ +int +air_defense(coord x, coord y, natid victim, struct emp_qelem *bomb_list, struct emp_qelem *esc_list) +{ + int dam=0,cn; + int mission_flags, tech, combat=0, rel, dist, z; + struct emp_qelem *qp, interceptors, airp, i, empty, *next; + struct plist *plp; + struct genlist *glp; + struct genitem *gp; + struct genlist mi[MAXNOC]; + s_char path[512]; + int count; + int tcount; + + count = 0; + for (qp = bomb_list->q_forw; qp != bomb_list; qp = qp->q_forw) + count++; + for (qp = esc_list->q_forw; qp != esc_list; qp = qp->q_forw) + count++; + + bzero((s_char *)mi,sizeof(mi)); + for (z = 1; z < MAXNOC; z++) + emp_initque((struct emp_qelem *)&mi[z]); + + build_mission_list_type(mi,x,y,MI_AIR_DEFENSE,EF_PLANE,victim); + + for (cn = 1; cn < MAXNOC; cn++) { + /* Check our relations */ + rel = getrel(getnatp(cn),victim); + + if (rel > HOSTILE) + continue; + + if (QEMPTY(&mi[cn].queue)) + continue; + + /* Ok, make a list of all the interceptors. Note that this *copies* the + * list from the mission creation. This list must be deleted later. */ + emp_initque(&interceptors); + for (qp = mi[cn].queue.q_forw; qp != (&mi[cn].queue); qp = next) { + next = qp->q_forw; + + glp = (struct genlist *)qp; + gp = (struct genitem *)glp->thing; + plp = (struct plist *)qp; + + dist = mapdist(x,y,gp->x,gp->y); + + plp = (struct plist *)malloc(sizeof(struct plist)); + bzero((s_char *)plp,sizeof(struct plist)); + plp->pcp = (struct plchrstr *)glp->cp; + bcopy(glp->thing, (s_char *)&plp->plane, + sizeof(struct plnstr)); + + /* missiles go one way, so we can use all the range */ + if (!(plp->pcp->pl_flags & P_M)) + dist *= 2; + /* If it's out of range, free it and continue on */ + if (dist > plp->plane.pln_range) { + free(plp); + continue; + } + emp_insque(&plp->queue, &interceptors); + } + + /* Remove those who cannot go */ + mission_pln_sel(&interceptors,P_F,0,SECT_HARDTARGET); + + if (QEMPTY(&interceptors)) + continue; + + /* Now, delete all the extras, but delete the first ones, not the last ones, so + * that the higher numbered planes go into battle (they should be the better ones + * at fighting, if all went well.) */ + tcount = 0; + for (qp = interceptors.q_forw; qp != (&interceptors); qp = qp->q_forw) + tcount++; + tcount -= (count * 2); + /* Just in case there are more incoming than we have */ + if (tcount < 0) + tcount = 0; + for (qp = interceptors.q_forw; qp != (&interceptors); qp = next) { + next = qp->q_forw; + if (tcount) { + tcount--; + /* Free it up and continue */ + emp_remque(qp); + glp = (struct genlist *)qp; + free((s_char *)glp); + } + } + + /* Now, make a list of all the airports these planes are coming from */ + emp_initque(&airp); + for (qp = interceptors.q_forw ; qp != (&interceptors); qp = qp->q_forw) { + plp = (struct plist *)qp; + if (!find_airport(&airp,plp->plane.pln_x, plp->plane.pln_y)) + add_airport(&airp,plp->plane.pln_x, plp->plane.pln_y); + } + + /* Now, fly them out one airport at a time */ + for (qp = airp.q_forw; qp != (&airp); qp = qp->q_forw) { + struct airport *air; + + air = (struct airport *)qp; + dist = mapdist(x,y,air->x,air->y); + + emp_initque(&i); + + /* Split off the interceptors at this base into i */ + divide(&interceptors, &i, air->x, air->y); + + tech = 0; + mission_flags = 0; + mission_flags |= P_X; /* stealth (shhh) */ + /* gets turned off if not all choppers */ + mission_flags |= P_H; + sam_intercept(bomb_list, &i, cn, victim, x, y, 0); + sam_intercept(esc_list, &i, cn, victim, x, y, 1); + + /* Did we run out of interceptors? */ + if (QEMPTY(&i)) + continue; + /* Did we run out of bombers? */ + if (QEMPTY(bomb_list)) { + /* Yes, so we have to put the rest of the interceptors back, and + then continue, or we leak memory */ + pln_put(&i); + continue; + } + mission_flags = mission_pln_arm(&i,air->x,air->y,2*dist,'r',0, + P_F,mission_flags,&tech); + + /* Did we run out of interceptors? */ + if (QEMPTY(&i)) + continue; + /* Did we run out of bombers? */ + if (QEMPTY(bomb_list)) { + /* Yes, so we have to put the rest of the interceptors back, and + then continue, or we leak memory */ + pln_put(&i); + continue; + } + + BestAirPath(path, air->x, air->y, x, y); + wu(0, cn, "Flying %s mission from %s\n", + mission_name(MI_AIR_DEFENSE), + xyas(air->x, air->y, cn)); + if (air->own && (air->own != cn)) { + wu(0, air->own, "%s is flying %s mission from %s\n", + cname(cn), mission_name(MI_AIR_DEFENSE), + xyas(air->x, air->y, air->own)); + } + + /* Now, fly the planes to the sector */ + emp_initque(&empty); + ac_encounter(&i, &empty, air->x, air->y, + path, mission_flags,1, bomb_list, esc_list); + + /* If none made it, continue */ + if (QEMPTY(&i)) + continue; + + /* Some made it, so now they get to try to fight. */ + /* Intercept the escorts first */ + combat = 0; + if (!QEMPTY(esc_list)){ + mpr(victim, "%s air defense planes intercept!\n", + cname(cn)); + ac_combat_headers(victim, cn); + ac_airtoair(esc_list,&i,air->own); + combat = 1; + } + /* Now intercept the bombers */ + if (!QEMPTY(bomb_list)) { + if (!combat) { + mpr(victim, "%s air defense planes intercept!\n", cname(cn)); + ac_combat_headers(victim, cn); + } + ac_airtoair(bomb_list, &i, air->own); + PR(cn, "\n"); + PR(victim, "\n"); + } + + pln_put(&i); + } + } + + /* We have to free all of these, if they are still there, otherwise they get + lost and we leak memory all over the place. */ + for (cn = 1; cn < MAXNOC; cn++) { + /* free up all this memory if it's still there */ + for (qp = mi[cn].queue.q_forw; qp != (&mi[cn].queue); qp = next) { + next = qp->q_forw; + glp = (struct genlist *)qp; + free(glp->thing); + free((s_char *)glp); + } + } + + return dam; +} + + + diff --git a/src/lib/subs/move.c b/src/lib/subs/move.c new file mode 100644 index 00000000..ea35d85c --- /dev/null +++ b/src/lib/subs/move.c @@ -0,0 +1,375 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * move.c: Move something somewhere. + * + * Known contributors to this file: + * + */ + +#include "misc.h" +#include "player.h" +#include "var.h" +#include "sect.h" +#include "item.h" +#include "file.h" +#include "deity.h" +#include "xy.h" +#include "path.h" +#include "nat.h" +#include "map.h" +#include "nsc.h" +#include "damage.h" +#include "prototypes.h" + +extern int move_map(s_char *what, coord curx, coord cury, s_char *arg); + +int +move_ground(s_char *what, struct sctstr *start, struct sctstr *end, double mobility, double weight, s_char *path, int (*map) (s_char *, coord, coord, s_char *), int exploring, int *dam) + + + /* RESULT */ + + + + + +{ + struct sctstr sect, ending_sect; + struct sctstr next, dsect; + int vec[I_MAX+1]; + coord curx, cury, oldx, oldy; + coord tmpx, tmpy; + coord dx, dy; + s_char *movstr, *BestLandPath(s_char *, struct sctstr *, struct sctstr *, double *, int); + double sect_mcost; + double total_mcost; + double mv_cost; + int dir; + int intcost; + int takedam = (*dam), out=0; + s_char bpath[512]; + s_char buf2[512]; + s_char prompt[128]; + s_char buf[1024]; + + if (mobility <= 0.0) + return -1; + *dam = 0; + if (path && sarg_xy(path, &dx, &dy) && getsect(dx,dy,&ending_sect)){ + if ((ending_sect.sct_x == start->sct_x) && + (ending_sect.sct_y == start->sct_y)){ + pr("Start sector is ending sector!\n"); + return -1; + } + pr("Looking for best path to %s\n", path); + path = BestLandPath(buf2, start, &ending_sect, &total_mcost, MOB_ROAD); + if (exploring && (path != (s_char *)0)) /* take off the 'h' */ + *(path+strlen(path)-1) = '\0'; + if (path == (s_char *)0) + pr("No owned path exists!\n"); + else{ + pr("Using best path '%s', movement cost %1.3f\n", + path,total_mcost); + bzero(bpath,512); + bcopy(path,bpath,strlen(path)); + path = bpath; + } + if ((total_mcost*weight) > mobility){ + pr("Not enough mobility to go all the way. Nothing moved.\n"); + *end = *start; + return -1; + } + } + movstr = path; + tmpx = start->sct_x; + curx = tmpx; + tmpy = start->sct_y; + cury = tmpy; + total_mcost = 0.0; + if (getsect(curx, cury, §) < 0) { + logerror("move_path: getsect %d,%d", curx, cury); + return -1; + } + for (;;) { + tmpx = curx; + tmpy = cury; + oldx = curx; + oldy = cury; + if (movstr == 0 || *movstr == 0) { + if (exploring) { + map(what, curx, cury, (s_char *)0); } + else { + move_map(what, curx, cury, (s_char *)0); } + sprintf(prompt, "<%.1f: %c %s> ", mobility, + dchr[sect.sct_type].d_mnem, + xyas(sect.sct_x, sect.sct_y, player->cnum)); + movstr = getstring(prompt, buf); + } + if (movstr && sarg_xy(movstr, &dx, &dy)){ + if (getsect(dx,dy,&dsect)){ + movstr=BestLandPath(buf2,§,&dsect,&mv_cost,MOB_ROAD); + }else{ + pr("Invalid destination sector!\n"); + movstr=(s_char *)0; + } + + if (movstr == (s_char *)0){ + pr("Can't get to %s from here!\n", + xyas(dx,dy,player->cnum)); + movstr=(s_char *)0; + }else{ + if ((mv_cost*weight) > mobility){ + pr("Not enough mobility to go all the way. Nothing moved.\n"); + movstr = (s_char *)0; + }else{ + pr("Using best path '%s', movement cost %1.3f\n", + movstr,mv_cost); + bzero(bpath,512); + bcopy(movstr,bpath,strlen(movstr)); + movstr = bpath; + } + } + } + if (movstr == 0 || *movstr == 0) + movstr = dirch; + if ((dir = chkdir(*movstr, DIR_STOP, DIR_MAP)) < 0) { + pr("\"%c\" is not legal...", *movstr); + direrr("'%c' to stop ", "'%c' to view ", + "& '%c' to map\n"); + *movstr = 0; + continue; + } + movstr++; + if (dir == DIR_MAP) { + if (!exploring) + map(what, curx, cury, movstr+1); + *movstr = 0; + continue; + } else if (dir == DIR_STOP) + break; + else if (dir == DIR_VIEW) { + pr("%d%% %s with %d civilians.\n", sect.sct_effic, + dchr[sect.sct_type].d_name, + getvar(V_CIVIL, (s_char *)§, EF_SECTOR)); + continue; + } + /* + * now see if we can move into the + * next sector. Mobility, terrain, + * or ownership may prevent us. + */ + tmpx += diroff[dir][0]; + tmpy += diroff[dir][1]; + if (getsect(tmpx, tmpy, &next) < 0) { + pr("You can't go there...\n"); + *movstr = 0; + continue; + } + if (!player->god) { + if ((next.sct_type == SCT_SANCT) && + (next.sct_own != player->cnum)) { + pr("Converts, huh?\n"); + *end = next; + intcost = (int) total_mcost; + if (chance(total_mcost - intcost)) + intcost++; + return intcost; + } + getvec(VT_ITEM, vec, (s_char *)&next, EF_SECTOR); + sect_mcost = sector_mcost(&next, MOB_ROAD); + if ((!player->owner && (!exploring || + (vec[I_MILIT] || vec[I_CIVIL]))) || + sect_mcost == -1.0) { + /* already-owned, or prohibited terrain */ + pr("You can't go there...\n"); + *movstr = 0; + continue; + } + sect_mcost *= weight; + if (sect_mcost > mobility) { + pr("Not enough mobility. "); + pr("You can't go there...\n"); + *movstr = 0; + continue; + } + mobility -= sect_mcost; + total_mcost += sect_mcost; + } + curx = tmpx; + cury = tmpy; + if (cury != start->sct_y) + out=1; + if (curx != start->sct_x) + out=1; + + sect = next; + + if (takedam) + *dam += check_lmines(sect.sct_x, sect.sct_y, weight); + if (*dam >= 100) + break; + /* + * Check and see if anyone will interdict us + */ + if (takedam && chance(weight/100.0) && + ((curx != oldx) || (cury != oldy))) + (*dam) += ground_interdict(curx,cury,player->cnum,"commodities"); + if (*dam >= 100) + break; + } + *end = sect; + intcost = (int) total_mcost; + if (intcost < 0) + return -1; + if ((start->sct_x == end->sct_x) && (start->sct_y == end->sct_y) && !out) + return -1; + + if (chance(total_mcost - intcost)) + intcost++; + return intcost; +} + + +/*ARGSUSED*/ +int +move_map(s_char *what, coord curx, coord cury, s_char *arg) +{ + struct nstr_sect ns; + struct natstr *np; + struct sctstr sect; + coord rel_x, rel_y; + s_char range[128]; + s_char view[7]; + int i; + int vec[I_MAX+1]; + int changed = 0; + + np = getnatp(player->cnum); + rel_x = xrel(np, curx); + rel_y = yrel(np, cury); + sprintf(range, "%d:%d,%d:%d", rel_x-2, rel_x+2, rel_y-1, rel_y+1); + player->condarg = 0; + /* This is necessary, otherwise move_map would attempt to pay */ + /* attention to the conditional arguments left behind by such */ + /* a command as "tran p -1,-1 ?eff=100".. It'd then only see */ + /* 100% efficienct sects, and get all screwed up --ts */ + if (!snxtsct(&ns, range)) + return RET_FAIL; + i = 0; + while (i < 7 && nxtsct(&ns, §)) { + view[i] = dchr[sect.sct_type].d_mnem; + switch (sect.sct_type) { + case SCT_WATER: + case SCT_RURAL: + case SCT_MOUNT: + case SCT_WASTE: + case SCT_PLAINS: + break; + default: + if (sect.sct_own != player->cnum && !player->god) + view[i] = '?'; + break; + } + changed += map_set(player->cnum, ns.x, ns.y, view[i], 0); + i++; + } + if (changed) + writemap(player->cnum); + if (!getsect(curx, cury, §)) + return RET_FAIL; + getvec(VT_ITEM, vec, (s_char *)§, EF_SECTOR); + pr(" %c %c eff mob civ mil uw food work avail\n", + view[0], view[1]); + pr(" %c %c %c %3d %3d %4d %4d %4d %4d %3d %3d\n", + view[2], view[3], view[4], + sect.sct_effic, sect.sct_mobil, vec[I_CIVIL],vec[I_MILIT], + vec[I_UW],vec[I_FOOD], sect.sct_work, sect.sct_avail); + pr(" %c %c\n", view[5], view[6]); + return RET_OK; +} + +int +fly_map(coord curx, coord cury) +{ + struct nstr_sect ns; + struct natstr *np; + struct sctstr sect; + coord rel_x, rel_y; + s_char view[7]; + int i; + s_char range[128]; + + np = getnatp(player->cnum); + rel_x = xrel(np, curx); + rel_y = yrel(np, cury); + sprintf(range, "%d:%d,%d:%d", rel_x-2, rel_x+2, rel_y-1, rel_y+1); + player->condarg = 0; + /* This is necessary, otherwise move_map would attempt to pay */ + /* attention to the conditional arguments left behind by such */ + /* a command as "tran p -1,-1 ?eff=100".. It'd then only see */ + /* 100% efficienct sects, and get all screwed up --ts */ + + if (!snxtsct(&ns, range)) + return RET_FAIL; + i = 0; + while (i < 7 && nxtsct(&ns, §)){ + if (!(view[i] = player->bmap[sctoff(ns.x, ns.y)])) + view[i] = ' '; + i++; + } + + pr(" %c %c\n",view[0], view[1]); + pr(" %c %c %c\n", view[2], view[3], view[4]); + pr(" %c %c\n", view[5], view[6]); + return RET_OK; +} + +int +check_lmines(coord x, coord y, double weight) +{ + struct sctstr sect; + int mines; + int dam = 0; + + getsect(x, y, §); + mines = getvar(V_MINE, (s_char *)§, EF_SECTOR); + if (mines > 0 && + sect.sct_oldown != player->cnum && + chance(DMINE_LHITCHANCE(mines)) && + chance(weight/100.0)) { + pr_beep(); + pr("Blammo! Landmines detected! in %s ", + xyas(sect.sct_x,sect.sct_y,player->cnum)); + dam = roll(20); + --mines; + putvar(V_MINE, mines, (s_char *)§, EF_SECTOR); + putsect(§); + pr("%d damage sustained.\n", dam); + } + return dam; +} diff --git a/src/lib/subs/mslsub.c b/src/lib/subs/mslsub.c new file mode 100644 index 00000000..8f76405d --- /dev/null +++ b/src/lib/subs/mslsub.c @@ -0,0 +1,424 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * mslsub.c: Missile subroutine stuff + * + * Known contributors to this file: + * Ken Stevens, 1995 + * Steve McClure, 1996-2000 + */ + +#include "misc.h" +#include "queue.h" +#include "player.h" +#include "var.h" +#include "sect.h" +#include "ship.h" +#include "optlist.h" +#include "nuke.h" +#include "plane.h" +#include "land.h" +#include "news.h" +#include "item.h" +#include "xy.h" +#include "nsc.h" +#include "file.h" +#include "nat.h" +#include "path.h" +#include "mission.h" +#include "prototypes.h" + +int +msl_equip(struct plnstr *pp) +{ + struct plist pl; + + bzero((s_char *)&pl, sizeof(struct plist)); + pl.pcp = plchr + pp->pln_type; + bcopy((s_char *)pp, (s_char *)&pl.plane, sizeof(struct plnstr)); + return mission_pln_equip(&pl, 0, 0, 'p'); +} + +int +msl_hit(struct plnstr *pp, int hardtarget, int type, int news_item, int snews_item, s_char *what, coord x, coord y, int victim) +{ + int hit; + struct shpstr ship; + struct sctstr sect; + int sublaunch = 0; + struct plchrstr *pcp = plchr + pp->pln_type; + int hitchance = pln_hitchance(pp, hardtarget, type); + s_char *from; + int dam, dummyi; + + mpr(pp->pln_own,"Preparing to launch %s at %s %s %s%s\n", + prplane(pp), + cname(victim), + what, + (type==EF_SHIP||type==EF_PLANE)?"in ":"", + xyas(x, y, pp->pln_own)); + mpr(pp->pln_own, "\tLaunching from "); + if (pp->pln_ship >= 0) { + getship(pp->pln_ship, &ship); + mpr(pp->pln_own, "%s in ", prship(&ship)); + if (mchr[(int)ship.shp_type].m_flags & M_SUB) { + sublaunch = 1; + from = "in hatch"; + } else + from = "on deck"; + mpr(pp->pln_own, "%s\n", + xyas(ship.shp_x, ship.shp_y, pp->pln_own)); + } else { + if (pp->pln_harden > 0) { + mpr(pp->pln_own, "missile silo at "); + from = "in cilo"; + } else + from = "on launch pad"; + mpr(pp->pln_own, "%s\n", + xyas(pp->pln_x, pp->pln_y, pp->pln_own)); + } + + if (chance((0.05 + (100 - pp->pln_effic)/100.0) + * (1 - techfact(pp->pln_tech, 1.0)))) { + mpr(pp->pln_own, "KABOOOOM! Missile explodes %s!\n", from); + if (chance(0.33)) { + if (pp->pln_nuketype != (s_char)-1 && + opt_NUKEFAILDETONATE) { + pp->pln_flags &= ~PLN_AIRBURST; + detonate(pp, pp->pln_x, pp->pln_y); + } else { + dam = pln_damage(pp, pp->pln_x, pp->pln_y, + 'p', &dummyi, 1) / 2; + if (dam) { + if (pp->pln_ship >= 0) { + shipdamage(&ship, dam); + putship(ship.shp_uid, &ship); + } else { + pr("Explosion damages %s %d%%", + xyas(pp->pln_x, pp->pln_y, pp->pln_own), + dam); + getsect(pp->pln_x, pp->pln_y, §); + sectdamage(§, dam, 0); + putsect(§); + } + } + } + } + return 0; + } + + mpr(pp->pln_own, "\tSHWOOOOOSH! Missile launched!\n"); + + if (pp->pln_nuketype != (s_char)-1) + mpr(pp->pln_own, "\tArming nuclear warheads...\n"); + + if (pcp->pl_flags & P_T) + mpr(victim, "Incoming %s missile...\n",sublaunch?(s_char *)"":cname(pp->pln_own)); + + if (opt_PINPOINTMISSILE == 0 || + (pcp->pl_flags & P_T && !(pcp->pl_flags & P_MAR))) { + if (msl_intercept(x, y, pp->pln_own, pcp->pl_def, + sublaunch, P_N, P_O)) { + return 0; + } + } + if (pcp->pl_flags & P_MAR) { + if (shp_missile_defense(x, y, pp->pln_own, pcp->pl_def)) { + return 0; + } + } + + if (pp->pln_nuketype != (s_char)-1) + hitchance = 100; + + mpr(pp->pln_own,"\t%d%% hitchance...", hitchance); + hit = (roll(100) <= hitchance); + + mpr(pp->pln_own,hit?"HIT!\n":"miss\n"); + if (pcp->pl_flags & P_T) + mpr(victim, "...Incoming %s missile %s\n",sublaunch?(s_char *)"":cname(pp->pln_own), hit?"HIT!\n":"missed\n"); + if (hit && news_item) { + if (sublaunch) + nreport(victim, snews_item, 0, 1); + else + nreport(pp->pln_own, news_item, victim, 1); + } + return hit; +} + +void +msl_sel(struct emp_qelem *list, coord x, coord y, natid victim, int wantflags, int nowantflags, int mission) +{ + register struct plchrstr *pcp; + struct plnstr plane; + struct plist *irv; + struct nstr_item ni; + + emp_initque (list); + snxtitem_all (&ni, EF_PLANE); + while (nxtitem (&ni, (s_char *)&plane)) { + if (!plane.pln_own) + continue; + + pcp = &plchr[(int)plane.pln_type]; + if (!(pcp->pl_flags & P_M)) + continue; + if (wantflags && (pcp->pl_flags & wantflags) != wantflags) + continue; + if (nowantflags && pcp->pl_flags & nowantflags) + continue; + if (mission && plane.pln_mission != mission) + continue; + if (getrel(getnatp(plane.pln_own), victim) >= NEUTRAL) + continue; + /* missiles go one way, so we can use all the range */ + if (plane.pln_range < mapdist(x, y, plane.pln_x, plane.pln_y)) + continue; + if (plane.pln_mobil <= (s_char)0) + continue; + if (plane.pln_effic < 100) + continue; + /* got a valid interceptor */ + irv = (struct plist *) malloc(sizeof(*irv)); + irv->state = P_OK; + irv->bombs = 0; + irv->misc = 0; + irv->pcp = &plchr[(int)plane.pln_type]; + bcopy((s_char *)&plane, (s_char *)&irv->plane, sizeof(plane)); + emp_insque(&irv->queue, list); + } +} + +int +msl_intercept(coord x, coord y, natid bombown, int hardtarget, int sublaunch, int wantflags, int nowantflags) +{ + register struct plnstr *pp; + register struct plchrstr *pcp; + struct sctstr sect; + struct emp_qelem *irvlist; + struct emp_qelem foo; + struct emp_qelem *intlist; + struct emp_qelem intfoo; + struct emp_qelem *qp; + struct emp_qelem *next; + struct plist *ip; + int icount = 0; + short destroyed = 0; + s_char *att_name; + s_char *def_name; + int news_item; + s_char what[512]; + s_char *who = sublaunch?(s_char *)"":cname(bombown); + + getsect(x, y, §); + if (wantflags == P_O && !nowantflags) { + att_name = "satellite"; + def_name = "a-sat missile"; + news_item = N_SAT_KILL; + if (sect.sct_own) { + mpr(sect.sct_own, "%s has positioned a satellite over %s\n", sublaunch?(s_char *)"someone":cname(bombown), xyas(x,y,sect.sct_own)); + } + } else if (wantflags == P_N && nowantflags == P_O) { + att_name = "warhead"; + def_name = "abm"; + news_item = sublaunch?N_NUKE_SSTOP:N_NUKE_STOP; + } else { + att_name = "elephant"; + def_name = "tomato"; /* heh -KHS */ + news_item = N_NUKE_STOP; + } + sprintf(what,"%s %s",who, att_name); + irvlist = &foo; + + /* get all hostile abms in range */ + msl_sel(irvlist, x, y, bombown, wantflags, nowantflags, 0); + intlist = &intfoo; + emp_initque(intlist); + /* First choose interceptors belonging to the target sector */ + /* only allow two defense missiles per missile attack */ + for (qp = irvlist->q_forw; qp != irvlist && icount < 2; qp = next) { + next = qp->q_forw; + ip = (struct plist *)qp; + pp = &ip->plane; + if (pp->pln_own != sect.sct_own) + continue; + pcp = ip->pcp; + if (mission_pln_equip(ip, 0, 0, 'i') < 0) { + emp_remque(qp); + free((s_char *)qp); + continue; + } + /* got one interceptor, delete from irv_list and + * add to int_list. + */ + emp_remque(qp); + emp_insque(qp, intlist); + putplane(pp->pln_uid, pp); + icount++; + } + /* only allow two defense missiles per missile attack */ + for (qp = irvlist->q_forw; qp != irvlist && icount < 2; qp = next) { + next = qp->q_forw; + ip = (struct plist *)qp; + pp = &ip->plane; + pcp = ip->pcp; + if (mission_pln_equip(ip, 0, 0, 'i') < 0) { + emp_remque(qp); + free((s_char *)qp); + continue; + } + /* got one interceptor, delete from irv_list and + * add to int_list. + */ + emp_remque(qp); + emp_insque(qp, intlist); + putplane(pp->pln_uid, pp); + icount++; + } + /* Now, clean out the queue */ + while (!QEMPTY(irvlist)) { + qp = irvlist->q_forw; + emp_remque(qp); + free((s_char *)qp); + } + if (icount == 0) { + if(sect.sct_own != 0) + mpr(sect.sct_own, "No %ss launched to intercept.\n", def_name); + return (destroyed); + } + + /* attempt to destroy incoming missile */ + + while (!QEMPTY(intlist)) { + qp = intlist->q_forw; + ip = (struct plist *)qp; + pp = &ip->plane; + pcp = ip->pcp; + + mpr(bombown,"%s %s launched in defense!\n", + cname(pp->pln_own), def_name); + if (sect.sct_own == pp->pln_own) { + mpr(sect.sct_own, "%s launched to intercept %s %s!\n", + def_name, who, att_name); + } else { + if (sect.sct_own) + mpr(sect.sct_own, "%s launched an %s to intercept the %s %s!\n", + cname(pp->pln_own), def_name, who, att_name); + mpr(pp->pln_own, + "%s launched to intercept %s %s arcing towards %s territory!\n", + def_name, who, att_name, cname(sect.sct_own)); + } + + if (!destroyed && + msl_hit(pp, hardtarget, EF_PLANE, news_item, news_item, what, x, y, bombown)) { + mpr(bombown, "%s destroyed by %s %s!\n", att_name, + cname(pp->pln_own), def_name); + if (sect.sct_own) + mpr(sect.sct_own, "%s %s intercepted!\n", who, att_name); + if (sect.sct_own != pp->pln_own) + mpr(pp->pln_own, "%s %s intercepted!\n", who, att_name); + destroyed = 1; + } + /* zap the missile */ + makelost(EF_PLANE, pp->pln_own, pp->pln_uid, pp->pln_x, pp->pln_y); + pp->pln_own = 0; + putplane(pp->pln_uid, pp); + emp_remque(qp); + free((s_char *)qp); + if (destroyed) + break; + } + /* Clean out what is left in the list */ + while (!QEMPTY(intlist)) { + qp = intlist->q_forw; + emp_remque(qp); + free((s_char *)qp); + } + if (destroyed) + return (destroyed); + if (icount) { + mpr(bombown,"%s made it through %s defenses!\n", att_name, def_name); + if (sect.sct_own) + mpr(sect.sct_own, "%s made it through %s defenses!\n", att_name, + def_name); + } + return (destroyed); +} + +/* Keep launching missiles on list until mindam damage has been done */ +int +msl_launch_mindam(struct emp_qelem *list, coord x, coord y, int hardtarget, int type, int mindam, s_char *whatp, int victim, int mission) +{ + struct emp_qelem *qp; + struct emp_qelem *next; + struct plist *plp; + int newdam, dam = 0; + int nukedam = 0; + int news_item; + int snews_item; + + if (type == EF_SHIP) { + news_item = N_SHP_MISS; + snews_item = N_SHP_SMISS; + } else if (type == EF_LAND) { + news_item = N_LND_MISS; + snews_item = N_LND_SMISS; + } else { + news_item = N_SCT_MISS; + snews_item = N_SCT_SMISS; + } + + for (qp = list->q_back;qp != list && dam < mindam && !nukedam;qp = next) { + next = qp->q_back; + plp = (struct plist *)qp; + + if (mission_pln_equip(plp, 0, 0, 'p') >= 0) { + if (msl_hit(&plp->plane, + hardtarget, type, news_item, snews_item, + whatp, x, y, victim)) { + newdam = pln_damage(&plp->plane,x,y,'p',&nukedam, 1); + if (nukedam) { + if (mission == MI_INTERDICT && + type == EF_SECTOR) + dam += nukedam; + } else + dam += newdam; + } else { + /* Missiles that miss have to hit somewhere! */ + newdam = pln_damage(&plp->plane,x,y,'p',&nukedam, 0); + collateral_damage(x, y, newdam, 0); + } + makelost(EF_PLANE, plp->plane.pln_own, plp->plane.pln_uid, plp->plane.pln_x, plp->plane.pln_y); + plp->plane.pln_own = 0; + putplane(plp->plane.pln_uid, &plp->plane); + emp_remque(qp); + free(qp); + } + } + return dam; +} + diff --git a/src/lib/subs/mtch.c b/src/lib/subs/mtch.c new file mode 100644 index 00000000..d45e229a --- /dev/null +++ b/src/lib/subs/mtch.c @@ -0,0 +1,90 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * mtch.c: Matching operations on structures and commands. + * + * Known contributors to this file: + * (List known contributors to this file) + */ +/* + * XXX These routines gamble that structures are all longword-aligned. + * If this is not true, they will BREAK! + */ + +#include "misc.h" +#include "player.h" +#include "com.h" +#include "deity.h" +#include "match.h" +#include "prototypes.h" + +/* + * find a matching integer from a member of a structure. + * Inspired by stmtch above. + */ +int +intmatch(register int value, register int *ptr, int size) +{ + register int i; + + size /= sizeof(*ptr); + for (i=0; *ptr; i++, ptr += size) + if (value == *ptr) + return i; + return -1; +} + +/* + * find a matching command from coms[]. Return status is: + * >= 0: match found, value is array entry in coms[] + */ +int +comtch(register s_char *command, struct cmndstr *coms, int comstat, int god) +{ + register struct cmndstr *com; + register int status; + register int i; + + if (command == 0 || *command == 0) + return M_IGNORE; + status = M_NOTFOUND; + for (com=coms; com->c_form != 0; com++) { + if ((com->c_permit & comstat) != com->c_permit && !god) + continue; + if ((i = mineq(command, com->c_form)) == ME_MISMATCH) + continue; + if (i == ME_EXACT) + return com - coms; + /* partial */ + if (status != M_NOTFOUND) + return M_NOTUNIQUE; + status = com - coms; + } + + return status; +} + diff --git a/src/lib/subs/natarg.c b/src/lib/subs/natarg.c new file mode 100644 index 00000000..13e27034 --- /dev/null +++ b/src/lib/subs/natarg.c @@ -0,0 +1,81 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * natarg.c: Return countr # given country name or country # + * + * Known contributors to this file: + * (List known contributors to this file) + */ + +#include +#include "misc.h" +#include "nat.h" +#include "player.h" +#include "file.h" +#include "prototypes.h" +#include "optlist.h" + +int +natarg(s_char *arg, s_char *prompt) +{ + s_char buf[1024]; + int n; + struct natstr *np; + int byname = 0; + + arg = getstarg(arg, prompt, buf); + if (arg == 0 || *arg == 0) + return -1; + if (isdigit(*arg)) + n = atoi(arg); + else { + n = cnumb(arg); + if (opt_HIDDEN) { + byname = 1; + } + } + if (n < 0 || n >= MAXNOC) { + pr("No such country exists.\n"); + n = -1; + } + if (opt_HIDDEN) { + if (!player->god && !getcontact(getnatp(player->cnum), n)) { + if ((np = getnatp(n)) == 0) + return -1; + if ((np->nat_stat & STAT_GOD) == 0) { + if (byname) { + pr("No such country exists.\n"); + n = -1; + } else { + pr("Country has not been contacted.\n"); + n = -2; + } + } + } + } + return n; +} diff --git a/src/lib/subs/neigh.c b/src/lib/subs/neigh.c new file mode 100644 index 00000000..426b7878 --- /dev/null +++ b/src/lib/subs/neigh.c @@ -0,0 +1,53 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * neigh.c: Return true if a neighbor + * + * Known contributors to this file: + * + */ + +#include "misc.h" +#include "sect.h" +#include "path.h" +#include "file.h" +#include "nat.h" +#include "prototypes.h" + +int +neigh(coord x, coord y, natid own) +{ + register int i; + struct sctstr sect; + + for (i = DIR_FIRST; i <= DIR_LAST; i++) { + getsect(x + diroff[i][0], y + diroff[i][1], §); + if (sect.sct_own == own) + return 1; + } + return 0; +} diff --git a/src/lib/subs/nreport.c b/src/lib/subs/nreport.c new file mode 100644 index 00000000..356be274 --- /dev/null +++ b/src/lib/subs/nreport.c @@ -0,0 +1,200 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * nreport.c: File a news report. Downgrade relations if things get hostile. + * + * Known contributors to this file: + * Dave Pare, 1994 + * Steve McClure, 1997 + */ + +#include "misc.h" +#include "news.h" +#include "nat.h" +#include "deity.h" +#include "file.h" +#include "empio.h" +#include +#include "prototypes.h" + +void +nreport(natid actor, int event, natid victim, int times) +{ + int nice; + int rel; + struct natstr *np; + + filereport(actor, event, victim, times); + /* + * this is probably pretty expensive, but hopefully we + * don't fire zillions of these things off every second. + */ + if (victim == 0 || (nice = rpt[event].r_good_will) >= 0) + return; + /* + * Pretty schlocky to put it here, but + * I guess it can't go anywhere else. + */ + if (actor == victim) + return; + if (!chance((double)-nice * times/20.0)) + return; + if ((np = getnatp(victim)) == 0) + return; + if ((rel = getrel(np, actor)) < HOSTILE) + return; + + rel = HOSTILE; +/* + if (rel > HOSTILE) + rel = HOSTILE; + else + rel = AT_WAR; + */ + setrel(victim, actor, rel); +} + +struct free { + struct free *next; + int id; +}; + +struct free *freelist; + +static void +addfree(int n) +{ + struct free *fp; + + fp = (struct free *) malloc(sizeof(*fp)); + fp->next = freelist; + fp->id = n; + freelist = fp; +} + +/* + * snoop through the news articles looking + * for articles which have timed out. Only + * called when no free items left. + */ +static void +findfree(void) +{ + register time_t oldnewstime; + register int n; + struct nwsstr news; + time_t newstime; + + (void) time(&newstime); + oldnewstime = newstime - NEWS_PERIOD; + for (n=0; getnews(n, &news); n++) { + if (news.nws_when < oldnewstime) + addfree(n); + } + if (freelist == 0) { + if (!ef_extend(EF_NEWS, 100)) + return; + findfree(); + } +} + +static +int +nextfree(void) +{ + struct free *fp; + int id; + + if (freelist == 0) + findfree(); + if ((fp = freelist) == 0) + return 0; + freelist = fp->next; + id = fp->id; + free(fp); + return id; +} + +#define SLOTS 5 + +struct newscache { + struct nwsstr news; + int id; +}; + +static +struct newscache * +ncache(time_t now, int actor, int event, int victim, int times) +{ + static struct newscache cache[MAXNOC][SLOTS]; + register struct newscache *np; + int i; + int oldslot; + time_t oldtime; + + oldslot = -1; + oldtime = 0x7fffffff; + for (i=0; inews.nws_when < oldtime) { + oldslot = i; + oldtime = np->news.nws_when; + } + if (np->id == 0) + continue; + if ((now - np->news.nws_when) > minutes(5)) + continue; + if (np->news.nws_vrb == event && np->news.nws_vno == victim && + np->news.nws_ntm + times <= 127) { + np->news.nws_ntm += times; + return np; + } + } + if (oldslot < 0) { + logerror("internal error; ncache oldslot < 0"); + return &cache[actor][0]; + } + np = &cache[actor][oldslot]; + np->news.nws_ano = actor; + np->news.nws_vno = victim; + np->news.nws_when = now; + np->news.nws_vrb = event; + np->news.nws_ntm = times; + np->id = nextfree(); + return np; +} + +void +filereport(int actor, int event, int victim, int times) +{ + struct newscache *np; + time_t now; + + time(&now); + np = ncache(now, actor, event, victim, times); + ef_write(EF_NEWS, np->id, (s_char *)&np->news); +} diff --git a/src/lib/subs/nstr.c b/src/lib/subs/nstr.c new file mode 100644 index 00000000..57a8b2a9 --- /dev/null +++ b/src/lib/subs/nstr.c @@ -0,0 +1,176 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * nstr.c: compile and execute the item selections on sectors + * + * Known contributors to this file: + * Dave Pare, 1989 + * Steve McClure, 1997 + */ + +#include +#include "struct.h" +#include "misc.h" +#include "var.h" +#include "xy.h" +#include "sect.h" +#include "nsc.h" +#include "nat.h" +#include "match.h" +#include "file.h" +#include "player.h" +#include "prototypes.h" + +static int legal_val(s_char *str, int val); + +/* + * Compiles and adds "str" to the list of conditionals. + * type is the EF typename of the item type we're selecting. + * returns amount of "str" used by nstr_comp (i.e. how far + * the pointer was advanced). The last is only meaningful + * if several conditionals are expected in one string. + */ +s_char * +nstr_comp(struct nscstr *np, int *size, int type, s_char *str) +{ + register s_char *bp; + register s_char *cp; + register int c; + s_char ident[80]; + s_char arg[255]; + int op; + int val; + + strncpy(arg, str, sizeof(arg)-1); + arg[sizeof(arg)-1] = 0; + cp = arg; + bp = ident; + while ((c = *cp++) && bp < &ident[sizeof(ident)-1]) { + if (c == '<' || c == '=' || c == '>' || c == '#') + break; + *bp++ = c; + } + *bp = 0; + if (c == 0) { + pr("'%s'? -- meaningless condition?\n", arg); + return 0; + } + op = c; + np[*size].oper = op; + if ((val = encode(ident, &np[*size].fld1, type)) < 0) + return 0; + if (val == 2) + np[*size].oper += 255; + bp = ident; + while ((c = *cp++) && bp < &ident[sizeof(ident)-1]) { + if (c == '&') + break; + *bp++ = c; + } + *bp = 0; + if ((val = encode(ident, &np[*size].fld2, type)) < 0) + return 0; + if (val == 2) + np[*size].oper += 65535; + if (c == 0) + cp--; + (*size)++; + return str + (cp - arg); +} + +int +encode(register s_char *str, long int *val, int type) +{ + register int i; + struct castr *cap; + + if (str == 0) { + *val = 0; + return 0; + } + if (isdigit(*str) || ((*str == '-') && isdigit(str[1]))) { +#ifdef BIT16ONLY + /* XXX silently truncate to 16 bit int */ + *val = atoi(str) & 0xffff; +#else + *val = atoi(str); +#endif /* BIT16ONLY */ + return 2; + } + if ((i = typematch(str, type)) >= 0) { + *val = i; + return 1; + } + if ((cap = ef_cadef(type)) != 0) { + i = stmtch(str, (caddr_t)cap, fldoff(castr, ca_name), + sizeof(struct castr)); + if (i >= 0) { + *val = cap[i].ca_code|NSC_OFF; + *val &= ~NSC_ROUND; + return legal_val(str, *val); + } + if (i == M_NOTUNIQUE) { + pr("%s -- ambiguous type selector\n", str); + return 0; + } + } + /* + * Only check for commodity selectors on objects which + * are allowed to have commodities. + */ + if (ef_flags(type) & EFF_COM) { + i = stmtch(str, (caddr_t)var_ca, fldoff(castr, ca_name), + sizeof(struct castr)); + if (i >= 0) { + *val = var_ca[i].ca_code & ~NSC_ROUND; + return legal_val(str, *val); + return 1; + } + if (i == M_NOTUNIQUE) { + pr("%s -- ambiguous commodity selector\n", str); + return 0; + } + } + pr("%s -- not a valid selector\n", str); + return 0; +} + +static int +legal_val(s_char *str, int val) +{ + if (val & NSC_DEITY && !player->god) { + pr("%s -- permission denied\n", str); + return -1; + } + return 1; +} + + +/* + * The rest of this stuff has been moved to libcommon + * so it can be used elsewhere (emp_update, mostly) + */ diff --git a/src/lib/subs/nuke.c b/src/lib/subs/nuke.c new file mode 100644 index 00000000..31ff09a9 --- /dev/null +++ b/src/lib/subs/nuke.c @@ -0,0 +1,150 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * nuke.c: Nuke post-read and pre-write data massage + * + * Known contributors to this file: + * Dave Pare, 1989 + * Steve McClure, 1996 + */ + +#include "misc.h" +#include "player.h" +#include "var.h" +#include "nuke.h" +#include "sect.h" +#include "xy.h" +#include "nsc.h" +#include "file.h" +#include "nat.h" +#include "deity.h" +#include "prototypes.h" + +/*ARGSUSED*/ +int +nuk_postread(int n, s_char *ptr) +{ + struct nukstr *np = (struct nukstr *) ptr; + + if (np->nuk_uid != n) { + logerror("nuk_postread: Error - %d != %d, zeroing.\n", np->nuk_uid, n); + bzero(ptr, sizeof(struct nukstr)); + } + player->owner = (player->god || np->nuk_own == player->cnum); + return 1; +} + +/*ARGSUSED*/ +int +nuk_prewrite(int n, s_char *ptr) +{ + struct nukstr *np = (struct nukstr *) ptr; + struct nukstr nuke; + + np->ef_type = EF_NUKE; + np->nuk_uid = n; + + time(&np->nuk_timestamp); + + getnuke(n, &nuke); + + return 1; +} + +void +nuk_init(int n, s_char *ptr) +{ + struct nukstr *np = (struct nukstr *) ptr; + + np->ef_type = EF_NUKE; + np->nuk_uid = n; + np->nuk_own = 0; +} + +void +nuk_add(coord x, coord y, int type, int num) +{ + struct nukstr nuke; + struct sctstr sect; + int nuk_uid; + natid own; + int n; + + /* getsect in case of world wraparound */ + getsect(x, y, §); + if (!(own = sect.sct_own)) + return; + x = sect.sct_x; + y = sect.sct_y; + + /* + * either find a stockpile in x,y or add a new one + */ + nuk_uid = -1; + for (n = 0; getnuke(n, &nuke); n++) { + if (nuke.nuk_own == own) { + if (nuke.nuk_x == x && nuke.nuk_y == y) { + nuk_uid = n; + break; + } + } else if (nuke.nuk_own == 0 && nuk_uid == -1) + nuk_uid = n; + } + if (nuk_uid == -1) + nuk_uid = n; + if (getnuke(nuk_uid, &nuke) == 0) { + ef_extend(EF_NUKE, 10); + bzero((s_char *)&nuke, sizeof(struct nukstr)); + nuke.nuk_uid = nuk_uid; + nuke.nuk_ship = -1; + nuke.nuk_n = 0; + makenotlost(EF_NUKE, nuke.nuk_own, nuke.nuk_uid, nuke.nuk_x, nuke.nuk_y); + } + nuke.nuk_x = x; + nuke.nuk_y = y; + nuke.nuk_own = own; + nuke.nuk_types[type] += num; + nuke.nuk_n += num; + + if (!putnuke(nuke.nuk_uid, &nuke)) + pr("Problem with the nuclear stockpiles, tell the deity.\n"); + +} + +void +nuk_delete(struct nukstr *np, int type, int num) +{ + if (np->nuk_types[type] < num) + num = np->nuk_types[type]; + np->nuk_types[type] -= num; + np->nuk_n -= num; + if (np->nuk_n <= 0) { + makelost(EF_NUKE, np->nuk_own, np->nuk_uid, np->nuk_x, np->nuk_y); + np->nuk_own = 0; + } + putnuke(np->nuk_uid, np); +} diff --git a/src/lib/subs/nxtitem.c b/src/lib/subs/nxtitem.c new file mode 100644 index 00000000..d3cb1426 --- /dev/null +++ b/src/lib/subs/nxtitem.c @@ -0,0 +1,118 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * nxtitem.c: Get the next item from a list + * + * Known contributors to this file: + * Dave Pare, 1989 + */ + +#include "misc.h" +#include "player.h" +#include "var.h" +#include "xy.h" +#include "plane.h" +#include "ship.h" +#include "nuke.h" +#include "land.h" +#include "nsc.h" +#include "nat.h" +#include "file.h" +#include "genitem.h" +#include "prototypes.h" + +int +nxtitem(struct nstr_item *np, caddr_t ptr) +{ + struct genitem *gp; + int selected; + + if (np->sel == NS_UNDEF) + return 0; + gp = (struct genitem *) ptr; + do { + if (np->sel == NS_LIST) { + np->index++; + if (np->index >= np->size) + return 0; + np->cur = np->list[np->index]; + } else { + np->cur++; + } + if (!np->read(np->type, np->cur, ptr)) { + /* if read fails, fatal */ + return 0; + } + selected = 1; + switch (np->sel) { + /* + * This one won't work unless you're running in emp_player + * + */ + case NS_LIST: + if ((np->flags & EFF_OWNER) && !player->owner) + selected = 0; + break; + case NS_ALL: + /* XXX maybe combine NS_LIST and NS_ALL later */ + break; + case NS_DIST: + if (!xyinrange(gp->x, gp->y, &np->range)) { + selected = 0; + break; + } + np->curdist = mapdist((int)gp->x, (int)gp->y, + (int)np->cx, (int)np->cy); + if (np->curdist > np->dist) + selected = 0; + break; + case NS_AREA: + if (!xyinrange(gp->x, gp->y, &np->range)) + selected = 0; + if (gp->x == np->range.hx || gp->y == np->range.hy) + selected = 0; + break; + case NS_XY: + if (xnorm(gp->x) != np->cx || ynorm(gp->y) != np->cy) + selected = 0; + break; + case NS_GROUP: + if (np->group != gp->group) + selected = 0; + break; + default: + logerror("nxtitem: bad selector %d\n", np->sel); + return 0; + } + if (selected && np->ncond) { + /* nstr_exec is expensive, so we do it last */ + if (!nstr_exec(np->cond, np->ncond, ptr, np->type)) + selected = 0; + } + } while (!selected); + return 1; +} diff --git a/src/lib/subs/nxtsct.c b/src/lib/subs/nxtsct.c new file mode 100644 index 00000000..12265ff0 --- /dev/null +++ b/src/lib/subs/nxtsct.c @@ -0,0 +1,81 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * nxtsct.c: Select/get the next sector from a range of sectors + * + * Known contributors to this file: + * Dave Pare, 1989 + */ + +#include "misc.h" +#include "var.h" +#include "xy.h" +#include "sect.h" +#include "nsc.h" +#include "file.h" +#include "prototypes.h" +#include "optlist.h" + +/* + * get the next sector in the range + * that matches the conditions. + */ +int +nxtsct(register struct nstr_sect *np, struct sctstr *sp) +{ + while (1) { + np->dx++; + np->x++; + if (np->x >= WORLD_X) + np->x = 0; + if (np->dx >= np->range.width) { + np->dx = 0; + np->x = np->range.lx; + np->dy++; + if (np->dy >= np->range.height) + return 0; + np->y++; + if (np->y >= WORLD_Y) + np->y = 0; + } + if ((np->y + np->x) & 01) + continue; + if (np->type == NS_DIST) { + np->curdist = mapdist(np->x, np->y, np->cx, np->cy); + if (np->curdist > np->dist) + continue; + } + np->id = sctoff(np->x, np->y); + if (!np->read(EF_SECTOR, np->id, (caddr_t) sp)) + continue; + if (np->ncond == 0) + return 1; + if (nstr_exec(np->cond, np->ncond, (caddr_t)sp, EF_SECTOR)) + return 1; + } + /*NOTREACHED*/ +} diff --git a/src/lib/subs/paths.c b/src/lib/subs/paths.c new file mode 100644 index 00000000..59bd0f96 --- /dev/null +++ b/src/lib/subs/paths.c @@ -0,0 +1,332 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * path.c: Routines associated with paths, directions, etc. + * + * Known contributors to this file: + * + */ + +#include "misc.h" +#include "player.h" +#include "xy.h" +#include "path.h" +#include "nat.h" +#include "sect.h" +#include "file.h" +#include "prototypes.h" + +int +getdir(s_char *prompt, s_char *stop_msg, s_char *view_msg, s_char *bomb_msg) +{ + register int max_dir; + register int min_dir; + register int dir_num; + s_char buf[1024]; + + if (stop_msg != 0) + min_dir = DIR_STOP; + else + min_dir = DIR_FIRST; + if (view_msg == 0) + max_dir = DIR_LAST; + else + max_dir = DIR_VIEW; + while (1) { + if (getstring(prompt, buf) == 0 || *buf == 0) + return -1; + dir_num = chkdir(buf[0], min_dir, max_dir); + if (dir_num >= min_dir) + break; + direrr(stop_msg, view_msg, bomb_msg); + } + return dir_num; +} + +int +chkdir(s_char dir_char, int min_dir, int max_dir) +{ + register int i; + + for (i = min_dir; i <= max_dir; i++) + if (dir_char == dirch[i]) + return i; + return -1; +} + +void +direrr(s_char *stop_msg, s_char *view_msg, s_char *map_msg) +{ + pr("Legal directions are:\n"); + pr(" %c %c\n", dirch[DIR_UL], dirch[DIR_UR]); + pr("%c %c\n", dirch[DIR_L], dirch[DIR_R]); + pr(" %c %c\n", dirch[DIR_DL], dirch[DIR_DR]); + if (stop_msg != 0) + pr(stop_msg, dirch[DIR_STOP]); + if (view_msg != 0) + pr(view_msg, dirch[DIR_VIEW]); + if (map_msg != 0) + pr(map_msg, dirch[DIR_MAP]); +} + +/* + * return pointer to path; prompt user until a stop char + * or a bomb char have been entered. A "bomb" char in + * this context is actually "execute" for the partial + * move commands, and isn't valid for those commands + * which do not accept partial moves. + */ +s_char * +getpath(s_char *buf, s_char *arg, coord x, coord y, int onlyown, int showdes, int showxy, int destinations) +{ + s_char *p = buf; + s_char *bp; + s_char prompt[128]; + coord dx, dy; + struct sctstr sect, dsect; + coord nx, ny; + int dir; + s_char *execute; + double mv_cost; + + if (arg) { + strncpy(buf, arg, MAX_PATH_LEN - 1); + buf[MAX_PATH_LEN - 1] = 0; + } else { + *p = 0; + } + + if (showxy) + execute = " & '%c' to execute\n"; + else + execute = "\n"; + + getsect(x,y,§); + nx = x; + ny = y; + +more: + while (*p) { + if (sarg_xy(p, &dx, &dy)) { + bp = 0; + if (destinations == P_NONE) { + pr("Destination sectors not allowed here!\n"); + *p = 0; + } + if (getsect(dx,dy,&dsect)) { + if (destinations == P_WALKING){ + bp=BestLandPath(p, §,&dsect, + &mv_cost, MOB_ROAD); + } else if (destinations == P_FLYING) { + bp=BestAirPath(p, nx, ny, dx, dy); + } + } else { + pr("Invalid destination sector!\n"); + *p = 0; + } + if (bp) { + pr("Using best path '%s'\n", p); + pr("Using total path '%s'\n", buf); + return buf; + } else { + pr("Can't get to %s from here!\n", + xyas(nx,ny,player->cnum)); + *p = 0; + } + break; + } + dir = chkdir(*p, DIR_STOP, DIR_LAST); + if (dir < 0) { + pr("\"%c\" is not legal...", *p); + direrr("'%c' to stop", (s_char *)0, execute); + *p = 0; + break; + } + nx = x + diroff[dir][0]; + ny = y + diroff[dir][1]; + getsect(nx, ny, §); + if (onlyown && sect.sct_own != player->cnum) { + *p = 0; + pr("You don't own %s; you can't go there!\n", + xyas(nx, ny, player->cnum)); + break; + } + if (dir == DIR_STOP || dir == DIR_MAP) { + p[1] = 0; + return buf; + } + if (++p - buf == MAX_PATH_LEN) { + pr("Path length may not exceed %d.\n", MAX_PATH_LEN); + pr("Aborting...\n"); + *buf = 0; + return buf; + } + x = nx; + y = ny; + } + fly_map(x,y); + if (showdes) { + getsect(x, y, §); + sprintf(prompt, "<%c: %s> ", dchr[sect.sct_type].d_mnem, + xyas(x, y, player->cnum)); + } else { + sprintf(prompt, "<%d: %s> ", (int)(p - buf), + xyas(x, y, player->cnum)); + } + if (!(bp = getstring(prompt, p)) || !*bp) { + if (player->aborted) + *buf = 0; + return buf; + } + goto more; +} + +/* ARGSUSED */ +double +mcost(struct sctstr *sp, int own) +{ + return sector_mcost(sp, MOB_ROAD); + +/* + int m_cost; + + if (!(m_cost = dchr[sp->sct_type].d_mcst)) + return -1.0; + if (m_cost < 25) + return (200.0 + (m_cost - 3.0) * sp->sct_effic) / 500.0; + else + return (m_cost * 5.0 - (double)sp->sct_effic) / 25.0; + */ +} + +/* + * fly move cost + */ +/* ARGSUSED */ +double +fcost(struct sctstr *sp, natid own) +{ + return 1.0; +} + +/* + * nav move cost + */ +/* ARGSUSED */ +double +ncost(struct sctstr *sp, natid own) +{ + return 1.0; +} + +/* + * return end x,y of path, and the base + * movement cost it takes to get there. + */ +double +pathtoxy(s_char *path, coord *xp, coord *yp, double (*cost) (struct sctstr *, natid)) +{ + struct sctstr s; + s_char *pp; + coord x; + coord y; + int val; + double m; + int c; + + x = *xp; + y = *yp; + m = 0.0; + for (pp = path; *pp; pp++) { + if ((val = chkdir(*pp, DIR_STOP, DIR_LAST)) == 0) + break; + x += diroff[val][0]; + y += diroff[val][1]; + c = dirch[val]; + if (c == DIR_STOP) + break; + if (!getsect(x, y, &s)) + return -1.0; + m += cost(&s, s.sct_own); + } + *xp = xnorm(x); + *yp = ynorm(y); + return m; +} + +/* + * return true if "who" owns the path starting at x,y + */ +int +chkpath(natid who, s_char *path, coord x, coord y) +{ + s_char *pp; + int val; + struct sctstr sect; + + for (pp = path; *pp; pp++) { + if ((val = chkdir(*pp, DIR_STOP, DIR_LAST)) == 0) + break; + x += diroff[val][0]; + y += diroff[val][1]; + if (!getsect(x, y, §) || sect.sct_own != who) + return 0; + } + return 1; +} + +void +pathrange(register coord cx, register coord cy, register s_char *pp, int border, struct range *range) +{ + int dir; + + range->lx = cx; + range->hx = cx; + range->ly = cy; + range->hy = cy; + range->width = 0; + range->height = 0; + while ((dir = chkdir(*pp, DIR_FIRST, DIR_LAST)) >= 0) { + pp++; + cx += diroff[dir][0]; + cy += diroff[dir][1]; + if (cx < range->lx) + range->lx = cx; + if (cx > range->hx) + range->hx = cx; + if (cy < range->ly) + range->ly = cy; + if (cy > range->hy) + range->hy = cy; + } + range->lx = xnorm(range->lx - border*2); + range->ly = ynorm(range->ly - border); + range->hx = xnorm(range->hx + border*2 + 1); + range->hy = ynorm(range->hy + border + 1); + xysize_range(range); +} + diff --git a/src/lib/subs/plane.c b/src/lib/subs/plane.c new file mode 100644 index 00000000..f5338d98 --- /dev/null +++ b/src/lib/subs/plane.c @@ -0,0 +1,147 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * plane.c: Plane post-read and pre-write data massage + * + * Known contributors to this file: + * Dave Pare, 1989 + * Steve McClure, 1996 + */ + +#include "misc.h" +#include "player.h" +#include "var.h" +#include "plane.h" +#include "ship.h" +#include "land.h" +#include "xy.h" +#include "file.h" +#include "nat.h" +#include "deity.h" +#include "prototypes.h" +#include "optlist.h" + +int +pln_postread(int n, s_char *ptr) +{ + struct plnstr *pp = (struct plnstr *) ptr; + struct shpstr theship; + struct lndstr theland; + + if (pp->pln_uid != n) { + logerror("pln_postread: Error - %d != %d, zeroing.\n", pp->pln_uid, n); + bzero(ptr, sizeof(struct plnstr)); + } + + if (pp->pln_ship >= 0 && pp->pln_own && pp->pln_effic >= PLANE_MINEFF) { + if (getship(pp->pln_ship, &theship) && + (theship.shp_effic >= SHIP_MINEFF)) { + /* wooof! Carriers are a pain */ + if (pp->pln_mission){ + /* + * If the plane is on a mission centered + * on it's loc, the op-area travels with + * the plane. + */ + if ((pp->pln_opx == pp->pln_x) && + (pp->pln_opy == pp->pln_y)){ + pp->pln_opx = theship.shp_x; + pp->pln_opy = theship.shp_y; + } + } + if (pp->pln_x != theship.shp_x || pp->pln_y != theship.shp_y) + time(&pp->pln_timestamp); + pp->pln_x = theship.shp_x; + pp->pln_y = theship.shp_y; + } + } + if (pp->pln_land >= 0 && pp->pln_own && pp->pln_effic >= PLANE_MINEFF) { + if (getland(pp->pln_land, &theland) && + (theland.lnd_effic >= LAND_MINEFF)) { + /* wooof! Units are a pain, too */ + if (pp->pln_mission){ + /* + * If the plane is on a mission centered + * on it's loc, the op-area travels with + * the plane. + */ + if ((pp->pln_opx == pp->pln_x) && + (pp->pln_opy == pp->pln_y)){ + pp->pln_opx = theland.lnd_x; + pp->pln_opy = theland.lnd_y; + } + } + if (pp->pln_x != theland.lnd_x || pp->pln_y != theland.lnd_y) + time(&pp->pln_timestamp); + pp->pln_x = theland.lnd_x; + pp->pln_y = theland.lnd_y; + } + } + player->owner = (player->god || pp->pln_own == player->cnum); + if (opt_MOB_ACCESS) + pln_do_upd_mob(pp); + return 1; +} + +/*ARGSUSED*/ +int +pln_prewrite(int n, s_char *ptr) +{ + struct plnstr *pp = (struct plnstr *) ptr; + struct plnstr plane; + + if (pp->pln_effic < PLANE_MINEFF) { + if (pp->pln_own) + makelost(EF_PLANE, pp->pln_own, pp->pln_uid, pp->pln_x, pp->pln_y); + pp->pln_own = 0; + pp->pln_effic = 0; + } + pp->ef_type = EF_PLANE; + pp->pln_uid = n; + + time(&pp->pln_timestamp); + + getplane(n, &plane); + + return 1; +} + +void +pln_init(int n, s_char *ptr) +{ + struct plnstr *pp = (struct plnstr *) ptr; + + pp->ef_type = EF_PLANE; + pp->pln_uid = n; + pp->pln_own = 0; +} + +s_char * +prplane(struct plnstr *pp) +{ + return prbuf("%s #%d", plchr[(int)pp->pln_type].pl_name, pp->pln_uid); +} diff --git a/src/lib/subs/plnsub.c b/src/lib/subs/plnsub.c new file mode 100644 index 00000000..8a7d4873 --- /dev/null +++ b/src/lib/subs/plnsub.c @@ -0,0 +1,1172 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * plnsub.c: Plane subroutine stuff + * + * Known contributors to this file: + * Dave Pare, 1986 + * Ken Stevens, 1995 + * Steve McClure, 1998-2000 + */ + +#include "misc.h" +#include "player.h" +#include "var.h" +#include "sect.h" +#include "ship.h" +#include "land.h" +#include "item.h" +#include "plane.h" +#include "nuke.h" +#include "xy.h" +#include "nsc.h" +#include "news.h" +#include "file.h" +#include "nat.h" +#include "path.h" +#include "prototypes.h" +#include "optlist.h" + +int +pln_onewaymission(struct sctstr *target, int *shipno, int *flagp) +{ + int nships; + int cno; + int flags; + int n; + struct shpstr ship; + s_char buf[1024]; + s_char *p; + + flags = *flagp; + if ((target->sct_own && target->sct_own != player->cnum && + (getrel(getnatp(target->sct_own),player->cnum) != ALLIED)) && + (target->sct_type != SCT_HARBR) && + (target->sct_type != SCT_BSPAN)) { + pr("Nowhere to land at sector %s!\n", + xyas(target->sct_x, target->sct_y, player->cnum)); + return -1; + } + if (target->sct_type == SCT_MOUNT) { + pr("Nowhere to land at sector %s!\n", + xyas(target->sct_x, target->sct_y, player->cnum)); + return -1; + } + cno = -1; + if (target->sct_type != SCT_AIRPT || target->sct_effic < 60) + flags |= P_V; + if (target->sct_type == SCT_WATER || target->sct_type == SCT_HARBR + || target->sct_type == SCT_BSPAN) { + nships = carriersatxy(target->sct_x, target->sct_y, + M_FLY|M_CHOPPER, 0, player->cnum); + if (nships <= 0) { + if (target->sct_type == SCT_WATER){ + pr("Nowhere to land at sector %s!\n", + xyas(target->sct_x, target->sct_y, player->cnum)); + return -1; + }else{ + if ((target->sct_own && target->sct_own != player->cnum) + && (getrel(getnatp(target->sct_own),player->cnum) != ALLIED)){ + pr("Nowhere to land at sector %s!\n", + xyas(target->sct_x, + target->sct_y, player->cnum)); + return -1; + } + *shipno=cno; + *flagp=flags; + return 0; + } + } + cno = (-1); + n = (-1); + while (cno < 0) { + if (!(p = getstarg(0, "Carrier #? ", buf)) || !*p) + break; + n = atoi(p); + if (n < 0 || !getship(n, &ship) || (!player->owner && + (getrel(getnatp(ship.shp_own),player->cnum) != ALLIED))) { + pr("Not yours\n"); + continue; + } + if (ship.shp_x != target->sct_x || + ship.shp_y != target->sct_y) { + pr("Ship #%d not in %s\n", n, + xyas(target->sct_x, target->sct_y, player->cnum)); + continue; + } + if (!(mchr[(int)ship.shp_type].m_flags & M_FLY) + && !(mchr[(int)ship.shp_type].m_flags & M_XLIGHT) + && !(mchr[(int)ship.shp_type].m_flags & M_CHOPPER) + ){ + pr("Can't land on %s.\n", prship(&ship)); + continue; + } + pr("landing on carrier %d\n",n); + cno = n; + flags &= ~P_V; + if (mchr[(int)ship.shp_type].m_flags & M_FLY) + flags |= P_L; + if (mchr[(int)ship.shp_type].m_flags & M_CHOPPER) + flags |= P_K; + if (mchr[(int)ship.shp_type].m_flags & M_XLIGHT) + flags |= P_E; + } + if ((target->sct_own && target->sct_own != player->cnum) && + (getrel(getnatp(target->sct_own),player->cnum)!= ALLIED) && + (cno== -1)) { + pr("Nowhere to land at sector %s!\n", + xyas(target->sct_x, target->sct_y, player->cnum)); + return -1; + } + } + + if ((target->sct_own == 0) && (cno < 0)) { + pr("Nowhere to land at sector %s!\n", + xyas(target->sct_x, target->sct_y, player->cnum)); + return -1; + } + + *shipno = cno; + *flagp = flags; + return 0; +} + +void +pln_newlanding(struct emp_qelem *list, coord tx, coord ty, int cno) +{ + struct emp_qelem *qp; + struct plist *plp; + struct shpstr ship; + struct sctstr sect; + + if (cno >= 0) + getship(cno, &ship); + for (qp = list->q_forw; qp != list; qp = qp->q_forw) { + plp = (struct plist *)qp; + /* XXX - need to restrict # of planes per ship */ + if (cno >= 0){ + count_planes(&ship); + if (!can_be_on_ship(plp->plane.pln_uid,ship.shp_uid)) + pr("\t%s cannot land on ship #%d! %s aborts!\n",prplane(&plp->plane),cno,prplane(&plp->plane)); + else if (!put_plane_on_ship(&plp->plane,&ship)) + pr("\tNo room on ship #%d! %s aborts!\n",cno,prplane(&plp->plane)); + else{ + if (plp->plane.pln_own != ship.shp_own){ +/* plp->plane.pln_own = ship.shp_own;*/ + wu(0,ship.shp_own, + "%s %s lands on your %s\n", + cname(player->cnum), + prplane(&plp->plane), + prship(&ship)); + } + } + } + else{ + plp->plane.pln_x = tx; + plp->plane.pln_y = ty; + getsect(tx,ty,§); + if (plp->plane.pln_own != sect.sct_own){ +/* plp->plane.pln_own = sect.sct_own;*/ + wu(0,sect.sct_own, + "%s %s lands at your sector %s\n", + cname(player->cnum), + prplane(&plp->plane), + xyas(tx,ty,sect.sct_own)); + } + plp->plane.pln_ship = cno; + } + } + if (cno >= 0) + putship(ship.shp_uid, &ship); +} + +void +pln_dropoff(struct emp_qelem *list, struct ichrstr *ip, coord tx, coord ty, s_char *ptr, int type) +{ + struct emp_qelem *qp; + struct plist *plp; + int amt; + struct shpstr *ship; + int there; + int max; + struct mchrstr *mp; + int mines_there; + + if (ip == 0) + return; + amt = 0; + for (qp = list->q_forw; qp != list; qp = qp->q_forw) { + plp = (struct plist *)qp; + amt += plp->misc; + } + if (type == EF_SECTOR && + (((struct sctstr *)ptr)->sct_type == SCT_WATER) && + ip->i_vtype == V_SHELL){ + mines_there = getvar(V_MINE, ptr, EF_SECTOR); + putvar(V_MINE, amt + mines_there, ptr, EF_SECTOR); + pr("%d mines laid in %s.\n", amt, + xyas(((struct sctstr *)ptr)->sct_x, + ((struct sctstr *)ptr)->sct_y, player->cnum)); + if (amt > 0 && + map_set(player->cnum, ((struct sctstr *)ptr)->sct_x, + ((struct sctstr *)ptr)->sct_y, 'X', 0)) + writemap(player->cnum); + putsect((struct sctstr *) ptr); + }else{ + there = getvar(ip->i_vtype, ptr, type) + amt; + max = 32767; + if (type == EF_SHIP) { + ship = (struct shpstr *) ptr; + mp = &mchr[(int)ship->shp_type]; + max = vl_find(ip->i_vtype, mp->m_vtype, + mp->m_vamt, (int)mp->m_nv); + } + if (there > max) { + pr("%d excess %s discarded\n", max-there, ip->i_name); + amt = max - there; + there = max; + } + putvar(ip->i_vtype, there, ptr, type); + pr("%d %s landed safely", amt, ip->i_name); + if (type == EF_SECTOR) { + struct sctstr *sectp = (struct sctstr *)ptr; + if (sectp->sct_own != player->cnum) + wu(0, sectp->sct_own, "%s planes drop %d %s in %s\n", + cname(player->cnum),amt,ip->i_name, + xyas(sectp->sct_x,sectp->sct_y, + sectp->sct_own)); + pr(" at %s\n", xyas(tx, ty, player->cnum)); + putsect((struct sctstr *) ptr); + } else { + struct shpstr *sp = (struct shpstr *)ptr; + if (sp->shp_own != player->cnum) + wu(0, sp->shp_own, "%s planes land %d %s on carrier %d\n", + cname(player->cnum),amt,ip->i_name,sp->shp_uid); + pr(" on carrier #%d\n", ship->shp_uid); + putship(ship->shp_uid, ship); + } + } +} + +void +pln_sel(struct nstr_item *ni, struct emp_qelem *list, struct sctstr *ap, int ap_to_target, int rangemult, int wantflags, int nowantflags) +{ + struct plnstr plane; + struct shpstr ship; + struct lndstr land; + struct sctstr sect; + int range; + struct plchrstr *pcp; + struct plist *plp; + register int y; + register int bad,bad1; + unsigned int x; + + emp_initque(list); + while (nxtitem(ni, (s_char *)&plane)) { + if (!player->owner) + continue; + if (plane.pln_mobil <= (s_char)0) + continue; + if (opt_MARKET) { + if (ontradingblock(EF_PLANE, (int *)&plane)) { + pr("plane #%d inelligible - it's for sale.\n", plane.pln_uid); + continue; + } + } + + range = mapdist(plane.pln_x, plane.pln_y, ap->sct_x, ap->sct_y); + if (range > 4) { + pr("%s too far from assembly point\n", + prplane(&plane)); + continue; + } + if (plane.pln_effic < 40) { + pr("%s not efficient enough (must be 40%%)\n", prplane(&plane)); + continue; + } + range += ap_to_target; + pcp = &plchr[(int)plane.pln_type]; + bad=0; + bad1=0; + if (wantflags) { + for(x=0;xpl_flags & y) != y){ + switch(y){ + case P_F: + case P_ESC: bad1=2; + break; + case P_E: + case P_L: + case P_K: bad1=1; + break; + default: bad=1; + } + } + } + if (bad) + continue; + if (bad1 == 2){ + if ((pcp->pl_flags & P_ESC) || + (pcp->pl_flags & P_F)) + bad1=0; + } + if (bad1 == 1){ + if ((wantflags & P_L) && (pcp->pl_flags & P_L)) + bad1=0; + if ((wantflags & P_K) && (pcp->pl_flags & P_K)) + bad1=0; + if ((wantflags & P_E) && (pcp->pl_flags & P_E)) + bad1=0; + } + if (bad1) + continue; + } + bad=0; + bad1=0; + if (nowantflags) { + for(x=0;xpl_flags & y) == y) + bad=1; + } + if (bad) + continue; + } + range *= rangemult; + if (plane.pln_range < range) { + pr("%s out of range (%d:%d)\n", prplane(&plane), + plane.pln_range, range); + continue; + } + if (plane.pln_ship >= 0) { + if (!getship(plane.pln_ship, &ship) || + plane.pln_own != player->cnum) { + shipsunk: + plane.pln_effic = 0; + pr("(note) ship not valid for %s\n", + prplane(&plane)); + putplane(plane.pln_uid, &plane); + continue; + } + if (!can_be_on_ship(plane.pln_uid,ship.shp_uid)) + goto shipsunk; + if (ship.shp_effic < SHIP_MINEFF) + goto shipsunk; + if (ship.shp_effic < 50) + continue; + /* Can't fly off non-owned ships or non-allied ship */ + if ((ship.shp_own != player->cnum) && + (getrel(getnatp(ship.shp_own), player->cnum) != ALLIED)) { + pr("(note) An ally does not own the ship %s is on\n", + prplane(&plane)); + continue; + } + } + if (plane.pln_land >= 0) { + if (!getland(plane.pln_land, &land) || + (plane.pln_own != player->cnum)) { + landdead: + plane.pln_effic = 0; + pr("(note) land unit not valid for %s\n", + prplane(&plane)); + putplane(plane.pln_uid, &plane); + continue; + } + if (!(plchr[(int)plane.pln_type].pl_flags & P_E)) + goto landdead; + if (land.lnd_effic < LAND_MINEFF) + goto landdead; + if (land.lnd_effic < 50) + continue; + /* Can't fly off units in ships or other units */ + if ((land.lnd_ship >= 0) || (land.lnd_land >= 0)) + continue; + /* Can't fly off non-owned units or non-allied unit */ + if ((land.lnd_own != player->cnum) && + (getrel(getnatp(land.lnd_own), player->cnum) != ALLIED)) { + pr("(note) An ally does not own the unit %s is on\n", + prplane(&plane)); + continue; + } + } + /* Now, check the sector status if not on a plane or unit */ + if ((plane.pln_ship < 0) && (plane.pln_land < 0)) { + if (!getsect(plane.pln_x, plane.pln_y, §)) + continue; + /* First, check allied status */ + /* Can't fly from non-owned sectors or non-allied sectors */ + if ((sect.sct_own != player->cnum) && + (getrel(getnatp(sect.sct_own), player->cnum) != ALLIED)) { + pr("(note) An ally does not own the sector %s is in\n", + prplane(&plane)); + continue; + } + /* non-vtol plane */ + if ((pcp->pl_flags & P_V) == 0) { + if (sect.sct_type != SCT_AIRPT) { + pr("%s not at airport\n", prplane(&plane)); + continue; + } + if (sect.sct_effic < 40) { + pr("%s is not 40%% efficient, %s can't take off from there.\n", + xyas(sect.sct_x,sect.sct_y,plane.pln_own), + prplane(&plane)); + continue; + } + if (rangemult == 2 && sect.sct_effic < 60) { + pr("%s is not 60%% efficient, %s can't land there.\n", + xyas(sect.sct_x,sect.sct_y,plane.pln_own), + prplane(&plane)); + continue; + } + } + } + pr("%s standing by\n", prplane(&plane)); + plane.pln_mission = 0; + putplane(plane.pln_uid, &plane); + plp = (struct plist *) malloc(sizeof(struct plist)); + plp->state = P_OK; + plp->misc = 0; + plp->bombs = 0; + plp->pcp = pcp; + bcopy((s_char *)&plane, (s_char *)&plp->plane, + sizeof(struct plnstr)); + emp_insque(&plp->queue, list); + } +} + +int +pln_arm(struct emp_qelem *list, int dist, int mission, struct ichrstr *ip, int flags, int mission_flags, int *tech) +{ + struct emp_qelem *qp; + struct emp_qelem *next; + struct plist *plp; + + if (*tech == 0) + *tech = 9999; + for (qp = list->q_forw; qp != list; qp = next) { + next = qp->q_forw; + plp = (struct plist *) qp; + if (pln_equip(plp, ip, flags, mission) < 0) { + emp_remque(qp); + free((s_char *)qp); + continue; + } + if (flags & (P_S|P_I)) { + if(plp->pcp->pl_flags & P_S) + mission_flags |= P_S; + if(plp->pcp->pl_flags & P_I) + mission_flags |= P_I; + } + if (*tech > plp->plane.pln_tech) + *tech = plp->plane.pln_tech; + if (!(plp->pcp->pl_flags & P_H)) + /* no stealth on this mission */ + mission_flags &= ~P_H; + if (!(plp->pcp->pl_flags & P_X)) + /* no stealth on this mission */ + mission_flags &= ~P_X; + if (!(plp->pcp->pl_flags & P_A)) { + /* no asw on this mission */ + mission_flags &= ~P_A; + } + if (!(plp->pcp->pl_flags & P_MINE)) { + /* no asw on this mission */ + mission_flags &= ~P_MINE; + } + plp->plane.pln_mobil -= pln_mobcost(dist,&plp->plane,flags); + pr("%s equipped\n", prplane(&plp->plane)); + } + return mission_flags; +} + +int +pln_equip(struct plist *plp, struct ichrstr *ip, int flags, s_char mission) +{ + register struct plchrstr *pcp; + struct plnstr *pp; + int needed; + struct lndstr land; + struct shpstr ship; + struct sctstr sect; + int type; + s_char *ptr; + int item; + int rval; + int vec[I_MAX+1]; + int own; + + pp = &plp->plane; + pcp = plp->pcp; + if (pp->pln_ship >= 0) { + getship(pp->pln_ship, &ship); + type = EF_SHIP; + ptr = (s_char *) &ship; + own = ship.shp_own; + } else if (pp->pln_land >= 0) { + getland(pp->pln_land, &land); + type = EF_LAND; + ptr = (s_char *) &land; + own = land.lnd_own; + } else { + getsect(pp->pln_x, pp->pln_y, §); + type = EF_SECTOR; + ptr = (s_char *) § + own = sect.sct_oldown; + } + if (ip) { + if (ip->i_vtype == V_CIVIL) { + if (pp->pln_own != own) { + pr("You don't control those civilians!\n"); + return -1; + } + } + } + getvec(VT_ITEM, vec, ptr, type); + if (pcp->pl_fuel > vec[I_PETROL]) { + pr("%s not enough petrol there!\n", prplane(pp)); + return -1; + } + vec[I_PETROL] -= pcp->pl_fuel; + rval = 0; + if ((flags & P_F) == 0) { + item = 0; + needed = 0; + switch (mission) { + case 's': + case 'p': + if (pp->pln_nuketype == -1) { + item = I_SHELL; + needed = pp->pln_load; + } + break; + case 't': + if ((pcp->pl_flags & P_C) == 0 || ip == 0) + break; + item = ip - ichr; + needed = (pp->pln_load * 2) / ip->i_lbs; + break; + case 'd': + item = ip - ichr; + needed = (pp->pln_load * 2) / ip->i_lbs; + /* Is this mine dropping excursion? */ + if ((item == I_SHELL) && (pcp->pl_flags & P_MINE)) + break; + /* Is this a cargo drop? */ + if ((pcp->pl_flags & P_C) == 0 || ip == 0) { + item = 0; + needed = 0; + break; + } + break; + case 'a': + if ((pcp->pl_flags & (P_V|P_C)) == 0) + break; + item = I_MILIT; + needed = pp->pln_load / ip->i_lbs; + break; + case 'n': + if (pp->pln_nuketype == (s_char)-1) + rval = -1; + break; + default: + break; + } + if (rval < 0 || (item && needed <= 0)) { + pr("%s can't contribute to mission\n", prplane(pp)); + return -1; + } +#if 0 + /* Supply is broken somewhere, so don't use it for now */ + if ((vec[item] < needed) && (item == I_SHELL)) + vec[item] += supply_commod(plp->plane.pln_own, + plp->plane.pln_x,plp->plane.pln_y,I_SHELL, + needed); +#endif + if (vec[item] < needed) { + pr("Not enough %s for %s\n", + ichr[item].i_name, prplane(pp)); + return -1; + } else { + vec[item] -= needed; + } + if (item == I_SHELL && (mission == 's' || mission == 'p')) + plp->bombs = needed; + else + plp->misc = needed; + } + putvec(VT_ITEM, vec, ptr, type); + if (type == EF_SHIP) { + if (pp->pln_own != ship.shp_own) { + wu(0, ship.shp_own, "%s %s prepares for takeoff from ship %s\n", + cname(pp->pln_own), prplane(pp), prship(&ship)); + } + putship(ship.shp_uid,&ship); + } else if (type == EF_LAND) { + if (pp->pln_own != land.lnd_own) { + wu(0, land.lnd_own, "%s %s prepares for takeoff from unit %s\n", + cname(pp->pln_own), prplane(pp), prland(&land)); + } + putland(land.lnd_uid,&land); + } else { + if (pp->pln_own != sect.sct_own) { + wu(0, sect.sct_own, "%s %s prepares for takeoff from %s\n", + cname(pp->pln_own), prplane(pp), xyas(sect.sct_x, sect.sct_y, sect.sct_own)); + } + putsect(§); + } + return rval; +} + +void +pln_put(struct emp_qelem *list) +{ + register struct emp_qelem *qp; + register struct emp_qelem *newqp; + struct plist *plp; + struct plnstr *pp; + struct shpstr ship; + struct sctstr sect; + + /* Here is where planes return home from bombing runs. + We need to make sure they still have somewhere to return + home to! */ + qp = list->q_forw; + while (qp != list) { + plp = (struct plist *) qp; + pp = &plp->plane; + /* Ok, check out where it wants to land */ + if (pp->pln_ship >= 0) { + /* It is landing on a carrier */ + getship(pp->pln_ship, &ship); + /* We should do more, like make sure it's really + a carrier, etc. but for now just make sure it's + not sunk. */ + if (ship.shp_effic < SHIP_MINEFF) { + mpr(pp->pln_own, "Ship #%d has been sunk, plane #%d has nowhere to land, and\nsplashes into the sea.\n", pp->pln_ship, pp->pln_uid); + pp->pln_effic = 0; + } + } else { + /* Presume we are landing back in a sector. */ + getsect(pp->pln_x, pp->pln_y, §); + if (sect.sct_type == SCT_WATER || + sect.sct_type == SCT_WASTE) { + mpr(pp->pln_own, "Nowwhere to land at %s, plane #%d crashes and burns...\n", xyas(pp->pln_x, pp->pln_y, pp->pln_own), pp->pln_uid); + pp->pln_effic = 0; + } + } + putplane(pp->pln_uid, pp); + newqp = qp->q_forw; + emp_remque(qp); + free((s_char *)qp); + qp = newqp; + } +} + +void +pln_removedupes(struct emp_qelem *bomb_list, struct emp_qelem *esc_list) +{ + struct emp_qelem *bomb; + struct emp_qelem *esc; + struct plist *bombp; + struct plist *escp; + + if (QEMPTY(bomb_list) || QEMPTY(esc_list)) + return; + bomb = bomb_list->q_forw; + while (bomb != bomb_list) { + if (QEMPTY(esc_list)) { + bomb = bomb_list; + continue; + } + esc = esc_list->q_forw; + bombp = (struct plist *) bomb; + while (esc != esc_list) { + escp = (struct plist *) esc; + if (escp->plane.pln_uid == bombp->plane.pln_uid) { + emp_remque(esc); + free((s_char *)esc); + esc = esc_list; + } else + esc = esc->q_forw; + } + bomb = bomb->q_forw; + } +} + +int +put_plane_on_ship(struct plnstr *plane, struct shpstr *ship) +{ + struct plchrstr *pcp; + struct mchrstr *mcp; + + pcp = &plchr[(int)plane->pln_type]; + mcp = &mchr[(int)ship->shp_type]; + + if (((int)plane->pln_ship) == ((int)ship->shp_uid)) + return 1; /* Already on ship */ + + /* Try to put on ship as a chopper plane */ + if ((pcp->pl_flags & P_K) && + (mcp->m_flags & M_CHOPPER) && + (ship->shp_nchoppers < mcp->m_nchoppers)){ + + ship->shp_nchoppers++; + plane->pln_x = ship->shp_x; + plane->pln_y = ship->shp_y; + plane->pln_ship = ship->shp_uid; + putship(ship->shp_uid,ship); + putplane(plane->pln_uid,plane); + return 1; + } + + /* Try to put on ship as an xlight plane */ + if ((pcp->pl_flags & P_E) && + (mcp->m_flags & M_XLIGHT) && + (ship->shp_nxlight < mcp->m_nxlight)){ + + ship->shp_nxlight++; + plane->pln_x = ship->shp_x; + plane->pln_y = ship->shp_y; + plane->pln_ship = ship->shp_uid; + putship(ship->shp_uid,ship); + putplane(plane->pln_uid,plane); + return 1; + } + + /* Try to put on ship as a normal plane */ + if ( ( ((pcp->pl_flags & P_L) && (mcp->m_flags & M_FLY)) || + ((pcp->pl_flags & P_M) && (pcp->pl_flags & P_L) && + (mcp->m_flags & M_MSL)) ) && + (ship->shp_nplane < mcp->m_nplanes)){ + + ship->shp_nplane++; + plane->pln_x = ship->shp_x; + plane->pln_y = ship->shp_y; + plane->pln_ship = ship->shp_uid; + putship(ship->shp_uid,ship); + putplane(plane->pln_uid,plane); + return 1; + } + + /* We have failed */ + return 0; +} + +int +take_plane_off_ship(struct plnstr *plane, struct shpstr *ship) +{ + struct plchrstr *pcp; + struct mchrstr *mcp; + + pcp = &plchr[(int)plane->pln_type]; + mcp = &mchr[(int)ship->shp_type]; + + /* Try to take off ship as a chopper plane */ + if ((pcp->pl_flags & P_K) && + (mcp->m_flags & M_CHOPPER) && + (ship->shp_nchoppers)){ + + ship->shp_nchoppers--; + plane->pln_ship = -1; + putship(ship->shp_uid,ship); + putplane(plane->pln_uid,plane); + return 1; + } + + /* Try to take off ship as an xlight plane */ + if ((pcp->pl_flags & P_E) && + (mcp->m_flags & M_XLIGHT) && + (ship->shp_nxlight)){ + + ship->shp_nxlight--; + plane->pln_ship = -1; + putship(ship->shp_uid,ship); + putplane(plane->pln_uid,plane); + return 1; + } + + /* Try to take off ship as a normal plane */ + if ( ( ((pcp->pl_flags & P_L) && (mcp->m_flags & M_FLY)) || + ((pcp->pl_flags & P_M) && (pcp->pl_flags & P_L) && + (mcp->m_flags & M_MSL)) ) && + (ship->shp_nplane)){ + + ship->shp_nplane--; + plane->pln_ship = -1; + putship(ship->shp_uid,ship); + putplane(plane->pln_uid,plane); + return 1; + } + + /* We have failed */ + return 0; +} + +int +take_plane_off_land(struct plnstr *plane, struct lndstr *land) +{ + struct plchrstr *pcp; + struct lchrstr *lcp; + + pcp = &plchr[(int)plane->pln_type]; + lcp = &lchr[(int)land->lnd_type]; + + /* Try to take off ship as an xlight plane */ + if ((pcp->pl_flags & P_E) && + (lcp->l_flags & L_XLIGHT) && + (land->lnd_nxlight)){ + + land->lnd_nxlight--; + plane->pln_land = -1; + putland(land->lnd_uid,land); + putplane(plane->pln_uid,plane); + return 1; + } + + /* We have failed */ + return 0; +} + +int +can_be_on_ship(int p, int s) +{ + struct plnstr plane; + struct shpstr ship; + struct plchrstr *pcp; + struct mchrstr *mcp; + + getplane(p,&plane); + getship(s,&ship); + + pcp = &plchr[(int)plane.pln_type]; + mcp = &mchr[(int)ship.shp_type]; + + if (pcp->pl_flags & P_L) + if (mcp->m_flags & M_FLY) + return 1; + + if (pcp->pl_flags & P_K) + if (mcp->m_flags & M_CHOPPER) + return 1; + + if (pcp->pl_flags & P_M) + if (mcp->m_flags & M_MSL) + return 1; + + if (pcp->pl_flags & P_E) + if (mcp->m_flags & M_XLIGHT) + return 1; + + return 0; +} + +void +plane_sweep(struct emp_qelem *plane_list, coord x, coord y) +{ + struct plnstr *pp; + struct plchrstr *pcp; + struct emp_qelem *qp; + struct emp_qelem *next; + struct plist *ip; + struct sctstr sect; + int mines_there; + int found = 0; + + getsect(x,y,§); + mines_there = getvar(V_MINE, (s_char *)§, EF_SECTOR); + + if (mines_there == 0) + return; + + if ((sect.sct_type != SCT_WATER) && (sect.sct_type != SCT_HARBR)) + return; + + for (qp=plane_list->q_forw;((qp!=plane_list)&&(mines_there));qp=next) { + next = qp->q_forw; + ip = (struct plist *) qp; + pp = &ip->plane; + pcp = ip->pcp; + if (!(pcp->pl_flags & P_SWEEP)) /* if it isn't an sweep plane */ + continue; + + if (chance( ((double) (100-pp->pln_acc))/100.0 )){ + pr("Sweep! in %s\n", + xyas(sect.sct_x,sect.sct_y,pp->pln_own)); + mines_there--; + found = 1; + } + } + + if (found && map_set(player->cnum, sect.sct_x, sect.sct_y, 'X', 0)) + writemap(player->cnum); + putvar(V_MINE, mines_there, (s_char *)§, EF_SECTOR); + putsect(§); +} + +void +count_planes(struct shpstr *sp) +{ + struct nstr_item ni; + struct plnstr plane; + struct plchrstr *pcp; + struct mchrstr *mcp; + int nplane = 0; + int nchoppers = 0; + int nxlight = 0; + + if (sp->shp_effic < SHIP_MINEFF) + return; + + mcp = &mchr[(int)sp->shp_type]; + snxtitem_xy(&ni, EF_PLANE, sp->shp_x, sp->shp_y); + while (nxtitem(&ni, (s_char *)&plane)){ + if (plane.pln_own == 0) + continue; + if (plane.pln_ship == sp->shp_uid){ + pcp = &plchr[(int)plane.pln_type]; + if ((pcp->pl_flags & P_K) && + (nchoppers < mcp->m_nchoppers)) + nchoppers++; + else + if ((pcp->pl_flags & P_E) && + (nxlight < mcp->m_nxlight)) + nxlight++; + else + if ((pcp->pl_flags & P_L) || (pcp->pl_flags & P_M)) + nplane++; + } + } + + if (nplane != sp->shp_nplane || + nxlight != sp->shp_nxlight || + nchoppers != sp->shp_nchoppers) { + sp->shp_nplane = nplane; + sp->shp_nxlight = nxlight; + sp->shp_nchoppers = nchoppers; + putship(sp->shp_uid, sp); + } +} + +void +count_land_planes(struct lndstr *lp) +{ + struct nstr_item ni; + struct plnstr plane; + int nplane = 0; + + if (lp->lnd_effic < LAND_MINEFF) + return; + + snxtitem_all(&ni, EF_PLANE); + while (nxtitem(&ni, (s_char *)&plane)) { + if (plane.pln_own == 0) + continue; + if (plane.pln_land == lp->lnd_uid) + nplane++; + } + + if (lp->lnd_nxlight != nplane) { + lp->lnd_nxlight = nplane; + putland(lp->lnd_uid,lp); + } +} + +int +count_sect_planes(struct sctstr *sp) +{ + int count = 0; + struct nstr_item ni; + struct plnstr plane; + + snxtitem_all(&ni, EF_PLANE); + while (nxtitem(&ni, (s_char *)&plane)) { + if (!plane.pln_own) + continue; + if (plane.pln_flags & PLN_LAUNCHED) + continue; + if (plane.pln_x == sp->sct_x && plane.pln_y == sp->sct_y) + ++count; + } + + return count; +} + +int +put_plane_on_land(struct plnstr *plane, struct lndstr *land) +{ + struct plchrstr *pcp; + struct lchrstr *lcp; + + pcp = &plchr[(int)plane->pln_type]; + lcp = &lchr[(int)land->lnd_type]; + + if (((int)plane->pln_land) == ((int)land->lnd_uid)) + return 1; /* Already on unit */ + + /* Try to put on unit as an xlight plane */ + if ((pcp->pl_flags & P_E) && + (lcp->l_flags & L_XLIGHT) && + (land->lnd_nxlight < lcp->l_nxlight)){ + + land->lnd_nxlight++; + plane->pln_x = land->lnd_x; + plane->pln_y = land->lnd_y; + plane->pln_land = land->lnd_uid; + putland(land->lnd_uid,land); + putplane(plane->pln_uid,plane); + return 1; + } + + /* We have failed */ + return 0; +} + +int +pln_hitchance(struct plnstr *pp, int hardtarget, int type) +{ + struct plchrstr *pcp = plchr + pp->pln_type; + float tfact = (float)(pp->pln_tech - pcp->pl_tech) / + (pp->pln_tech - pcp->pl_tech / 2); + int acc = pp->pln_acc; + int hitchance; + + if (type == EF_SHIP) { + if (pcp->pl_flags & P_A) + acc -= 20; + if (!(pcp->pl_flags & P_T)) + acc += 35; + } + hitchance = (int)(pp->pln_effic * (1.0 - 0.1 * tfact) * + (1.0 - (float)acc / 100.0)) - hardtarget; + + /* smooth out the bottom of the graph with asymtote at 5 -KHS */ + if (hitchance < 20) + hitchance = 5 + ldround(300.0 / (40.0 - hitchance), 1); + if (hitchance > 100) + hitchance = 100; + return hitchance; +} + +/* return 0 if there was a nuclear detonation */ + +int +pln_damage(struct plnstr *pp, coord x, coord y, s_char type, int *nukedamp, int noisy) +{ + struct plchrstr *pcp = plchr + pp->pln_type; + int i; + int hitroll; + int dam = 0; + int aim; + int effective = 1; + int pinbomber = 0; + + if (pp->pln_nuketype != (s_char)-1) { + mpr(pp->pln_own, "Releasing RV's for %s detonation...\n", + pp->pln_flags & PLN_AIRBURST?"airburst":"groundburst"); + *nukedamp = detonate(pp, x, y); + return 0; + } else + *nukedamp = 0; + + if (!pp->pln_load) /* e.g. ab, blowing up on launch pad */ + return 0; + + i = roll(pp->pln_load) + 1; + if (i > pp->pln_load) + i = pp->pln_load; + + if (pcp->pl_flags & P_M) { + if (pcp->pl_flags & P_MAR) + pinbomber = 1; + } else if (pcp->pl_flags & P_T) + pinbomber = 1; + + aim = 100 - pp->pln_acc; + if (type == 's') { + if (pinbomber) { + aim = pp->pln_acc; + effective = 0; + } + aim += 30; + } else { + if (!pinbomber) { + effective = 0; + } + } + while (i--) { + dam += roll(6); + hitroll = roll(100); + if (hitroll >= 90) { + dam += 8; + if (noisy) + mpr(pp->pln_own, "BLAM"); + } else if (hitroll < aim) { + dam += 5; + if (noisy) + mpr(pp->pln_own, "Blam"); + } else { + dam += 1; + if (noisy) + mpr(pp->pln_own, "blam"); + } + if (i && noisy) + mpr(pp->pln_own, "-"); + } + if (noisy) + mpr(pp->pln_own, "\n"); + if (effective) + dam *= 2; + return dam; +} + +int +pln_identchance(struct plnstr *pp, int hardtarget, int type) +{ + double misschance = (100.0-pln_hitchance(pp, hardtarget, type))/100.0; + return (int)(100 - 100 * misschance * misschance); +} + +int +pln_mobcost(int dist, struct plnstr *pp, int flags) +{ + int cost; + + if ((flags & P_F) || (flags & P_ESC)) + cost = 10 * 100 / pp->pln_effic; + else + cost = 20 * 100 / pp->pln_effic; + + cost = ldround((double)cost * dist/pp->pln_range_max, 1); + + return min(32 + pp->pln_mobil, cost + 5); +} + diff --git a/src/lib/subs/pr.c b/src/lib/subs/pr.c new file mode 100644 index 00000000..dc0c69a2 --- /dev/null +++ b/src/lib/subs/pr.c @@ -0,0 +1,341 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * pr.c: Use to do output to a player + * + * Known contributors to this file: + * Dave Pare, 1986, 1989 + * Steve McClure, 1998-2000 + */ +/* + * The pr routine historically arranged for nonbuffered i/o + * because stdio didn't used to automatically flush stdout before + * it read something from stdin. Now pr() prepends an "output id" + * in front of each line of text, informing the user interface + * what sort of item it is seeing; prompt, noecho prompt, + * more input data, etc. + */ + +#ifdef Rel4 +#include +#endif /* Rel4 */ +#include +#include +#include +#include "proto.h" +#include "misc.h" +#include "player.h" +#include "nat.h" +#include "empio.h" +#include "file.h" +#include "com.h" +#include "news.h" +#include "tel.h" +extern int update_pending; +#include "prototypes.h" + +void outid(struct player *pl, int n); + +/*VARARGS*/ +void +pr(s_char *format, ...) +{ + s_char buf[4096]; + va_list ap; + + va_start(ap, format); + (void) vsprintf(buf, format, ap); + va_end(ap); + pr_player(player, C_DATA, buf); +} + +void +prnf(s_char *buf) +{ + pr_player(player, C_DATA, buf); +} + +/*VARARGS*/ +void +pr_id(struct player *p, int id, s_char *format, ...) +{ + s_char buf[4096]; + va_list ap; + + if (p->curid >= 0) { + io_puts(p->iop, "\n"); + p->curid = -1; + } + va_start(ap, format); + (void) vsprintf(buf, format, ap); + va_end(ap); + pr_player(p, id, buf); +} + +void +pr_flash(struct player *pl, s_char *format, ...) +{ + s_char buf[4096]; + va_list ap; + + if (pl->state != PS_PLAYING) + return; + va_start(ap, format); + (void) vsprintf(buf, format, ap); + va_end(ap); + pr_player(pl, C_FLASH, buf); + io_output(pl->iop, IO_NOWAIT); +} + +void +pr_inform(struct player *pl, s_char *format, ...) +{ + s_char buf[4096]; + va_list ap; + + if (pl->state != PS_PLAYING) + return; + va_start(ap, format); + (void) vsprintf(buf, format, ap); + va_end(ap); + pr_player(pl, C_INFORM, buf); + io_output(pl->iop, IO_NOWAIT); +} + +void +pr_wall(s_char *format, ...) +{ + s_char buf[4096]; + struct player *p; + va_list ap; + + va_start(ap, format); + (void) vsprintf(buf, format, ap); + va_end(ap); + for (p = player_next(0); p; p = player_next(p)) { + if (p->state != PS_PLAYING) + continue; + pr_player(p, C_FLASH, buf); + io_output(p->iop, IO_NOWAIT); + } +} + +void +pr_player(struct player *pl, int id, s_char *buf) +{ + register s_char *p; + register s_char *bp; + register int len; + + bp = buf; + while (*bp != '\0') { + if (pl->curid != -1 && pl->curid != id) { + io_puts (pl->iop, "\n"); + pl->curid = -1; + } + if (pl->curid == -1) { + outid(pl, id); + } + p = index(bp, '\n'); + if (p != 0) { + len = (p - bp) + 1; + if (pl->command && (pl->command->c_flags & C_MOD)) + io_write(pl->iop, bp, len, IO_NOWAIT); + else + io_write(pl->iop, bp, len, IO_WAIT); + bp += len; + pl->curid = -1; + } else { + len = io_puts(pl->iop, bp); + bp += len; + } + } +} + +/* + * highlighted characters have hex 80 or'ed in + * with them to designate their highlightedness + */ +void +pr_hilite(s_char *buf) +{ + register s_char *bp; + register s_char c; + s_char *p; + + p = (s_char *)malloc(strlen(buf) + 1); + strcpy(p, buf); + for (bp=p; 0 != (c = *bp); bp++) + if (isprint(c)) + *bp |= 0x80; + pr(p); + free(p); +} + +/* + * output hex code + space + */ +void +outid(struct player *pl, int n) +{ + s_char c; + s_char buf[3]; + + if (n > C_LAST) { + logerror("outid: %d not valid code\n", n); + return; + } + if (n >= 10) + c = 'a' - 10 + n; + else + c = '0' + n; + buf[0] = c; + buf[1] = ' '; + buf[2] = '\0'; + io_puts(pl->iop, buf); + pl->curid = n; +} + +void +prredir(s_char *redir) +{ + pr_id(player, *redir == '>' ? C_REDIR : C_PIPE, "%s\n", redir); +} + +void +prexec(s_char *file) +{ + pr_id(player, C_EXECUTE, "%s\n", file); +} + +void +prprompt(int min, int btu) +{ + pr_id(player, C_PROMPT, "%d %d\n", min, btu); +} + +void +showvers(int vers) +{ + pr_id(player, C_INIT, "%d\n", vers); +} + +int +prmptrd(s_char *prompt, s_char *str, int size) +{ + int r; + + pr_id(player, C_FLUSH, "%s\n", prompt); + if ((r = recvclient(str, size)) < 0) + return r; + time(&player->curup); + if (*str == 0) + return 1; + return strlen(str); +} + +void +prdate(void) +{ + time_t now; + + (void) time(&now); + pr(ctime(&now)); +} + +/* + * print x,y formatting as country + */ +void +prxy(s_char *format, coord x, coord y, natid country) +{ + s_char buf[255]; + struct natstr *np; + + np = getnatp(country); + sprintf(buf, format, xrel(np, x), yrel(np, y)); + pr(buf); +} + +/*VARARGS*/ +void +PR(int cn, s_char *format, ...) +{ + /* XXX should really do this on a per-nation basis */ + static s_char longline[MAXNOC][512]; + int newline; + va_list ap; + s_char buf[1024]; + + va_start(ap, format); + (void) vsprintf(buf, format, ap); + va_end(ap); + newline = strrchr(buf, '\n') ? 1 : 0; + strcat(longline[cn], buf); + if (newline){ + if (update_pending || (cn && cn != player->cnum)) + typed_wu(0, cn, longline[cn], TEL_BULLETIN); + else + pr_player(player, C_DATA, longline[cn]); + longline[cn][0] = '\0'; + } +} + +void +PRdate(natid cn) +{ + time_t now; + + (void) time(&now); + PR(cn, ctime(&now)); +} + +void +pr_beep(void) +{ + struct natstr *np = getnatp(player->cnum); + + if (np->nat_flags & NF_BEEP) + pr("\07"); +} + +void +mpr(int cn, s_char *format, ...) +{ + s_char buf[4096]; + va_list ap; + + va_start(ap, format); + (void) vsprintf(buf, format, ap); + va_end(ap); + if (cn) { + if (update_pending || cn != player->cnum) + typed_wu(0, cn, buf, TEL_BULLETIN); + else + pr_player(player, C_DATA, buf); + } +} diff --git a/src/lib/subs/radmap.c b/src/lib/subs/radmap.c new file mode 100644 index 00000000..d2eec472 --- /dev/null +++ b/src/lib/subs/radmap.c @@ -0,0 +1,214 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * radmap.c: Do a radar map given an x,y location, effic, and other + * + * Known contributors to this file: + * Dave Pare, 1989 + */ + +#include "misc.h" +#include "player.h" +#include "xy.h" +#include "nat.h" +#include "sect.h" +#include "ship.h" +#include "plane.h" +#include "file.h" +#include "nsc.h" +#include "deity.h" +#include "prototypes.h" +#include "optlist.h" + +void +radmap(int cx, int cy, int eff, int range, double seesub) +{ + radmap2(player->cnum, cx, cy, eff, range, seesub, 1); +} + +void +radmapnopr(int cx, int cy, int eff, int range, double seesub) +{ + radmap2(player->cnum, cx, cy, eff, range, seesub, 0); +} + +void +radmapupd(int own, int cx, int cy, int eff, int range, double seesub) +{ + radmap2(own, cx, cy, eff, range, seesub, 0); +} + +/* More dynamic world sized buffers. We create 'em once, and then + * never again. No need to keep creating/tearint apart. We may + * want to do this in other places too where it doesn't matter. */ +static s_char **rad; +static s_char *radbuf; +static s_char **vis; +static s_char *visbuf; + +void +radmap2(int owner, + int cx, + int cy, + int eff, + int range, + double seesub, + int pr_flag) +{ + int rng; + struct sctstr sect; + struct shpstr ship; + struct plnstr plane; + struct nstr_sect ns; + struct nstr_item ni; + int x, y; + int row; + int n; + int changed = 0; + + if (!radbuf) + radbuf = (s_char *)malloc((WORLD_Y * (WORLD_X + 1)) * + sizeof(s_char)); + if (!visbuf) + visbuf = (s_char *)malloc((WORLD_Y * (WORLD_X + 1)) * + sizeof(s_char)); + if (!rad) { + rad = (s_char **)malloc(WORLD_Y * sizeof(s_char *)); + if (rad && radbuf) { + for (x = 0; x < WORLD_Y; x++) + rad[x] = &radbuf[(WORLD_X + 1) * x]; + } + } + if (!vis) { + vis = (s_char **)malloc(WORLD_Y * sizeof(s_char *)); + if (vis && visbuf) { + for (x = 0; x < WORLD_Y; x++) + vis[x] = &visbuf[(WORLD_X + 1) * x]; + } + } + if (!radbuf || !visbuf || !rad || !vis) { + pr("Memory error in radmap2, tell the deity.\n"); + return; + } + + bzero((s_char *)visbuf, (WORLD_Y * (WORLD_X + 1))); + range = (int) (range * (eff / 100.0)); + if (range < 1) + range = 1; + if (pr_flag) + pr("%s efficiency %d%%, max range %d\n", + xyas(cx, cy, owner), eff, range); + snxtsct_dist(&ns, cx, cy, range); + blankfill((s_char *)radbuf, &ns.range, 1); + while (nxtsct(&ns, §)) { + if (sect.sct_own == owner || + (sect.sct_type <= SCT_RURAL && sect.sct_type != SCT_SANCT) + || ns.curdist <= range/3) + rad[ns.dy][ns.dx] = dchr[sect.sct_type].d_mnem; + else + rad[ns.dy][ns.dx] = '?'; + changed += map_set(owner, ns.x, ns.y, rad[ns.dy][ns.dx],0); + } + if (changed) + writemap(owner); + if (!pr_flag) + return; + snxtitem_dist(&ni, EF_PLANE, cx, cy, range); + while (nxtitem(&ni, (caddr_t)&plane)) { + if (plane.pln_own == 0) + continue; + /* Used to have 'ghosts' when scanning whole world --ts */ + x = deltx(&ns.range,(int)plane.pln_x); + y = delty(&ns.range,(int)plane.pln_y); + + if ((plane.pln_flags & PLN_LAUNCHED) && + plane.pln_own != owner) { + vis[y][x] = (s_char) 100; + rad[y][x] = '$'; + } + } + snxtitem_dist(&ni, EF_SHIP, cx, cy, range); + while (nxtitem(&ni, (caddr_t)&ship)) { + if (ship.shp_own == 0) + continue; + /* Used to have 'ghosts' when scanning whole world --ts */ + x = deltx(&ns.range,(int)ship.shp_x); + y = delty(&ns.range,(int)ship.shp_y); + + rng = (int) (range * ship.shp_visib / 20.0); + if (ni.curdist > rng) + continue; + if ((mchr[(int)ship.shp_type].m_flags & M_SUB) && + ni.curdist > rng * seesub) + continue; + if (ship.shp_visib > vis[y][x]) { + vis[y][x] = ship.shp_visib; + /* &~0x20 makes it a cap letter */ + rad[y][x] = (*mchr[(int)ship.shp_type].m_name) & ~0x20; + } + } + /* + * make the center of the display 0 + * so ve et al can find it. + */ + rad[deltay(cy, ns.range.ly)][deltax(cx, ns.range.lx)] = '0'; + /* won't work for radar maps > WORLD_Y/2 */ +#ifdef HAY + /* This is not correct for small, hitech worlds. */ + n = deltay(ns.range.hy, ns.range.ly); +#else + /* This is already available, so why not use it. */ + n = ns.range.height; +#endif + for (row=0; row < n; row++) + pr("%s\n", rad[row]); + pr("\n"); +} + +int +deltx(struct range *r, coord x) +{ + if (r->lx < r->hx) + return x-r->lx; + + if (x >= r->lx) + return x-r->lx; + + return x+WORLD_X-r->lx; +} + +int +delty(struct range *r, coord y) +{ + if (r->ly < r->hy) + return y-r->ly; + + if (y >= r->ly) + return y-r->ly; + + return y+WORLD_Y-r->ly; +} diff --git a/src/lib/subs/rej.c b/src/lib/subs/rej.c new file mode 100644 index 00000000..31ba58ef --- /dev/null +++ b/src/lib/subs/rej.c @@ -0,0 +1,167 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * rej.c: Various relations setting routines + * + * Known contributors to this file: + * Dave Pare, 1994 + */ + +#include "misc.h" +#include "nat.h" +#include "file.h" +#include "news.h" +#include "player.h" +#include "prototypes.h" +#include "optlist.h" + +extern s_char *relates[]; +extern int update_pending; + +int +setrel(natid us, natid them, int rel) +{ + struct natstr *mynp; + struct natstr *themnp; + s_char *myname = cname(us); + s_char *themname; + int oldrel; + s_char *whichway; + int n_up = 0; + int n_down = 0; + s_char *addendum = 0; + int theirrel; + extern int War_Cost; + + if (rel < AT_WAR) + rel = AT_WAR; + if (rel > ALLIED) + rel = ALLIED; + if (!(mynp = getnatp(us))) + return RET_FAIL; + if (!(themnp = getnatp(them))) + return RET_FAIL; + if ((oldrel = getrel(mynp, them)) == rel) + return RET_FAIL; + themname = cname(them); + if (rel > oldrel) + whichway = "upgraded"; + else + whichway = "downgraded"; + if (rel == ALLIED) { + addendum = "Congratulations!"; + n_up = N_DECL_ALLY; + } else if (rel == FRIENDLY) { + n_up = N_UP_FRIENDLY; + n_down = N_DOWN_FRIENDLY; + } else if (rel == NEUTRAL) { + n_up = N_UP_NEUTRAL; + n_down = N_DOWN_NEUTRAL; + } else if (rel == HOSTILE) { + addendum = "Another cold war..."; + n_up = N_UP_HOSTILE; + n_down = N_DOWN_HOSTILE; + } else if (rel < HOSTILE) { + if (opt_SLOW_WAR) { + struct natstr *natp2; + double cost; + + if (!player->god) { + natp2 = themnp; + theirrel = getrel(natp2,us); + if (theirrel <= MOBILIZATION) { + rel = theirrel; + cost = 0; + } else if (us == player->cnum && !update_pending) { + if (mynp->nat_money < War_Cost){ + mpr(us, "You don't have the money!\n"); + return RET_FAIL; + } + rel = MOBILIZATION; + cost = War_Cost; + } else { /* nreport is forcing us to decl war */ + return RET_FAIL; + } + if (rel >= oldrel) { + if (us == player->cnum && !update_pending) + mpr(us, "No change required for that!\n"); + return RET_FAIL; + } + player->dolcost += cost; + } + } + addendum = "Declaration made (give 'em hell)."; + n_down = N_DECL_WAR; + } + + if (addendum && us == player->cnum && !update_pending) + pr("%s\n", addendum); + mpr(us, "Diplomatic relations with %s %s to \"%s\".\n", themname, whichway, relates[rel]); + if(!(getrejects(us, themnp) & REJ_TELE)) + mpr(them, + "Country %s (#%d) has %s their relations with you to \"%s\"!\n", myname, us, whichway, relates[rel]); + + putrel(mynp, them, rel); + putnat(mynp); + + if (!player->god) { + if (oldrel == ALLIED) + nreport(us, N_DIS_ALLY, them, 1); + else if (oldrel < HOSTILE && rel >= HOSTILE) + nreport(us, N_DIS_WAR, them, 1); + if (rel > oldrel) + nreport(us, n_up, them, 1); + else + nreport(us, n_down, them, 1); + } + + return RET_OK; +} + +int +setcont(natid us, natid them, int contact) +{ + struct natstr *np; + + if ((np = getnatp(us)) == 0) + return 0; + putcontact(np, them, contact); + putnat(np); + return 1; +} + +int +setrej(natid us, natid them, int how, int what) +{ + struct natstr *np; + + if ((np = getnatp(us)) == 0) + return 0; + putreject(np, them, how, what); + putnat(np); + return 1; +} diff --git a/src/lib/subs/retreat.c b/src/lib/subs/retreat.c new file mode 100644 index 00000000..9d4a6d4c --- /dev/null +++ b/src/lib/subs/retreat.c @@ -0,0 +1,567 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * retreat.c: Retreat subroutines + * + * Known contributors to this file: + * Steve McClure, 2000 + * + */ + +#include "misc.h" +#include "player.h" +#include "nat.h" +#include "var.h" +#include "retreat.h" +#include "ship.h" +#include "land.h" +#include "sect.h" +#include "news.h" +#include "xy.h" +#include "nsc.h" +#include "path.h" +#include "deity.h" +#include "file.h" +#include "options.h" +#include "damage.h" +#include "prototypes.h" +#include "optlist.h" + +struct ccode{ + s_char code; + s_char *desc[2]; +} conditions[] = { + { 'i', { + "retreated with a damaged friend", + "was damaged", + }, }, + { 't', { + "retreated with a torpedoed ship", + "was hit by a torpedo", + }, }, + { 's', { + "retreated with a ship scared by sonar", + "detected a sonar ping", + }, }, + { 'h', { + "retreated with a helpless ship", + "was fired upon with no one able to defend it", + }, }, + { 'b', { + "retreated with a bombed friend", + "was bombed", + }, }, + { 'd', { + "retreated with a depth-charged ship", + "was depth-charged", + }, }, + { 'u', { + "retreated with a boared ship", + "was boarded", + }, }, + { 0, {"",""} }, +}; + +int +check_retreat_and_do_shipdamage(struct shpstr *sp, int dam) +{ + if (dam <=0) + return 0; + + shipdamage(sp,dam); + if (sp->shp_rflags & RET_INJURED) + retreat_ship(sp, 'i'); + + return 1; +} + +void +retreat_ship(struct shpstr *sp, s_char code) +{ + struct nstr_item ni; + struct shpstr ship; + s_char buf[2]; + + if (sp->shp_rflags & RET_GROUP){ + bzero(buf,2); + buf[0] = sp->shp_fleet; + snxtitem(&ni, EF_SHIP, buf); + while(nxtitem(&ni,(s_char *)&ship)) + if ((ship.shp_fleet == buf[0]) && + (ship.shp_own == sp->shp_own)) { + if (ship.shp_uid == sp->shp_uid){ + retreat_ship1(sp,code,1); + if (sp->shp_rpath[0] == 0) + sp->shp_rflags = 0; + } else { + retreat_ship1(&ship,code,0); + getship(ship.shp_uid,&ship); + if (ship.shp_rpath[0] == 0){ + ship.shp_rflags = 0; + putship(ship.shp_uid,&ship); + } + } + } + } else { + retreat_ship1(sp,code,1); + if (sp->shp_rpath[0] == 0) + sp->shp_rflags = 0; + } +} + +int +retreat_ship1(struct shpstr *sp, s_char code, int orig) + + + /* Is this the originally scared ship, or a follower */ +{ + extern double techfact(int, double); + struct sctstr sect; + register int n; + register int m; + int max; + int dir; + coord newx; + coord newy; + coord dx; + coord dy; + int stopping; + int mines; + int shells; + double mobcost; + struct mchrstr *mcp; + int vec[I_MAX+1]; + int time_to_stop; + s_char buf[RET_LEN-1]; + + sp->shp_mission = 0; + if (sp->shp_own == 0) + return 0; + + if (isupper(code)) + code = tolower(code); + + n = 0; + if (sp->shp_effic < SHIP_MINEFF){ + wu(0, sp->shp_own, "%s %s,\nbut it died in the attack, and so couldn't retreat!\n", prship(sp), + conditions[findcondition(code)].desc[orig]); + if (!orig) putship(sp->shp_uid,sp); + return 0; + } + + if (opt_SAIL) { + /* can't retreat a ship that's sailin, bad things happend */ + if (*sp->shp_path){ + wu(0, sp->shp_own, "%s %s,\nbut had sailing orders, and couldn't retreat!\n", prship(sp), + conditions[findcondition(code)].desc[orig]); + if (!orig) putship(sp->shp_uid,sp); + return 0; + } + } + /* check crew - uws don't count */ + getvec(VT_ITEM, vec, (s_char *)sp, EF_SHIP); + if (vec[I_MILIT] == 0 && vec[I_CIVIL] == 0){ + wu(0, sp->shp_own, "%s %s,\nbut had no crew, and couldn't retreat!\n", prship(sp), + conditions[findcondition(code)].desc[orig]); + if (!orig) putship(sp->shp_uid,sp); + return 0; + } + + getsect(sp->shp_x,sp->shp_y,§); + switch (check_nav(§)) { + case CN_CONSTRUCTION: + wu(0, sp->shp_own, "%s %s,\nbut was caught in a construction zone, and couldn't retreat!\n", prship(sp), + conditions[findcondition(code)].desc[orig]); + if (!orig) putship(sp->shp_uid,sp); + return 0; + case CN_LANDLOCKED: + wu(0, sp->shp_own, "%s %s,\nbut was landlocked, and couldn't retreat!\n", prship(sp), + conditions[findcondition(code)].desc[orig]); + if (!orig) putship(sp->shp_uid,sp); + return 0; + /*NOTREACHED*/ + case CN_NAVIGABLE: + break; + case CN_ERROR: + default: + wu(0, sp->shp_own, "%s %s,\nbut was subject to an empire error, and couldn't retreat!\n", prship(sp), + conditions[findcondition(code)].desc[orig]); + if (!orig) putship(sp->shp_uid,sp); + return 0; + /*NOTREACHED*/ + } + + if (sp->shp_mobil <= 0.0) { + wu(0, sp->shp_own, "%s %s,\nbut had no mobility, and couldn't retreat!\n", prship(sp), + conditions[findcondition(code)].desc[orig]); + if (!orig) putship(sp->shp_uid,sp); + return 0; + } + + n=(-1*MAX_RETREAT); + stopping = 0; + time_to_stop = 0; + while ((!stopping) && n){ + dx = dy = 0; + if (sp->shp_rpath[0] == 0 || sp->shp_rpath[0] == 0){ + stopping=1; + continue; + } + if (sp->shp_mobil <= 0.0) { + wu(0, sp->shp_own, "%s %s,\nbut ran out of mobility, and couldn't retreat fully!\n", prship(sp), + conditions[findcondition(code)].desc[orig]); + if (!orig) putship(sp->shp_uid,sp); + return 0; + } + dir = chkdir(sp->shp_rpath[0], DIR_STOP, DIR_VIEW); + bzero(buf,RET_LEN-1); + bcopy(&sp->shp_rpath[1],buf,RET_LEN-1); + bzero(sp->shp_rpath,RET_LEN); + bcopy(buf,sp->shp_rpath,RET_LEN-1); + if (dir == -1) + continue; + if (dir == DIR_STOP) + stopping++; + else { + dx = diroff[dir][0]; + dy = diroff[dir][1]; + } + n++; + + mcp = &mchr[(int)sp->shp_type]; + newx = xnorm(sp->shp_x + dx); + newy = ynorm(sp->shp_y + dy); + mobcost = sp->shp_effic * 0.01 * sp->shp_speed; + mobcost = 480.0 / (mobcost + techfact(sp->shp_tech, mobcost)); + + getsect(newx, newy, §); + if (check_nav(§) != CN_NAVIGABLE || + (sect.sct_own && !player->owner && + getrel(getnatp(sect.sct_own), sp->shp_own) < FRIENDLY)) { + wu(0, sp->shp_own, "%s %s,\nbut could not retreat to %s!\n", prship(sp), + conditions[findcondition(code)].desc[orig], + xyas(newx, newy, sp->shp_own)); + if (!orig) putship(sp->shp_uid,sp); + return 0; + } + sp->shp_x = newx; + sp->shp_y = newy; + sp->shp_mobil -= mobcost; + if (stopping) + continue; + + mines = getvar(V_MINE, (s_char *)§, EF_SECTOR); + if ((mcp->m_flags & M_SWEEP) && mines > 0 && !player->owner) { + max = vl_find(V_SHELL, mcp->m_vtype, + mcp->m_vamt, (int) mcp->m_nv); + shells = getvar(V_SHELL, (s_char *)sp, EF_SHIP); + for (m=0; mines > 0 && m < 5; m++) { + if (chance(0.66)) { + mines--; + shells = min(max, shells + 1); + } + } + putvar(V_MINE, mines, (s_char *)§, EF_SECTOR); + putvar(V_SHELL, shells, (s_char *)sp, EF_SHIP); + putsect(§); + } + if (mines > 0 && !player->owner && + chance(DMINE_HITCHANCE(mines))) { + wu(0, sp->shp_own, "%s %s,\nand hit a mine in %s while retreating!\n", prship(sp), + conditions[findcondition(code)].desc[orig], + xyas(newx, newy, sp->shp_own)); + nreport(sp->shp_own, N_HIT_MINE, 0, 1); + m = MINE_DAMAGE(); + shipdamage(sp, m); + mines--; + putvar(V_MINE, mines, (s_char *)§, EF_SECTOR); + putsect(§); + if (sp->shp_effic < SHIP_MINEFF) + time_to_stop = 1; + if (!orig) putship(sp->shp_uid,sp); + return 0; + } + if (time_to_stop) + stopping = 1; + } + + if (orig) { + wu(0, sp->shp_own, "%s %s, and retreated to %s\n", prship(sp), + conditions[findcondition(code)].desc[orig], + xyas(sp->shp_x, sp->shp_y, sp->shp_own)); + }else{ + wu(0, sp->shp_own, "%s %s, and ended up at %s\n", + prship(sp), + conditions[findcondition(code)].desc[orig], + xyas(sp->shp_x, sp->shp_y, sp->shp_own)); + } + if (!orig) putship(sp->shp_uid,sp); + return 1; +} + +#if 0 +static int +check_nav(sect) + struct sctstr *sect; +{ + extern struct dchrstr dchr[]; + + switch (dchr[sect->sct_type].d_flg & 03) { + case NAVOK: + break; + + case NAV_02: + if (sect->sct_effic < 2) + return CN_CONSTRUCTION; + break; + case NAV_60: + if (sect->sct_effic < 60) + return CN_CONSTRUCTION; + break; + default: + return CN_LANDLOCKED; + } + return CN_NAVIGABLE; +} +#endif +int +findcondition(s_char code) +{ + int x; + + x=0; + while (conditions[x].code){ + if (conditions[x].code == code) + return(x); + x++; + } + + return(x); +} + +int +check_retreat_and_do_landdamage(struct lndstr *lp, int dam) +{ + if (dam <=0) + return 0; + + landdamage(lp,dam); + if (lp->lnd_rflags & RET_INJURED) + retreat_land(lp, 'i'); + + return 1; +} + +void +retreat_land(struct lndstr *lp, s_char code) +{ + struct nstr_item ni; + struct lndstr land; + s_char buf[2]; + + if (lp->lnd_rflags & RET_GROUP){ + bzero(buf,2); + buf[0] = lp->lnd_army; + snxtitem(&ni, EF_SHIP, buf); + while(nxtitem(&ni,(s_char *)&land)) + if ((land.lnd_army == buf[0]) && + (land.lnd_own == lp->lnd_own)) { + if (land.lnd_uid == lp->lnd_uid){ + retreat_land1(lp,code,1); + if (lp->lnd_rpath[0] == 0) + lp->lnd_rflags = 0; + }else{ + retreat_land1(&land,code,0); + getland(land.lnd_uid,&land); + if (land.lnd_rpath[0] == 0){ + land.lnd_rflags = 0; + putland(land.lnd_uid,&land); + } + } + } + }else{ + retreat_land1(lp,code,1); + if (lp->lnd_rpath[0] == 0) + lp->lnd_rflags = 0; + } +} + +int +retreat_land1(struct lndstr *lp, s_char code, int orig) + + + /* Is this the originally scared unit, or a follower */ +{ + extern double techfact(int, double); + struct sctstr sect; + register int n; + register int m; + int max; + int dir; + coord newx; + coord newy; + coord dx; + coord dy; + int stopping; + int mines; + int shells; + double mobcost; + struct lchrstr *lcp; + int time_to_stop; + s_char buf[RET_LEN-1]; + + lp->lnd_mission = 0; + if (lp->lnd_own == 0) + return 0; + + if (isupper(code)) + code = tolower(code); + + n = 0; + if (lp->lnd_effic < LAND_MINEFF){ + wu(0, lp->lnd_own, "%s %s,\nbut it died in the attack, and so couldn't retreat!\n", prland(lp), + conditions[findcondition(code)].desc[orig]); + if (!orig) putland(lp->lnd_uid,lp); + return 0; + } + + getsect(lp->lnd_x,lp->lnd_y,§); + + if (lp->lnd_mobil <= 0.0) { + wu(0, lp->lnd_own, "%s %s,\nbut had no mobility, and couldn't retreat!\n", + prland(lp), + conditions[findcondition(code)].desc[orig]); + if (!orig) putland(lp->lnd_uid,lp); + return 0; + } + + n=(-1*MAX_RETREAT); + stopping = 0; + time_to_stop = 0; + while ((!stopping) && n){ + dx = dy = 0; + if (lp->lnd_rpath[0] == 0 || lp->lnd_rpath[0] == 0){ + stopping=1; + continue; + } + if (lp->lnd_mobil <= 0.0) { + wu(0, lp->lnd_own, "%s %s,\nbut ran out of mobility, and couldn't retreat fully!\n", + prland(lp), + conditions[findcondition(code)].desc[orig]); + if (!orig) putland(lp->lnd_uid,lp); + return 0; + } + dir = chkdir(lp->lnd_rpath[0], DIR_STOP, DIR_VIEW); + bzero(buf,RET_LEN-1); + bcopy(&lp->lnd_rpath[1],buf,RET_LEN-1); + bzero(lp->lnd_rpath,RET_LEN); + bcopy(buf,lp->lnd_rpath,RET_LEN-1); + if (dir == -1) + continue; + if (dir == DIR_STOP) + stopping++; + else { + dx = diroff[dir][0]; + dy = diroff[dir][1]; + } + n++; + + lcp = &lchr[(int)lp->lnd_type]; + newx = xnorm(lp->lnd_x + dx); + newy = ynorm(lp->lnd_y + dy); + + getsect(newx, newy, §); + if ((sect.sct_type == SCT_WATER) || + (sect.sct_type == SCT_MOUNT) || + (sect.sct_type == SCT_SANCT) || + (sect.sct_type == SCT_WASTE) || + (sect.sct_own != lp->lnd_own)){ + wu(0, lp->lnd_own, "%s %s,\nbut could not retreat to %s!\n", + prland(lp), + conditions[findcondition(code)].desc[orig], + xyas(newx, newy, lp->lnd_own)); + if (!orig) putland(lp->lnd_uid,lp); + return 0; + } + mobcost = lnd_mobcost(lp, §, MOB_ROAD); + lp->lnd_x = newx; + lp->lnd_y = newy; + lp->lnd_mobil -= mobcost; + if (stopping) + continue; + + mines = getvar(V_MINE, (s_char *)§, EF_SECTOR); + if ((lcp->l_flags & L_ENGINEER) && mines > 0 && + (sect.sct_oldown != lp->lnd_own)){ + max = vl_find(V_SHELL, lcp->l_vtype, + lcp->l_vamt, (int) lcp->l_nv); + shells = getvar(V_SHELL, (s_char *)lp, EF_LAND); + for (m=0; mines > 0 && m < 5; m++) { + if (chance(0.66)) { + mines--; + shells = min(max, shells + 1); + } + } + putvar(V_MINE, mines, (s_char *)§, EF_SECTOR); + putvar(V_SHELL, shells, (s_char *)lp, EF_LAND); + putsect(§); + } + if (mines > 0 && (sect.sct_oldown != lp->lnd_own) && + chance(DMINE_HITCHANCE(mines))) { + wu(0, lp->lnd_own, "%s %s,\nand hit a mine while retreating!\n", + prland(lp), + conditions[findcondition(code)].desc[orig], + xyas(newx, newy, lp->lnd_own)); + nreport(lp->lnd_own, N_LHIT_MINE, 0, 1); + m = MINE_LDAMAGE(); + landdamage(lp, m); + mines--; + putvar(V_MINE, mines, (s_char *)§, EF_SECTOR); + putsect(§); + if (lp->lnd_effic < LAND_MINEFF) + time_to_stop = 1; + if (!orig) putland(lp->lnd_uid,lp); + return 0; + } + if (time_to_stop) + stopping = 1; + } + + if (orig){ + wu(0, lp->lnd_own, "%s %s, and retreated to %s\n", + prland(lp), + conditions[findcondition(code)].desc[orig], + xyas(lp->lnd_x, lp->lnd_y, lp->lnd_own)); + }else{ + wu(0, lp->lnd_own, "%s %s, and ended up at %s\n", + prland(lp), + conditions[findcondition(code)].desc[orig], + xyas(lp->lnd_x, lp->lnd_y, lp->lnd_own)); + } + if (!orig) putland(lp->lnd_uid,lp); + return 1; +} diff --git a/src/lib/subs/sarg.c b/src/lib/subs/sarg.c new file mode 100644 index 00000000..128a03f8 --- /dev/null +++ b/src/lib/subs/sarg.c @@ -0,0 +1,228 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * sarg.c: Parse selection arguments + * + * Known contributors to this file: + * Dave Pare, 1989 + */ + +#include +#include "misc.h" +#include "player.h" +#include "xy.h" +#include "nsc.h" +#include "sect.h" +#include "nat.h" +#include "deity.h" +#include "file.h" +#include "prototypes.h" +#include "optlist.h" + +/* + * returns one of + * + * #1, lx:ly,hx:hy --> NS_AREA + * @x,y:dist --> NS_DIST + * %d or %d/%d/%d --> NS_LIST + * * --> NS_ALL + * + * or 0 for none of the above. + */ +int +sarg_type(s_char *ptr) +{ + int c; + + c = *ptr; + if (c == '@') + return NS_DIST; + if (c == '*') + return NS_ALL; + if (c == '#' || index(ptr, ',') != 0) + return NS_AREA; + if (isdigit(c)) + return NS_LIST; + if (c == '~' || isupper(c) || islower(c)) + return NS_GROUP; + return 0; +} + +int +sarg_xy(s_char *ptr, coord *xp, coord *yp) +{ + if (sarg_type(ptr) != NS_AREA) + return 0; + *xp = atoip(&ptr); + if (*ptr++ != ',') + return 0; + if (!isdigit(*ptr) && *ptr != '-') + return 0; + *yp = atoi(ptr); + inputxy(xp, yp, player->cnum); + if ((*xp ^ *yp) & 01) + return 0; + return 1; +} + +/* returns absolute coords */ +int +sarg_getrange(s_char *buf, register struct range *rp) +{ + register int rlm; + register int c; + struct natstr *np; + s_char *bp; + + bp = buf; + c = *bp; + if (c == '#') { + /* + * realm #X where (X > 0 && X < MAXNOR) + * Assumes realms are in abs coordinates + */ + bp++; + rlm = atoi(bp); + if (rlm < 0 || rlm >= MAXNOR) + return 0; + np = getnatp(player->cnum); + rp->lx = np->nat_b[rlm].b_xl; + rp->hx = np->nat_b[rlm].b_xh; + rp->ly = np->nat_b[rlm].b_yl; + rp->hy = np->nat_b[rlm].b_yh; + } else { + /* + * full map specification + * LX:LY,HX:HY where + * ly, hy are optional. + */ + if (!isdigit(c) && c != '-') + return 0; + rp->lx = rp->hx = atoip(&bp); + if (*bp == ':') { + bp++; + rp->hx = atoip(&bp); + } + if (*bp++ != ',') + return 0; + if (!isdigit(c) && c != '-') + return 0; + rp->ly = rp->hy = atoip(&bp); + if (*bp == ':') { + bp++; + rp->hy = atoip(&bp); + } + inputxy(&rp->lx, &rp->ly, player->cnum); + inputxy(&rp->hx, &rp->hy, player->cnum); + } + xysize_range(rp); + return 1; +} + +/* + * translate #1 or lx:ly,hx:hy into + * a result range struct + */ +int +sarg_area(s_char *buf, register struct range *rp) +{ + if (!sarg_getrange(buf, rp)) + return 0; + rp->hx += 1; + if (rp->hx >= WORLD_X) + rp->hx = 0; + rp->hy += 1; + if (rp->hy >= WORLD_Y) + rp->hy = 0; + xysize_range(rp); + return 1; +} + +/* + * translate @x,y:int into + * result params + */ +int +sarg_range(s_char *buf, coord *xp, coord *yp, int *dist) +{ + s_char *bp; + + bp = buf; + if (bp == 0 || *bp == 0) + return 0; + if (*bp++ != '@') + return 0; + *xp = atoip(&bp); + if (*bp++ != ',') + return 0; + *yp = atoip(&bp); + if (*bp++ != ':') + return 0; + inputxy(xp, yp, player->cnum); + *dist = atoi(bp); + return 1; +} + +/* + * list of idents; id/id/id/id/id + */ +int +sarg_list(s_char *str, register int *list, int max) +{ + register int i; + register int j; + register int n; + s_char *arg; + + arg = str; + for (i=0; icnum), + eff, range); + bzero(noise, sizeof(noise)); + if (eff < 100) { + pr("Some noise on the transmission...\n"); + for (n = 0; n < (100 - eff); ++n) + noise[100 * n / (100 - eff)] = 1; + } + + /* Have to convert to player coords, since it gets converted + back from there */ + sprintf(selection, "@%s:%d", xyas(x, y, player->cnum), range); + + if (type == EF_BAD || type == EF_SECTOR) { + if (type == EF_SECTOR) /* Use ?conditionals */ + snxtsct(&ns, selection); + else + snxtsct_dist(&ns, x, y, range); + + blankfill((s_char *)radbuf, &ns.range, 1); + if (flags & P_S) { + pr("Satellite sector report\n"); + prdate(); + sathead(); + acc = (flags & P_I) ? 5 : 50; + } + crackle = count = 0; + while (nxtsct(&ns, §)) { + if (++crackle == 100) + crackle = 0; + if (noise[crackle]) + continue; + if (flags & P_S) { + if (sect.sct_type > SCT_RURAL) { + satdisp(§, acc,0); + ++count; + } + if (opt_HIDDEN) { + setcont(player->cnum, sect.sct_own, FOUND_FLY); + } + } + if ((flags & P_I) || + sect.sct_type == SCT_WATER || + sect.sct_type == SCT_MOUNT) { + rad[ns.dy][ns.dx] = dchr[sect.sct_type].d_mnem; + } else + rad[ns.dy][ns.dx] = '?'; + changed += map_set(player->cnum, ns.x, ns.y, rad[ns.dy][ns.dx],0); + } + if (changed) + writemap(player->cnum); + if (flags & P_S) + pr(" %d sectors\n\n", count); + } + + if ((type == EF_BAD || type == EF_SHIP) && + (flags & P_S || flags & P_I)) { + if (type == EF_SHIP) + snxtitem(&ni, EF_SHIP, selection); + else + snxtitem_dist(&ni, EF_SHIP, x, y, range); + + crackle = count = 0; + if (flags & P_S) { + pr("Satellite ship report\n"); + prdate(); + if (opt_SHIPNAMES) { + pr(" own shp# ship type sector eff\n"); + } else { + pr(" own shp# ship type sector eff\n"); + } + } + while (nxtitem(&ni, (caddr_t)&ship)) { + if (ship.shp_own == 0) + continue; + if ((mchr[(int)ship.shp_type].m_flags & M_SUB) && + ((flags & (P_S|P_I)) != (P_S|P_I))) + continue; + if (++crackle == 100) + crackle = 0; + if (noise[crackle]) + continue; + if (flags & P_S) { + pr("%4d %4d %-16.16s ", + ship.shp_own, ship.shp_uid, + mchr[(int)ship.shp_type].m_name); + if (opt_SHIPNAMES) + pr("%-25.25s ", ship.shp_name); + prxy("%4d,%-4d ", ship.shp_x, ship.shp_y, + player->cnum); + pr("%3d%%\n", ship.shp_effic); + ++count; + if (opt_HIDDEN) { + setcont(player->cnum, ship.shp_own, FOUND_FLY); + } + } + /* If we are imaging *and* drawing the map */ + if ((flags & P_I) && (type == EF_BAD)) { + /* Figure out where to put the ship */ + /* First, figure out the distance from the two */ + rx = diffx((int)ship.shp_x, x); + ry = diffy((int)ship.shp_y, y); + /* Next, determine which direction to add it to the center */ + /* We can only do this if imaging and we have gotten the center + up above by imaging the sectors. */ + rx = deltax(x, ns.range.lx) + rx; + ry = deltay(y, ns.range.ly) + ry; + /* &~0x20 makes it a cap letter */ + rad[ry][rx] = (*mchr[(int)ship.shp_type].m_name) & ~0x20; + } + } + if (flags & P_S) + pr(" %d ships\n\n", count); + } + + if ((type == EF_BAD || type == EF_LAND) && + (flags & P_S || flags & P_I)) { + if (type == EF_LAND) + snxtitem(&ni, EF_LAND, selection); + else + snxtitem_dist(&ni, EF_LAND, x, y, range); + + crackle = count = 0; + if (flags & P_S) { + pr("Satellite unit report\n"); + prdate(); + pr(" own lnd# unit type sector eff\n"); + } + while (nxtitem(&ni, (caddr_t)&land)) { + if (land.lnd_own == 0) + continue; + if (!chance((double)land.lnd_effic/20.0)) + continue; + if (++crackle == 100) + crackle = 0; + if (noise[crackle]) + continue; + if (flags & P_S) { + pr("%4d %4d %-16.16s ", + land.lnd_own, land.lnd_uid, + lchr[(int)land.lnd_type].l_name); + prxy("%4d,%-4d", land.lnd_x, land.lnd_y, + player->cnum); + pr("%3d%%\n", land.lnd_effic); + ++count; + } + /* If we are imaging *and* drawing the map */ + if ((flags & P_I) && (type == EF_BAD)) { + /* Figure out where to put the unit */ + /* First, figure out the distance from the two */ + rx = diffx((int)land.lnd_x, x); + ry = diffy((int)land.lnd_y, y); + /* Next, determine which direction to add it to the center */ + /* We can only do this if imaging and we have gotten the center + up above by imaging the sectors. */ + rx = deltax(x, ns.range.lx) + rx; + ry = deltay(y, ns.range.ly) + ry; + /* &~0x20 makes it a cap letter */ + rad[ry][rx] = (*lchr[(int)land.lnd_type].l_name) & ~0x20; + } + } + if (flags & P_S) + pr(" %d units\n\n", count); + } + + /* Ok, have we made the map? If so, display it */ + if (type == EF_BAD) { + /* + * print out the map + * We have to make the center a '0' for ve + * ve needs a garbage line to terminate the map + */ + rad[deltay(y, ns.range.ly)][deltax(x, ns.range.lx)] = '0'; + + pr("Satellite radar report\n"); +#ifdef HAY + /* This is wrong for small, hitech worlds. */ + n = deltay(ns.range.hy, ns.range.ly); +#else + /* This is already available, so why not use it. */ + n = ns.range.height; +#endif + for (row=0; row < n; row++) + pr("%s\n", rad[row]); + pr("\n(c) 1989 Imaginative Images Inc.\n"); + } +} + +void +sathead(void) +{ +pr(" sct rd rl def\n"); +pr(" sect type own eff eff eff eff civ mil shl gun iron pet food\n"); +} + +void +satdisp(struct sctstr *sp, int acc, int showstuff) +{ + int vec[I_MAX+1], first; + struct nstr_item ni; + struct shpstr ship; + struct lndstr land; + + if (getvec(VT_ITEM, vec, (caddr_t)sp, EF_SECTOR) < 0) + return; + prxy("%4d,%-4d ", sp->sct_x, sp->sct_y, player->cnum), + pr("%c %3d %3d %3d %3d %3d %4d %4d %4d %4d %4d %4d %5d\n", + dchr[sp->sct_type].d_mnem, + sp->sct_own, roundintby((int)sp->sct_effic, acc / 2), + roundintby((int)sp->sct_road, acc / 2), + roundintby((int)sp->sct_rail, acc / 2), + roundintby((int)sp->sct_defense, acc / 2), + roundintby(vec[I_CIVIL], acc), roundintby(vec[I_MILIT], acc), + roundintby(vec[I_SHELL], acc), roundintby(vec[I_GUN], acc), + roundintby(vec[I_IRON], acc), roundintby(vec[I_PETROL], acc), + roundintby(vec[I_FOOD], acc)); + map_set(player->cnum, sp->sct_x, sp->sct_y, dchr[sp->sct_type].d_mnem, 0); + if (!showstuff) + return; + snxtitem_xy(&ni, EF_SHIP, sp->sct_x, sp->sct_y); + first=1; + while (nxtitem(&ni, (caddr_t)&ship)) { + if (ship.shp_own == 0) + continue; + if (mchr[(int)ship.shp_type].m_flags & M_SUB) + continue; + if (first){ + if (opt_SHIPNAMES) { +pr("\t own shp# ship type sector eff\n"); + } else { +pr("\t own shp# ship type sector eff\n"); + } + first=0; + } + pr("\t%4d %4d %-16.16s ", ship.shp_own, ship.shp_uid, + mchr[(int)ship.shp_type].m_name); + if (opt_SHIPNAMES) + pr("%-25.25s ", ship.shp_name); + prxy("%4d,%-4d ", ship.shp_x, ship.shp_y, player->cnum); + pr("%3d%%\n", ship.shp_effic); + } + + if (!first) + pr("\n"); + + snxtitem_xy(&ni, EF_LAND, sp->sct_x, sp->sct_y); + first=1; + + while (nxtitem(&ni, (caddr_t)&land)) { + if (land.lnd_own == 0) + continue; + if (!chance((double)land.lnd_effic/20.0)) + continue; + + if (first){ + pr("\t own lnd# unit type sector eff\n"); + first=0; + } + + pr("\t%4d %4d %-16.16s ",land.lnd_own, land.lnd_uid, + lchr[(int)land.lnd_type].l_name); + prxy("%4d,%-4d ",land.lnd_x, land.lnd_y, player->cnum); + pr("%3d%%\n", land.lnd_effic); + } + + if (!first) + pr("\n"); +} + diff --git a/src/lib/subs/sect.c b/src/lib/subs/sect.c new file mode 100644 index 00000000..2d723e11 --- /dev/null +++ b/src/lib/subs/sect.c @@ -0,0 +1,168 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * sect.c: Sector pre-write and post-read data massage + * + * Known contributors to this file: + * Dave Pare, 1989 + * Steve McClure, 1996 + */ + +#include "misc.h" +#include "player.h" +#include "var.h" +#include "sect.h" +#include "xy.h" +#include "nat.h" +#include "deity.h" +#include "file.h" +#include "land.h" +#include "nsc.h" +#include "plane.h" +#include "prototypes.h" +#include "optlist.h" + +static void give_back_cap(struct sctstr *sp); + +/*ARGSUSED*/ +int +sct_postread(int id, s_char *ptr) +{ + struct sctstr *sp = (struct sctstr *) ptr; + + checksect(sp); + player->owner = (player->god || sp->sct_own == player->cnum); + if (opt_MOB_ACCESS) + sct_do_upd_mob(sp); + return 1; +} + +/*ARGSUSED*/ +int +sct_prewrite(int id, s_char *ptr) +{ + struct sctstr *sp = (struct sctstr *) ptr; + struct sctstr sect; + + time(&sp->sct_timestamp); + + checksect(sp); + getsect(sp->sct_x, sp->sct_y, §); + return 1; +} + +int +checksect(struct sctstr *sp) +{ + int mil, civs, loyalcivs; + + /* shouldn't happen, but... */ + if (sp->sct_mobil > 127) + sp->sct_mobil = 0; + + mil = getvar(V_MILIT, (s_char *)sp, EF_SECTOR); + civs = getvar(V_CIVIL, (s_char *)sp, EF_SECTOR); + if (sp->sct_own == sp->sct_oldown) + loyalcivs = civs; + else + loyalcivs = 0; + + if (sp->sct_effic < 20) { + if (sp->sct_type == SCT_BSPAN) + knockdown(sp, 0); + else if (sp->sct_type == SCT_BTOWER) { + knockdown(sp, 0); + bridgefall(sp, 0); + } + } + if (sp->sct_own != 0 && !civs) { + sp->sct_work = 100; + sp->sct_oldown = sp->sct_own; + } + /* If they have a military unit there, they still own it */ + if (sp->sct_own && !loyalcivs && !(sp->sct_flags & MOVE_IN_PROGRESS)) { + if (!mil && !has_units(sp->sct_x,sp->sct_y,sp->sct_own,0)) { + /* more cruft! */ + if (sp->sct_type == SCT_CAPIT || + sp->sct_type == SCT_MOUNT) + caploss(sp, sp->sct_own, ""); + + if (sp->sct_oldown == sp->sct_own) { + makelost(EF_SECTOR, sp->sct_own, 0, sp->sct_x, sp->sct_y); + sp->sct_own = 0; + sp->sct_oldown = 0; + } else { + /* if oldown gets his cap back make agri */ + if (sp->sct_oldown && + player->cnum == sp->sct_own && + sp->sct_type == SCT_CAPIT && + sp->sct_newtype == SCT_CAPIT) + give_back_cap(sp); + takeover(sp, sp->sct_oldown); + } + sp->sct_mobil = 0; + } + } + if (!opt_DEFENSE_INFRA) + sp->sct_defense = sp->sct_effic; + return 1; +} + +int +issector(s_char *arg) +{ + s_char c; + + while (0 != (c = *arg++)) + if (!isdigit(c) && !isspace(c) && (c != '/')) + return 1; + + return 0; +} + +static void +give_back_cap(struct sctstr *sp) +{ + struct natstr *natp = getnatp(sp->sct_oldown); + + if (xrel(natp,natp->nat_xcap) == xrel(natp,sp->sct_x) && + yrel(natp,natp->nat_ycap) == yrel(natp,sp->sct_y)) { + sp->sct_newtype = SCT_AGRI; + } +} + +void +sct_init(coord x, coord y, s_char *ptr) +{ + struct sctstr *sp = (struct sctstr *) ptr; + + sp->ef_type = EF_SECTOR; + sp->sct_x = x; + sp->sct_y = y; + sp->sct_dist_x = x; + sp->sct_dist_y = y; +} diff --git a/src/lib/subs/ship.c b/src/lib/subs/ship.c new file mode 100644 index 00000000..71fb2a78 --- /dev/null +++ b/src/lib/subs/ship.c @@ -0,0 +1,134 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * ship.c: Ship pre-write data massage + * + * Known contributors to this file: + * Dave Pare, 1989 + * Steve McClure, 1996 + */ + +#include "misc.h" +#include "player.h" +#include "var.h" +#include "xy.h" +#include "file.h" +#include "nat.h" +#include "ship.h" +#include "deity.h" +#include "land.h" +#include "plane.h" +#include "nsc.h" +#include "prototypes.h" +#include "optlist.h" + +/*ARGSUSED*/ +int +shp_postread(int n, s_char *ptr) +{ + struct shpstr *sp = (struct shpstr *)ptr; + + if (sp->shp_uid != n) { + logerror("shp_postread: Error - %d != %d, zeroing.\n", sp->shp_uid, n); + bzero(ptr, sizeof(struct shpstr)); + } + + if (opt_MOB_ACCESS) + shp_do_upd_mob(sp); + player->owner = (player->god || sp->shp_own == player->cnum); + return 1; +} + +int +shp_prewrite(int n, s_char *ptr) +{ + struct shpstr *sp = (struct shpstr *) ptr; + struct shpstr ship; + struct lndstr *lp; + struct plnstr *pp; + int i; + + sp->ef_type = EF_SHIP; + sp->shp_uid = n; + + time(&sp->shp_timestamp); + + if (sp->shp_own != 0 && sp->shp_effic < SHIP_MINEFF) { + mpr(sp->shp_own, "\t%s sunk!\n", prship(sp)); + makelost(EF_SHIP, sp->shp_own, sp->shp_uid, sp->shp_x, sp->shp_y); + sp->shp_own = 0; + + getship(n, &ship); + + for (i = 0; NULL != (lp = getlandp(i)); i++) { + if (lp->lnd_own && lp->lnd_ship == n) { + mpr(lp->lnd_own, "%s sunk!\n", prland(lp)); + makelost(EF_LAND, lp->lnd_own, lp->lnd_uid, lp->lnd_x, lp->lnd_y); + lp->lnd_own = 0; + lp->lnd_effic = 0; + lp->lnd_ship = -1; + lp->lnd_land = -1; + putland(lp->lnd_uid, lp); + } + } + for (i = 0; NULL != (pp = getplanep(i)); i++) { + if (pp->pln_own && pp->pln_ship == n) { + mpr(pp->pln_own, "%s sunk!\n", prplane(pp)); + makelost(EF_PLANE, pp->pln_own, pp->pln_uid, pp->pln_x, pp->pln_y); + pp->pln_own = 0; + pp->pln_effic = 0; + pp->pln_ship = -1; + pp->pln_land = -1; + putplane(pp->pln_uid, pp); + } + } + } else + getship(n, &ship); + + return 1; +} + +void +shp_init(int n, s_char *ptr) +{ + struct shpstr *sp = (struct shpstr *) ptr; + + sp->ef_type = EF_SHIP; + sp->shp_uid = n; + sp->shp_own = 0; +} + +s_char * +prship(struct shpstr *sp) +{ + if (opt_SHIPNAMES) { + return prbuf("%s %s(#%d)", + mchr[(int)sp->shp_type].m_name, sp->shp_name, sp->shp_uid); + } else { + return prbuf("%s #%d", mchr[(int)sp->shp_type].m_name, sp->shp_uid); + } +} diff --git a/src/lib/subs/show.c b/src/lib/subs/show.c new file mode 100644 index 00000000..dba03716 --- /dev/null +++ b/src/lib/subs/show.c @@ -0,0 +1,786 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * show.c: General show routines + * + * Known contributors to this file: + * Julian Onions, 1988 + * Jeff Bailey, 1990 + * Steve McClure, 1996 + */ + +/* + * general routines that are callable to give info on things. + * currently, planes, ships, nukes and bridges. Tanks & regiments one day? + * + * Added nuke_flags to be consistent. Jeff Bailey 12/15/90 + * (bailey@mcs.kent.edu) + */ + +#include "misc.h" +#include "player.h" +#include "nuke.h" +#include "var.h" +#include "ship.h" +#include "land.h" +#include "item.h" +#include "plane.h" +#include "sect.h" +#include "optlist.h" +#include "file.h" +#include "nat.h" +#include "prototypes.h" + +double sqrt(double); +double logx(double, double); + +/* + * This cruft really belongs in the empglb.c file. + * Yuck. + */ + +struct lookup { + int key; + s_char *value; +}; + +struct lookup ship_flags[] = { + { M_FOOD, "fish" }, + { M_TORP, "torp" }, + { M_DCH, "dchrg" }, + { M_FLY, "plane" }, + { M_MSL, "miss" }, + { M_OIL, "oil" }, + { M_SONAR, "sonar" }, + { M_MINE, "mine" }, + { M_SWEEP, "sweep" }, + { M_SUB, "sub" }, + { M_SPY, "spy" }, + { M_LAND, "land" }, + { M_SUBT, "sub-torp" }, + { M_TRADE, "trade" }, + { M_SEMILAND, "semi-land" }, + { M_OILER, "oiler" }, + { M_SUPPLY, "supply" }, + { M_ANTIMISSILE, "anti-missile" }, + { 0, 0 } +}; + +struct lookup land_flags[] = { + { L_XLIGHT, "xlight" }, + { L_ENGINEER, "engineer" }, + { L_SUPPLY, "supply" }, + { L_SECURITY, "security" }, + { L_LIGHT, "light" }, + { L_MARINE, "marine" }, + { L_RECON, "recon" }, + { L_RADAR, "radar" }, + { L_ASSAULT, "assault" }, + { L_FLAK, "flak" }, + { L_SPY, "spy" }, + { L_TRAIN, "train" }, + { L_HEAVY, "heavy" }, + { 0, 0 } +}; + + +struct lookup plane_flags[] = { + { P_T, "tactical" }, + { P_B, "bomber" }, + { P_F, "intercept" }, + { P_C, "cargo" }, + { P_V, "VTOL" }, + { P_M, "missile" }, + { P_L, "light" }, + { P_S, "spy" }, + { P_I, "image" }, + { P_O, "satellite" }, + { P_X, "stealth" }, + { P_N, "SDI" }, + { P_H, "half-stealth" }, + { P_E, "x-light" }, + { P_K, "helo" }, + { P_A, "ASW" }, + { P_P, "para" }, + { P_ESC, "escort" }, + { P_MINE, "mine" }, + { P_SWEEP, "sweep" }, + { P_MAR, "marine" }, + { 0, 0 } +}; + +struct lookup nuke_flags[] = { + { N_NEUT, "neutron" }, + { 0, 0 } +}; + +struct look_list { + union { + struct lchrstr *lp; + struct plchrstr *pp; + struct mchrstr *mp; + int value; + } l_u; + int tech; +} lookup_list[200]; /* Change this if there are ever more than 200 planes, ships + or land units. */ +static int lookup_list_cnt = 0; + +void +sort_lookup_list(void) +{ + struct natstr *np = getnatp(player->cnum); + struct look_list tmp; + int i; + int j; + + if (!(np->nat_flags & NF_TECHLISTS)) + return; + for (i = 0; i < lookup_list_cnt; i++) { + for (j = i; j < lookup_list_cnt; j++) { + if (lookup_list[j].tech < lookup_list[i].tech) { + tmp = lookup_list[j]; + lookup_list[j] = lookup_list[i]; + lookup_list[i] = tmp; + } + } + } +} + +static +void +make_new_list(int tlev, int type) +{ + struct plchrstr *pp; + struct lchrstr *lp; + struct mchrstr *mp; + int count; + + lookup_list_cnt = 0; + if (type == EF_PLANE) { + for (pp = plchr, count = 0; count < pln_maxno; count++, pp++) { + if (pp->pl_tech > tlev) + continue; + if (pp->pl_name == 0 || pp->pl_name[0] == '\0') + continue; + lookup_list[lookup_list_cnt].l_u.pp = pp; + lookup_list[lookup_list_cnt].tech = pp->pl_tech; + lookup_list_cnt++; + } + } else if (type == EF_SHIP) { + for (mp = mchr, count = 0; count < shp_maxno; count++, mp++) { + if (mp->m_tech > tlev) + continue; + if (mp->m_name == 0 || mp->m_name[0] == '\0') + continue; + lookup_list[lookup_list_cnt].l_u.mp = mp; + lookup_list[lookup_list_cnt].tech = mp->m_tech; + lookup_list_cnt++; + } + } else if (type == EF_LAND) { + for (lp = lchr, count = 0; count < lnd_maxno; count++, lp++) { + if (lp->l_tech > tlev) + continue; + if (lp->l_name == 0 || lp->l_name[0] == '\0') + continue; + lookup_list[lookup_list_cnt].l_u.lp = lp; + lookup_list[lookup_list_cnt].tech = lp->l_tech; + lookup_list_cnt++; + } + } else + return; + + sort_lookup_list(); +} + +static +s_char * +lookup(int key, struct lookup *table) +{ + int match; + + if ((match = intmatch(key, &table->key, sizeof(*table))) < 0) + return 0; + return table[match].value; +} + +void +show_bridge(int tlev) +{ + extern double buil_bt, buil_bc; + extern int buil_bh; + + if (tlev < buil_bt) + return; + pr("Bridges require %g tech,", buil_bt); + if (!opt_NO_HCMS) + pr(" %d hcm,", buil_bh); + else if (!opt_NO_LCMS) + pr(" %d lcm,", buil_bh); + pr(" %d workers,\n", buil_bh * 2); + pr("%d available workforce, and cost $%g\n", + 1 + (buil_bh * 40 / 100), buil_bc); +} + +void +show_tower(int tlev) +{ + extern double buil_tower_bt, buil_tower_bc; + extern int buil_tower_bh; + + if (tlev < buil_tower_bt) + return; + pr("Bridge Towers require %g tech,", buil_tower_bt); + if (!opt_NO_HCMS) + pr(" %d hcm,", buil_tower_bh); + else if (!opt_NO_LCMS) + pr(" %d lcm,", buil_tower_bh); + pr(" %d workers,\n", buil_tower_bh * 2); + pr("%d available workforce, and cost $%g\n", + 1 + (buil_tower_bh * 40 / 100), buil_tower_bc); +} + +void +show_nuke_stats(int tlev) +{ + show_nuke_capab(tlev); +} + +void +show_nuke_build(int tlev) +{ + register struct nchrstr *np; + register int n; + register int avail; + extern float drnuke_const; + + if (opt_DRNUKE) + pr("%13s lcm hcm oil rad avail tech res $\n", ""); + else + pr("%13s lcm hcm oil rad avail tech $\n", ""); + + if (opt_NONUKES) + return; + for (np = nchr, n = 0; n < N_MAXNUKE; np++, n++) { + avail = (4 + np->n_rad + np->n_oil + np->n_lcm + np->n_hcm * 2)/5; + if (np->n_tech > tlev) + continue; + if (np->n_name == 0 || np->n_name[0] == '\0') + continue; + if (opt_NEUTRON == 0 && (np->n_flags & N_NEUT)) + continue; + if (opt_DRNUKE) + pr("%-13.13s %3d %3d %4d %4d %5d %4d %3d $%6d\n", + np->n_name, np->n_lcm, np->n_hcm, np->n_oil, + np->n_rad, avail, np->n_tech, + (int)(np->n_tech*drnuke_const)+1, + np->n_cost); + else /* not DRNUKE */ + pr("%-13.13s %3d %3d %4d %4d %5d %4d $%6d\n", + np->n_name, np->n_lcm, np->n_hcm, np->n_oil, + np->n_rad, avail, np->n_tech, np->n_cost); + } +} + +void +show_nuke_capab(int tlev) +{ + register struct nchrstr *np; + register int i,j,n; + s_char *p; + extern float drnuke_const; + + if (opt_DRNUKE) + pr("%13s blst dam lbs tech res $%7s abilities\n", "",""); + else + pr("%13s blst dam lbs tech $%7s abilities\n", "",""); + + if (opt_NONUKES) + return; + for (np = nchr, n = 0; n < N_MAXNUKE; np++, n++) { + if (np->n_tech > tlev) + continue; + if (opt_NEUTRON == 0 && (np -> n_flags & N_NEUT)) + continue; + if (np->n_name == 0 || np->n_name[0] == '\0') + continue; + if (opt_DRNUKE) + pr("%-13.13s %4d %3d %3d %4d %3d $%7d ", + np->n_name, np->n_blast, np->n_dam, + np->n_weight, np->n_tech, + (int)(np->n_tech * drnuke_const)+1, + np->n_cost); + else /* not DRNUKE */ + pr("%-13.13s %4d %3d %3d %4d $%7d ", + np->n_name, np->n_blast, np->n_dam, + np->n_weight, np->n_tech, np->n_cost); + + for (i = j = 0; i < 32; i++) { + if (!(np->n_flags & bit(i))) + continue; + if (NULL != (p = lookup(bit(i), nuke_flags))) { + if (j++ > 0) + pr(" "); + pr(p); + } + } + pr("\n"); + } +} + +void +show_ship_build(int tlev) +{ + register struct mchrstr *mp; + register int n; + + pr("%25s lcm hcm avail tech $\n", ""); + make_new_list(tlev, EF_SHIP); + for (n = 0; n < lookup_list_cnt; n++) { + mp = (struct mchrstr *)lookup_list[n].l_u.mp; + /* Can't show trade ships unless it's turned on */ + if ((mp->m_flags & M_TRADE) && !opt_TRADESHIPS) + continue; + + pr("%-25.25s %3d %3d %5d %4d $%d\n", + mp->m_name, mp->m_lcm, mp->m_hcm, + 20 + mp->m_lcm + mp->m_hcm * 2, + mp->m_tech, mp->m_cost); + } +} + +void +show_ship_stats(int tlev) +{ + register struct mchrstr *mp; + int scount; + int techdiff; + + pr("%25s s v s r f l p",""); + pr(" h"); + pr(" x"); + if (opt_FUEL) + pr(" fuel"); + pr("\n"); + + pr("%25s p i p n i n l",""); + pr(" e"); + pr(" p"); + if (opt_FUEL) + pr(" c/u"); + pr("\n"); + + pr("%25s def d s y g r d n",""); + pr(" l"); + pr(" l"); + if (opt_FUEL) + pr(" "); + pr("\n"); + + + make_new_list(tlev, EF_SHIP); + for (scount = 0; scount < lookup_list_cnt; scount++) { + mp = (struct mchrstr *)lookup_list[scount].l_u.mp; + /* Can't show trade ships unless it's turned on */ + if ((mp->m_flags & M_TRADE) && !opt_TRADESHIPS) + continue; + + techdiff = (int)(tlev - mp->m_tech); + pr("%-25.25s %3d %2d %2d %2d %2d %2d ", + mp->m_name, + (short)SHP_DEF(mp->m_armor, techdiff), + (short)SHP_SPD(mp->m_speed, techdiff), + (short)SHP_VIS(mp->m_visib, techdiff), + mp->m_vrnge, + (short)SHP_RNG(mp->m_frnge, techdiff), + (short)SHP_FIR(mp->m_glim, techdiff)); + + pr("%2d ", mp->m_nland); + pr("%2d ", mp->m_nplanes); + pr("%2d ", mp->m_nchoppers); + pr("%2d ", mp->m_nxlight); + if (opt_FUEL) + pr("%3d/%1d ", mp->m_fuelc,mp->m_fuelu); + pr("\n"); + } +} + +void +show_ship_capab(int tlev) +{ + register struct mchrstr *mp; + register u_short *ap; + register u_char *type; + register int i; + register int it; + int scount; + int n; + s_char c; + s_char *p; + + pr("%25s cargos & capabilities\n",""); + + make_new_list(tlev, EF_SHIP); + for (scount = 0; scount < lookup_list_cnt; scount++) { + mp = (struct mchrstr *)lookup_list[scount].l_u.mp; + /* Can't show trade ships unless it's turned on */ + if ((mp->m_flags & M_TRADE) && !opt_TRADESHIPS) + continue; + + pr("%-25.25s ", mp->m_name); + + /* + * should use vector stuff + */ + for (ap = mp->m_vamt, type = mp->m_vtype, i = 0; + i < mp->m_nv; i++, ap++, type++) { + it = unitem((int) *type); + if (it > 0 && it <= I_MAX && ichr[it].i_name != 0) + c = ichr[it].i_name[0]; + else + c = '?'; + pr(" %d%c", *ap, c); + } + pr(" "); + for (i = n = 0; i < 32; i++) { + if (!(mp->m_flags & bit(i))) + continue; + if (NULL != (p = lookup(bit(i), ship_flags))) { + if (n++ > 0) + pr(" "); + pr(p); + } + } + pr("\n"); + } +} + +void +show_plane_stats(int tlev) +{ + register struct plchrstr *pp; + int pcount; + + pr("%25s acc load att def ran fuel stlth\n", ""); + make_new_list(tlev, EF_PLANE); + for (pcount = 0; pcount < lookup_list_cnt; pcount++) { + pp = (struct plchrstr *)lookup_list[pcount].l_u.pp; + pr("%-25.25s %3d %4d %3d %3d %3d %4d ", + pp->pl_name, + (int)PLN_ACC(pp->pl_acc, (int)(tlev - pp->pl_tech)), + (int)PLN_LOAD(pp->pl_load, (int)(tlev - pp->pl_tech)), + (int)PLN_ATTDEF(pp->pl_att, (int)(tlev - pp->pl_tech)), + (int)PLN_ATTDEF(pp->pl_def, (int)(tlev - pp->pl_tech)), + (int)PLN_RAN(pp->pl_range, (int)(tlev - pp->pl_tech)), + pp->pl_fuel); + pr("%4d%% ",pp->pl_stealth); + pr("\n"); + } +} + +void +show_plane_capab(int tlev) +{ + register struct plchrstr *pp; + register int i; + int pcount; + int n; + s_char *p; + + pr("%25s capabilities\n",""); + make_new_list(tlev, EF_PLANE); + for (pcount = 0; pcount < lookup_list_cnt; pcount++) { + pp = (struct plchrstr *)lookup_list[pcount].l_u.pp; + pr("%-25.25s ", pp->pl_name); + + for (i = n = 0; i < 32; i++) { + if (!(pp->pl_flags & bit(i))) + continue; + if (NULL != (p = lookup(bit(i), plane_flags))) { + if (n++ > 0) + pr(" "); + pr(p); + } + } + pr("\n"); + } +} + +void +show_plane_build(int tlev) +{ + register struct plchrstr *pp; + register int pcount; + + pr("%25s lcm hcm crew avail tech $\n", ""); + make_new_list(tlev, EF_PLANE); + for (pcount = 0; pcount < lookup_list_cnt; pcount++) { + pp = (struct plchrstr *)lookup_list[pcount].l_u.pp; + pr("%-25.25s %3d %3d %3d %5d %4d $%d\n", + pp->pl_name, pp->pl_lcm, + pp->pl_hcm, pp->pl_crew, + 20 + 2 * pp->pl_hcm + pp->pl_lcm, + pp->pl_tech, pp->pl_cost); + } +} + +void +show_land_build(int tlev) +{ + register struct lchrstr *lp; + register int n; + + pr("%25s lcm hcm guns avail tech $\n", ""); + make_new_list(tlev, EF_LAND); + for (n = 0; n < lookup_list_cnt; n++) { + lp = (struct lchrstr *)lookup_list[n].l_u.lp; + if ((lp->l_flags & L_SPY) && !opt_LANDSPIES) + continue; + pr("%-25.25s %3d %3d %4d %5d %4d $%d\n", + lp->l_name, lp->l_lcm, + lp->l_hcm, + lp->l_gun, + 20 + lp->l_lcm + (lp->l_hcm * 2), + lp->l_tech, lp->l_cost); + } +} + +void +show_land_capab(int tlev) +{ + struct lchrstr *lcp; + int lcount; + register u_short *ap; + register u_char *type; + register int i,n; + register int it; + register s_char *p,c; + + pr("%25s capabilities\n",""); + + make_new_list(tlev, EF_LAND); + for (lcount = 0; lcount < lookup_list_cnt; lcount++) { + lcp = (struct lchrstr *)lookup_list[lcount].l_u.lp; + if ((lcp->l_flags & L_SPY) && !opt_LANDSPIES) + continue; + + pr("%-25s ", lcp->l_name); + + /* + * should use vector stuff + */ + for (ap = lcp->l_vamt, type = lcp->l_vtype, i = 0; + i < lcp->l_nv; i++, ap++, type++) { + it = unitem((int) *type); + if (it > 0 && it <= I_MAX && ichr[it].i_name != 0) + c = ichr[it].i_name[0]; + else + c = '?'; + pr(" %d%c", *ap, c); + } + pr(" "); + for (i = n = 0; i < 32; i++) { + if (!(lcp->l_flags & bit(i))) + continue; + if (NULL != (p = lookup(bit(i), land_flags))) { + if (n++ > 0) + pr(" "); + pr(p); + } + } + pr("\n"); + } +} + +void +show_land_stats(int tlev) +{ + struct lchrstr *lcp; + int lcount; + int ourtlev; + +pr("%25s s v s r r a f a a x l\n",""); +pr("%25s p i p a n c i m a f f p n\n",""); +pr("%25s att def vul d s y d g c r m f c u l d\n",""); + + make_new_list(tlev, EF_LAND); + for (lcount = 0; lcount < lookup_list_cnt; lcount++) { + lcp = (struct lchrstr *)lookup_list[lcount].l_u.lp; + if ((lcp->l_flags & L_SPY) && !opt_LANDSPIES) + continue; + + ourtlev = (int)(tlev - lcp->l_tech); + pr("%-25s %1.1f %1.1f %3d ", + lcp->l_name, (float)LND_ATTDEF(lcp->l_att, ourtlev), + (float)LND_ATTDEF(lcp->l_def, ourtlev), + (int)LND_VUL(lcp->l_vul, ourtlev)); + pr("%2d %2d %2d %2d ", + (int)LND_SPD(lcp->l_spd, ourtlev), + (int)LND_VIS(lcp->l_vis, ourtlev), + (int)LND_SPY(lcp->l_spy, ourtlev), + (int)LND_RAD(lcp->l_rad, ourtlev)); + pr("%2d %2d %2d %2d %2d ", + (int)LND_FRG(lcp->l_frg, ourtlev), + (int)LND_ACC(lcp->l_acc, ourtlev), + (int)LND_DAM(lcp->l_dam, ourtlev), + (int)LND_AMM(lcp->l_ammo, lcp->l_dam, ourtlev), + (int)LND_AAF(lcp->l_aaf, ourtlev)); + pr("%2d %2d %2d %2d ", + (int)LND_FC(lcp->l_fuelc, ourtlev), + (int)LND_FU(lcp->l_fuelu, ourtlev), + (int)LND_XPL(lcp->l_nxlight, ourtlev), + (int)LND_MXL(lcp->l_mxland, ourtlev)); + + pr("\n"); + } +} + +void +show_sect_build(int foo) +{ + register int x, first=1; + + for(x=5;x0) || (dchr[x].d_build!=1) || + (dchr[x].d_lcms>0) || (dchr[x].d_hcms>0)){ + if (first){ + pr("sector type cost to des cost for 1%% eff lcms for 1%% hcms for 1%%\n"); + first=0; + } + pr("%-14c %-14d %-17d %-14d %d\n", + dchr[x].d_mnem, dchr[x].d_cost, dchr[x].d_build, + dchr[x].d_lcms, dchr[x].d_hcms); + } + } + pr("\n"); + pr("Infrastructure building - adding 1 point of efficiency costs:\n"); + pr(" type lcms hcms mobility $$$$\n"); + for (x = 0; intrchr[x].in_name; x++) { + pr("%-20s %4d %4d %8d %4d\n", intrchr[x].in_name, + intrchr[x].in_lcms, intrchr[x].in_hcms, + intrchr[x].in_mcost, intrchr[x].in_dcost); + } +} + +void +show_sect_stats(int foo) +{ + register int x, first=1; + struct sctstr sect; + struct natstr *natp; + + natp = getnatp(player->cnum); + /* We fake this */ + sect.sct_effic = 100; + for(x=0;xnat_level[NAT_RLEV], §)); + } +} + +void +show_sect_capab(int foo) +{ + register int x, first=1, i, j; + char *tmpstr; + char c; + char *outputs = " cmsgpidbfolhur"; + + for(x = 0; x < SCT_MAXDEF + 2; x++) { + if ((dchr[x].d_mnem == 0) || (dchr[x].d_prd == 0)) + continue; + if (first) { + pr(" --- level --- reso \n"); + pr(" sector type product use1 use2 use3 level min lag eff%% $$$ dep c\n"); + first = 0; + } + + j = dchr[x].d_prd; + + pr("%c %-23s %-7s ", dchr[x].d_mnem, dchr[x].d_name, pchr[j].p_sname); + /*for(i=0;i 0)) { + pr("%2d %c ", pchr[j].p_vamt[i], + ichr[pchr[j].p_vtype[i] & (~VT_ITEM)].i_name[0]); + } else { + pr(" "); + } + } + switch(pchr[j].p_nlndx) { + case NAT_TLEV: + tmpstr = "tech"; + break; + case NAT_ELEV: + tmpstr = "edu"; + break; + case NAT_RLEV: + tmpstr = "res"; + break; + case NAT_HLEV: + tmpstr = "hap"; + break; + default: + tmpstr = " "; + break; + } + if (pchr[j].p_type) + c = outputs[pchr[j].p_type - VT_ITEM]; + else + c = ' '; + pr("%-5s %3d %3d %4d %3d %3d %c", + tmpstr, + pchr[j].p_nlmin, + pchr[j].p_nllag, + pchr[j].p_effic, + pchr[j].p_cost, + pchr[j].p_nrdep, + c); + + pr("\n"); + } +} + diff --git a/src/lib/subs/shpsub.c b/src/lib/subs/shpsub.c new file mode 100644 index 00000000..d55a342a --- /dev/null +++ b/src/lib/subs/shpsub.c @@ -0,0 +1,1052 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-1999, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * shpsub.c: Ship subroutine stuff + * + * Known contributors to this file: + * Ken Stevens, 1995 + * Steve McClure, 1996-2000 + */ + +#include "misc.h" +#include "queue.h" +#include "player.h" +#include "var.h" +#include "sect.h" +#include "ship.h" +#include "plane.h" +#include "land.h" +#include "news.h" +#include "item.h" +#include "xy.h" +#include "nsc.h" +#include "file.h" +#include "nat.h" +#include "path.h" +#include "mission.h" +#include "optlist.h" +#include "damage.h" +#include "prototypes.h" + +extern double tfactfire(natid, double); + +extern int etu_per_update; + +void +shp_sel(struct nstr_item *ni, struct emp_qelem *list) + + + /* int wantflags; + int nowantflags; + */ +{ + struct shpstr ship; + struct mchrstr *mcp; + struct mlist *mlp; + + emp_initque(list); + while (nxtitem(ni, (s_char *)&ship)) { + if (!player->owner) + continue; + mcp = &mchr[(int)ship.shp_type]; + /* if (wantflags && (mcp->m_flags & wantflags) != wantflags) + continue; + if (nowantflags && mcp->m_flags & nowantflags) + continue; + */ + if (opt_MARKET) { + if (ontradingblock(EF_SHIP, (int *)&ship)) { + pr("ship #%d inelligible - it's for sale.\n", ship.shp_uid); + continue; + } + } + /* This abuse is better fixed by building a ship with the normal negative + mobility that everything else is built with */ +/* + if (opt_MOB_ACCESS) { + if (ship.shp_effic < 21 && + ship.shp_mobil < etu_per_update) { + pr("%s needs at least %d mob to navigate.\n", + prship(&ship), etu_per_update); + continue; + } + } +*/ + ship.shp_mission = 0; + ship.shp_rflags = 0; + bzero(ship.shp_rpath,RET_LEN); + putship(ship.shp_uid, &ship); + mlp = (struct mlist *) malloc(sizeof(struct mlist)); + mlp->mcp = mcp; + bcopy((s_char *)&ship, (s_char *)&mlp->ship, + sizeof(struct shpstr)); + mlp->mobil = (double)ship.shp_mobil; + emp_insque(&mlp->queue, list); + } +} + +/* This function assumes that the list was created by shp_sel */ +void +shp_nav(struct emp_qelem *list, double *minmobp, double *maxmobp, int *togetherp, natid actor) +{ + extern int update_pending; + struct emp_qelem *qp; + struct emp_qelem *next; + struct mlist *mlp; + struct sctstr sect; + struct shpstr ship; + int vec[I_MAX+1]; + coord allx; + coord ally; + int first=1; + + *minmobp = 9876.0; + *maxmobp = -9876.0; + *togetherp = 1; + for (qp = list->q_back; qp != list; qp = next) { + next = qp->q_back; + mlp = (struct mlist *) qp; + getship(mlp->ship.shp_uid, &ship); + if (ship.shp_own != actor) { + mpr(actor, "%s was sunk at %s\n", + prship(&ship), + xyas(ship.shp_x, ship.shp_y, actor)); + emp_remque((struct emp_qelem *)mlp); + free((s_char *)mlp); + continue; + } + if (opt_SAIL) { + if (*ship.shp_path && !update_pending) { + shp_mess("has a sail path", mlp); + mpr(actor, "Use `sail <#> -' to reset\n"); + continue; + } + } + /* check crew - uws don't count */ + getvec(VT_ITEM, vec, (s_char *)&ship, EF_SHIP); + if (vec[I_MILIT] == 0 && vec[I_CIVIL] == 0) { + shp_mess("is crewless", mlp); + continue; + } + if (!getsect(ship.shp_x, ship.shp_y, §)) { + shp_mess("was sucked into the sky by a strange looking spaceship", mlp); /* heh -KHS */ + continue; + } + switch (shp_check_nav(§)) { + case CN_CONSTRUCTION: + shp_mess("is caught in a construction zone", mlp); + continue; + case CN_LANDLOCKED: + shp_mess("is landlocked", mlp); + break; + case CN_NAVIGABLE: + break; + case CN_ERROR: + default: + shp_mess("was just swallowed by a big green worm", mlp); + continue; + } + if (first){ + allx = ship.shp_x; + ally = ship.shp_y; + first = 0; + } + if (ship.shp_x != allx || + ship.shp_y != ally) + *togetherp = 0; + if (ship.shp_mobil + 1 < (int)mlp->mobil) { + mlp->mobil = (double)ship.shp_mobil; + } + if (mlp->mobil < *minmobp) + *minmobp = mlp->mobil; + if (mlp->mobil > *maxmobp) + *maxmobp = mlp->mobil; + bcopy((s_char *)&ship, (s_char *)&mlp->ship, + sizeof(struct shpstr)); + } +} + +void +shp_put(struct emp_qelem *list, natid actor) +{ + register struct emp_qelem *qp; + register struct emp_qelem *newqp; + struct mlist *mlp; + + qp = list->q_back; + while (qp != list) { + mlp = (struct mlist *) qp; + mpr(actor, "%s stopped at %s\n", prship(&mlp->ship), + xyas(mlp->ship.shp_x, mlp->ship.shp_y, mlp->ship.shp_own)); + mlp->ship.shp_mobil = (int)mlp->mobil; + putship(mlp->ship.shp_uid, &mlp->ship); + newqp = qp->q_back; + emp_remque(qp); + free((s_char *)qp); + qp = newqp; + } +} + +int +shp_sweep(struct emp_qelem *ship_list, int verbose, natid actor) +{ + struct emp_qelem *qp; + struct emp_qelem *next; + struct mlist *mlp; + struct sctstr sect; + int mines, m, max, shells; + int changed = 0; + int stopping = 0; + double mobcost; + + for (qp=ship_list->q_back;qp!=ship_list;qp=next) { + next = qp->q_back; + mlp = (struct mlist *) qp; + if (!(mlp->mcp->m_flags & M_SWEEP)) { + if (verbose) + mpr(actor, "%s doesn't have minesweeping capability!\n", prship(&mlp->ship)); + continue; + } + if (mlp->mobil <= 0.0) { + if (verbose) + mpr(actor, "%s is out of mobility!\n", prship(&mlp->ship)); + continue; + } + getsect(mlp->ship.shp_x,mlp->ship.shp_y,§); + if (sect.sct_type != SCT_WATER) { + if (verbose) + mpr(actor, "%s is not at sea. No mines there!\n", prship(&mlp->ship)); + continue; + } + mobcost = mlp->ship.shp_effic * 0.01 * mlp->ship.shp_speed; + mobcost = 480.0 / (mobcost + + techfact(mlp->ship.shp_tech,mobcost)); + mlp->mobil -= mobcost; + mlp->ship.shp_mobil = (int)mlp->mobil; + putship(mlp->ship.shp_uid, &mlp->ship); + if (!(mines=getvar(V_MINE,(s_char *)§,EF_SECTOR))) + continue; + max = vl_find(V_SHELL, mlp->mcp->m_vtype, + mlp->mcp->m_vamt, (int)mlp->mcp->m_nv); + shells = getvar(V_SHELL, (s_char *)&mlp->ship, EF_SHIP); + for (m=0; mines > 0 && m < 5; m++) { + if (chance(0.66)) { + mpr(actor, "Sweep...\n"); + mines--; + shells = min(max, shells + 1); + changed |= map_set(actor, + sect.sct_x, + sect.sct_y, + 'X', 0); + } + } + putvar(V_MINE, mines, (s_char *)§, EF_SECTOR); + putvar(V_SHELL, shells, (s_char *)&mlp->ship, EF_SHIP); + if (shp_check_one_mines(mlp)) { + stopping = 1; + emp_remque(qp); + free((s_char *)qp); + } + putship(mlp->ship.shp_uid, &mlp->ship); + putsect(§); + } + if (changed) + writemap(actor); + return stopping; +} + +int +shp_check_one_mines(struct mlist *mlp) +{ + struct sctstr sect; + int mines; + int changed = 0; + int actor; + + getsect(mlp->ship.shp_x, mlp->ship.shp_y, §); + if (sect.sct_type != SCT_WATER) + return 0; + if (!(mines = getvar(V_MINE, (s_char *)§, EF_SECTOR))) + return 0; + if (chance(DMINE_HITCHANCE(mines))) { + actor = mlp->ship.shp_own; + shp_hit_mine(&mlp->ship, mlp->mcp); + mines--; + changed |= map_set(actor, sect.sct_x, sect.sct_y, 'X', 0); + if (changed) + writemap(actor); + putvar(V_MINE, mines, (s_char *)§, EF_SECTOR); + putsect(§); + putship(mlp->ship.shp_uid, (s_char *)&mlp->ship); + if (!mlp->ship.shp_own) + return 1; + } + return 0; +} + +int +shp_check_mines(struct emp_qelem *ship_list) +{ + struct emp_qelem *qp; + struct emp_qelem *next; + struct mlist *mlp; + int stopping = 0; + + for (qp=ship_list->q_back;qp!=ship_list;qp=next) { + next = qp->q_back; + mlp = (struct mlist *) qp; + if (shp_check_one_mines(mlp)) { + stopping = 1; + emp_remque(qp); + free((s_char *)qp); + } + } + return stopping; +} + +void +shp_list(struct emp_qelem *ship_list) +{ + struct emp_qelem *qp; + struct emp_qelem *next; + struct mlist *mlp; + struct shpstr *shp; + int vec[I_MAX+1]; + + pr("shp# ship type x,y fl eff mil sh gun pn he xl ln mob tech\n"); + + for (qp=ship_list->q_back;qp!=ship_list;qp=next) { + next = qp->q_back; + mlp = (struct mlist *) qp; + shp = &mlp->ship; + pr("%4d ", shp->shp_uid); + pr("%-16.16s ", mlp->mcp->m_name); + prxy("%4d,%-4d ", shp->shp_x, shp->shp_y, mlp->ship.shp_own); + pr("%1c", shp->shp_fleet); + pr("%4d%%", shp->shp_effic); + getvec(VT_ITEM, vec, (s_char *)shp, EF_SHIP); + pr("%4d", vec[I_MILIT]); + pr("%4d", vec[I_SHELL]); + pr("%4d", vec[I_GUN]); + count_planes(shp); + pr("%3d", shp->shp_nplane); + pr("%3d",shp->shp_nchoppers); + pr("%3d",shp->shp_nxlight); + count_units(shp); + pr("%3d", shp->shp_nland); + pr("%4d", shp->shp_mobil); + pr("%4d\n", shp->shp_tech); + } +} + +void +shp_mess(s_char *str, struct mlist *mlp) +{ + mpr(mlp->ship.shp_own, "%s %s & stays in %s\n", + prship(&mlp->ship), + str, xyas(mlp->ship.shp_x, mlp->ship.shp_y, mlp->ship.shp_own)); + mlp->ship.shp_mobil = (int)mlp->mobil; + putship(mlp->ship.shp_uid, &mlp->ship); + emp_remque((struct emp_qelem *)mlp); + free((s_char *)mlp); +} + +int +shp_check_nav(struct sctstr *sect) +{ + extern struct dchrstr dchr[]; + + switch (dchr[sect->sct_type].d_flg & 03) { + case NAVOK: + break; + + case NAV_02: + if (sect->sct_effic < 2) + return CN_CONSTRUCTION; + break; + case NAV_60: + if (sect->sct_effic < 60) + return CN_CONSTRUCTION; + break; + default: + return CN_LANDLOCKED; + } + return CN_NAVIGABLE; +} + +static int +shp_count(struct emp_qelem *list, int wantflags, int nowantflags, int x, int y) +{ + struct emp_qelem *qp; + struct emp_qelem *next; + struct mlist *mlp; + int count = 0; + + for (qp = list->q_back; qp != list; qp = next) { + next = qp->q_back; + mlp = (struct mlist *) qp; + if (mlp->ship.shp_x != x || mlp->ship.shp_y != y) + continue; + if (wantflags && (mlp->mcp->m_flags & wantflags) != wantflags) + continue; + if (nowantflags && mlp->mcp->m_flags & nowantflags) + continue; + ++count; + } + return count; +} + +static void +shp_damage_one(struct mlist *mlp, int dam) +{ + shipdamage(&mlp->ship, dam); + putship(mlp->ship.shp_uid, &mlp->ship); + if (!mlp->ship.shp_own) { + emp_remque((struct emp_qelem *)mlp); + free((s_char *)mlp); + } +} + +static int +shp_damage(struct emp_qelem *list, int totdam, int wantflags, int nowantflags, int x, int y) +{ + struct emp_qelem *qp; + struct emp_qelem *next; + struct mlist *mlp; + int dam; + int count; + + if (!totdam || !(count = shp_count(list, wantflags, nowantflags, x, y))) + return 0; + dam = ldround(((double)totdam/(double)count),1); + for (qp = list->q_back; qp != list; qp = next) { + next = qp->q_back; + mlp = (struct mlist *) qp; + if (mlp->ship.shp_x != x || mlp->ship.shp_y != y) + continue; + if (wantflags && (mlp->mcp->m_flags & wantflags) != wantflags) + continue; + if (nowantflags && mlp->mcp->m_flags & nowantflags) + continue; + shp_damage_one(mlp, dam); + } + return dam; +} + +static int +shp_contains(struct emp_qelem *list, int newx, int newy, int wantflags, int nowantflags) +{ + struct emp_qelem *qp; + struct emp_qelem *next; + struct mlist *mlp; + + for (qp = list->q_back; qp != list; qp = next) { + next = qp->q_back; + mlp = (struct mlist *) qp; +/* If the ship isn't in the requested sector, then continue */ + if (newx != mlp->ship.shp_x || newy != mlp->ship.shp_y) + continue; + if (wantflags && (mlp->mcp->m_flags & wantflags) != wantflags) + continue; + if (nowantflags && mlp->mcp->m_flags & nowantflags) + continue; + return 1; + } + return 0; +} + +static struct mlist * +most_valuable_ship(struct emp_qelem *list) +{ + struct emp_qelem *qp; + struct emp_qelem *next; + struct mlist *mlp; + struct mlist *mvs = 0; + + for (qp = list->q_back; qp != list; qp = next) { + next = qp->q_back; + mlp = (struct mlist *) qp; + if (mlp->mcp->m_flags & M_SUB) + continue; + if (!mlp->mcp->m_nxlight && + !mlp->mcp->m_nchoppers && + mlp->mcp->m_cost < 1000 && + !mlp->mcp->m_nplanes && + !mlp->mcp->m_nland) + continue; + if (!mvs) { + mvs = mlp; + continue; + } + if (mlp->mcp->m_cost * mlp->ship.shp_effic > + mvs->mcp->m_cost * mvs->ship.shp_effic) + mvs = mlp; + } + return mvs; +} + +static int shp_easiest_target(struct emp_qelem *list, int wantflags, int nowantflags) +{ + struct emp_qelem *qp; + struct emp_qelem *next; + struct mlist *mlp; + int hard; + int easiest = 9876; /* things start great for victim */ + int count = 0; + + for (qp = list->q_back; qp != list; qp = next) { + next = qp->q_back; + mlp = (struct mlist *) qp; + if (wantflags && (mlp->mcp->m_flags & wantflags) != wantflags) + continue; + if (nowantflags && mlp->mcp->m_flags & nowantflags) + continue; + hard = shp_hardtarget(&mlp->ship); + if (hard < easiest) + easiest = hard; /* things get worse for victim */ + ++count; + } + return easiest - count; +} + +static int +shp_missile_interdiction(struct emp_qelem *list, coord newx, coord newy, natid victim) +{ + int dam; + int twotries; + int stopping = 0; + struct emp_qelem msl_list, *qp, *newqp; + struct mlist *mvs; + s_char what[512]; + + msl_sel(&msl_list, newx, newy, victim, P_T|P_MAR, 0, MI_INTERDICT); + + twotries = 0; + while (!QEMPTY(&msl_list) && (mvs = most_valuable_ship(list))) { + sprintf(what, "%s", prship(&mvs->ship)); + dam = msl_launch_mindam(&msl_list, newx, newy, + shp_hardtarget(&mvs->ship), + EF_SHIP, + 1, + what, victim, MI_INTERDICT); + if (dam) { + mpr(victim, "missile interdiction mission does %d damage to %s!\n", dam, what); + shp_damage_one(mvs, dam); + twotries = 0; + stopping |= 1; + } else if (++twotries >= 2) { + break; + } + } + qp = msl_list.q_forw; + while(qp != msl_list.q_forw) { + newqp=qp->q_forw; + emp_remque(qp); + free(qp); + qp = newqp; + } + + return stopping; +} + +/* Note that this function has a side effect - it uses coastwatch + * ranges to see if it should fire upon a ship. So, this function + * is expected to return positive if a ship is in range, and 0 if a + * ship is not in range. */ +static int +notify_coastguard(struct emp_qelem *list, int trange, struct sctstr *sectp) +{ + struct emp_qelem *qp; + struct emp_qelem *next; + struct mlist *mlp; + struct natstr *natp; + int vrange; + + natp = getnatp(sectp->sct_own); + + vrange = sectp->sct_type==SCT_RADAR?14:4; + vrange *= tfact(sectp->sct_own, 1.0) * sectp->sct_effic / 100.0; + + if (vrange < 1) + vrange = 1; + + if (vrange < trange) + return 0; + + /* We got here, so we could theoretically see the ship. Now, + * do we want to see it in our telebox? If not, return positive + * since we could see the ship and want forts to fire. */ + if (!(natp->nat_flags & NF_COASTWATCH)) + return 1; + + for (qp = list->q_back; qp != list; qp = next) { + next = qp->q_back; + mlp = (struct mlist *) qp; + if (mlp->mcp->m_flags & M_SUB) + continue; + wu(0, sectp->sct_own, + "%s %s sighted at %s\n", + cname(mlp->ship.shp_own), + prship(&mlp->ship), + xyas(mlp->ship.shp_x, mlp->ship.shp_y, sectp->sct_own)); + if (opt_HIDDEN) { + setcont(sectp->sct_own, mlp->ship.shp_own, FOUND_LOOK); + } + } + + return 1; +} + +static int +shp_fort_interdiction(struct emp_qelem *list, coord newx, coord newy, natid victim) +{ + extern int fort_max_interdiction_range; + struct nstr_sect ns; + struct sctstr fsect; + int trange; + double range, range2, guneff; + int shell, gun; + int dam; + int totdam = 0; + s_char notified[MAXNOC]; + int i; + + /* Inform neutral and worse */ + for (i = 0; i < MAXNOC; ++i) { + if (getrel(getnatp(i),victim) <= NEUTRAL) + notified[i] = 0; + else + notified[i] = 1; + } + + snxtsct_dist(&ns,newx,newy,fort_max_interdiction_range); + while (nxtsct(&ns,&fsect)){ + if (!fsect.sct_own) + continue; + if (fsect.sct_own == victim) + continue; + if (notified[fsect.sct_own]) + continue; + trange = mapdist(newx, newy, + fsect.sct_x, fsect.sct_y); + if (notify_coastguard(list, trange, &fsect)) + notified[fsect.sct_own] = 1; + } + if (opt_NO_FORT_FIRE) return 0; /* Only coastwatch notify in nofortfire */ + /* Only fire at Hostile ships */ + for (i = 0; i < MAXNOC; ++i) { + if (getrel(getnatp(i),victim) >= NEUTRAL) + notified[i] = 0; + } + snxtsct_dist(&ns,newx,newy,fort_max_interdiction_range); + while (nxtsct(&ns,&fsect)){ + if (!notified[fsect.sct_own]) + continue; + if (fsect.sct_type != SCT_FORTR) + continue; + gun=getvar(V_GUN,(s_char *)&fsect,EF_SECTOR); + if (gun < 1) + continue; + range = tfactfire(fsect.sct_own,(double)min(gun,7)); + if (fsect.sct_effic > 59) + range++; + range2 = roundrange(range); + trange = mapdist(newx, newy, + fsect.sct_x, fsect.sct_y); + if (trange > range2) + continue; + if (getvar(V_MILIT,(s_char *)&fsect,EF_SECTOR)<5) + continue; + shell = getvar(V_SHELL,(s_char *)&fsect,EF_SECTOR); + if (shell < 1) + shell += supply_commod(fsect.sct_own, + fsect.sct_x,fsect.sct_y,I_SHELL, + 1); + if (shell < 1) + continue; + shell--; + putvar(V_SHELL,shell,(s_char *)&fsect,EF_SECTOR); + putsect(&fsect); + if (gun > 7) + gun = 7; + guneff = landgun((int)fsect.sct_effic, gun); + dam = (int)guneff; + totdam += dam; + mpr(victim, "Incoming fire does %d damage!\n", dam); +/* + mpr(victim, "%s fires at you for %d!\n", + xyas(fsect.sct_x,fsect.sct_y,victim), + dam); +*/ + wu(0,fsect.sct_own, + "%s fires at %s ships in %s for %d!\n", + xyas(fsect.sct_x,fsect.sct_y, + fsect.sct_own), + cname(victim), + xyas(newx,newy,fsect.sct_own), dam); + nreport(fsect.sct_own, N_SHP_SHELL, victim, 1); + } + if (totdam > 0) + return shp_damage(list, totdam, 0, M_SUB, newx, newy); + return 0; +} + +int +shp_interdict(struct emp_qelem *list, coord newx, coord newy, natid victim) +{ + int stopping = 0; + + if (shp_contains(list, newx, newy, 0, M_SUB)) { + stopping |= shp_fort_interdiction(list, newx, newy, victim); + + if (shp_contains(list, newx, newy, 0, M_SUB)) { + stopping |= shp_damage(list, unit_interdict(newx,newy,victim,"ships", shp_easiest_target(list, 0, M_SUB), MI_INTERDICT), 0, M_SUB, newx, newy); + if (most_valuable_ship(list)) { + stopping |= shp_missile_interdiction(list,newx,newy,victim); + } + } + } + if (shp_contains(list, newx, newy, M_SUB, 0)) { + stopping |= shp_damage(list, unit_interdict(newx, newy, victim, "subs", shp_easiest_target(list, M_SUB, 0), MI_SINTERDICT), M_SUB, 0, newx, newy); + } + return stopping; +} + +/* high value of hardtarget is harder to hit */ +int shp_hardtarget(struct shpstr *sp) +{ + struct sctstr sect; + int vis, onsea; + struct mchrstr *mcp = mchr + sp->shp_type; + + vis = sp->shp_visib; + getsect(sp->shp_x,sp->shp_y, §); + onsea = (sect.sct_type == SCT_WATER); + if (mcp->m_flags & M_SUB) + vis *= 4; + return (int)(((double)sp->shp_effic/100.0) * + (20 + (double)sp->shp_speed * onsea/2.0 - vis)); +} + +int +shp_hit_mine(struct shpstr *sp, struct mchrstr *mcp) +{ + double m; + + mpr(sp->shp_own, "Kawhomp! Mine detected in %s!\n", + xyas(sp->shp_x, sp->shp_y, sp->shp_own)); + + nreport(sp->shp_own, N_HIT_MINE, 0, 1); + + m = 22.0 + (double)(random() % 21); + if (mcp->m_flags & M_SWEEP) + m /= 2.0; + + shipdamage(sp, ldround(m,1)); + + return (int)m; +} + +void +shp_view(struct emp_qelem *list) +{ + struct sctstr sect; + struct emp_qelem *qp; + struct emp_qelem *next; + struct mlist *mlp; + + for (qp=list->q_back;qp!=list;qp=next) { + next = qp->q_back; + mlp = (struct mlist *)qp; + getsect(mlp->ship.shp_x,mlp->ship.shp_y,§); + if (mlp->mcp->m_flags & M_FOOD) + mpr(mlp->ship.shp_own, "[fert:%d] ", sect.sct_fertil); + if (mlp->mcp->m_flags & M_OIL) + mpr(mlp->ship.shp_own, "[oil:%d] ", sect.sct_oil); + mpr(mlp->ship.shp_own, "%s @ %s %d%% %s\n", + prship(&mlp->ship), + xyas(mlp->ship.shp_x, mlp->ship.shp_y, player->cnum), + sect.sct_effic, + dchr[sect.sct_type].d_name); + } +} + +int +shp_nav_one_sector(struct emp_qelem *list, int dir, natid actor, int together) +{ + struct sctstr sect; + struct emp_qelem *qp; + struct emp_qelem *next; + struct emp_qelem *nqp; + struct emp_qelem *nnext; + struct mlist *mlp; + coord dx; + coord dy; + coord newx; + coord newy; + int stopping = 0; + double mobcost; + double tech; /* for mapping */ + double tf; /* for mapping */ + s_char dp[80]; + + if (dir <= DIR_STOP || dir >= DIR_VIEW) { + shp_put(list, actor); + return 1; + } + dx = diroff[dir][0]; + dy = diroff[dir][1]; + for (qp=list->q_back;qp!=list;qp=next) { + next = qp->q_back; + mlp = (struct mlist *)qp; + newx = xnorm(mlp->ship.shp_x + dx); + newy = ynorm(mlp->ship.shp_y + dy); + getsect(newx, newy, §); + if (shp_check_nav(§) != CN_NAVIGABLE || + (sect.sct_own && actor != sect.sct_own && + getrel(getnatp(sect.sct_own), actor) < FRIENDLY)) { + if (together) { + mpr(actor,"can't go to %s\n",xyas(newx, newy, actor)); + return 2; + } else { + sprintf(dp, "can't go to %s", + xyas(newx, newy, actor)); + shp_mess(dp, mlp); + continue; + } + } + if (opt_BIG_CITY && sect.sct_type == SCT_CAPIT) { + if (mlp->mcp->m_lcm + 2 * mlp->mcp->m_hcm >= 60) { + sprintf(dp, "is too large to fit into the canal system at %s", xyas(newx, newy, actor)); + shp_mess(dp, mlp); + continue; + } + } + if (mlp->mobil <= 0.0) { + shp_mess("is out of mobility", mlp); + continue; + } + mobcost = mlp->ship.shp_effic * 0.01 * mlp->ship.shp_speed; + mobcost = 480.0 / + (mobcost + techfact(mlp->ship.shp_tech, mobcost)); + mlp->ship.shp_x = newx; + mlp->ship.shp_y = newy; + if (mlp->mobil - mobcost < -127) { + mlp->mobil = -127; + } else { + mlp->mobil -= mobcost; + } + mlp->ship.shp_mobil = (int)mlp->mobil; + putship(mlp->ship.shp_uid, &mlp->ship); + mlp->done = 0; /* We haven't interdicted this ship yet */ + + /* Now update the map for this ship */ + tech = techfact(mlp->ship.shp_tech, (double)mlp->mcp->m_vrnge); + if (mlp->mcp->m_flags & M_SONAR) + tf = techfact(mlp->ship.shp_tech, 1.0); + else + tf = 0.0; + radmapupd(mlp->ship.shp_own, mlp->ship.shp_x, mlp->ship.shp_y, + (int)mlp->ship.shp_effic, (int)tech, tf); + } + if (QEMPTY(list)) + return stopping; + stopping |= shp_sweep(list, 0, actor); + if (QEMPTY(list)) + return stopping; + stopping |= shp_check_mines(list); + if (QEMPTY(list)) + return stopping; + +/* Ok, run through each ship and interdict each coordinate */ + for (qp = list->q_back; qp != list; qp = next) { + next = qp->q_back; + mlp = (struct mlist *) qp; +/* Has this ship been interdicted yet? */ + if (mlp->done) + continue; + newx = mlp->ship.shp_x; + newy = mlp->ship.shp_y; + stopping |= shp_interdict(list, newx, newy, actor); + if (QEMPTY(list)) + return stopping; +/* Now, set all ships in this coordinate to done */ + for (nqp = list->q_back; nqp != list; nqp = nnext) { + nnext = nqp->q_back; + mlp = (struct mlist *)nqp; + if (mlp->ship.shp_x == newx && mlp->ship.shp_y == newy) + mlp->done = 1; + } + } + + return stopping; +} + +/* + * shp_miss_defence + * Check for incoming missiles with a P_MAR flag. + * Return True=1 if the missile was shotdown. + * Or False=0 + * + * Chad Zabel, July 95 + */ + +int +shp_missile_defense(coord dx, coord dy, natid bombown, int hardtarget) +{ + struct nstr_item ni; + struct shpstr ship; + int hitchance; + int vec[I_MAX+1]; + double gun,eff,teff; + + snxtitem_dist(&ni,EF_SHIP,dx,dy,1); + + while (nxtitem(&ni,(caddr_t)&ship)) { + if (!ship.shp_own) + continue; + + if (!(mchr[(int)ship.shp_type].m_flags & M_ANTIMISSILE)) + continue; + + if (getrel(getnatp(ship.shp_own), bombown) >= NEUTRAL) + continue; + + if (ship.shp_effic < 60) + continue; + + if (getvec(VT_ITEM,vec,(caddr_t)&ship,EF_SHIP) < 0) + continue; + if (vec[I_MILIT] < 1) /* do we have mil? */ + continue; + if (vec[I_SHELL] < 2) { /* do we need shells */ + if (vec[I_SHELL] += supply_commod(ship.shp_own, + ship.shp_x, + ship.shp_y, + I_SHELL,2) < 2) + continue; + } + if (vec[I_GUN] < 1) /* we need at least 1 gun */ + continue; + + /* now calculate the odds */ + gun = ((double)min(vec[I_GUN],ship.shp_glim)); + eff = (double)ship.shp_effic / 100.0; + teff = (((double)ship.shp_tech)/(((double)ship.shp_tech)+200.0)); + /* raise 4.5 for better interception -KHS */ + hitchance = (int)(gun*eff*teff*4.5) - hardtarget; + if (hitchance < 0) + hitchance = 0; + if (hitchance > 100) + hitchance = 100; + + mpr(bombown,"%s anti-missile system activated...",cname(ship.shp_own)); + mpr(ship.shp_own, + "Ship #%i anti-missile system activated!\n",ship.shp_uid); + mpr(ship.shp_own, + "%d%% hitchance...", hitchance); + /* use ammo */ + putvar (V_SHELL, vec[I_SHELL]-2,(caddr_t)&ship, EF_SHIP); + putship(ship.shp_uid,&ship); + + if (roll(100) <= hitchance) { + mpr(bombown,"KABOOOM!! Missile destroyed\n\n"); + mpr(ship.shp_own, + "KABOOOM!! Incoming missile destroyed!\n\n"); + return 1; + } else { + mpr(bombown, "SWOOSH!! anti-missile system failed!!\n"); + mpr(ship.shp_own, + "SWOOSH!! Missile evades anti-missile systems\n\n"); + } + } + return 0; /* all attempts failed */ +} + +s_char * +shp_path(int together, struct shpstr *shp, s_char *buf) +{ + coord destx; + coord desty; + struct sctstr d_sect; + s_char *cp; + + if (!sarg_xy(buf, &destx, &desty)) + return 0; + if (!together){ + mpr(shp->shp_own, "Cannot go to a destination sector if not all starting in the same sector\n"); + return 0; + } + if (!getsect(destx, desty, &d_sect)) { + mpr(shp->shp_own, "%d,%d is not a sector\n", destx, desty); + return 0; + } + + cp = (s_char *)BestShipPath(buf, shp->shp_x, shp->shp_y, + d_sect.sct_x, d_sect.sct_y, player->cnum); + if (!cp || shp->shp_mobil <= 0) { + mpr(shp->shp_own, "Can't get to '%s' right now.\n", + xyas(d_sect.sct_x, d_sect.sct_y, player->cnum)); + return 0; + } + return cp; +} + +/* Fire missiles at a ship which has fired shells */ +void +shp_missdef(struct shpstr *sp, natid victim) +{ + struct emp_qelem list; + struct mlist *mlp; + int eff; + s_char buf[512]; + + emp_initque(&list); + + mlp = (struct mlist *) malloc(sizeof(struct mlist)); + mlp->mcp = &mchr[(int)sp->shp_type]; + bcopy((s_char *)sp, (s_char *)&mlp->ship, sizeof(struct shpstr)); + mlp->mobil = (double)sp->shp_mobil; + emp_insque(&mlp->queue, &list); + sprintf(buf, "%s", prship(&mlp->ship)); + + eff = sp->shp_effic; + if (most_valuable_ship(&list)) { + shp_missile_interdiction(&list, sp->shp_x, sp->shp_y, sp->shp_own); + getship(sp->shp_uid, sp); + + if (!sp->shp_own) { + wu(0, victim, "missiles launched in defense did 100%% damage to %s\n", buf); + wu(0, victim, "%s sunk!\n", buf); + } else if (eff > 0 && sp->shp_effic < eff) { + wu(0, victim, "missiles launched in defense did %d%% damage to %s\n", 100*(eff - sp->shp_effic)/eff, buf); + } + } + if (!QEMPTY(&list)) + free(mlp); +} + diff --git a/src/lib/subs/snxtitem.c b/src/lib/subs/snxtitem.c new file mode 100644 index 00000000..d1113889 --- /dev/null +++ b/src/lib/subs/snxtitem.c @@ -0,0 +1,136 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * snxtitem.c: Arrange item selection using one of many criteria. + * + * Known contributors to this file: + * Dave Pare, 1989 + */ + +#include "misc.h" +#include "player.h" +#include "var.h" +#include "xy.h" +#include "sect.h" +#include "nsc.h" +#include "file.h" +#include "com.h" +#include "prototypes.h" + +/* + * setup the nstr structure for sector selection. + * can select on NS_ALL, NS_AREA, NS_DIST, and NS_LIST. + * iterate thru the "condarg" string looking + * for arguments to compile into the nstr. + */ +int +snxtitem(register struct nstr_item *np, int type, s_char *str) +{ + register s_char *cp; + struct range range; + int list[NS_LSIZE]; + int n; + coord cx, cy; + int dist; + int flags; + s_char natnumber[16]; + s_char prompt[128]; + s_char buf[1024]; + + np->type = NS_UNDEF; + np->sel = NS_UNDEF; + if (str == 0) { + sprintf(prompt, "%s(s)? ", ef_nameof(type)); + str = getstring(prompt, buf); + if (str == 0) + return 0; + } + if (*str == 0) { + /* str present, but only : nil string passed by player */ + return 0; + } + if (type == EF_NATION && isalpha(*str)) { + sprintf(natnumber, "%d", natarg(str, "")); + str = natnumber; + } + flags = ef_flags(type); + switch (sarg_type(str)) { + case NS_AREA: + if (!(flags & EFF_XY)) + return 0; + if (!sarg_area(str, &range)) + return 0; + snxtitem_area(np, type, &range); + break; + case NS_DIST: + if (!(flags & EFF_XY)) + return 0; + if (!sarg_range(str, &cx, &cy, &dist)) + return 0; + snxtitem_dist(np, type, cx, cy, dist); + break; + case NS_ALL: + snxtitem_all(np, type); + break; + case NS_LIST: + if ((n = sarg_list(str, list, NS_LSIZE)) == 0) + return 0; + if (!snxtitem_list(np, type, list, n)) + return 0; + break; + case NS_XY: + if (!(flags & EFF_XY)) + return 0; + if (!sarg_xy(str, &cx, &cy)) + return 0; + snxtitem_xy(np, type, cx, cy); + break; + case NS_GROUP: + if (!(flags & EFF_GROUP)) + return 0; + snxtitem_group(np, type, *str); + break; + default: + return 0; + } + np->flags = flags; + if (player->condarg == 0) + return 1; + cp = player->condarg; + while ((cp = nstr_comp(np->cond, &np->ncond, type, cp)) && *cp) + ; + if (cp == 0) + return 0; + return 1; +} + +/* + * The rest of these (snxtitem_area, snxtitem_dist, etc, have been moved + * into the common lib, since they don't use condargs, and are useful + * elsewhere (update, chiefly). ---ts + * + */ diff --git a/src/lib/subs/snxtsct.c b/src/lib/subs/snxtsct.c new file mode 100644 index 00000000..510e6a43 --- /dev/null +++ b/src/lib/subs/snxtsct.c @@ -0,0 +1,102 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * snxtsct.c: Arrange sector selection using either distance or area + * + * Known contributors to this file: + * Dave Pare, 1989 + */ + +#include "misc.h" +#include "player.h" +#include "var.h" +#include "xy.h" +#include "sect.h" +#include "nsc.h" +#include "file.h" +#include "com.h" +#include "prototypes.h" +#include "optlist.h" + +/* + * setup the nstr_sect structure for sector selection. + * can select on either NS_ALL, NS_AREA, or NS_RANGE + * iterate thru the "condarg" string looking + * for arguments to compile into the nstr. + */ +int +snxtsct(register struct nstr_sect *np, s_char *str) +{ + register s_char *cp; + struct range range; + coord cx, cy; + int dist; + s_char buf[1024]; + struct range wr; + + if (str == 0 || *str == 0) { + if ((str = getstring("(sects)? ", buf)) == 0) + return 0; + } + wr.lx = -WORLD_X/2; + wr.ly = -WORLD_Y/2; + wr.hx = WORLD_X/2; + wr.hy = WORLD_Y/2; + wr.width = wr.height = 0; + switch (sarg_type(str)) { + case NS_AREA: + if (!sarg_area(str, &range)) + return 0; + snxtsct_area(np, &range); + break; + case NS_DIST: + if (!sarg_range(str, &cx, &cy, &dist)) + return 0; + snxtsct_dist(np, cx, cy, dist); + break; + case NS_ALL: + /* fake "all" by doing a world-sized area query */ + snxtsct_area(np, &wr); + break; + default: + return 0; + } + if (player->condarg == 0) + return 1; + cp = player->condarg; + while ((cp = nstr_comp(np->cond, &np->ncond, EF_SECTOR, cp)) && *cp) + ; + if (cp == 0) + return 0; + return 1; +} +/* + * The rest of these (snxtsct_all, snxtsct_area, etc, have been moved + * into the common lib, since they don't use condargs, and are useful + * elsewhere (update, chiefly). ---ts + * + */ diff --git a/src/lib/subs/supply.c b/src/lib/subs/supply.c new file mode 100644 index 00000000..99a57ee1 --- /dev/null +++ b/src/lib/subs/supply.c @@ -0,0 +1,688 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * supply.c: Supply subroutines + * + * Known contributors to this file: + * + */ + +#include "misc.h" +#include "nat.h" +#include "var.h" +#include "retreat.h" +#include "ship.h" +#include "land.h" +#include "sect.h" +#include "news.h" +#include "xy.h" +#include "nsc.h" +#include "path.h" +#include "deity.h" +#include "item.h" +#include "file.h" +#include "options.h" +#include "optlist.h" +#include "player.h" +#include "prototypes.h" + +/* + * We want to get enough guns to be maxed out, enough shells to + * fire once, one update's worth of food, enough fuel for + * one update. + * + * Firts, try to forage in the sector + * Second look for a warehouse or headquarters to leech + * Third, look for a ship we own in a harbor + * Fourth, look for supplies in a supply unit we own + * (one good reason to do this last is that the supply + * unit will then call resupply, taking more time) + * + * May want to put code to resupply with SAMs here, later --ts + * + */ + +void +resupply_all(struct lndstr *lp) +{ + if (!opt_NOFOOD) + resupply_commod(lp,I_FOOD); + resupply_commod(lp,I_SHELL); + if (opt_FUEL) + resupply_commod(lp,I_PETROL); +} + +/* + * If the unit has less than it's minimum level of a + * certain commodity, fill it, to the best of our abilities. + */ + +void +resupply_commod(struct lndstr *lp, int type) +{ + int vec[I_MAX+1]; + int svec[I_MAX+1]; + int amt; + struct lchrstr *lcp; + struct shpstr ship; + + lcp = &lchr[(int)lp->lnd_type]; + + getvec(VT_ITEM, vec, (s_char *)lp, EF_LAND); + /* Ok, do we now have enough? */ + if (vec[type] < get_minimum(lp,type)) { + vec[type] += supply_commod(lp->lnd_own,lp->lnd_x,lp->lnd_y,type, + get_minimum(lp,type)-vec[type]); + putvec(VT_ITEM, vec, (s_char *)lp, EF_LAND); + } + /* Now, check again to see if we have enough. */ + if (vec[type] < get_minimum(lp,type)) { + /* Nope. How much do we need? */ + amt = (get_minimum(lp, type) - vec[type]); + /* Are we on a ship? if so, try to get it from the ship first. */ + if (lp->lnd_ship >= 0) { + getship(lp->lnd_ship, &ship); + getvec(VT_ITEM, svec, (s_char *)&ship, EF_SHIP); + /* Now, determine how much we can get */ + amt = (amt < svec[type]) ? amt : svec[type]; + /* Now, add and subtract */ + vec[type] += amt; + svec[type] -= amt; + putvec(VT_ITEM, vec, (s_char *)lp, EF_LAND); + putvec(VT_ITEM, svec, (s_char *)&ship, EF_SHIP); + putship(lp->lnd_ship, &ship); + } + } + + if (opt_FUEL && type == I_PETROL) { + extern float land_mob_scale; + extern int etu_per_update; + int fuel_needed = (lp->lnd_fuelu * (((float)etu_per_update + * land_mob_scale))/10.0); + + while((lp->lnd_fuel < fuel_needed) && vec[I_PETROL]){ + lp->lnd_fuel += 10; + if (lp->lnd_fuel > lp->lnd_fuelc) + lp->lnd_fuel = lp->lnd_fuelc; + vec[I_PETROL]--; + putvec(VT_ITEM, vec, (s_char *)lp, EF_LAND); + } + } +} + +/* + * Actually get the commod + */ +int +supply_commod(int own, int x, int y, int type, int total_wanted) +{ + if (total_wanted < 0) + return 0; + return s_commod(own, x, y, type,total_wanted,!player->simulation); +} + +/* + * Just return the number you COULD get, without doing it + */ +int +try_supply_commod(int own, int x, int y, int type, int total_wanted) +{ + if (total_wanted < 0) + return 0; + + return s_commod(own, x, y, type,total_wanted,0); +} + +/* Get supplies of a certain type */ +int +s_commod(int own, int x, int y, int type, int total_wanted, int actually_doit) +{ + int wanted=total_wanted; + int gotten=0, lookrange; + struct sctstr sect, dest; + int vec[I_MAX+1]; + struct nstr_sect ns; + struct nstr_item ni; + struct lchrstr *lcp; + struct shpstr ship; + struct lndstr land; + /* leave at least 1 military in sectors/ships */ + int minimum=(type == I_MILIT ? 1 : 0); + int can_move; + double move_cost, weight, mobcost; + int packing; + extern double eatrate; + extern int etu_per_update; + struct dchrstr *dp; + struct ichrstr *ip; + s_char buf[1024]; + + /* try to get it from sector we're in */ + getsect(x,y,&dest); + getsect(x,y,§); + if (sect.sct_own == own){ + getvec(VT_ITEM, vec, (s_char *)§, EF_SECTOR); + if ((vec[type]-minimum) >= wanted){ + vec[type] -= wanted; + if (actually_doit){ + putvec(VT_ITEM,vec,(s_char *)§,EF_SECTOR); + putsect(§); + } + return total_wanted; + }else if ((vec[type]-minimum) > 0){ + gotten += (vec[type]-minimum); + wanted -= (vec[type]-minimum); + vec[type] = minimum; + if (actually_doit){ + putvec(VT_ITEM,vec,(s_char *)§,EF_SECTOR); + putsect(§); + } + } + } + /* look for a headquarters or warehouse */ + lookrange = tfact(own,(double)10.0); + snxtsct_dist(&ns, x, y, lookrange); + while (nxtsct(&ns, §) && wanted){ + if (sect.sct_own != own) + continue; + if ((sect.sct_type != SCT_WAREH) && + (sect.sct_type != SCT_HEADQ) && + (sect.sct_type != SCT_HARBR)) + continue; + if ((sect.sct_type == SCT_HEADQ) && + (sect.sct_dist_x == sect.sct_x) && + (sect.sct_dist_y == sect.sct_y)) + continue; + if (sect.sct_effic < 60) + continue; + if (BestLandPath(buf, &dest,§,&move_cost,MOB_ROAD) == (s_char *)0) + continue; + getvec(VT_ITEM, vec, (s_char *)§, EF_SECTOR); + if (!opt_NOFOOD && type == I_FOOD) { + minimum=(((double)etu_per_update * eatrate) * + (double)(vec[I_CIVIL]+vec[I_MILIT]+vec[I_UW])) + +2; + } + if (vec[type] <= minimum) { + /* Don't bother... */ + continue; + } + ip = &ichr[type]; + dp = &dchr[sect.sct_type]; + packing = ip->i_pkg[dp->d_pkg]; + if (packing > 1 && sect.sct_effic < 60) + packing = 1; + weight = ((double)ip->i_lbs / (double)packing); + mobcost = move_cost * weight; + if (mobcost > 0) + can_move = ((double)sect.sct_mobil / mobcost); + else + can_move = vec[type]-minimum; + if (can_move > (vec[type]-minimum)) + can_move = (vec[type]-minimum); + + if (can_move >= wanted){ + int n; + + vec[type] -= wanted; + + /* take off mobility for delivering sect */ + n = roundavg(total_wanted*weight*move_cost); + if (n < 0) + n = 0; + if (n > sect.sct_mobil) + n = sect.sct_mobil; + sect.sct_mobil -= (u_char)n; + + if (actually_doit){ + putvec(VT_ITEM, vec, (s_char *)§, EF_SECTOR); + putsect(§); + } + + return total_wanted; + }else if (can_move > 0){ + int n; + gotten += can_move; + wanted -= can_move; + vec[type] -= can_move; + + /* take off mobility for delivering sect */ + n = roundavg(can_move*weight*move_cost); + if (n < 0) + n = 0; + if (n > sect.sct_mobil) + n = sect.sct_mobil; + sect.sct_mobil -= (u_char)n; + + if (actually_doit){ + putvec(VT_ITEM, vec, (s_char *)§, EF_SECTOR); + putsect(§); + } + } + } + + /* look for an owned ship in a harbor */ + snxtitem_dist(&ni, EF_SHIP, x, y, lookrange); + + while (nxtitem(&ni, (s_char *)&ship) && wanted){ + if (ship.shp_own != own) + continue; + + if (!(mchr[(int)ship.shp_type].m_flags & M_SUPPLY)) + continue; + getsect(ship.shp_x,ship.shp_y,§); + if (sect.sct_type != SCT_HARBR) + continue; + if (sect.sct_effic < 2) + continue; + if (BestLandPath(buf, &dest,§,&move_cost,MOB_ROAD) == (s_char *)0) + continue; + getvec(VT_ITEM, vec, (s_char *)&ship, EF_SHIP); + if (!opt_NOFOOD && type == I_FOOD) + minimum=(((double)etu_per_update * eatrate) * + (double)(vec[I_CIVIL]+vec[I_MILIT]+vec[I_UW])) + +2; + if (vec[type] <= minimum) { + /* Don't bother... */ + continue; + } + ip = &ichr[type]; + dp = &dchr[sect.sct_type]; + packing = ip->i_pkg[dp->d_pkg]; + if (packing > 1 && sect.sct_effic < 60) + packing = 1; + weight = ((double)ip->i_lbs / (double)packing); + mobcost = move_cost * weight; + if (mobcost > 0) + can_move = ((double)sect.sct_mobil / mobcost); + else + can_move = vec[type]-minimum; + if (can_move > (vec[type]-minimum)) + can_move = (vec[type]-minimum); + if (can_move >= wanted){ + int n; + vec[type] -= wanted; + + n = roundavg(wanted*weight*move_cost); + if (n < 0) + n = 0; + if (n > sect.sct_mobil) + n = sect.sct_mobil; + sect.sct_mobil -= (u_char)n; + if (actually_doit){ + putvec(VT_ITEM, vec, (s_char *)&ship, EF_SHIP); + putship(ship.shp_uid,&ship); + putsect(§); + } + return total_wanted; + }else if (can_move > 0){ + int n; + gotten += can_move; + wanted -= can_move; + vec[type] -= can_move; + + n = roundavg(can_move*weight*move_cost); + if (n < 0) + n = 0; + if (n > sect.sct_mobil) + n = sect.sct_mobil; + sect.sct_mobil -= (u_char)n; + + if (actually_doit){ + putvec(VT_ITEM, vec, (s_char *)&ship, EF_SHIP); + putship(ship.shp_uid,&ship); + putsect(§); + } + } + } + + /* look for an owned supply unit */ + snxtitem_dist(&ni, EF_LAND, x, y, lookrange); + + while (nxtitem(&ni, (s_char *)&land) && wanted){ + int min; + + if (land.lnd_own != own) + continue; + + lcp = &lchr[(int)land.lnd_type]; + if (!(lcp->l_flags & L_SUPPLY)) + continue; + + getvec(VT_ITEM, vec, (s_char *)&land, EF_LAND); + if (vec[type] <= get_minimum(&land,type)) + continue; + + getsect(land.lnd_x,land.lnd_y,§); + if (BestLandPath(buf, &dest,§,&move_cost,MOB_ROAD) == (s_char *)0) + continue; + + if ((land.lnd_ship >= 0) && (sect.sct_type != SCT_HARBR)) + continue; + + if ((land.lnd_ship >= 0) && (sect.sct_effic < 2)) + continue; + + if ((vec[type]-wanted) < get_minimum(&land,type)){ + int hold; + struct lndstr l2; + + bcopy((s_char *)&land,(s_char *)&l2,sizeof(struct lndstr)); + hold = vec[type]; + vec[type] = 0; + putvec(VT_ITEM, vec, (s_char *)&land, EF_LAND); + land.lnd_fuel = 0; + putland(land.lnd_uid,&land); + hold += s_commod(own,land.lnd_x,land.lnd_y,type,wanted, actually_doit); + vec[type] = hold; + putvec(VT_ITEM, vec, (s_char *)&land, EF_LAND); + putland(land.lnd_uid,&land); + if (!actually_doit) + putland(l2.lnd_uid,&l2); + } + + getvec(VT_ITEM, vec, (s_char *)&land, EF_LAND); + ip = &ichr[type]; + weight = ((double)ip->i_lbs); + mobcost = move_cost * weight; + if (mobcost > 0) + can_move = ((double)land.lnd_mobil / mobcost); + else + can_move = vec[type]-min; + min = get_minimum(&land,type); + if (can_move > (vec[type]-min)) + can_move = (vec[type]-min); + + if (can_move >= wanted){ + vec[type] -= wanted; + + /* resupply the supply unit */ + resupply_commod(&land, type); + + land.lnd_mobil -= roundavg(wanted*weight*move_cost); + + if (actually_doit){ + putvec(VT_ITEM, vec, (s_char *)&land, EF_LAND); + putland(land.lnd_uid,&land); + } + return total_wanted; + }else if (can_move > 0){ + gotten += can_move; + wanted -= can_move; + vec[type] -= can_move; + + land.lnd_mobil -= roundavg(can_move*weight*move_cost); + + if (actually_doit){ + putvec(VT_ITEM, vec, (s_char *)&land, EF_LAND); + putland(land.lnd_uid,&land); + } + } + } + + /* We've done the best we could */ + /* return the number gotten */ + return gotten; +} + + +s_char * +itemname(int type) +{ + register int t; + register struct ichrstr *ip; + + t=V_ITEM(type); + for (ip = &ichr[1]; ip->i_mnem != 0; ip++) { + if (t == ip->i_vtype) + return ip->i_name; + } + return 0; +} + +int +at_minimum(struct lndstr *lp, int type) +{ + int vec[I_MAX+1]; + + getvec(VT_ITEM, vec, (s_char *)lp, EF_LAND); + if (vec[type] <= get_minimum(lp,type)) + return 1; + + return 0; +} + +/* + * We want to get enough shells to fire once, + * one update's worth of food, enough fuel for + * one update. + */ + +int +get_minimum(struct lndstr *lp, int type) +{ + struct lchrstr *lcp; + int max, want=0; + extern double eatrate; + extern int etu_per_update; + extern float land_mob_scale; + + lcp = &lchr[(int)lp->lnd_type]; + max = vl_find(V_ITEM(type), lcp->l_vtype, lcp->l_vamt, (int) lcp->l_nv); + + switch (type) { + case I_FOOD: + if (opt_NOFOOD) + return 0; /* no food reqd, get out */ + want = (((double)etu_per_update * eatrate) * + (double)total_mil(lp))+1; + break; + case I_SHELL: + want = lp->lnd_ammo; + break; + + /* + * return the amount of pet we'd need to get to + * enough fuel for 1 update + * + */ + case I_PETROL: + if (opt_FUEL == 0) return 0; + want = (lp->lnd_fuelu * (((float)etu_per_update * + land_mob_scale))/10.0); + want -= lp->lnd_fuel; + if (want > 0){ + double d; + d = (double)want/10.0; + want = (int)d; + if (want == 0) + want++; + } + + max = want; + break; + default: return 0; + } + + if (want > max) + want = max; + + return want; +} + +int +has_supply(struct lndstr *lp) +{ + struct lchrstr *lcp; + int vec[I_MAX+1], shells_needed, shells, keepshells; + int food, food_needed, keepfood; + int fuel_needed, fuel, petrol_needed, petrol, keeppetrol; + + lcp = &lchr[(int)lp->lnd_type]; + getvec(VT_ITEM, vec, (s_char *)lp, EF_LAND); + + if (!opt_NOFOOD) { + food_needed = get_minimum(lp,I_FOOD); + food = keepfood = vec[I_FOOD]; + if (food < food_needed){ + vec[I_FOOD]=0; + putvec(VT_ITEM, vec, (s_char *)lp, EF_LAND); + food += try_supply_commod(lp->lnd_own,lp->lnd_x,lp->lnd_y, + I_FOOD,(food_needed-food)); + vec[I_FOOD]=keepfood; + putvec(VT_ITEM, vec, (s_char *)lp, EF_LAND); + } + if (food < food_needed) + return 0; + + } + + shells_needed = lp->lnd_ammo; + shells = keepshells = vec[I_SHELL]; + if (shells < shells_needed){ + vec[I_SHELL]=0; + putvec(VT_ITEM, vec, (s_char *)lp, EF_LAND); + shells += try_supply_commod(lp->lnd_own,lp->lnd_x,lp->lnd_y, + I_SHELL,(shells_needed-shells)); + vec[I_SHELL]=keepshells; + putvec(VT_ITEM, vec, (s_char *)lp, EF_LAND); + } + + if (shells < shells_needed) + return 0; + + if (opt_FUEL) { + fuel_needed = lp->lnd_fuelu; + + fuel = lp->lnd_fuel; + + petrol=petrol_needed = 0; + + if (fuel < fuel_needed){ + petrol_needed = + ldround(((double)(fuel_needed-fuel)/10.0),1); + petrol = keeppetrol = vec[I_PETROL]; + } + + if (petrol < petrol_needed){ + vec[I_PETROL]=0; + putvec(VT_ITEM, vec, (s_char *)lp, EF_LAND); + petrol += try_supply_commod(lp->lnd_own, + lp->lnd_x,lp->lnd_y, + I_PETROL,(petrol_needed-petrol)); + vec[I_PETROL]=keeppetrol; + putvec(VT_ITEM, vec, (s_char *)lp, EF_LAND); + fuel += petrol*10; + } + + if (fuel < fuel_needed) + return 0; + } /* end opt_FUEL */ + + return 1; +} + +int +use_supply(struct lndstr *lp) +{ + struct lchrstr *lcp; + int vec[I_MAX+1], shells_needed, shells, food, food_needed; + int fuel_needed, fuel, petrol_needed, petrol; + + lcp = &lchr[(int)lp->lnd_type]; + getvec(VT_ITEM, vec, (s_char *)lp, EF_LAND); + + shells_needed = lp->lnd_ammo; + shells = vec[I_SHELL]; + if (shells < shells_needed){ + vec[I_SHELL] = 0; + putvec(VT_ITEM, vec, (s_char *)lp, EF_LAND); + shells += supply_commod(lp->lnd_own,lp->lnd_x,lp->lnd_y,I_SHELL, + (shells_needed-shells)); + vec[I_SHELL] = shells; + } + + vec[I_SHELL] = max(vec[I_SHELL] - shells_needed, 0); + + if (lp->lnd_frg) /* artillery */ + goto artillery; + + food_needed = get_minimum(lp,I_FOOD); + food = vec[I_SHELL]; + + if (food < food_needed){ + vec[I_FOOD]=0; + putvec(VT_ITEM, vec, (s_char *)lp, EF_LAND); + food += supply_commod(lp->lnd_own,lp->lnd_x,lp->lnd_y,I_FOOD, + (food_needed-food)); + vec[I_FOOD]=food; + } + + vec[I_FOOD] = max(vec[I_FOOD]-food_needed,0); + + if (opt_FUEL) { + fuel_needed = lp->lnd_fuelu; + fuel = lp->lnd_fuel; + + petrol=petrol_needed = 0; + + if (fuel < fuel_needed){ + petrol_needed = + ldround(((double)(fuel_needed-fuel)/10.0),1); + petrol = vec[I_PETROL]; + } + + if (petrol < petrol_needed){ + vec[I_PETROL]=0; + putvec(VT_ITEM, vec, (s_char *)lp, EF_LAND); + petrol += supply_commod(lp->lnd_own, + lp->lnd_x,lp->lnd_y, + I_PETROL,(petrol_needed-petrol)); + vec[I_PETROL]=petrol; + } + + if (petrol_needed){ + if (petrol>=petrol_needed){ + vec[I_PETROL]= + max(vec[I_PETROL]-petrol_needed,0); + lp->lnd_fuel += petrol_needed * 10; + } + else{ + lp->lnd_fuel += vec[I_PETROL]*10; + vec[I_PETROL]=0; + } + } + + lp->lnd_fuel = max(lp->lnd_fuel - fuel_needed, 0); + } /* end opt_FUEL */ + + artillery: + putvec(VT_ITEM, vec, (s_char *)lp, EF_LAND); + putland(lp->lnd_uid,lp); + return 1; +} + diff --git a/src/lib/subs/takeover.c b/src/lib/subs/takeover.c new file mode 100644 index 00000000..c1bac946 --- /dev/null +++ b/src/lib/subs/takeover.c @@ -0,0 +1,342 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * takeover.c: Take over from another country + * + * Known contributors to this file: + * Dave Pare, 1986 + * Steve McClure, 1996-2000 + */ + +#include "misc.h" +#include "var.h" +#include "sect.h" +#include "xy.h" +#include "nsc.h" +#include "nat.h" +#include "plane.h" +#include "land.h" +#include "ship.h" +#include "file.h" +#include "prototypes.h" +#include "optlist.h" + +#define CHE_MAX 255 + +void takeover_land(register struct lndstr *landp, natid newown, int hostile); +void takeover_plane(register struct plnstr *pp, natid newown); + +void +takeover(register struct sctstr *sp, natid newown) +{ + struct plnstr *pp; + struct lndstr *lp; + int civ; + int che; + int che_count; + int oldche; + int n, vec[I_MAX+1]; + double odds; + struct nstr_item ni; + struct plnstr p; + struct lndstr land; + extern double hap_fact(struct natstr *, struct natstr *); + extern int etu_per_update; + extern int sect_mob_neg_factor; + + /* Wipe all the distribution info */ + bzero((s_char *)vec, sizeof(vec)); + putvec(VT_DIST, vec, (s_char *)sp, EF_SECTOR); + putvec(VT_DEL, vec, (s_char *)sp, EF_SECTOR); + if (sp->sct_own == 0) + sp->sct_off = 0; + else + sp->sct_off = 1; + sp->sct_dist_x = sp->sct_x; + sp->sct_dist_y = sp->sct_y; + + pp = &p; + /* Take over planes */ + snxtitem_dist(&ni, EF_PLANE, sp->sct_x, sp->sct_y, 0); + while (nxtitem(&ni, (caddr_t)pp)) { + if (pp->pln_own != sp->sct_own) + continue; + takeover_plane(pp, newown); + } + + /* Take over land units */ + lp = &land; + snxtitem_dist(&ni, EF_LAND, sp->sct_x, sp->sct_y, 0); + while (nxtitem(&ni, (caddr_t)lp)) { + if ((lp->lnd_own == newown) || (lp->lnd_own == 0)) + continue; + if (lp->lnd_own != sp->sct_own) + continue; + if (lp->lnd_ship >= 0 || lp->lnd_land >= 0) + continue; + /* Spies get a chance to hide */ + if (lchr[(int)lp->lnd_type].l_flags & L_SPY) { + odds = (double)(100 - lp->lnd_effic) + 0.10; + if (!(chance(odds))) + continue; + } + n = lp->lnd_effic - (30 + (random() % 100)); + if (n < 0) + n = 0; + lp->lnd_effic = n; + if (lp->lnd_effic < LAND_MINEFF) { + lp->lnd_effic = 0; + mpr(newown,"%s blown up by the crew!\n", prland(lp)); + wu(0, lp->lnd_own, + "%s blown up by the crew when %s took %s!\n", + prland(lp), + cname(newown), xyas(lp->lnd_x, lp->lnd_y, lp->lnd_own)); + } else { + mpr(newown, "We have captured %s!\n", prland(lp)); + wu(0, lp->lnd_own, + "%s captured when %s took %s!\n", + prland(lp), + cname(newown), xyas(lp->lnd_x, lp->lnd_y, lp->lnd_own)); + } + takeover_land(lp, newown, 1); + } + + sp->sct_avail = 0; + civ = getvar(V_CIVIL, (s_char *)sp, EF_SECTOR); + oldche = get_che_value(getvar(V_CHE, (s_char *)sp, EF_SECTOR)); + /* + * create guerrillas from civilians + * how spunky are these guys? + * n: random number from -25:75 + (50 - loyalty) + */ + n = (50 - sp->sct_loyal) + ((random() % 100) - 25); + che_count = 0; + che = 0; + if (n > 0 && sp->sct_own == sp->sct_oldown) { + che_count = (civ * n/3000) + 5; + if (che_count * 2 > civ) + che_count = civ / 2; + che_count /= hap_fact(getnatp(newown),getnatp(sp->sct_own)); + if (che_count + oldche > CHE_MAX) + che_count = CHE_MAX - oldche; + if (che_count > 0) { + civ -= che_count; + che_count += oldche; + } else + che_count = oldche; + } else + che_count = oldche; + set_che_value(che, che_count); + if (newown != sp->sct_oldown) + set_che_cnum(che, newown); + (void) putvar(V_CHE, che, (s_char *)sp, EF_SECTOR); + (void) putvar(V_CIVIL, civ, (s_char *)sp, EF_SECTOR); + if (sp->sct_oldown == newown || civ == 0) { + /* + * taking over one of your old sectors + */ + sp->sct_loyal = 0; + sp->sct_oldown = newown; + } else { + /* + * taking over someone else's sector + */ + sp->sct_loyal = 50; + } + makelost(EF_SECTOR, sp->sct_own, 0, sp->sct_x, sp->sct_y); + makenotlost(EF_SECTOR, newown, 0, sp->sct_x, sp->sct_y); + sp->sct_own = newown; + if (opt_MOB_ACCESS) { + time(&sp->sct_access); + sp->sct_mobil = -(etu_per_update / sect_mob_neg_factor); + } else { + sp->sct_mobil = 0; + } +} + +void +takeover_plane(register struct plnstr *pp, natid newown) +{ + int n; + + if ((pp->pln_own == newown) || (pp->pln_own == 0)) + return; + if (pp->pln_flags & PLN_LAUNCHED) + return; + if (pp->pln_ship >= 0 || pp->pln_land >= 0) + return; + /* + * XXX If this was done right, planes could escape, + * flying to a nearby friendly airport. + */ + n = pp->pln_effic - (30 + (random() % 100)); + if (n < 0) n = 0; + pp->pln_effic = n; + if (pp->pln_effic < PLANE_MINEFF || pp->pln_harden > (s_char)0) { + pp->pln_effic = 0; + mpr(newown,"%s blown up by the crew!\n", prplane(pp)); + wu(0, pp->pln_own, + "%s blown up by the crew to avoid capture by %s at %s!\n", + prplane(pp), + cname(newown), xyas(pp->pln_x, pp->pln_y, pp->pln_own)); + } else { + mpr(newown, "We have captured %s!\n", prplane(pp)); + wu(0, pp->pln_own, + "%s captured by %s at %s!\n", + prplane(pp), + cname(newown), xyas(pp->pln_x, pp->pln_y, pp->pln_own)); + } + if (opt_MARKET) + trdswitchown(EF_PLANE, (int *)pp, newown); + if (pp->pln_mobil > (s_char)0) + pp->pln_mobil = 0; + makelost(EF_PLANE, pp->pln_own, pp->pln_uid, pp->pln_x, pp->pln_y); + pp->pln_own = newown; + makenotlost(EF_PLANE, pp->pln_own, pp->pln_uid, pp->pln_x, pp->pln_y); + pp->pln_mission = 0; + putplane(pp->pln_uid, pp); +} + +void +takeover_ship(register struct shpstr *sp, natid newown, int hostile) +{ + register struct plnstr *pp; + register struct lndstr *lp; + struct nstr_item ni; + struct plnstr p; + struct lndstr llp; + + if (opt_MARKET) + trdswitchown(EF_SHIP, (int *)sp, newown); + makelost(EF_SHIP, sp->shp_own, sp->shp_uid, sp->shp_x, sp->shp_y); + sp->shp_own = newown; + makenotlost(EF_SHIP, sp->shp_own, sp->shp_uid, sp->shp_x, sp->shp_y); + sp->shp_mission = 0; + sp->shp_fleet = ' '; + sp->shp_rflags = 0; + /* Keep track of when this was taken over */ + time(&sp->shp_access); + bzero(sp->shp_rpath,RET_LEN); + pp = &p; + lp = &llp; + /* Take over planes */ + snxtitem_all(&ni, EF_PLANE); + while (nxtitem(&ni, (caddr_t)pp)) { + if (pp->pln_ship != sp->shp_uid) + continue; + if (pp->pln_own == 0) + continue; + if (hostile) { + if (pp->pln_effic > PLANE_MINEFF) + pp->pln_effic = PLANE_MINEFF; + } + pp->pln_mobil = 0; + /* Keep track of when this was taken over */ + time(&pp->pln_access); + if (opt_MARKET) + trdswitchown(EF_PLANE, (int *)pp, newown); + pp->pln_mission = 0; + makelost(EF_PLANE, pp->pln_own, pp->pln_uid, pp->pln_x, pp->pln_y); + pp->pln_own = newown; + makenotlost(EF_PLANE, pp->pln_own, pp->pln_uid, pp->pln_x, pp->pln_y); + putplane(pp->pln_uid, pp); + } + /* Take over land units */ + snxtitem_all(&ni, EF_LAND); + while (nxtitem(&ni, (caddr_t)lp)) { + if (lp->lnd_ship != sp->shp_uid) + continue; + if (lp->lnd_own == 0) + continue; + takeover_land(lp, newown, hostile); + } + putship(sp->shp_uid, sp); +} + +void +takeover_land(register struct lndstr *landp, natid newown, int hostile) +{ + register struct plnstr *pp; + register struct lndstr *lp; + struct nstr_item ni; + struct plnstr p; + struct lndstr llp; + + if (landp->lnd_effic < LAND_MINEFF) { + putland(landp->lnd_uid, landp); + return; + } + landp->lnd_army = ' '; + landp->lnd_mobil = 0; + landp->lnd_harden = 0; + /* Keep track of when this was taken over */ + time(&landp->lnd_access); + if (opt_MARKET) + trdswitchown(EF_LAND, (int *)landp, newown); + landp->lnd_mission = 0; + makelost(EF_LAND, landp->lnd_own, landp->lnd_uid, landp->lnd_x, landp->lnd_y); + landp->lnd_own = newown; + makenotlost(EF_LAND, landp->lnd_own, landp->lnd_uid, landp->lnd_x, landp->lnd_y); + pp = &p; + lp = &llp; + /* Take over planes */ + snxtitem_all(&ni, EF_PLANE); + while (nxtitem(&ni, (caddr_t)pp)) { + if (pp->pln_land != landp->lnd_uid) + continue; + if (pp->pln_own == 0) + continue; + if (hostile) { + if (pp->pln_effic > PLANE_MINEFF) + pp->pln_effic = PLANE_MINEFF; + } + pp->pln_mobil = 0; + /* Keep track of when this was taken over */ + time(&pp->pln_access); + if (opt_MARKET) + trdswitchown(EF_PLANE, (int *)pp, newown); + pp->pln_mission = 0; + makelost(EF_PLANE, pp->pln_own, pp->pln_uid, pp->pln_x, pp->pln_y); + pp->pln_own = newown; + makenotlost(EF_PLANE, pp->pln_own, pp->pln_uid, pp->pln_x, pp->pln_y); + putplane(pp->pln_uid, pp); + } + /* Take over land units */ + snxtitem_all(&ni, EF_LAND); + while (nxtitem(&ni, (caddr_t)lp)) { + if (lp->lnd_land != landp->lnd_uid) + continue; + if (lp->lnd_own == 0) + continue; + takeover_land(lp, newown, hostile); + } + putland(landp->lnd_uid, landp); +} + + + + diff --git a/src/lib/subs/trdsub.c b/src/lib/subs/trdsub.c new file mode 100644 index 00000000..cf4d947c --- /dev/null +++ b/src/lib/subs/trdsub.c @@ -0,0 +1,327 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * trdsub.c: Trade helper functions + * + * Known contributors to this file: + * St Phil, 1989 + * Pat Loney, 1992 + * Steve McClure, 1996 + */ + +#include "misc.h" +#include "player.h" +#include "var.h" +#include "sect.h" +#include "nat.h" +#include "item.h" +#include "ship.h" +#include "land.h" +#include "nuke.h" +#include "plane.h" +#include "trade.h" +#include "xy.h" +#include "nsc.h" +#include "file.h" +#include "loan.h" +#include "prototypes.h" +#include "optlist.h" + +int +trade_check_ok(int lot, struct trdstr *tp, union trdgenstr *tgp) +{ + union trdgenstr check; + struct trdstr trade; + int result = 0; + + trade_getitem(tp, &check); + if (tp->trd_type == EF_LAND) + result = memcmp(&(check.lnd), &(tgp->lnd), sizeof(struct lndstr)); + else if (tp->trd_type == EF_PLANE) + result = memcmp(&(check.pln), &(tgp->pln), sizeof(struct plnstr)); + else if (tp->trd_type == EF_SHIP) + result = memcmp(&(check.shp), &(tgp->shp), sizeof(struct shpstr)); + else + result = memcmp(&(check.nuk), &(tgp->nuk), sizeof(struct nukstr)); + if (result) { + pr("That item has changed!\n"); + return 0; + } + gettrade(lot, &trade); + if (memcmp((s_char *)&trade, (s_char *)tp, sizeof(struct trdstr))) { + pr("That item has changed!\n"); + return 0; + } + return 1; +} + +s_char * +trade_nameof(struct trdstr *tp, union trdgenstr *tgp) +{ + switch (tp->trd_type) { + case EF_NUKE: + return "nuclear stockpile"; + case EF_PLANE: + return plchr[(int)tgp->pln.pln_type].pl_name; + case EF_SHIP: + return mchr[(int)tgp->shp.shp_type].m_name; + case EF_LAND: + return lchr[(int)tgp->lnd.lnd_type].l_name; + } + return "Bad trade type, get help"; +} + +/* + * Describe an item up for sale. "tgp" is a union containing + * the details of the generic item. + * Return 1 on success, 0 on error + */ +int +trade_desc(struct trdstr *tp, union trdgenstr *tgp) +{ + int i; + float price; + struct sctstr sect; + struct nukstr *np; + struct shpstr *sp; + struct plnstr *pp; + struct lndstr *lp; + struct natstr *natp; + int needcomma; + struct nstr_item ni; + struct plnstr plane; + struct lndstr land; + + price = multread(tp->trd_owner, player->cnum) * tp->trd_price; + switch (tp->trd_type) { + case EF_NUKE: + np = &tgp->nuk; + if (!getsect(np->nuk_x, np->nuk_y, §)) + return 0; + tp->trd_owner = sect.sct_own; + natp = getnatp(tp->trd_owner); + pr("(%3d) ", sect.sct_own); + needcomma = 0; + for (i = 0; i < N_MAXNUKE; i++) { + if (np->nuk_types[i]) { + if (needcomma) + pr(","); + pr("%dx%s", np->nuk_types[i], nchr[i].n_name); + needcomma = 1; + } + } + break; + case EF_SHIP: + sp = &tgp->shp; + tp->trd_owner = sp->shp_own; + pr("(%3d) tech %d %d%% %s [", + tp->trd_owner, + sp->shp_tech, + sp->shp_effic, + prship(sp)); + + for (i = 0; i < sp->shp_nv; i++) { + pr("%c:%d ", + ichr[sp->shp_vtype[i] & ~VT_TYPE].i_mnem, + sp->shp_vamt[i]); + } + pr("] #%d", tp->trd_unitid); + if (opt_SHOWPLANE) { + snxtitem_all(&ni, EF_PLANE); + while (nxtitem(&ni, (s_char *)&plane)) + { + if (plane.pln_ship == sp->shp_uid && + plane.pln_own != 0) + { + pr("\n\t\t\t\t tech %3d %3d%% %s #%d", + plane.pln_tech, + plane.pln_effic, + plchr[(int)plane.pln_type].pl_name, + plane.pln_uid); + if (plane.pln_nuketype != (s_char)-1) + { + pr("(%s)",nchr[(int)plane.pln_nuketype].n_name); + } + } + } + snxtitem_all(&ni, EF_LAND); + while (nxtitem(&ni, (s_char *)&land)) + { + if (land.lnd_ship == sp->shp_uid && + land.lnd_own != 0) + { + pr("\n\t\t\t\t tech %3d %3d%% %s #%d", + land.lnd_tech, + land.lnd_effic, + lchr[(int)land.lnd_type].l_name, + land.lnd_uid); + if (land.lnd_nxlight) + { + snxtitem_all(&ni, EF_PLANE); + while (nxtitem(&ni, (s_char *)&plane)) + { + if (plane.pln_land == land.lnd_uid) + { + pr("\n\t\t\t\t tech %3d %3d%% %s #%d", + plane.pln_tech, + plane.pln_effic, + plchr[(int)plane.pln_type].pl_name, + plane.pln_uid); + if (plane.pln_nuketype != (s_char)-1) + { + pr("(%s)", + nchr[(int)plane.pln_nuketype].n_name); + } + } + } + } + } + } + } + getsect(sp->shp_x, sp->shp_y, §); + if (sect.sct_type != SCT_WATER) + pr(" in a %s %s", cname(sect.sct_own), + dchr[sect.sct_type].d_name); + else + pr(" at sea"); + break; + case EF_LAND: + lp = &tgp->lnd; + tp->trd_owner = lp->lnd_own; + pr("(%3d) tech %d %d%% %s [", + tp->trd_owner, + lp->lnd_tech, + lp->lnd_effic, + lchr[(int)lp->lnd_type].l_name); + for (i = 0; i < lp->lnd_nv; i++) { + pr("%c:%d ", + ichr[lp->lnd_vtype[i] & ~VT_TYPE].i_mnem, + lp->lnd_vamt[i]); + } + pr("] #%d", tp->trd_unitid); + if (opt_SHOWPLANE) { + snxtitem_all(&ni, EF_PLANE); + while (nxtitem(&ni, (s_char *)&plane)) + { + if (plane.pln_land == lp->lnd_uid && + plane.pln_own != 0) + { + pr("\n\t\t\t\t tech %3d %3d%% %s #%d", + plane.pln_tech, + plane.pln_effic, + plchr[(int)plane.pln_type].pl_name, + plane.pln_uid); + if (plane.pln_nuketype != (s_char)-1) + { + pr("(%s)", + nchr[(int)plane.pln_nuketype].n_name); + } + } + } + } + getsect(lp->lnd_x, lp->lnd_y, §); + break; + case EF_PLANE: + pp = &tgp->pln; + tp->trd_owner = pp->pln_own; + pr("(%3d) tech %d %d%% %s #%d", + tp->trd_owner, + pp->pln_tech, + pp->pln_effic, + plchr[(int)pp->pln_type].pl_name, + tp->trd_unitid); + if (pp->pln_nuketype != (s_char)-1) { + pr("(%s)", nchr[(int)pp->pln_nuketype].n_name); + } + break; + default: + pr("flaky unit type %d", tp->trd_type); + break; + } + return 1; +} + +int +trade_getitem(struct trdstr *tp, union trdgenstr *tgp) +{ + if (!ef_read(tp->trd_type, tp->trd_unitid, (s_char *)tgp)) + return 0; + return 1; +} + +long +get_couval(int cnum) +{ + struct sctstr *sp; + register int j, k, val; + long secttot = 0; + + for (j = 0; NULL != (sp = getsectid(j)); j++) { + if (sp->sct_own != cnum) + continue; + secttot += (long)(dchr[sp->sct_type].d_value * + ((float)sp->sct_effic+100.0)); + for (k = 0; ichr[k].i_name; k++) { + if (ichr[k].i_value == 0 || ichr[k].i_vtype == 0) + continue; + val = getvar(ichr[k].i_vtype, (s_char *)sp, EF_SECTOR); + secttot += val * ichr[k].i_value; + } + } + return secttot; +} + +long +get_outstand(int cnum) +{ + struct lonstr loan; + int j; + long loantot = 0; + + for (j = 0; getloan(j, &loan); j++) { + if (loan.l_status == LS_FREE) + continue; + if (loan.l_lonee == cnum) + loantot += loan.l_amtdue; + } + return loantot; +} + +struct ichrstr * +whichitem(char p) +{ + register int i; + + if (p == 0) + return 0; + for (i = 1; ichr[i].i_mnem != 0; i++) + if (p == ichr[i].i_mnem) + return (struct ichrstr *)(&ichr[i]); + pr("Unrecognized item \"%c\"\n", p); + return 0; +} + diff --git a/src/lib/subs/trechk.c b/src/lib/subs/trechk.c new file mode 100644 index 00000000..e301f45c --- /dev/null +++ b/src/lib/subs/trechk.c @@ -0,0 +1,134 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * trechk.c: Check to see if an actor has violated a treaty. + * + * Known contributors to this file: + * Steve McClure, 1998-1999 + * + */ +/* + * Check to see if an actor has a treaty forbidding a given action, + * and if so, see if the actor wishes to break the treaty. + * All applicable treaties are checked. All treaties must be broken + * if the action is to be allowed. Propsed treaties are warned about, + * but no mention of broken pending treaties are made in the news. + */ + +#include "misc.h" +#include "treaty.h" +#include "nat.h" +#include "news.h" +#include "file.h" +#include "xy.h" +#include "nsc.h" +#include "prototypes.h" +#include "optlist.h" + +int +trechk(register natid actor, register natid victim, int provision) +{ + register natid cn; + s_char buf[1024]; + int news_verb; + int involved[MAXNOC]; + struct trtstr treaty; + time_t now; + int conditions; + natid other; + int broken; + int applied; + struct nstr_item nstr; + + if (!opt_TREATIES) + return 1; + (void) time(&now); + broken = 0; + applied = 0; + for (cn = 0; cn < MAXNOC; cn++) + involved[cn] = 0; + snxtitem_all(&nstr, EF_TREATY); + while (nxtitem(&nstr, (s_char *)&treaty)) { + if (treaty.trt_status == TS_FREE) + continue; + if (treaty.trt_exp < now) + continue; + if (actor == treaty.trt_cna) { + conditions = treaty.trt_acond; + other = treaty.trt_cnb; + } else if (actor == treaty.trt_cnb) { + conditions = treaty.trt_bcond; + other = treaty.trt_cna; + } else + continue; + if ((conditions & provision) == 0) + continue; + if (victim != other) { + switch (provision) { + /* These are violations no matter who the victim is */ + case NEWSHP: + case NEWLND: + case NEWNUK: + case NEWPLN: + case TRTENL: + break; + default: + /* The rest are only violations against the victim */ + continue; + } + } + /* treaty applies to actor */ + applied++; + pr("This action is in contravention of "); + if (treaty.trt_status == TS_PROPOSED) + pr("pending "); + pr(" treaty #%d (with %s)\n", nstr.cur, cname(other)); + getstring("Do you wish to go ahead anyway? [yn] ", buf); + if (*buf == 'n' || *buf == 'N') + broken = 0; + else + broken = 1; + if (treaty.trt_status == TS_SIGNED) + involved[other]++; + } + if (applied > 0) { + news_verb = N_HONOR_TRE; + if (broken > 0) + news_verb = N_VIOL_TRE; + for (cn=0; cn < MAXNOC; cn++) + if (involved[cn] > 0) + nreport(actor, news_verb, cn, 1); + } + if (applied && !broken) { + /* + * if any treaty applied, and none were broken + * the intended action is NOT performed. + */ + return 0; + } + return 1; +} diff --git a/src/lib/subs/whatitem.c b/src/lib/subs/whatitem.c new file mode 100644 index 00000000..e531739c --- /dev/null +++ b/src/lib/subs/whatitem.c @@ -0,0 +1,54 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * whatitem.c: Return pointer to item chr struct given an item name + * + * Known contributors to this file: + * + */ + +#include "misc.h" +#include "item.h" +#include "prototypes.h" + +struct ichrstr * +whatitem(s_char *ptr, s_char *prompt) +{ + register s_char *p; + register struct ichrstr *ip; + s_char buf[1024]; + + p = getstarg(ptr, prompt, buf); + if (p == 0 || *p == 0) + return 0; + for (ip = &ichr[1]; ip->i_mnem != 0; ip++) { + if (*p == ip->i_mnem) + return ip; + } + pr("Unrecognized item \"%c\"\n", *p); + return 0; +} diff --git a/src/lib/subs/wire.c b/src/lib/subs/wire.c new file mode 100644 index 00000000..12e5482e --- /dev/null +++ b/src/lib/subs/wire.c @@ -0,0 +1,89 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * wire.c: Write an announcement to the world + * + * Known contributors to this file: + * + */ + +#include "misc.h" +#include +#if !defined(_WIN32) +#include +#endif +#include "nat.h" +#include "tel.h" +#include "file.h" +#include "prototypes.h" + +#if 0 +int +typed_wire(natid from, natid to, s_char *message, int type) +{ + register s_char *bp; + int len; + struct telstr tel; + struct natstr *np; + struct iovec iov[2]; + int fd; + s_char buf[1024]; + + if ((np = getnatp(to)) == 0 || + ((np->nat_stat & STAT_NORM) == 0 && + (np->nat_stat & STAT_SANCT) == 0)) + return 0; + if ((fd = open(wirebox(buf, to), O_WRONLY|O_APPEND, 0)) < 0) { + logerror("telegram 'open' of %s (#%d) failed", + wirebox(buf, to), to); + return 0; + } + tel.tel_from = from; + (void) time(&tel.tel_date); + bp = message; + while (*bp++) + ; + len = bp - message; + if (len >= MAXTELSIZE) + len = MAXTELSIZE; + message[len] = 0; + tel.tel_length = len; + tel.tel_type = type; + iov[0].iov_base = (caddr_t) &tel; + iov[0].iov_len = sizeof(tel); + iov[1].iov_base = message; + iov[1].iov_len = len; + if (writev(fd, iov, 2) < iov[0].iov_len + iov[1].iov_len) { + logerror("telegram 'write' to #%d failed", to); + } else { + np->nat_ann++; + /* don't do putnat because of expense */ + } + (void) close(fd); + return 0; +} +#endif diff --git a/src/lib/subs/wu.c b/src/lib/subs/wu.c new file mode 100644 index 00000000..6f516db2 --- /dev/null +++ b/src/lib/subs/wu.c @@ -0,0 +1,194 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * wu.c: Write a telegram to a user from another + * + * Known contributors to this file: + * Steve McClure, 2000 + * + */ + +#include +#include "misc.h" +#include +#if !defined(_WIN32) +#include +#endif +#include "nat.h" +#include "tel.h" +#include "file.h" +#include "player.h" +#include "prototypes.h" + +static struct telstr last_tel[MAXNOC]; + +void +clear_telegram_is_new(natid to) +{ + last_tel[to].tel_type = 0; + last_tel[to].tel_from = 0; + last_tel[to].tel_date = 0; +} + +/* + * telegram_is_new counts new telegrams the same as read_telegrams in + * lib/commands/mail.c and lib/commands/rea.c + */ + +static int +telegram_is_new (natid to, struct telstr *tel) +{ + extern int update_pending; + int is_new = 0; + + is_new |= tel->tel_type != last_tel[to].tel_type; + is_new |= tel->tel_from != last_tel[to].tel_from; + is_new |= !update_pending && /* sometimes updates take a long time */ + abs (tel->tel_date - last_tel[to].tel_date) > TEL_SECONDS; + + last_tel[to].tel_type = tel->tel_type; + last_tel[to].tel_from = tel->tel_from; + last_tel[to].tel_date = tel->tel_date; + + return is_new; +} + +/*VARARGS*/ +int +wu(natid from, natid to, s_char *format, ...) +{ + struct natstr *np; + va_list ap; + s_char buf[4096]; + extern int update_pending; + + va_start(ap, format); + (void) vsprintf(buf, format, ap); + va_end(ap); + np = getnatp(from); + if (update_pending) + return typed_wu(from, to, buf, TEL_UPDATE); + else if (np->nat_stat & STAT_GOD) + return typed_wu(from, to, buf, TEL_BULLETIN); + else + return typed_wu(from, to, buf, TEL_NORM); +} + +int +typed_wu(natid from, natid to, s_char *message, int type) +{ + register s_char *bp; + int len; + struct telstr tel; + struct natstr *np; +#if !defined(_WIN32) + struct iovec iov[2]; +#endif + int fd; + s_char box[1024]; + int notify = 0; + int new_tele = 0; + struct player *other; + + if (type == TEL_ANNOUNCE) + strcpy(box, annfil); + else + mailbox(box, to); + + if (type != TEL_ANNOUNCE) + if ((np = getnatp(to)) == 0 || + ((np->nat_stat & STAT_NORM) == 0 && + (np->nat_stat & STAT_SANCT) == 0)) { + return -1; + } + +#if !defined(_WIN32) + if ((fd = open(box, O_WRONLY|O_APPEND, 0)) < 0) { +#else + if ((fd = open(box, O_WRONLY|O_APPEND|O_BINARY, 0)) < 0) { +#endif + logerror("telegram 'open' of %s (#%d) failed", box, to); + return -1; + } + tel.tel_from = from; + (void) time(&tel.tel_date); + bp = message; + while (*bp++) + ; + len = bp - message; + if (len >= MAXTELSIZE) + len = (MAXTELSIZE - 1); + message[len] = 0; + tel.tel_length = len; + tel.tel_type = type; +#if !defined(_WIN32) + iov[0].iov_base = (caddr_t) &tel; + iov[0].iov_len = sizeof(tel); + iov[1].iov_base = message; + iov[1].iov_len = len; + if (writev(fd, iov, 2) < (int)(iov[0].iov_len + iov[1].iov_len)) { +#else + if ((write(fd, &tel, sizeof(tel)) != sizeof(tel)) || + (write(fd, message, len) != len)) { +#endif + logerror("telegram 'write' to #%d failed", to); + } else if (type == TEL_ANNOUNCE) { + for (to=0; NULL != (np = getnatp(to)); to++) { + if (!(np->nat_stat & STAT_NORM) && + !(np->nat_stat & STAT_SANCT)) + continue; + if (!player->god && (getrejects(from,np) & REJ_ANNO)) + continue; + notify = (np->nat_ann == 0); + np->nat_ann++; + putnat(np); + if (notify) + player_wakeup_all(to); + } + } else { + notify = (np->nat_tgms == 0); + new_tele = telegram_is_new(to, &tel); + np->nat_tgms += new_tele || notify; + putnat(np); + + if (new_tele && np->nat_flags & NF_INFORM) { + if (NULL != (other = getplayer(to))) { + if (np->nat_tgms == 1) + pr_inform(other, "[new tele]\n"); + else + pr_inform(other, "[%d new teles]\n", + np->nat_tgms); + player_wakeup_all(to); + } + } else if (notify) + player_wakeup_all(to); + } + + close(fd); + return 0; +} + diff --git a/src/lib/update/Makefile b/src/lib/update/Makefile new file mode 100644 index 00000000..54b86cd2 --- /dev/null +++ b/src/lib/update/Makefile @@ -0,0 +1,67 @@ +# +# Empire - A multi-player, client/server Internet based war game. +# Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, +# Ken Stevens, Steve McClure +# +# 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 2 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, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# --- +# +# See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the +# related information and legal notices. It is expected that any future +# projects/authors will amend these files as needed. +# +# Makefile - Wolfpack, 1996 + +# Note that these could have been listed 1 per line, but I chose to just +# stick them all together this way to shorten the file. + +include ../../../build.conf +include ../../make.src +include ../../make.defs + +LIB = $(SRCDIR)/lib/libupdate.a +NTLIB = $(SRCDIR)\lib\libupdate.lib + +OBJS = age.o anno.o bp.o deliver.o distribute.o finish.o human.o land.o \ + main.o material.o mobility.o move_sat.o nat.o nav_ship.o nav_util.o \ + nxtitemp.o nxtsctp.o plague.o plane.o populace.o prepare.o produce.o \ + removewants.o revolt.o sail.o sect.o ship.o + +NTOBJS = age.obj anno.obj bp.obj deliver.obj distribute.obj finish.obj \ + human.obj land.obj main.obj material.obj mobility.obj move_sat.obj \ + nat.obj nav_ship.obj nav_util.obj nxtitemp.obj nxtsctp.obj plague.obj \ + plane.obj populace.obj prepare.obj produce.obj removewants.obj \ + revolt.obj sail.obj sect.obj ship.obj + +all: $(LIB) + +nt: $(NTLIB) + +$(NTLIB): $(NTOBJS) + -del /q $@ + lib /OUT:$@ /DEBUGTYPE:CV $(NTOBJS) + +$(LIB): $(OBJS) + rm -f $(LIB) + ar cq $(LIB) $(OBJS) + $(RANLIB) $(LIB) + +clean: + -(rm -f $(OBJS)) + -(del /q $(NTOBJS)) + +include ../../make.rules +include Makedepend diff --git a/src/lib/update/age.c b/src/lib/update/age.c new file mode 100644 index 00000000..2e1c7896 --- /dev/null +++ b/src/lib/update/age.c @@ -0,0 +1,102 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * age.c: Age people + * + * Known contributors to this file: + * Dave Pare, 1986 + */ + +#include "misc.h" +#include "nat.h" +#include "file.h" +#include "update.h" +#include "gen.h" + +void +age_levels(int etu) +{ + extern float level_age_rate; + register float best_tech; + register float best_res; + register struct natstr *np; + int i; + double level; + double delta; + int deltares; + + best_tech = 0.0; + best_res = 0.0; + for (i=0; NULL != (np = getnatp(i)); i++) { + if ((np->nat_stat & STAT_NORM) == 0) + continue; + + if (np->nat_stat & STAT_GOD) + continue; + + if (np->nat_stat == VIS) + continue; + + if (best_tech < np->nat_level[NAT_TLEV]) + best_tech = np->nat_level[NAT_TLEV]; + if (best_res < np->nat_level[NAT_RLEV]) + best_res = np->nat_level[NAT_RLEV]; + if (level_age_rate != 0.0) { + delta = np->nat_level[NAT_RLEV] * etu / + (100 * level_age_rate); + np->nat_level[NAT_RLEV] -= delta; + delta = np->nat_level[NAT_TLEV] * etu / + (100 * level_age_rate); + np->nat_level[NAT_TLEV] -= delta; + } + /* + * age reserves by 1% per every 24 etus + */ + deltares = -roundavg(np->nat_reserve * etu / 2400.0); + if (deltares != 0) + np->nat_reserve += deltares; + /* Chad Zabel - above number is negative ( was a -= there + which was wrong. */ + } + best_tech /= 5; + best_res /= 5; + for (i=0; NULL != (np = getnatp(i)); i++) { + if ((np->nat_stat & STAT_INUSE) == 0) + continue; + if (np->nat_stat & STAT_GOD) + continue; + if (np->nat_stat == VIS) + continue; + level = np->nat_level[NAT_TLEV]; + if (level < best_tech && chance(0.2)) + np->nat_level[NAT_TLEV] += (best_tech - level) / 3; + level = np->nat_level[NAT_RLEV]; + if (level < best_res && chance(0.2)) + np->nat_level[NAT_RLEV] += (best_res - level) / 3; + } +} + diff --git a/src/lib/update/anno.c b/src/lib/update/anno.c new file mode 100644 index 00000000..76395172 --- /dev/null +++ b/src/lib/update/anno.c @@ -0,0 +1,137 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * anno.c: Delete announcements older than ANNO_KEEP_DAYS + * + * Known contributors to this file: + * Ken Stevens, 1995 + * Doug Hay, 1998 + * Steve McClure, 2000 + */ + +#include "misc.h" +#include "tel.h" +#include +#include +#if !defined(_WIN32) +#include +#include +#endif +#include "update.h" +#include "common.h" + +void +delete_old_announcements(void) +{ + time_t now; + time_t old; + struct telstr tgm; + FILE *oldfp; + int tmpfd; + s_char tmp_filename[1024]; + int writeit; + s_char message[MAXTELSIZE]; + int deleted = 0; + int saved = 0; + int length; + int nbytes; + int first = 1; + + time(&now); + old = now - days(ANNO_KEEP_DAYS); + logerror("Deleting annos older than %s", ctime(&old)); + +#if !defined(_WIN32) + if ((oldfp = fopen(annfil, "r+")) == 0) { +#else + if ((oldfp = fopen(annfil, "r+b")) == 0) { +#endif + logerror("can't read telegram file %s", annfil); + return; + } + sprintf(tmp_filename, "%s.tmp", annfil); +#if !defined(_WIN32) + if ((tmpfd = open(tmp_filename, O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0) { +#else + if ((tmpfd = open(tmp_filename, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, 0666)) < 0) { +#endif + logerror("can't write telegram file %s", tmp_filename); + return; + } + while (fread((s_char *) &tgm, sizeof(tgm), 1, oldfp) == 1) { + writeit = 1; + if (tgm.tel_length < 0) { + logerror("bad telegram file header (length)"); + return; + } + if (tgm.tel_type < 0 || tgm.tel_type > TEL_LAST) { + logerror("bad telegram file header (type)"); + writeit = 0; + } + if (first) { + first = 0; + if (tgm.tel_date >= old) { + fclose(oldfp); + return; + } + } + + if (tgm.tel_date < old) { + writeit = 0; + } + + if (writeit) { + if (write(tmpfd, &tgm, sizeof(tgm)) < (int)sizeof(tgm)) { + logerror("error writing to ann.tmp"); + return; + } + ++saved; + } else { + ++deleted; + } + length = tgm.tel_length; + while (length > 0) { + nbytes = length; + if (nbytes > (int)sizeof(message)) + nbytes = sizeof(message); + (void) fread(message, sizeof(s_char), nbytes, oldfp); + if (writeit) { + if (write(tmpfd, message, nbytes) < nbytes) { + logerror("Error writing to ann.tmp"); + return; + } + } + length -= nbytes; + } + } + logerror("%d announcements deleted; %d announcements saved", + deleted, saved); + fclose(oldfp); + close(tmpfd); + unlink(annfil); + rename(tmp_filename, annfil); +} diff --git a/src/lib/update/bp.c b/src/lib/update/bp.c new file mode 100644 index 00000000..e608f720 --- /dev/null +++ b/src/lib/update/bp.c @@ -0,0 +1,97 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * bp.c: Functions for build pointer (bp) handling + * + * Known contributors to this file: + * Ville Virrankoski, 1996 + */ + +#include "misc.h" +#include "nat.h" +#include "file.h" +#include "sect.h" +#include "var.h" +#include "budg.h" +#include "update.h" +#include "common.h" +#include "optlist.h" + +static int bud_key[I_MAX+2] = {0,1,2,3,4,0,0,0,0,0,0,5,6,0,0,7}; + +int +*get_wp(int *bp, struct sctstr *sp, int cm) +{ + return (bp + (sp->sct_x + (sp->sct_y * WORLD_X)) + WORLD_X * WORLD_Y * (cm - 1)); +} + +int +gt_bg_nmbr(int *bp, struct sctstr *sp, int comm) +{ + int *wp; + int cm; + int svec[I_MAX+1]; + + if ((cm = bud_key[comm]) == 0) { + getvec(VT_ITEM, svec, (s_char *)sp, EF_SECTOR); + return svec[comm]; + } else { + wp = get_wp(bp, sp, cm); + return *wp; + } +} + +void pt_bg_nmbr(int *bp, struct sctstr *sp, int comm, int amount) +{ + int *wp; + int cm; + + if ((cm = bud_key[comm]) != 0) { + wp = get_wp(bp, sp, cm); + *wp = amount; + } +} + +void +fill_update_array(int *bp, struct sctstr *sp) +{ + int vec[I_MAX+1]; + int i, k; + int *wp; + + if (getvec(VT_ITEM, vec, (s_char *)sp, EF_SECTOR) <= 0) + return; + for (i=1;i<=I_MAX;i++) + if ((k = bud_key[i]) != 0) { + wp = get_wp(bp, sp, k); + *wp = vec[i]; + } + wp = get_wp(bp, sp, bud_key[I_MAX+1]); + *wp = sp->sct_avail; +} + + diff --git a/src/lib/update/deliver.c b/src/lib/update/deliver.c new file mode 100644 index 00000000..025b4a01 --- /dev/null +++ b/src/lib/update/deliver.c @@ -0,0 +1,119 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * deliver.c: Deliver commodities to neighboring sector + * + * Known contributors to this file: + * + */ + +#include "misc.h" +#include "var.h" +#include "sect.h" +#include "item.h" +#include "path.h" +#include "file.h" +#include "xy.h" +#include "update.h" +#include "subs.h" +#include "common.h" + +int +deliver(register struct sctstr *from, struct ichrstr *ip, int dir, int thresh, int amt_src, int plague) +{ + register struct sctstr *to; + int vtype; /* item vartype */ + int pack_src; + int amt_moved; + int amt_dst; + int mobility; + float mcost; + struct dchrstr *dp; + int n; + + if (dir <= 0 || dir > DIR_UL) + return 0; + if (amt_src <= 0) + return 0; + if ((amt_moved = amt_src - thresh) <= 0) + return 0; + /* + * make sure delivery looks ok. Check where its going, + * where its coming from, and see if there is more than + * the threshold amount + */ + if (!military_control(from)) + return 0; + to = getsectp(from->sct_x+diroff[dir][0], from->sct_y+diroff[dir][1]); + if (to->sct_own != from->sct_own) { + wu(0, from->sct_own, "%s delivery walkout at %s\n", + ip->i_name, ownxy(from)); + return 0; + } + dp = &dchr[from->sct_type]; + vtype = ip->i_vtype; + pack_src = ip->i_pkg[dp->d_pkg]; + mobility = from->sct_mobil / 2; + if (vtype == V_CIVIL && from->sct_own != from->sct_oldown) { + wu(0, from->sct_own, "The conquered populace in %s refuses to relocate!\n", ownxy(from)); + return 0; + } + /* + * disallow delivery into prohibited sectors. + * calculate unit movement cost; decrease amount if + * there isn't enough mobility. + */ + mcost = sector_mcost(to, MOB_ROAD)*ip->i_lbs/pack_src; + mcost /= 4.0; + + if (mobility < mcost * amt_moved) { + /* XXX can mcost be == 0? */ + amt_moved = (int) (mobility / mcost); + if (amt_moved <= 0) + return 0; + } + amt_dst = getvar(vtype, (caddr_t)to, EF_SECTOR); + if (amt_moved + amt_dst > 9990) { + /* delivery backlog */ + if ((amt_moved = 9990 - amt_dst) <= 0) + return 0; + } + if (putvar(vtype, amt_moved + amt_dst, (s_char *)to, EF_SECTOR) < 0) { + /* "No room to deliver commodities */ + wu(0, from->sct_own, "no room for %s in %s\n", + ip->i_name, ownxy(to)); + return 0; + } + /* deliver the plague too! */ + if (plague == PLG_INFECT && getvar(V_PSTAGE, (s_char *)to,EF_SECTOR) == 0) + putvar(V_PSTAGE, PLG_EXPOSED, (s_char *)to, EF_SECTOR); + n = from->sct_mobil - (int) (mcost * amt_moved); + if (n < 0) + n = 0; + from->sct_mobil = n; + return amt_moved; +} diff --git a/src/lib/update/distribute.c b/src/lib/update/distribute.c new file mode 100644 index 00000000..95b2d3d8 --- /dev/null +++ b/src/lib/update/distribute.c @@ -0,0 +1,223 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * distribute.c: Do distribution to sectors + * + * Known contributors to this file: + * Dave Pare, 1986 + * Steve McClure, 1998 + */ + +#include +#include "misc.h" +#include "var.h" +#include "nat.h" +#include "sect.h" +#include "item.h" +#include "xy.h" +#include "path.h" +#include "file.h" +#include "distribute.h" +#include "update.h" +#include "subs.h" +#include "common.h" + +int +dodistribute(struct sctstr *sp, int imex, s_char *path, double dist_i_cost, double dist_e_cost) + /* import or export? */ +{ + struct sctstr *getdistsp(); + float distpathcost(); + struct ichrstr *ip; + struct sctstr *dist; + int amt; + int thresh; + int amt_dist; + int amt_sect; + int packing; + float imcost; + float excost; + int dist_packing; + int diff; + int item; + int dists[I_MAX+1]; + int remote[I_MAX+1]; + int local[I_MAX+1]; + int changed; + int rplague; + int lplague; + + getvec(VT_ITEM, local, (s_char *)sp, EF_SECTOR); + if ((sp->sct_dist_x == sp->sct_x) && (sp->sct_dist_y == sp->sct_y)) + return 0; + + if (getvec(VT_DIST, dists, (s_char *)sp, EF_SECTOR) <= 0) + return 0; + + if (path == (s_char *)0){ + if (sp->sct_own != 0) { + if (imex == EXPORT) /* only want this once */ + wu(0,sp->sct_own,"No path to dist sector for %s\n", + ownxy(sp)); + } + return 0; + } + + dist = getsectp(sp->sct_dist_x,sp->sct_dist_y); + if (dist->sct_effic >= 60) + dist_packing = dchr[dist->sct_type].d_pkg; + else + dist_packing = NPKG; /* No packing */ + + if (sp->sct_effic >= 60) + packing = dchr[sp->sct_type].d_pkg; + else + packing = NPKG; /* No packing */ + + if ((dist->sct_effic >= 60) && dchr[dist->sct_type].d_pkg == WPKG) + packing = dchr[dist->sct_type].d_pkg; + + getvec(VT_ITEM, remote, (s_char *)dist, EF_SECTOR); + lplague = rplague = changed = 0; + for (item = 1; item < I_MAX+1; item++) { + if (dists[item] == 0) + continue; + ip = &ichr[item]; + thresh = dists[item]; + /* + * calculate costs for importing and exporting. + * the div 10.0 is because delivering straight through + * to the dist sect is cheaper than stopping at each + * sector along the way (processor-timewise) + */ + excost = (dist_e_cost/ip->i_pkg[packing] * ip->i_lbs) / 10.0; + imcost = (dist_i_cost/ip->i_pkg[dist_packing] *ip->i_lbs)/10.0; + amt_sect = local[item]; + amt_dist = remote[item]; + diff = amt_sect - thresh; + if (item == I_CIVIL) + if (sp->sct_own != sp->sct_oldown) + continue; + if (item == I_CIVIL) + if (dist->sct_own != dist->sct_oldown) + continue; + if (diff < 0){ + if (imex != IMPORT) + continue; + + if (!military_control(dist)) + continue; + + diff = -diff; + /* + * import. + * don't import if no mobility. + * check to make sure have enough mobility in the + * dist sector to import what we need. + */ + if (dist->sct_mobil <= 0) { + /*logerror(" dist mobil < 0");*/ + continue; + } + amt = diff; + if (item == I_CIVIL) + amt_dist--; /* Don't send your last civ */ + + if (amt_dist < amt) { + amt = amt_dist; + if (amt_dist == 0) + continue; + } + if (dist->sct_mobil < imcost * amt) + amt = dist->sct_mobil / imcost; + + lplague++; + /* XXX replace with vector assign and putvec() */ + remote[item] -= amt; + changed++; + dist->sct_mobil -= (int) (imcost * amt); + local[item] += amt; + } else { + if (imex != EXPORT) + continue; + if (!military_control(sp)) + continue; + if ((item == I_CIVIL)&&(sp->sct_work < 100)) + continue; + if ((item == I_CIVIL)&&(sp->sct_own != sp->sct_oldown)) + continue; + /* + * export. + * don't export if no mobility. check to make sure we + * have mobility enough to do the right thing. + * also make sure that there's enough space in the + * target sector to hold the required amt. + */ + if (sp->sct_mobil <= 0) { + /*logerror(" sp mob is zero");*/ + continue; + } + amt = diff; + if (amt > amt_sect) + amt = amt_sect; + if (sp->sct_mobil < excost * amt) + amt = sp->sct_mobil / excost; + if (amt + amt_dist > 9999) + amt = 9999 - amt_dist; + if (amt == 0) + continue; + /* XXX replace with vector assign and putvec() */ + + rplague++; + local[item] -= amt; + changed++; + sp->sct_mobil -= (int) (excost * amt); + remote[item] += amt; + } + } + putvec(VT_ITEM, remote, (s_char *)dist, EF_SECTOR); + putvec(VT_ITEM, local, (s_char *)sp, EF_SECTOR); + + if (lplague) { + lplague = getvar(V_PSTAGE, (s_char *)dist, EF_SECTOR); + if (lplague == PLG_INFECT && + getvar(V_PSTAGE, (s_char *)sp, EF_SECTOR) == PLG_HEALTHY) { + putvar(V_PSTAGE, PLG_EXPOSED, (s_char *)sp, EF_SECTOR); + } + } + + if (rplague) { + rplague = getvar(V_PSTAGE, (s_char *)sp, EF_SECTOR); + if (rplague == PLG_INFECT && + getvar(V_PSTAGE, (s_char *)dist, EF_SECTOR) == PLG_HEALTHY) { + putvar(V_PSTAGE, PLG_EXPOSED, (s_char *)dist, EF_SECTOR); + } + } + + return changed; +} + diff --git a/src/lib/update/finish.c b/src/lib/update/finish.c new file mode 100644 index 00000000..6811602d --- /dev/null +++ b/src/lib/update/finish.c @@ -0,0 +1,270 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * finish.c: Finish the update + * + * Known contributors to this file: + * Dave Pare, 1986 + * Thomas Ruschak, 1993 + * Steve McClure, 1998 + */ + +#include +#include "misc.h" +#include "var.h" +#include "sect.h" +#include "nat.h" +#include "item.h" +#include "news.h" +#include "file.h" +#include "xy.h" +#include "path.h" +#include "distribute.h" +#include "update.h" +#include "common.h" +#include "optlist.h" + +/* Used for building up distribution info */ +struct distinfo { + s_char *path; /* path to take */ + double imcost; /* import cost */ + double excost; /* export cost */ +}; + +/* This is our global buffer of distribution pointers. Note that + * We only malloc this once, and never again (until reboot time + * of course :) ) We do clear it each and every time. */ +struct distinfo *g_distptrs = (struct distinfo *)0; + +/* Note that even though we malloc and save the path, it is never + * used. Thus, this option. If you want to malloc and save every + * path and then free when done, just enable this. Or, if the + * dodistribute ever uses the path for something other than checking + * to see that a path exists, enable this */ +/* #define SAVE_FINISH_PATHS */ + +#ifndef SAVE_FINISH_PATHS +static s_char *finish_path = "h"; /* Placeholder indicating path exists */ +#endif /* SAVE_FINISH_PATHS */ + +static void assemble_dist_paths(struct distinfo *distptrs); +s_char *BestDistPath(); +s_char *ReversePath(s_char *path); +double pathcost(); + +void +finish_sects(int etu) +{ + register struct sctstr *sp; + struct natstr *np; + int n; + int vec[I_MAX+1]; + int changed; + struct distinfo *infptr; + + if (g_distptrs == (struct distinfo *)0) { + logerror("First update since reboot, allocating buffer\n"); + /* Allocate the information buffer */ + g_distptrs = (struct distinfo *)(malloc((WORLD_X * WORLD_Y) * + sizeof(struct distinfo))); + if (g_distptrs == (struct distinfo *)0) { + logerror("malloc failed in finish_sects.\n"); + return; + } + + logerror("Allocated '%d' bytes '%d' indices\n", + ((WORLD_X * WORLD_Y) * sizeof(struct distinfo)), + (WORLD_X * WORLD_Y)); + + } + + /* Wipe it clean */ + bzero((s_char *)g_distptrs, ((WORLD_X * WORLD_Y) * + sizeof(struct distinfo))); + + logerror("delivering...\n"); + /* Do deliveries */ + for (n=0; NULL != (sp = getsectid(n)); n++) { + if (sp->sct_type == SCT_WATER) + continue; + if (sp->sct_own == 0) + continue; + np = getnatp(sp->sct_own); + if (np->nat_money < 0) + continue; + changed = 0; + if (getvec(VT_ITEM, vec, (s_char *)sp, EF_SECTOR) > 0) + changed += dodeliver(sp, vec); + if (changed) + putvec(VT_ITEM, vec, (s_char *)sp, EF_SECTOR); + } + logerror("done delivering\n"); + + logerror("assembling paths...\n"); + + /* First, enable the best_path cacheing */ + bp_enable_cachepath(); + + /* Now assemble the paths */ + assemble_dist_paths(g_distptrs); + + /* Now disable the best_path cacheing */ + bp_disable_cachepath(); + + /* Now, clear the best_path cache that may have been created */ + bp_clear_cachepath(); + + logerror("done assembling paths\n"); + + logerror("exporting..."); + for (n=0; NULL != (sp = getsectid(n)); n++) { + if (sp->sct_type == SCT_WATER || sp->sct_own == 0) + continue; + np = getnatp(sp->sct_own); + if (np->nat_money < 0) + continue; + /* Get the pointer */ + infptr = &g_distptrs[XYOFFSET(sp->sct_x, sp->sct_y)]; + dodistribute(sp, EXPORT, + infptr->path, infptr->imcost, infptr->excost); + } + logerror("done exporting\n"); + + /* Note that we free the paths (if allocated) as we loop here */ + logerror("importing..."); + for (n=0; NULL != (sp = getsectid(n)); n++) { + /* Get the pointer (we do it first so we can free if needed) */ + infptr = &g_distptrs[XYOFFSET(sp->sct_x, sp->sct_y)]; + if (sp->sct_type == SCT_WATER || sp->sct_own == 0) { +#ifdef SAVE_FINISH_PATHS + if (infptr->path) + free((s_char *)infptr->path); +#endif /* SAVE_FINISH_PATHS */ + continue; + } + np = getnatp(sp->sct_own); + if (np->nat_money < 0) { +#ifdef SAVE_FINISH_PATHS + if (infptr->path) + free((s_char *)infptr->path); +#endif /* SAVE_FINISH_PATHS */ + continue; + } + dodistribute(sp, IMPORT, + infptr->path, infptr->imcost, infptr->excost); +#ifdef SAVE_FINISH_PATHS + if (infptr->path) + free((s_char *)infptr->path); +#endif /* SAVE_FINISH_PATHS */ + } + logerror("done importing\n"); + +} + +static void +assemble_dist_paths(struct distinfo *distptrs) +{ + s_char *path, *p; + double d; + struct sctstr *sp; + struct sctstr *dist; + struct distinfo *infptr; + int n; + s_char buf[512]; + + for (n=0; NULL != (sp = getsectid(n)); n++) { + if ((sp->sct_dist_x == sp->sct_x) && (sp->sct_dist_y == sp->sct_y)) + continue; + /* Set the pointer */ + infptr = &distptrs[XYOFFSET(sp->sct_x, sp->sct_y)]; + /* now, get the dist sector */ + dist = getsectp(sp->sct_dist_x, sp->sct_dist_y); + if (dist == (struct sctstr *)0){ + logerror("Bad dist sect %d,%d for %d,%d !\n",sp->sct_dist_x, + sp->sct_dist_y,sp->sct_x,sp->sct_y); + continue; + } + /* Now, get the best distribution path over roads */ + /* Note we go from the dist center to the sector. This gives + us the import path for that sector. */ + path = BestDistPath(buf, dist, sp, &d, MOB_ROAD); + + /* Now, we have a path */ + if (path != (s_char *)0) { +#ifdef SAVE_FINISH_PATHS + int len; + /* Here we malloc a buffer and save it */ + len = strlen(path); + infptr->path = (s_char *)malloc(len); + if (infptr->path == (s_char *)0) { + logerror("malloc failed in assemble_dist_path!\n"); + return; + } +#endif /* SAVE_FINISH_PATHS */ + /* Save the import cost */ + infptr->imcost = d; + /* Now, reverse the path */ + p = ReversePath(path); + /* And walk the path back to the dist center to get the export + cost */ + infptr->excost = pathcost(sp, p, MOB_ROAD); +#ifdef SAVE_FINISH_PATHS + bcopy(p, infptr->path, len); +#else + infptr->path = finish_path; +#endif /* SAVE_FINISH_PATHS */ + } + } +} + +s_char +*ReversePath(s_char *path) +{ + s_char *patharray = "aucdefjhigklmyopqrstbvwxnz"; + static s_char new_path[512]; + int ind; + + if (path == (s_char *)0) + return (s_char *)0; + + ind = strlen(path); + if (ind == 0) + return (s_char *)0; + + if (path[ind - 1] == 'h') + ind--; + + new_path[ind--] = '\0'; + new_path[ind] = '\0'; + + while (ind >= 0) { + new_path[ind--] = patharray[*(path++) - 'a']; + } + + return new_path; +} + diff --git a/src/lib/update/human.c b/src/lib/update/human.c new file mode 100644 index 00000000..45812a83 --- /dev/null +++ b/src/lib/update/human.c @@ -0,0 +1,326 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * human.c: Food related functions + * + * Known contributors to this file: + * Dave Pare, 1986 + * Steve McClure, 1996 + */ + +#include +#include "misc.h" +#include "var.h" +#include "sect.h" +#include "nat.h" +#include "item.h" +#include "news.h" +#include "file.h" +#include "xy.h" +#include "optlist.h" +#include "budg.h" +#include "player.h" +#include "update.h" +#include "common.h" +#include "gen.h" +#include "subs.h" + +/* + * feed the individual sector + * + */ +int +do_feed(register struct sctstr *sp, register struct natstr *np, int *vec, int *workp, int *bp, int etu) +{ + extern double eatrate; + int people; + int work_avail; + int starved, sctwork; + int needed, dummy; + int civvies, uws; + int mil; + int maxpop; + + /* grow people & stuff */ + sctwork = sp->sct_work; + + maxpop = max_pop(np->nat_level[NAT_RLEV], sp); + civvies = (vec[I_CIVIL] > maxpop) ? maxpop : vec[I_CIVIL]; + uws = (vec[I_UW] > maxpop) ? maxpop : vec[I_UW]; + mil = (vec[I_MILIT] > maxpop) ? maxpop : vec[I_MILIT]; + work_avail = total_work(sctwork, etu, civvies, mil, uws); + + people = vec[I_CIVIL] + vec[I_MILIT] + vec[I_UW]; + if (sp->sct_type != SCT_SANCT) { + if (opt_NOFOOD == 0) { + if (vec[I_FOOD] < 1 + etu * people * eatrate) { + /* need to grow "emergency rations" */ + work_avail -= (2 * + growfood(sp, vec, (int)(work_avail/2), etu)); + /* It's twice as hard to grow those than norm*/ + pt_bg_nmbr(bp, sp, I_MAX+1, work_avail); + if (!player->simulation) + sp->sct_avail = work_avail; + } + if ((vec[I_FOOD] < 1 + etu * people * eatrate) && + (sp->sct_own == sp->sct_oldown)){ + + /* steal food from warehouses, headquarters, + supply ships in port, or supply units */ + int needed; + + needed = ldround((double)(1+etu*people*eatrate),1); + + /* Now, find some food */ + vec[I_FOOD] = supply_commod(sp->sct_own,sp->sct_x, + sp->sct_y,I_FOOD,needed); + + } + } + starved = feed_people(vec, etu, &needed); + if ((starved > 0 && sp->sct_own) && (!player->simulation)) { + /* don't report POGO starvation */ + wu(0, sp->sct_own, "%d starved in %s.\n", starved, + xyas(sp->sct_x, sp->sct_y, sp->sct_own)); + if (starved > 25) + nreport(sp->sct_own, N_DIE_FAMINE, 0, 1); + } + if (starved > 0) { + if (!player->simulation) + starvation(sp); + sctwork = 0; + } else { + if (sp->sct_work < 100) + sctwork = sp->sct_work + 8 + (random() % 15); + if (sctwork > 100) + sctwork = 100; + if (!player->simulation) + sp->sct_work = sctwork; + dummy = grow_people(sp, etu, np, &work_avail, sctwork, vec); + } + } else + sctwork = sp->sct_work = 100; + /* Here is where we truncate extra people, always */ + trunc_people(sp, np, vec); + + pt_bg_nmbr(bp, sp, I_CIVIL, vec[I_CIVIL]); + pt_bg_nmbr(bp, sp, I_UW, vec[I_UW]); + pt_bg_nmbr(bp, sp, I_MILIT, vec[I_MILIT]); + *workp = work_avail; + return sctwork; +} + +int +growfood(struct sctstr *sp, register int *vec, int work, int etu) +{ + extern double fgrate; + extern double fcrate; + double food_fertil; + double food_workers; + double food; + int work_used; + + /* I'm being very nice and commenting out this so players + * won't whine about starvation + if (sp->sct_fertil == 0 || work == 0) + return 0; + */ + food_workers = work * fcrate; + food_fertil = etu * sp->sct_fertil * fgrate; + food = food_fertil; + if (food > food_workers) + food = food_workers; + /* + * be nice; grow minimum one food unit. + * This makes life simpler for the player. + */ + vec[I_FOOD] += (int) food; + if (vec[I_FOOD] == 0) + vec[I_FOOD] = 1; + if (vec[I_FOOD] > 9999) + vec[I_FOOD] = 9999; + work_used = (int) food / fcrate; + return work_used; +} + +/* + * returns the number who starved, if any. + */ +int +feed_people(register int *vec, int etu, int *needed) +{ + extern double eatrate; + double food_eaten; + double people_left; + int can_eat; + int total_people; + int to_starve; + int starved; + + if (opt_NOFOOD) + return 0; + food_eaten = (double)(((double)etu * (double)eatrate) * + (double)(vec[I_CIVIL] + vec[I_MILIT] + vec[I_UW])); + if (food_eaten <= 1) + return 0; + starved = 0; + *needed = 0; + if (food_eaten > vec[I_FOOD]) { + *needed = food_eaten - vec[I_FOOD]; + if ((double)(*needed) < (double)(food_eaten - (double)vec[I_FOOD])) + (*needed)++; + if (opt_NEW_STARVE) { + can_eat = (vec[I_FOOD] / (etu * eatrate)); + total_people = vec[I_CIVIL] + vec[I_MILIT] + vec[I_UW]; + + /* only want to starve off at most 1/2 the populace. */ + if (can_eat < (total_people/2)) + can_eat = total_people/2; + + to_starve = total_people - can_eat; + while(to_starve && vec[I_UW]){ + to_starve--; + starved++; + vec[I_UW]--; + } + while(to_starve && vec[I_CIVIL]){ + to_starve--; + starved++; + vec[I_CIVIL]--; + } + while(to_starve && vec[I_MILIT]){ + to_starve--; + starved++; + vec[I_MILIT]--; + } + + vec[I_FOOD] = 0; + } + else { /* ! opt_NEW_STARVE */ + + people_left = (vec[I_FOOD] + 0.01) / (food_eaten + 0.01); + starved = vec[I_CIVIL] + vec[I_MILIT] + vec[I_UW]; + /* only want to starve off at most 1/2 the populace. */ + if (people_left < 0.5) + people_left = 0.5; + vec[I_CIVIL] = (int) (vec[I_CIVIL] * people_left); + vec[I_MILIT] = (int) (vec[I_MILIT] * people_left); + vec[I_UW] = (int) (vec[I_UW] * people_left); + starved -= vec[I_CIVIL] + vec[I_MILIT] + vec[I_UW]; + vec[I_FOOD] = 0; + } /* end opt_NEW_STARVE */ + } else { + vec[I_FOOD] -= roundavg(food_eaten); + } + return starved; +} + +/* + * Truncate any extra people that may be around + */ +void +trunc_people(struct sctstr *sp, register struct natstr *np, register int *vec) +{ + int maxpop = max_pop(np->nat_level[NAT_RLEV], sp); + + if (vec[I_CIVIL] > maxpop) + vec[I_CIVIL] = maxpop; + if (vec[I_UW] > maxpop) + vec[I_UW] = maxpop; +} + +/* + * Grow babies, and add to populace. + * XXX Might think about dropping in a birth + * rate limitation on countries with high tech + * production? Maybe with just high education? + */ +int grow_people(struct sctstr *sp, register int etu, register struct natstr *np, int *workp, int sctwork, register int *vec) +{ + extern double obrate; + extern double uwbrate; + extern double babyeat; + int newciv; + int newuw; + int new_birth; + int new_food; + int maxpop = max_pop(np->nat_level[NAT_RLEV], sp); + + newciv = 0; + newuw = 0; + if (vec[I_CIVIL] < maxpop) { + new_birth = (int) roundavg(obrate * (double)(etu * vec[I_CIVIL])); + if (opt_NOFOOD) + new_food = (int) (0.5 + maxpop / (2.0 * babyeat)); + else /* we are using food */ + new_food = (int) (0.5 + vec[I_FOOD] / (2.0 * babyeat)); + + newciv = new_birth; + if (newciv > new_food) + newciv = new_food; + /* Now, check max pops */ + if ((vec[I_CIVIL] + newciv) > maxpop) + newciv = maxpop - vec[I_CIVIL]; + vec[I_CIVIL] += newciv; + } + if (vec[I_UW] < maxpop) { + /* + * now grow uw's + */ + new_birth = (int) roundavg(uwbrate * (double)(etu * vec[I_UW])); + if (opt_NOFOOD) + new_food = (int) (0.5 + maxpop / (2.0 * babyeat)); + else /* food is important */ + new_food = (int) (0.5 + vec[I_FOOD] / (2.0 * babyeat)); + + newuw = new_birth; + if (newuw > new_food) + newuw = new_food; + /* Now, check max pops */ + if ((vec[I_UW] + newuw) > maxpop) + newuw = maxpop - vec[I_UW]; + vec[I_UW] += newuw; + } + /* + * subtract the baby eat food (if we are using FOOD) and return + * # of births. + */ + if (opt_NOFOOD == 0 && (newciv || newuw)) + vec[I_FOOD] -= roundavg((newciv + newuw) * babyeat); + *workp += total_work(sctwork, etu, newciv, 0, newuw); + return newciv + newuw; +} + +/* + * percentage of people who starved + */ +void +starvation(struct sctstr *sp) +{ + sp->sct_work = 0; + sp->sct_loyal += (random() % 8) + 2; +} diff --git a/src/lib/update/land.c b/src/lib/update/land.c new file mode 100644 index 00000000..2ba16105 --- /dev/null +++ b/src/lib/update/land.c @@ -0,0 +1,439 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * land.c: Do production for land units + * + * Known contributors to this file: + * Dave Pare, 1986 + * Thomas Ruschak, 1992 + * Steve McClure, 1996 + */ + +#include "misc.h" +#include "var.h" +#include "sect.h" +#include "nat.h" +#include "land.h" +#include "ship.h" +#include "var.h" +#include "news.h" +#include "file.h" +#include "product.h" +#include "optlist.h" +#include "budg.h" +#include "player.h" +#include "update.h" +#include "lost.h" +#include "common.h" +#include "subs.h" +#include "common.h" +#include "gen.h" + +int mil_dbl_pay; + +#ifndef MIN +#define MIN(x,y) ((x) > (y) ? (y) : (x)) +#endif + +void upd_land(register struct lndstr *lp, int landno, register int etus, struct natstr *np, int *bp, int build); + +int +prod_land(int etus, int natnum, int *bp, int build) + /* build = 1, maintain = 0 */ +{ + register struct lndstr *lp; + struct sctstr *sp; + struct natstr *np; + int n, k=0; + extern long lnd_money[MAXNOC]; + int start_money; + int lastx = 9999, lasty = 9999; + + bp_enable_cachepath(); + for (n=0; NULL != (lp = getlandp(n)); n++) { + if (lp->lnd_own == 0) + continue; + if (lp->lnd_own != natnum) + continue; + + sp = getsectp(lp->lnd_x,lp->lnd_y); + if (sp->sct_type == SCT_SANCT) + continue; + if (lastx == 9999 || lasty == 9999) { + lastx = lp->lnd_x; + lasty = lp->lnd_y; + } + if (lastx != lp->lnd_x || lasty != lp->lnd_y) { + /* Reset the cache */ + bp_disable_cachepath(); + bp_clear_cachepath(); + bp_enable_cachepath(); + } + np = getnatp(lp->lnd_own); + start_money = np->nat_money; + upd_land(lp, n, etus, np, bp, build); + lnd_money[lp->lnd_own] += np->nat_money - start_money; + if ((build && (np->nat_money != start_money)) || (!build)) + k++; + if (player->simulation) + np->nat_money = start_money; + } + bp_disable_cachepath(); + bp_clear_cachepath(); + + return k; +} + +void +upd_land(register struct lndstr *lp, int landno, register int etus, struct natstr *np, int *bp, int build) + /* build = 1, maintain = 0 */ +{ + extern int morale_base; + struct lchrstr *lcp; + int vec[I_MAX+1]; + int cvec[I_MAX+1]; + int n; + double techfact(int, double); + int min = morale_base-(int)np->nat_level[NAT_HLEV]; + int mult; + extern double money_land; + int needed; + int cost; + int eff; + + if (!player->simulation) + if (lp->lnd_retreat < min) + lp->lnd_retreat = min; + + lcp = &lchr[(int)lp->lnd_type]; + getvec(VT_ITEM, vec, (s_char *)lp, EF_LAND); + if (build == 1){ + if (np->nat_priorities[PRI_LBUILD] == 0 || + np->nat_money < 0) + return; + if (lp->lnd_effic < LAND_MINEFF || + !(landrepair(lp,vec,np,bp,etus))){ + makelost(EF_LAND, lp->lnd_own, lp->lnd_uid, lp->lnd_x, lp->lnd_y); + lp->lnd_own = 0; + return; + } + }else{ + mult = 1; + if (np->nat_level[NAT_TLEV] < lp->lnd_tech * 0.85) + mult = 2; + if (lcp->l_flags & L_ENGINEER) + mult *= 3; +/* cost = -(mult * etus * dmin(0.0, money_land * LND_COST(lcp->l_cost, lp->lnd_tech - lcp->l_tech)));*/ + cost = -(mult * etus * dmin(0.0, money_land * lcp->l_cost)); + if ((np->nat_priorities[PRI_LMAINT] == 0 || + np->nat_money < cost) && !player->simulation) { + if ((eff = lp->lnd_effic - etus/5) < LAND_MINEFF) { + wu(0, lp->lnd_own, + "%s lost to lack of maintenance\n", + prland(lp)); + makelost(EF_LAND, lp->lnd_own, lp->lnd_uid, lp->lnd_x, lp->lnd_y); + lp->lnd_own = 0; + return; + } + wu(0, lp->lnd_own, + "%s lost %d%% to lack of maintenance\n", + prland(lp), lp->lnd_effic - eff); + lp->lnd_effic = eff; + } else { + np->nat_money -= cost; + } +/* Mil costs are now part of regular mil costs, not maint costs */ +/* np->nat_money += (int) (money_mil * etus * lnd_getmil(lp));*/ + + /* Grab more stuff */ + if ((opt_NOFOOD == 0) && !player->simulation) + resupply_commod(lp,I_FOOD); + + getvec(VT_ITEM, vec, (s_char *)lp, EF_LAND); + if (!player->simulation) { + if ((n = feed_land(lp, vec, etus, &needed, 1)) > 0) { + wu(0, lp->lnd_own, "%d starved in %s%s\n", + n, prland(lp), + (lp->lnd_effic < LAND_MINEFF ? + ", killing it" : "")); + if (n > 10) + nreport(lp->lnd_own, N_DIE_FAMINE, 0, 1); + } + /* + * do plague stuff. plague can't break out on land units, + * but it can still kill people on them. + */ + getvec(VT_COND, cvec, (s_char *)lp, EF_LAND); + if (cvec[C_PSTAGE] > 0) { + n = plague_people(np, vec, cvec, etus); + switch (n) { + case PLG_DYING: + wu(0, lp->lnd_own, + "PLAGUE deaths reported on %s\n", + prland(lp)); + nreport(lp->lnd_own, N_DIE_PLAGUE, 0, 1); + break; + case PLG_INFECT: + wu(0, lp->lnd_own, "%s battling PLAGUE\n", + prland(lp)); + break; + case PLG_INCUBATE: + /* Are we still incubating? */ + if (n == cvec[C_PSTAGE]) { + /* Yes. Will it turn "infectious" next time? */ + if (cvec[C_PTIME] <= etus) { + /* Yes. Report an outbreak. */ + wu(0, lp->lnd_own, + "Outbreak of PLAGUE on %s!\n", + prland(lp)); + nreport(lp->lnd_own, N_OUT_PLAGUE, 0, 1); + } + } else { + /* It has already moved on to "infectious" */ + wu(0, lp->lnd_own, + "%s battling PLAGUE\n", prland(lp)); + } + break; + case PLG_EXPOSED: + /* Has the plague moved to "incubation" yet? */ + if (n != cvec[C_PSTAGE]) { + /* Yes. Will it turn "infectious" next time? */ + if (cvec[C_PTIME] <= etus) { + /* Yes. Report an outbreak. */ + wu(0, lp->lnd_own, + "Outbreak of PLAGUE on %s!\n", + prland(lp)); + nreport(lp->lnd_own, N_OUT_PLAGUE, 0, 1); + } + } + break; + default: + break; + } + putvec(VT_COND, cvec, (s_char *)lp, EF_LAND); + } + putvec(VT_ITEM, vec, (s_char *)lp, EF_LAND); + } /* end !player->simulation */ + } +} + +/*ARGSUSED*/ +int +landrepair(register struct lndstr *land, int *vec, struct natstr *np, int *bp, int etus) +{ + extern int mil_dbl_pay; + extern int land_grow_scale; + register int delta; + struct sctstr *sp; + struct lchrstr *lp; + float leftp, buildp; + int left, build; + int mil_needed, lcm_needed, hcm_needed, gun_needed, shell_needed; + int avail; + int w_p_eff; + int mult; + int svec[I_MAX+1]; + int mvec[I_MAX+1]; + + lp = &lchr[(int)land->lnd_type]; + sp = getsectp(land->lnd_x, land->lnd_y); + if (sp->sct_off) + return 1; + getvec(VT_ITEM, svec, (s_char *)sp, EF_SECTOR); + mult = 1; + if (np->nat_level[NAT_TLEV] < land->lnd_tech * 0.85) + mult = 2; + + if (land->lnd_effic == 100) { + /* land is ok; no repairs needed */ + return 1; + } + if (sp->sct_own != land->lnd_own) + return 1; + + if (!player->simulation) + avail = sp->sct_avail * 100; + else + avail = gt_bg_nmbr(bp, sp, I_MAX+1) * 100; + + w_p_eff = 20 + (lp->l_lcm + 2 * lp->l_hcm); + delta = roundavg((double)avail/w_p_eff); + if (delta <= 0) + return 1; + if (delta > etus*land_grow_scale) + delta = etus*land_grow_scale; + + /* delta is the max amount we can grow */ + + left = 100 - land->lnd_effic; + if (left > delta) + left = delta; + + leftp = ((float)left/100.0); + + bzero((s_char *)mvec, sizeof(mvec)); + mvec[I_LCM] = lcm_needed = ldround((double)(lp->l_lcm * leftp),1); + mvec[I_HCM] = hcm_needed = ldround((double)(lp->l_hcm * leftp),1); +/* + mvec[I_GUN] = gun_needed = ldround((double)(lp->l_gun * leftp),1); + mvec[I_MILIT] = mil_needed = ldround((double)(lp->l_mil * leftp),1); + mvec[I_SHELL] = shell_needed = ldround((double)(lp->l_shell *leftp),1); + */ + mvec[I_GUN] = gun_needed = 0; + mvec[I_MILIT] = mil_needed = 0; + mvec[I_SHELL] = shell_needed = 0; + + get_materials(sp, bp, mvec, 0); + + if (mvec[I_MILIT]>=mil_needed) + buildp=leftp; + else + buildp=((float)mvec[I_MILIT]/(float)lp->l_mil); + if (mvec[I_LCM] < lcm_needed) + buildp = MIN(buildp,((float)mvec[I_LCM]/(float)lp->l_lcm)); + if (mvec[I_HCM] < hcm_needed) + buildp = MIN(buildp,((float)mvec[I_HCM]/(float)lp->l_hcm)); + if (mvec[I_GUN] < gun_needed) + buildp = MIN(buildp,((float)mvec[I_GUN]/(float)lp->l_gun)); + if (mvec[I_SHELL] < shell_needed) + buildp = MIN(buildp,((float)mvec[I_SHELL]/(float)lp->l_shell)); + + build=ldround((double)(buildp*100.0),1); + + bzero((s_char *)mvec, sizeof(mvec)); + mvec[I_LCM] = lcm_needed = roundavg((double)(lp->l_lcm * buildp)); + mvec[I_HCM] = hcm_needed = roundavg((double)(lp->l_hcm * buildp)); +/* + mvec[I_GUN] = gun_needed = roundavg((double)(lp->l_gun * buildp)); + mvec[I_MILIT] = mil_needed = roundavg((double)(lp->l_mil * buildp)); + mvec[I_SHELL] = shell_needed = roundavg((double)(lp->l_shell *buildp)); + */ + mvec[I_GUN] = gun_needed = 0; + mvec[I_MILIT] = mil_needed = 0; + mvec[I_SHELL] = shell_needed = 0; + mil_dbl_pay += mil_needed; + + get_materials(sp, bp, mvec, 1); + + if ((sp->sct_type != SCT_HEADQ) && (sp->sct_type != SCT_FORTR)) + build /= 3; + + avail -= build * w_p_eff; + if (!player->simulation) { + sp->sct_avail = avail/100; + if (sp->sct_avail < 0) + sp->sct_avail = 0; + } else { + pt_bg_nmbr(bp, sp, I_MAX+1, avail/100); + if (gt_bg_nmbr(bp, sp, I_MAX+1) < 0) + pt_bg_nmbr(bp, sp, I_MAX+1, 0); + } + +if (build<0) + logerror("land unit %d building %d ! \n",land->lnd_uid,build); + np->nat_money -= mult * lp->l_cost * build / 100.0; + if (!player->simulation) { + land->lnd_effic += (s_char)build; + + putsect(sp); + } + return 1; +} + +/* + * returns the number who starved, if any. + */ +int +feed_land(struct lndstr *lp, register int *vec, int etus, int *needed, int doit) +{ + extern double eatrate; + double food_eaten, ship_eaten; + double people_left; + int can_eat, need, svec[I_MAX+1]; + int total_people; + int starved; + struct lchrstr *lcp; + struct shpstr *sp; + + if (opt_NOFOOD) return 0; /* no food no work to be done */ + + lcp = &lchr[(int)lp->lnd_type]; + + food_eaten = (etus * eatrate) * total_mil(lp); + starved = 0; + *needed = 0; + /* + * If we're on a ship, and we don't have enough food, + * get some food off the carrying ship. (Don't starve + * the ship, tho... + */ +/* doit - Only try to take food off the ship during the update */ + if ((food_eaten > vec[I_FOOD]) && (lp->lnd_ship >= 0) && doit){ + need = (int)food_eaten - vec[I_FOOD]; + sp = getshipp(lp->lnd_ship); + getvec(VT_ITEM, svec, (s_char *)sp, EF_SHIP); + ship_eaten = (etus * eatrate) * + (svec[I_CIVIL]+svec[I_MILIT]+svec[I_UW]); + if ((svec[I_FOOD]-need) > ship_eaten){ + vec[I_FOOD] += need; + svec[I_FOOD] -= need; + } + else if ((svec[I_FOOD]-ship_eaten) > 0){ + vec[I_FOOD] += (svec[I_FOOD] - ship_eaten); + svec[I_FOOD] -= (svec[I_FOOD] - ship_eaten); + } + putvec(VT_ITEM, svec, (s_char *)sp, EF_SHIP); + } + + if (food_eaten > vec[I_FOOD]) { + *needed = food_eaten - vec[I_FOOD]; + if (*needed < (food_eaten - vec[I_FOOD])) + (*needed)++; + can_eat = (vec[I_FOOD] / (etus * eatrate)); + total_people = total_mil(lp); + /* only want to starve off at most 1/2 the populace. */ + if (can_eat < (total_people/2)) + can_eat = total_people/2; + + people_left = (vec[I_FOOD] + 0.01) / (food_eaten + 0.01); + /* only want to starve off at most 1/2 the populace. */ + if (people_left < 0.5) + people_left = 0.5; +/* lp->lnd_effic *= people_left;*/ + starved = vec[I_MILIT] - (vec[I_MILIT] * people_left); +/* if (!player->simulation) + wu(0, lp->lnd_own, "%d mil starved on unit %s.\n", + starved, + prland(lp));*/ + vec[I_MILIT] -= starved; + vec[I_FOOD] = 0; + } else { + vec[I_FOOD] -= (int)food_eaten; + } + return starved; +} + diff --git a/src/lib/update/main.c b/src/lib/update/main.c new file mode 100644 index 00000000..7f90e93d --- /dev/null +++ b/src/lib/update/main.c @@ -0,0 +1,252 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * main.c: World update main function + * + * Known contributors to this file: + * Dave Pare, 1994 + * Steve McClure, 1996 + * Doug Hay, 1998 + */ + +#include "misc.h" +#include "nat.h" +#include "file.h" +#include "sect.h" +#include "player.h" +#include "empthread.h" +#include "var.h" +#include "budg.h" +#include "product.h" +#include "player.h" +#include "update.h" +#include "common.h" +#include "optlist.h" +#include +#if !defined(_WIN32) +#include +#endif + +long money[MAXNOC]; +long pops[MAXNOC]; +long sea_money[MAXNOC]; +long lnd_money[MAXNOC]; +long air_money[MAXNOC]; +long tpops[MAXNOC]; + +extern int mil_dbl_pay; +int update_pending = 0; + +/*ARGSUSED*/ +void +update_main(void *argv) +{ + extern int etu_per_update; + extern double money_res; + int etu = etu_per_update; + int n; + int x; + int *bp; + int cn,cn2,rel; + struct natstr *cnp; + struct natstr *np; + + /* First, make sure all mobility is updated correctly. */ + if (opt_MOB_ACCESS) { + mob_ship(etu); + mob_sect(etu); + mob_plane(etu); + mob_land(etu); + } + update_pending = 1; + player->proc = empth_self(); + player->cnum = 0; + player->god = 1; + /* + * set up all the variables which get used in the + * sector production routine (for producing education, + * happiness, and printing out the state of the nation) + */ + logerror("production update (%d etus)", etu); + bzero((s_char *)pops, sizeof(pops)); + bzero((s_char *)air_money, sizeof(air_money)); + bzero((s_char *)sea_money, sizeof(sea_money)); + bzero((s_char *)lnd_money, sizeof(lnd_money)); + bp = (int *) calloc(WORLD_X * WORLD_Y * 7, sizeof(int)); + for (n=0; nnat_money; + tpops[n] = count_pop(n); + } + + logerror("preparing sectors..."); + prepare_sects(etu, bp); + logerror("done preparing sectors."); + logerror("producing for countries..."); + for (x=0; xnat_stat & STAT_SANCT ) { +#ifdef DEBUG + logerror("Country %i is in sanctuary and did not update",x); +#endif + continue; + } + np->nat_money += (int) (np->nat_reserve * money_res * etu); + + for(y=1; ynat_priorities[z] == y) { + do_prod(z, etu, x, bp, p_sect, + &sb, &sm, &pb, &pm, &lb, &lm); + } + } + } + /* 0 is maintain, 1 is build */ + if (!sm) prod_ship(etu, x, bp, 0); + if (!sb) prod_ship(etu, x, bp, 1); + if (!pm) prod_plane(etu, x, bp, 0); + if (!pb) prod_plane(etu, x, bp, 1); + if (!lm) prod_land(etu, x, bp, 0); + if (!lb) prod_land(etu, x, bp, 1); + + /* produce all sects that haven't produced yet */ + produce_sect(x, etu, bp, p_sect, -1); + np->nat_money -= p_sect[SCT_CAPIT][1]; + } + logerror("done producing for countries."); + + finish_sects(etu); + prod_nat(etu); + age_levels(etu); + free(bp); + /*flushwu();*/ + if (opt_SLOW_WAR) { + /* Update war declarations */ + /* MOBILIZATION->SITZKRIEG->AT_WAR */ + for (cn=1; cn < MAXNOC; cn++) { + if ((cnp = getnatp(cn)) == 0) + break; + for (cn2=1; cn2 < MAXNOC; cn2++) { + if (cn2 == cn) + continue; + rel=getrel(cnp,cn2); + if (rel == MOBILIZATION){ + rel = SITZKRIEG; + setrel(cn,cn2,rel); + } + else if (rel == SITZKRIEG){ + rel = AT_WAR; + setrel(cn,cn2,rel); + } + } + } + } + /* Age contact */ + if (opt_LOSE_CONTACT) { + for (cn=1; cnnat_money -= (int) (money_mil * etu * mil_dbl_pay); + prod_land(etu,n,bp,0); + *land_maint=1; + } + else + if (sector_type == PRI_LBUILD){ + prod_land(etu,n,bp,1); + *land_build=1; + } + else { + produce_sect(n,etu,bp,p_sect,sector_type); + } +} + diff --git a/src/lib/update/material.c b/src/lib/update/material.c new file mode 100644 index 00000000..15067e92 --- /dev/null +++ b/src/lib/update/material.c @@ -0,0 +1,93 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * material.c: Tries to find materials for production + * + * Known contributors to this file: + * Ville Virrankoski, 1996 + */ + +#include "misc.h" +#include "var.h" +#include "sect.h" +#include "file.h" +#include "optlist.h" +#include "budg.h" +#include "player.h" +#include "update.h" +#include "common.h" +#include "subs.h" + +#ifndef MIN +#define MIN(x,y) ((x) > (y) ? (y) : (x)) +#endif + +void +get_materials(struct sctstr *sp, int *bp, int *mvec, int check) + /* only check if found=0, remove them=1 */ +{ + struct sctstr *usp; + int i; + int used_already; + int still_left; + int svec[I_MAX+1]; + + getvec(VT_ITEM, svec, (s_char *)sp, EF_SECTOR); + for(i=1;i<=I_MAX;i++) { + if (mvec[i]==0) + continue; + + usp = sp; + if (check) { + still_left = gt_bg_nmbr(bp, sp, i); + if ((still_left - mvec[i])<0) + still_left = 0; + else + still_left -= mvec[i]; + + if (opt_GRAB_THINGS) + mvec[i] = supply_commod(usp->sct_own, usp->sct_x, usp->sct_y, + i, mvec[i]); + pt_bg_nmbr(bp, sp, i, still_left); + svec[i] = still_left; + if (!player->simulation) + putvec(VT_ITEM, svec, (s_char *)sp, EF_SECTOR); + + } else { + + if (opt_GRAB_THINGS) { + used_already = svec[i] - gt_bg_nmbr(bp, sp, i); + mvec[i] = try_supply_commod(usp->sct_own, usp->sct_x, usp->sct_y, + i, (mvec[i] + used_already)); + mvec[i] -= used_already; + } else { /* ! GRAB_THINGS */ + still_left = gt_bg_nmbr(bp, sp, i); + mvec[i] = MIN(mvec[i], still_left); + } + } + } +} diff --git a/src/lib/update/mobility.c b/src/lib/update/mobility.c new file mode 100644 index 00000000..36983252 --- /dev/null +++ b/src/lib/update/mobility.c @@ -0,0 +1,563 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * mobility.c: Add mobility to each of the items which accumulate mobility. + * + * Known contributors to this file: + * Dave Pare, 1986 + * Steve McClure, 1998-1999 + */ + +#include "misc.h" +#include "var.h" +#include "sect.h" +#include "ship.h" +#include "land.h" +#include "plane.h" +#include "nat.h" +#include "file.h" +#include "optlist.h" +#include "mission.h" +#include "update.h" +#include "gen.h" +#include "subs.h" +#include "optlist.h" + +extern int timestamp_fixing; +extern int update_pending; +int do_upd_checking = 0; + + +int +increase_mob(time_t *counter, float mult) +{ + time_t secs; + time_t now; + time_t left; + extern long s_p_etu; + extern int updating_mob; + int newetus; + float newmob; + int inewmob; + + time(&now); + + secs = now - *counter; + if (secs < 1 || secs < s_p_etu) + return 0; + newetus = (int)(secs / s_p_etu); + if (newetus < 1) + return 0; + left = (secs % s_p_etu); + do { + newmob = (float)(newetus * mult); + inewmob = (int)(newetus * mult); + if (newmob == inewmob || newetus > 7) + break; + newetus--; + left += s_p_etu; + } while (newetus > 0); + if (newetus <= 0) + return 0; + + time(counter); + *counter = *counter - left; + + if (updating_mob) + return (newetus); + return 0; +} + +void +update_timestamps(time_t lastsavedtime) +{ + struct shpstr *shipp; + struct sctstr *sectp; + struct lndstr *landp; + struct plnstr *planep; + int n; + time_t now; + time_t delta; + + timestamp_fixing = 1; + time(&now); + delta = now - lastsavedtime; + for (n = 0; (shipp = getshipp(n)); n++) + shipp->shp_access += delta; + for (n = 0; (sectp = getsectid(n)); n++) + sectp->sct_access += delta; + for (n = 0; (landp = getlandp(n)); n++) + landp->lnd_access += delta; + for (n = 0; (planep = getplanep(n)); n++) + planep->pln_access += delta; + timestamp_fixing = 0; +} + +void +update_all_mob(void) +{ + struct shpstr *shipp; + struct sctstr *sectp; + struct lndstr *landp; + struct plnstr *planep; + int n; + + n = 0; + while (1) { + do_upd_checking = 1; + shipp = getshipp(n); + sectp = getsectid(n); + landp = getlandp(n); + planep = getplanep(n); + do_upd_checking = 0; + if (shipp) + shp_do_upd_mob(shipp); + if (sectp) + sct_do_upd_mob(sectp); + if (landp) + lnd_do_upd_mob(landp); + if (planep) + pln_do_upd_mob(planep); + if (!shipp && !sectp && !landp && !planep) + break; + n++; + } + do_upd_checking = 0; +} + +void +sct_do_upd_mob(register struct sctstr *sp) +{ + extern float sect_mob_scale; + int etus; + + if (do_upd_checking || timestamp_fixing || update_pending) + return; + if (sp->sct_own == 0) + return; + if (sp->sct_type == SCT_SANCT) + return; + if ((etus = increase_mob(&sp->sct_access, sect_mob_scale)) == 0) + return; + do_upd_checking = 1; + do_mob_sect(sp, etus); +/* putsect(sp);*/ + do_upd_checking = 0; +} + +void +shp_do_upd_mob(register struct shpstr *sp) +{ + extern float ship_mob_scale; + int etus; + + if (do_upd_checking || timestamp_fixing || update_pending) + return; + if (sp->shp_own == 0) + return; + if ((etus = increase_mob(&sp->shp_access, ship_mob_scale)) == 0) + return; + do_upd_checking = 1; + do_mob_ship(sp, etus); + do_upd_checking = 0; +} + +void +lnd_do_upd_mob(register struct lndstr *lp) +{ + extern float land_mob_scale; + int etus; + + if (do_upd_checking || timestamp_fixing || update_pending) + return; + if (lp->lnd_own == 0) + return; + if ((etus = increase_mob(&lp->lnd_access, land_mob_scale)) == 0) + return; + + do_upd_checking = 1; + do_mob_land(lp, etus); + do_upd_checking = 0; +} + +void +pln_do_upd_mob(register struct plnstr *pp) +{ + extern float plane_mob_scale; + int etus; + + if (do_upd_checking || timestamp_fixing || update_pending) + return; + if (pp->pln_own == 0) + return; + if ((etus = increase_mob(&pp->pln_access, plane_mob_scale)) == 0) + return; + + do_upd_checking = 1; + do_mob_plane(pp, etus); + do_upd_checking = 0; +} + +void +mob_sect(register int etus) +{ + register struct sctstr *sp; + register int n; + time_t now; + + time(&now); + for (n=0; NULL != (sp = getsectid(n)); n++) { + sp->sct_timestamp = now; + if (opt_MOB_ACCESS) + sct_do_upd_mob(sp); + else + do_mob_sect(sp, etus); + } +} + +void +do_mob_sect(register struct sctstr *sp, register int etus) +{ + extern float sect_mob_scale; + extern int sect_mob_max; + register int value; + + if (sp->sct_own == 0) + return; + if (sp->sct_type == SCT_SANCT) + return; + /* Do we have to even bother? */ + if (sp->sct_mobil >= sect_mob_max) { + /* No, so set just in case and then return */ + sp->sct_mobil = sect_mob_max; + return; + } + value = sp->sct_mobil + ((float)etus * sect_mob_scale); + if (value > sect_mob_max) + value = sect_mob_max; + sp->sct_mobil = value; +} + +void +mob_ship(register int etus) +{ + register struct shpstr *sp; + register int n; + time_t now; + + time(&now); + for (n=0; NULL != (sp = getshipp(n)); n++) { + sp->shp_timestamp = now; + if (opt_MOB_ACCESS) + shp_do_upd_mob(sp); + else + do_mob_ship(sp, etus); + } +} + +void +do_mob_ship(register struct shpstr *sp, register int etus) +{ + extern int ship_mob_max; + extern float ship_mob_scale; + int newfuel=0; + register int value; + int can_add,have_fuel_for,total_add; + double d; + extern int fuel_mult; + + if (sp->shp_own == 0) + return; + + /* Do we even have to bother updating this mobility? */ + if (sp->shp_mobil >= ship_mob_max) { + /* No, so don't. Just set it to max (just in case) and + return. */ + sp->shp_mobil = ship_mob_max; + return; + } + + if (opt_FUEL == 0) { /* only a bit to do ... */ + value = sp->shp_mobil + ((float)etus * ship_mob_scale); + if (value > ship_mob_max) + value = ship_mob_max; + sp->shp_mobil = value; + return; /* so we ship the FUEL stuff */ + } + + /* opt_FUEL in force */ + if (mchr[(int)sp->shp_type].m_fuelu == 0) { + value = sp->shp_mobil + ((float)etus * ship_mob_scale); + if (value > ship_mob_max) + value = ship_mob_max; + sp->shp_mobil = (s_char)value; + } else { + can_add = ship_mob_max - sp->shp_mobil; + if (can_add > ((float)etus*ship_mob_scale)) + can_add = ((float)etus*ship_mob_scale); + have_fuel_for = ldround((((double)sp->shp_fuel / + (double)mchr[(int)sp->shp_type].m_fuelu)* + (double)fuel_mult),1); + + if (can_add > have_fuel_for){ + int need; + need = can_add - have_fuel_for; + d = (double)need; + d *= (double)mchr[(int)sp->shp_type].m_fuelu; + d /= (double)fuel_mult; + d /= 5.0; + if ((d-(int)d) > 0.0) + d++; + need = (int)d; + newfuel = supply_commod(sp->shp_own,sp->shp_x, + sp->shp_y,I_PETROL,need); + sp->shp_fuel += (u_char)(newfuel * 5); + } + + have_fuel_for = ldround((((double)sp->shp_fuel / + (double)mchr[(int)sp->shp_type].m_fuelu)* + (double)fuel_mult),1); + + if (can_add > have_fuel_for){ + int need; + need = can_add - have_fuel_for; + d = (double)need; + d *= (double)mchr[(int)sp->shp_type].m_fuelu; + d /= (double)fuel_mult; + d /= 50.0; + if ((d-(int)d) > 0.0) + d++; + need = (int)d; + newfuel = supply_commod(sp->shp_own,sp->shp_x, + sp->shp_y,I_OIL,need); + sp->shp_fuel += (u_char)(newfuel * 50); + } + + have_fuel_for = ldround((((double)sp->shp_fuel / + (double)mchr[(int)sp->shp_type].m_fuelu)* + (double)fuel_mult),1); + + if (can_add > have_fuel_for) + total_add = have_fuel_for; + else + total_add = can_add; + d = (double)total_add; + d *= (double)mchr[(int)sp->shp_type].m_fuelu; + d /= (double)fuel_mult; + sp->shp_fuel -= (u_char)ldround(d,1); + sp->shp_fuel = (u_char)min(sp->shp_fuel, + mchr[(int)sp->shp_type].m_fuelc); + sp->shp_mobil += (s_char)total_add; + } +} + +void +mob_land(register int etus) +{ + register struct lndstr *lp; + register int n; + time_t now; + + time(&now); + for (n=0; NULL != (lp = getlandp(n)); n++) { + lp->lnd_timestamp = now; + if (opt_MOB_ACCESS) + lnd_do_upd_mob(lp); + else + do_mob_land(lp, etus); + } +} + +void +do_mob_land(register struct lndstr *lp, register int etus) +{ + extern int land_mob_max; + extern float land_mob_scale; + int newfuel=0; + register int value; + int can_add,have_fuel_for,total_add; + double d; + extern int fuel_mult; + + if (lp->lnd_own == 0) + return; + + if (lp->lnd_mobil >= land_mob_max) { + lp->lnd_mobil = land_mob_max; + return; + } + + /* + * Give damaged units a break. When at low + * efficiency, units can go to -100 mob when + * marching 1 step, making them slower than + * normal mil. This helps take the curse off. + * If MOB_ACCESS is on, we don't do this, as it would + * be too much of an advantage. So, we just add double + * the small amount of mob if we are < 0 instead. + */ + + if (!opt_MOB_ACCESS) { + if (lp->lnd_mobil < 0) + lp->lnd_mobil /= 2; + } + + if (opt_FUEL == 0) { /* just some bits and pieces */ + if (opt_MOB_ACCESS) { + if (lp->lnd_mobil < 0) + value = lp->lnd_mobil + (2 * ((float)etus * land_mob_scale)); + else + value = lp->lnd_mobil + ((float)etus * land_mob_scale); + } else { + value = lp->lnd_mobil + ((float)etus * land_mob_scale); + } + if (value > land_mob_max) + value = land_mob_max; + lp->lnd_mobil = value; + + return; /* Done! */ + } + + /* opt_FUEL in force ... */ + if (lp->lnd_fuelu == 0){ + if (opt_MOB_ACCESS) { + if (lp->lnd_mobil < 0) + value = lp->lnd_mobil + (2 * ((float)etus * land_mob_scale)); + else + value = lp->lnd_mobil + ((float)etus * land_mob_scale); + } else { + value = lp->lnd_mobil + ((float)etus * land_mob_scale); + } + if (value > land_mob_max) + value = land_mob_max; + lp->lnd_mobil = value; + + } else { + + can_add = land_mob_max - lp->lnd_mobil; + + if (can_add > ((float)etus*land_mob_scale)) + can_add = ((float)etus*land_mob_scale); + + have_fuel_for = (lp->lnd_fuel / + lp->lnd_fuelu)*fuel_mult; + + if (can_add > have_fuel_for){ + int need; + need = can_add - have_fuel_for; + d = (double)need; + d *= (double)lp->lnd_fuelu; + d /= (double)fuel_mult; + d /= 5.0; + if ((d-(int)d) > 0.0) + d++; + need = (int)d; + newfuel = supply_commod(lp->lnd_own,lp->lnd_x, + lp->lnd_y,I_PETROL,need); + lp->lnd_fuel += (u_char)(newfuel * 5); + } + + have_fuel_for = (lp->lnd_fuel / + lp->lnd_fuelu)*fuel_mult; + + if (can_add > have_fuel_for){ + int need; + need = can_add - have_fuel_for; + d = (double)need; + d *= (double)lp->lnd_fuelu; + d /= (double)fuel_mult; + d /= 50.0; + if ((d-(int)d) > 0.0) + d++; + need = (int)d; + newfuel = supply_commod(lp->lnd_own,lp->lnd_x, + lp->lnd_y,I_OIL,need); + lp->lnd_fuel += (u_char)(newfuel * 50); + } + + have_fuel_for = (lp->lnd_fuel / + lp->lnd_fuelu)*fuel_mult; + + if (can_add > have_fuel_for){ + total_add = have_fuel_for; + } + else + total_add = can_add; + d = (double)total_add; + d *= (double)lp->lnd_fuelu; + d /= (double)fuel_mult; + lp->lnd_fuel -= (u_char)ldround(d,1); + lp->lnd_fuel = (u_char)min(lp->lnd_fuel, + lp->lnd_fuelc); + if(total_add + lp->lnd_mobil > land_mob_max) { + total_add = land_mob_max - lp->lnd_mobil; + } + + if (opt_MOB_ACCESS) { + if (lp->lnd_mobil < 0) + lp->lnd_mobil += (s_char)total_add; + } + lp->lnd_mobil += (s_char)total_add; + } +} + +void +mob_plane(register int etus) +{ + register struct plnstr *pp; + register int n; + time_t now; + + time(&now); + for (n=0; NULL != (pp = getplanep(n)); n++) { + pp->pln_timestamp = now; + if (opt_MOB_ACCESS) + pln_do_upd_mob(pp); + else + do_mob_plane(pp, etus); + } +} + +void +do_mob_plane(register struct plnstr *pp, register int etus) +{ + extern int plane_mob_max; + extern float plane_mob_scale; + register int value; + + if (pp->pln_own == 0) + return; + if (pp->pln_mobil >= plane_mob_max) { + pp->pln_mobil = plane_mob_max; + return; + } + + value = pp->pln_mobil + ((float)etus * plane_mob_scale); + if (value > plane_mob_max) + value = plane_mob_max; + pp->pln_mobil = value; +} diff --git a/src/lib/update/move_sat.c b/src/lib/update/move_sat.c new file mode 100644 index 00000000..b4345dc8 --- /dev/null +++ b/src/lib/update/move_sat.c @@ -0,0 +1,93 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * move_sat.c: Move a satellite to the next point in it's orbit. + * + * Known contributors to this file: + * + */ + +#include +#include "misc.h" +#include "var.h" +#include "plane.h" +#include "sect.h" +#include "xy.h" +#include "nsc.h" +#include "nat.h" +#include "path.h" +#include "deity.h" +#include "file.h" +#include "update.h" +#include "subs.h" +#include "optlist.h" + +#ifndef PI +#define PI 3.14159265358979323846 +#endif + +void +move_sat(register struct plnstr *pp) +{ + coord x1,y1,x2,y2; + coord dx,dy; + float newtheta; + struct sctstr sect; + + newtheta = pp->pln_theta + .05; + + if (newtheta >= 1.0) + { + newtheta -= 1.0; + } + + x1 = (coord)(2 * pp->pln_theta * WORLD_X); + x1 = xnorm(x1); + y1 = (coord)(sin(6 * PI * pp->pln_theta) * (WORLD_Y / 4)); + x2 = (coord)(2 * newtheta * WORLD_X); + x2 = xnorm(x2); + y2 = (coord)(sin(6 * PI * newtheta) * (WORLD_Y / 4)); + dx = x1 - pp->pln_x; + dy = y1 - pp->pln_y; + x2 -= dx; + y2 -= dy; + + if ((x2 + y2) & 1) + { + x2++; + } + + pp->pln_x = xnorm(x2); + pp->pln_y = ynorm(y2); + pp->pln_theta = newtheta; + getsect(pp->pln_x, pp->pln_y, §); + if (sect.sct_own) + if (pp->pln_own != sect.sct_own) + wu(0, sect.sct_own, "%s satellite spotted over %s\n", + cname(pp->pln_own), xyas(pp->pln_x, pp->pln_y, sect.sct_own)); + return; +} diff --git a/src/lib/update/nat.c b/src/lib/update/nat.c new file mode 100644 index 00000000..fc09f052 --- /dev/null +++ b/src/lib/update/nat.c @@ -0,0 +1,309 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * nat.c: Accumulate tech, edu, research and happiness. + * + * Known contributors to this file: + * Dave Pare, 1989 + * Steve McClure, 1997 + */ + +#include +#include "misc.h" +#include "var.h" +#include "sect.h" +#include "nat.h" +#include "item.h" +#include "news.h" +#include "file.h" +#include "xy.h" +#include "optlist.h" +#include "update.h" +#include "subs.h" + +float levels[MAXNOC][4]; + +/* + * hap and edu avg mean that the weight on current happiness is + * (cur_hap * hap_avg + hap_prod * etu) / (hap_avg + etu); + * same for education. + * right now, happiness has 1 day (48 etu) average, prod of 10 from + * initial level of 0 yields (1) 1.42, (6) 6.03, (12) 8.42, (18) 9.37 + * + * education has 4 day (192 etu) average, prod of 10 from initial + * level of 0 yields (1) 0.4, (6) 2.2, (12) 3.9, (18) 5.2. + */ + +extern float hap_avg; +extern float edu_avg; +extern float ally_factor; + +/* + * for values below the "easy level" values, production is + * as normal. For values above "easy", production gets harder + * based on an equation in "limit_level()" in update/nat.c. + * Basically, the smaller the the values for "level_log", the + * smaller return on investment above level_easy[] values. + */ +/* + * Damn! I hate this, but ... + * The values here for tech are *not* the real ones. + * They are changed later in the limit_level routine. + */ + /*tech res edu hap */ +float level_easy[4] = { 0.75, 0.75, 5.00, 5.00 }; +float level_log[4] = { 1.75, 2.00, 4.00, 6.00 }; + +/* + * technique to limit the sharpers who turn entire countries + * into tech plants overnight... + */ + +double +logx(double d, double base) +{ + if (base == 1.0) + return d; + return log10(d) / log10(base); +} + +double +limit_level(double level, int type, int flag) +{ + double above_easy; + double above; + double logbase; + double easy; + +/* + * Begin ugly hack. + */ + extern float easy_tech, tech_log_base; + + level_easy[0] = easy_tech; + level_log[0] = tech_log_base; +/* + * End ugly hack. + */ + + if (level > level_easy[type]) { + logbase = level_log[type]; + easy = level_easy[type]; + above_easy = level - easy; + if (flag) + above = above_easy / logx(logbase + above_easy,logbase); + else + above = logx(above_easy + 1.0, logbase); + if (above > 250) above = 250; + return ((above) < 0) ? easy : (easy + above); + } else + return level; +} + +void +prod_nat(int etu) +{ + extern long money[MAXNOC]; + extern long pops[MAXNOC]; + extern double hap_cons, edu_cons; + extern long sea_money[MAXNOC]; + extern long lnd_money[MAXNOC]; + extern long air_money[MAXNOC]; + struct natstr *np; + float hap; + float edu; + float hap_edu; + long pop; + double rlev; + double tlev; + double tech[MAXNOC]; + double res[MAXNOC]; + double newvalue; + natid n; + int cn,cont; + + for (n=0; NULL != (np = getnatp(n)); n++) { + if ((np->nat_stat & STAT_NORM) == 0) + continue; + /* + * hap_edu: the more education people have, the + * more happiness they want. + */ + hap_edu = np->nat_level[NAT_ELEV]; + hap_edu = 1.5 - ((hap_edu + 10.0) / (hap_edu + 20.0)); + pop = pops[n] + 1; + /* + * get per-population happiness and education + * see what the total per-civilian production is + * for this time period. + */ + hap = levels[n][NAT_HLEV] * hap_edu * hap_cons / + ((float)pop * etu); + edu = levels[n][NAT_ELEV] * edu_cons / + ((float)pop * etu); + wu((natid)0, n, "%3.0f happiness, %3.0f education produced\n", + levels[n][NAT_HLEV], levels[n][NAT_ELEV]); + hap = limit_level(hap, NAT_HLEV, 1); + edu = limit_level(edu, NAT_ELEV, 1); + /* + * change the "moving average"...old happiness and + * education levels are weighted heavier than current + * production. + */ + newvalue = (np->nat_level[NAT_HLEV] * hap_avg + hap * etu) / + (hap_avg + etu); + np->nat_level[NAT_HLEV] = newvalue; + newvalue = (np->nat_level[NAT_ELEV] * edu_avg + edu * etu) / + (edu_avg + etu); + np->nat_level[NAT_ELEV] = newvalue; + /* + * limit tech/research production + */ + levels[n][NAT_TLEV] = + limit_level(levels[n][NAT_TLEV] / 1, + NAT_TLEV, 0) * 1; + levels[n][NAT_RLEV] = + limit_level(levels[n][NAT_RLEV] / 1, + NAT_RLEV, 0) * 1; + wu((natid)0, n, + "total pop is %d, yielding %4.2f hap, %4.2f edu\n", + pop - 1, hap, edu); + } + if (ally_factor > 0.0) + share_incr(res, tech); + else { + bzero((s_char *)res, sizeof(res)); + bzero((s_char *)tech, sizeof(tech)); + } + for (n=0; NULL != (np = getnatp(n)); n++) { + if ((np->nat_stat & STAT_NORM) == 0) + continue; + tlev = levels[n][NAT_TLEV]; + rlev = levels[n][NAT_RLEV]; + if (tech[n] != 0.0 || res[n] != 0.0) { + wu((natid)0, n, + "%5.4f technology (%5.4f + %5.4f), ", + tlev + tech[n], tlev, tech[n]); + wu((natid)0, n, + "%5.4f research (%5.4f + %5.4f) produced\n", + rlev + res[n], rlev, res[n]); + } else + wu((natid)0, n, + "%5.4f tech, %5.4f research produced\n", + tlev, rlev); + rlev += res[n]; + tlev += tech[n]; + if (rlev != 0.0) + np->nat_level[NAT_RLEV] += rlev; + if (tlev != 0.0) + np->nat_level[NAT_TLEV] += tlev; + if ((sea_money[n] != 0) || (air_money[n] != 0) || + (lnd_money[n] != 0)) + wu((natid)0, n, + "Army delta $%d, Navy delta $%d, Air force delta $%d\n", + lnd_money[n], sea_money[n], air_money[n]); + wu((natid)0, n, "money delta was $%d for this update\n", + np->nat_money - money[n]); + if (opt_LOSE_CONTACT) { + for (cn=0; cn <= MAXNOC; cn++) { + cont = getcontact(np, cn); + if (cont > 0) { + logerror ("country %d at level %d with country %d.\n", n, cont, cn); + setcont(n, cn, cont-1); + } + } + } + } +} + +/* + * find out everyones increment + */ +void +share_incr(register double *res, register double *tech) +{ + register struct natstr *np; + register struct natstr *other; + register natid i; + register natid j; + int rnc; + int tnc; + + for (i=0; NULL != (np = getnatp(i)); i++) { + res[i] = tech[i] = 0.0; + if ((np->nat_stat & STAT_INUSE) == 0) + continue; + if (np->nat_stat & STAT_GOD) + continue; + if (np->nat_stat == VIS) + continue; + rnc = tnc = 0; + for (j=0; NULL != (other = getnatp(j)); j++) { + if (j == i) + continue; + if (other->nat_stat & STAT_GOD) + continue; + if (other->nat_stat == VIS) + continue; + if ((other->nat_stat & STAT_INUSE) == 0) + continue; + if (opt_HIDDEN) { + if (!getcontact(np, j)) + continue; + } + if (!opt_ALL_BLEED) { + if (getrel(np, j) != ALLIED) + continue; + if (getrel(other, i) != ALLIED) + continue; + res[i] += levels[j][NAT_RLEV]; + tech[i] += levels[j][NAT_TLEV]; + rnc++; + tnc++; + } else { + if (levels[j][NAT_TLEV] > 0.001) { + tech[i] += levels[j][NAT_TLEV]; + tnc++; + } + if (levels[j][NAT_RLEV] > 0.001) { + res[i] += levels[j][NAT_RLEV]; + rnc++; + } + } + } + if (rnc == 0 && tnc == 0) + continue; + if (rnc > 0) { + res[i] /= rnc * ally_factor; + } + if (tnc > 0) { + tech[i] /= tnc * ally_factor; + } +/* logerror("Country #%d gets %g res from %d allies, %g tech from %d allies", i, res[i], rnc, tech[i], tnc);*/ + } +} + diff --git a/src/lib/update/nav_ship.c b/src/lib/update/nav_ship.c new file mode 100644 index 00000000..d2e5c5b2 --- /dev/null +++ b/src/lib/update/nav_ship.c @@ -0,0 +1,373 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * nav_ship.c: Navigate ships and such + * + * Known contributors to this file: + * Chad Zabel, 1994 + * Ken Stevens, 1995 + */ + +#include "misc.h" + +#include +#include "var.h" +#include "ship.h" +#include "sect.h" +#include "news.h" +#include "xy.h" +#include "nsc.h" +#include "nat.h" +#include "path.h" +#include "deity.h" +#include "file.h" +#include "item.h" +#include "optlist.h" +#include "player.h" +#include "update.h" +#include "subs.h" +#include "common.h" +#include + +extern int check_nav(struct sctstr *sect); + +void +scuttle_it(register struct shpstr *sp) +{ + struct sctstr *sectp; + + sp->shp_autonav &= ~AN_SCUTTLE; + if (!(sectp = getsectp(sp->shp_x,sp->shp_y))) { + wu(0, 0, "bad sector (%d,%d) ship %d\n", sp->shp_x, sp->shp_y, + sp->shp_uid); + return; + } + if (sectp->sct_type != SCT_HARBR || sectp->sct_effic < 2) { + wu(0, sp->shp_own, + "%s is not in a harbor at least 2%% eff! Not scuttling.\n", + prship(sp)); + return; + } + if (opt_TRADESHIPS) { + if (!(mchr[(int)sp->shp_type].m_flags & M_TRADE)) { + wu(0, sp->shp_own, + "You can only autoscuttle trade ships!\n"); + return; + } + } + wu(0, sp->shp_own, "Scuttling %s in sector %s\n", + prship(sp), + xyas(sp->shp_x, sp->shp_y, sp->shp_own)); + if (opt_TRADESHIPS) { + scuttle_tradeship(sp, 0); + } + scuttle_ship(sp); +} + +static void +nav_check_atdest(register struct shpstr *sp, struct mchrstr *mcp) +{ + if ((sp->shp_x == sp->shp_destx[0]) && + (sp->shp_y == sp->shp_desty[0])) { + if ((sp->shp_destx[0] == sp->shp_destx[1]) && + (sp->shp_desty[0] == sp->shp_desty[1])) { + + /* End of road */ + + sp->shp_autonav &= ~AN_AUTONAV; + wu(0, sp->shp_own, "%s arrived at %s, finished\n", + prship(sp), + xyas(sp->shp_x,sp->shp_y,sp->shp_own)); + if (sp->shp_autonav & AN_SCUTTLE) { + scuttle_it(sp); + } + } else { + /* unload all cargo */ + unload_it(sp); + wu(0, sp->shp_own, "%s arrived at %s\n", + prship(sp), + xyas(sp->shp_x,sp->shp_y,sp->shp_own)); + /* Swap */ + swap(sp); + } + } else + sp->shp_autonav &= ~AN_LOADING; +} + +/* flip the 2 fields that deal with autonav movement. */ +/* CZ 6/1/94 */ + +void +swap(register struct shpstr *sp) +{ + coord tcord; + s_char tcomm[TMAX]; + short lev[TMAX]; + int i; + + tcord = sp->shp_destx[0]; + sp->shp_destx[0] = sp->shp_destx[1]; + sp->shp_destx[1] = tcord; + tcord = sp->shp_desty[0]; + sp->shp_desty[0] = sp->shp_desty[1]; + sp->shp_desty[1] = tcord; + + for (i=0;ishp_lstart[i]; + tcomm[i] = sp->shp_tstart[i]; } + + for (i=0;ishp_lstart[i] = sp->shp_lend[i]; + sp->shp_tstart[i] = sp->shp_tend[i]; } + + for (i=0;ishp_lend[i] = lev[i]; + sp->shp_tend[i] = tcomm[i]; } + + /* set load bit */ + sp->shp_autonav |= AN_LOADING; +} + +/* New Autonav code. + * Chad Zabel + * 6-1-94 + */ + +static int +nav_loadship(register struct shpstr *sp, natid cnum) +{ + struct sctstr *sectp; + s_char item; + int i, + landown, + shipown, + level, + didsomething[TMAX], + rel; + + for (i=0;ishp_autonav &= ~AN_LOADING; + + if (!(sectp = getsectp(sp->shp_x,sp->shp_y))) + return RET_SYS; /* safety */ + /* I suspect RET_SYS isn't really what you want here --dfp */ + + + landown = sectp->sct_own; + shipown = sp->shp_own; + rel = getrel(getnatp(sectp->sct_own),cnum); + + /* loop through each field for that ship */ + for (i=0;ishp_tend[i]; /* commodity */ + level = sp->shp_lend[i]; /* amount */ + + /* check and see if the data fields have been set. */ + + if (item == ' ' || level == 0) { + /* nothing to do move on. */ + didsomething[i] = 1; + continue; + } + if (landown == 0) { + /* either sea or deity harbor */ + didsomething[i] = 1; + continue; + } + if (sectp->sct_type != SCT_HARBR && + (!opt_BIG_CITY || sectp->sct_type != SCT_CAPIT)) { + /* we can only load in harbors */ + didsomething[i] = 1; + continue; + } + if (landown == shipown || rel >= FRIENDLY) + didsomething[i] = load_it(sp,sectp,i); + } + + /* check for any unsucessful loads */ + /* if we have any return 0 to stop */ + /* the nav_ship loop. */ + + for (i=0;ishp_autonav & AN_AUTONAV) || (sp->shp_autonav & AN_STANDBY)) + return RET_OK; + + cnum = sp->shp_own; + vship = mcp = &mchr[(int)sp->shp_type]; + + /* Make a list of one ships so we can use the navi.c code */ + emp_initque(&ship_list); + mlp = (struct mlist *) malloc(sizeof(struct mlist)); + mlp->mcp = mchr + sp->shp_type; + bcopy((s_char *)sp, (s_char *)&mlp->ship, sizeof(struct shpstr)); + mlp->mobil = (double)sp->shp_mobil; + emp_insque(&mlp->queue, &ship_list); + + quit = 1; /* setup loop, we want to check it 1 time. */ + + do { + if ((sp->shp_mobil > 0) && (!(sp->shp_autonav & AN_LOADING)) && + (!(sp->shp_autonav & AN_STANDBY))) { + shp_nav(&ship_list, &dummydouble, &dummydouble, &dummyint, + sp->shp_own); + if (QEMPTY(&ship_list)) + return RET_OK; + /* before we move check to see if ship needs fuel. */ + sectp = getsectp(sp->shp_x,sp->shp_y); + if (opt_FUEL && + sectp->sct_own != 0 && + sp->shp_fuel <= 0 && + mlp->mcp->m_fuelu != 0) + auto_fuel_ship(sp); + mlp->ship.shp_fuel = sp->shp_fuel; + + cp = BestShipPath(buf, sp->shp_x, sp->shp_y, + sp->shp_destx[0], sp->shp_desty[0], + sp->shp_own); + if (cp == 0 || (*cp == '\0') || (*cp == '?')) { + wu(0, cnum, + "%s bad path, ship put on standby\n", + prship(sp)); + sp->shp_autonav |= AN_STANDBY; + putship(sp->shp_uid, (s_char *)sp); + + /* We need to free the ship list */ + qp = ship_list.q_forw; + while (qp != &(ship_list)) { + newqp = qp->q_forw; + emp_remque(qp); + free((s_char *)qp); + qp = newqp; + } + return RET_SYN; + } + stopping = 0; + + while (*cp && !stopping && sp->shp_own && + mlp->mobil > 0.0) { + dir = chkdir(*cp++, DIR_STOP, DIR_LAST); + + stopping |= shp_nav_one_sector(&ship_list, dir, + sp->shp_own, 0); + } + +/* sp->shp_mobil = (int) mobil; + */ + /* Ship not sunk */ + if (sp->shp_own) + nav_check_atdest(sp, mcp); + } + + quit = 0; /* stop loop */ + + /* Try to load the ship */ + if (sp->shp_autonav & AN_LOADING) { + didsomething = nav_loadship(sp, cnum); + if (didsomething) + quit = 1; + } + /* special case for fishing boats */ + if ((mchr[(int)sp->shp_type].m_flags & M_FOOD) == 1) { + item = (s_char)'f'; + comm = com_num(&item); + food_amt=getvar(comm,(s_char *) sp, EF_SHIP); + max_amt=(vl_find(comm,vship->m_vtype, + vship->m_vamt, + (int) vship->m_nv)); + sectp=getsectp(sp->shp_x,sp->shp_y); + + if (food_amtsct_own==0)) + quit=0; + } + /* reset flag and check if we can move. */ + + } while (quit); /* end loop */ + + putship(sp->shp_uid, sp); + + /* We need to free the ship list (just in case) */ + qp = ship_list.q_forw; + while (qp != &(ship_list)) { + newqp = qp->q_forw; + emp_remque(qp); + free((s_char *)qp); + qp = newqp; + } + return RET_OK; +} diff --git a/src/lib/update/nav_util.c b/src/lib/update/nav_util.c new file mode 100644 index 00000000..30293b96 --- /dev/null +++ b/src/lib/update/nav_util.c @@ -0,0 +1,310 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * nav_util.c: Utilities for autonav and sail + * + * Known contributors to this file: + * + */ + +#include "misc.h" + +#include +#include "var.h" +#include "ship.h" +#include "plane.h" +#include "land.h" +#include "nuke.h" +#include "sect.h" +#include "news.h" +#include "xy.h" +#include "nsc.h" +#include "nat.h" +#include "path.h" +#include "deity.h" +#include "file.h" +#include "item.h" +#include "optlist.h" +#include "player.h" +#include "update.h" +#include "subs.h" +#include "common.h" +#include "gen.h" + +/* Format a ship name */ +int +check_nav(struct sctstr *sect) +{ + extern struct dchrstr dchr[]; + + switch (dchr[sect->sct_type].d_flg & 03) { + case NAVOK: + break; + + case NAV_02: + if (sect->sct_effic < 2) + return CN_CONSTRUCTION; + break; + case NAV_60: + if (sect->sct_effic < 60) + return CN_CONSTRUCTION; + break; + default: + return CN_LANDLOCKED; + } + return CN_NAVIGABLE; +} + +/* load a specific ship given its + * location and what field to modify. + * new autonav code + * Chad Zabel 6/1/94 + */ +int +load_it(register struct shpstr *sp, register struct sctstr *psect, int i) +{ + int comm, shipown, amount, ship_amt, sect_amt, + abs_max, max_amt, transfer; + s_char item; + struct mchrstr *vship; + + amount = sp->shp_lend[i]; + shipown = sp->shp_own; + item = sp->shp_tend[i]; /* commodity */ + comm = com_num(&item); + + ship_amt = getvar(comm,(s_char *) sp , EF_SHIP); + sect_amt = getvar(comm,(s_char *) psect, EF_SECTOR); + + /* check for disloyal civilians */ + if (psect->sct_oldown != shipown && comm == V_CIVIL) + { wu(0,shipown,"Ship #%d - unable to load disloyal civilians at %s.", + sp->shp_uid, xyas(psect->sct_x,psect->sct_y,psect->sct_own)); + return 0; + } + if (comm == V_CIVIL || comm == V_MILIT) + sect_amt--; /* leave 1 civ or mil to hold the sector. */ + vship = &mchr[(int)sp->shp_type]; + abs_max = max_amt = (vl_find(comm,vship->m_vtype, + vship->m_vamt,(int) vship->m_nv)); + + if (!abs_max) + return 0; /* can't load the ship, skip to the end. */ + + max_amt = min (sect_amt, max_amt - ship_amt); + if (max_amt <= 0 && (ship_amt != abs_max)) { + sp->shp_autonav |= AN_LOADING; + return 0; + } + + + transfer = amount - ship_amt; + if (transfer > sect_amt) { /* not enough in the */ + transfer = sect_amt; /* sector to fill the */ + sp->shp_autonav |= AN_LOADING; /* ship, set load flag */ + } + if (ship_amt + transfer > abs_max) /* Do not load more */ + transfer = abs_max-ship_amt; /* then the max alowed */ + /* on the ship. */ + + if (transfer == 0) + return 0; /* nothing to move */ + + + putvar(comm, ship_amt + transfer, (s_char *)sp, EF_SHIP); + if (comm == V_CIVIL || comm == V_MILIT) + sect_amt++; /*adjustment*/ + putvar(comm, sect_amt - transfer, (s_char *)psect, EF_SECTOR); + + /* deal with the plague */ + if (getvar(V_PSTAGE, (s_char *)psect, EF_SECTOR) == PLG_INFECT && + getvar(V_PSTAGE, (s_char *)sp , EF_SHIP) == PLG_HEALTHY) + putvar(V_PSTAGE, PLG_EXPOSED, (s_char *)sp, EF_SHIP); + if (getvar(V_PSTAGE, (s_char *)sp, EF_SHIP) == PLG_INFECT && + getvar(V_PSTAGE, (s_char *)psect, EF_SECTOR) == PLG_HEALTHY) + putvar(V_PSTAGE, PLG_EXPOSED, (s_char *)psect, EF_SECTOR); + + return 1; /* we did someloading return 1 to keep */ + /* our loop happy in nav_ship() */ + +} + +/* unload_it + * A guess alot of this looks like load_it but because of its location + * in the autonav code I had to split the 2 procedures up. + * unload_it dumps all the goods from the ship to the harbor. + * ONLY goods in the trade fields will be unloaded. + * new autonav code + * Chad Zabel 6/1/94 + */ +void +unload_it(register struct shpstr *sp) +{ + struct sctstr *sectp; + s_char item; + int i; + int landowner; + int shipown; + int comm; + int sect_amt; + int ship_amt; + int abs_max = 99999; /* max amount a sector can hold. */ + int max_amt; + int level; + + + sectp = getsectp(sp->shp_x,sp->shp_y); + + landowner = sectp->sct_own; + shipown = sp->shp_own; + + for(i=0;ishp_tend[i]; + level = sp->shp_lend[i]; + + if (item == ' ' || level == 0) + continue; + if (landowner == 0 ) + continue; + if (sectp->sct_type != SCT_HARBR) + continue; + + comm = com_num(&item); + ship_amt = getvar(comm,(s_char *) sp ,EF_SHIP); + sect_amt = getvar(comm,(s_char *) sectp ,EF_SECTOR); + + /* check for disloyal civilians */ + if (sectp->sct_oldown != shipown && comm == V_CIVIL) + { + wu(0,sp->shp_own,"Ship #%d - unable to unload civilians into a disloyal sector at %s.", + sp->shp_uid, xyas(sectp->sct_x,sectp->sct_y,sectp->sct_own)); + continue; + } + if (comm == V_CIVIL) + ship_amt--; /* This leaves 1 civs on board the ship */ + + if (sect_amt >= abs_max) + continue; /* The sector is full. */ + + max_amt = min (ship_amt,abs_max - sect_amt); + + if (max_amt <= 0) + continue; + + putvar(comm, ship_amt - max_amt, (s_char *) sp ,EF_SHIP); + putvar(comm, sect_amt + max_amt, (s_char *) sectp,EF_SECTOR); + + if (getvar(V_PSTAGE, (s_char *)sectp,EF_SECTOR) == PLG_INFECT && + getvar(V_PSTAGE, (s_char *)sp ,EF_SHIP ) == PLG_HEALTHY) + putvar(V_PSTAGE, PLG_EXPOSED,(s_char *)sp, EF_SHIP); + + if (getvar(V_PSTAGE, (s_char *)sp ,EF_SHIP ) == PLG_INFECT && + getvar(V_PSTAGE, (s_char *)sectp,EF_SECTOR) == PLG_HEALTHY) + putvar(V_PSTAGE, PLG_EXPOSED,(s_char *)sectp, EF_SECTOR); + + } + + } +/* com_num + * This small but useful bit of code runs through the list + * of commodities and return the integer value of the + * commodity it finds if possible. Very handy when using getvar(). + * Basicly its a hacked version of whatitem.c found in the + * /player directory. + * new autonav code. + * Chad Zabel 6/1/94 + */ + +int +com_num(s_char *ptr) +{ + struct ichrstr *ip; + + for(ip = &ichr[1];ip->i_mnem != 0; ip++) { + if (*ptr == ip->i_mnem) + return ip->i_vtype; + } + return 0; /*NOTREACHED*/ +} + + + +/* auto_fuel_ship + * Assume a check for fuel=0 has already been made and passed. + * Try to fill a ship using petro. and then oil. + * new autonav code. + * This should be merged with the fuel command someday. + * Chad Zabel 6/1/94 + */ + +void +auto_fuel_ship(register struct shpstr *sp) +{ + double d; + int totalfuel = 0; + int need; + int maxfuel; + int newfuel = 0; + int add_fuel = 0; + + if (opt_FUEL == 0) return; + getship(sp->shp_uid,sp); /* refresh */ + /* fill with petro */ + maxfuel = mchr[(int)sp->shp_type].m_fuelc; + d = (double) maxfuel / 5.0; + if (( d-(int)d > 0.0 )) + d++; + need = (int)d; + + newfuel = supply_commod(sp->shp_own,sp->shp_x, + sp->shp_y,I_PETROL,need); + add_fuel += newfuel * 5; + if (add_fuel > maxfuel) + add_fuel = maxfuel; + sp->shp_fuel += add_fuel; + totalfuel += add_fuel; + + if (totalfuel == maxfuel) { + putship(sp->shp_uid,sp); + return; /* the ship is full */ + } + add_fuel = 0; + /* fill with oil */ + d = (double) (maxfuel - totalfuel) / 50.0; + if ((d-(int)d > 0.0)) + d++; + need = (int)d; + + newfuel = supply_commod(sp->shp_own,sp->shp_x, + sp->shp_y,I_OIL,need); + add_fuel = newfuel * 50; + if (add_fuel > maxfuel) + add_fuel = maxfuel; + sp->shp_fuel += add_fuel; + putship(sp->shp_uid,sp); +} + diff --git a/src/lib/update/nxtitemp.c b/src/lib/update/nxtitemp.c new file mode 100644 index 00000000..f6268bad --- /dev/null +++ b/src/lib/update/nxtitemp.c @@ -0,0 +1,119 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * nxtitemp.c: Get next item from list + * + * Known contributors to this file: + * Dave Pare, 1989 + */ + +#include "misc.h" +#include "var.h" +#include "xy.h" +#include "plane.h" +#include "ship.h" +#include "nuke.h" +#include "land.h" +#include "nsc.h" +#include "nat.h" +#include "file.h" +#include "genitem.h" +#include "player.h" +#include "update.h" +#include "gen.h" +#include "common.h" + +s_char * +nxtitemp(struct nstr_item *np, int owner) +{ + struct genitem *gp; + int selected; + + if (np->sel == NS_UNDEF) + return 0; + do { + if (np->sel == NS_LIST) { + np->index++; + if (np->index >= np->size) + return 0; + np->cur = np->list[np->index]; + } else { + np->cur++; + } + gp = (struct genitem *)ef_ptr(np->type,np->cur); + if (gp == (struct genitem *)0) + return 0; + + selected = 1; + switch (np->sel) { + /* + * This one won't work unless you're running in emp_player + * + */ + case NS_LIST: + if ((np->flags & EFF_OWNER) && !owner) + selected = 0; + break; + case NS_ALL: + /* XXX maybe combine NS_LIST and NS_ALL later */ + break; + case NS_DIST: + if (!xyinrange(gp->x, gp->y, &np->range)) { + selected = 0; + break; + } + np->curdist = mapdist((int)gp->x, (int)gp->y, + (int)np->cx, (int)np->cy); + if (np->curdist > np->dist) + selected = 0; + break; + case NS_AREA: + if (!xyinrange(gp->x, gp->y, &np->range)) + selected = 0; + if (gp->x == np->range.hx || gp->y == np->range.hy) + selected = 0; + break; + case NS_XY: + if (xnorm(gp->x) != np->cx || ynorm(gp->y) != np->cy) + selected = 0; + break; + case NS_GROUP: + if (np->group != gp->group) + selected = 0; + break; + default: + logerror("nxtitemp: bad selector %d\n", np->sel); + return 0; + } + if (selected && np->ncond) { + /* nstr_exec is expensive, so we do it last */ + if (!nstr_exec(np->cond, np->ncond, (s_char *)gp, np->type)) + selected = 0; + } + } while (!selected); + return (s_char *)gp; +} diff --git a/src/lib/update/nxtsctp.c b/src/lib/update/nxtsctp.c new file mode 100644 index 00000000..fb9e7e92 --- /dev/null +++ b/src/lib/update/nxtsctp.c @@ -0,0 +1,76 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * nxtsctp.c: select/get the next sector from a rnage of sectors + * + * Known contributors to this file: + * Dave Pare, 1989 + */ + +#include "misc.h" +#include "var.h" +#include "xy.h" +#include "sect.h" +#include "nsc.h" +#include "file.h" +#include "update.h" +#include "gen.h" +#include "optlist.h" + +/* + * get the next sector in the range + * that matches the conditions. + */ +struct sctstr * +nxtsctp(register struct nstr_sect *np) +{ + while (1) { + np->dx++; + np->x++; + if (np->x >= WORLD_X) + np->x = 0; + if (np->dx >= np->range.width) { + np->dx = 0; + np->x = np->range.lx; + np->dy++; + if (np->dy >= np->range.height) + return (struct sctstr *)0; + np->y++; + if (np->y >= WORLD_Y) + np->y = 0; + } + if ((np->y + np->x) & 01) + continue; + if (np->type == NS_DIST) { + np->curdist = mapdist(np->x, np->y, np->cx, np->cy); + if (np->curdist > np->dist) + continue; + } + return(getsectp(np->x, np->y)); + } + /*NOTREACHED*/ +} diff --git a/src/lib/update/plague.c b/src/lib/update/plague.c new file mode 100644 index 00000000..6f0f2454 --- /dev/null +++ b/src/lib/update/plague.c @@ -0,0 +1,200 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * plague.c: Plague related functions + * + * Known contributors to this file: + * Steve McClure, 1998-2000 + */ + +#include +#include "misc.h" +#include "var.h" +#include "sect.h" +#include "nat.h" +#include "item.h" +#include "news.h" +#include "file.h" +#include "xy.h" +#include "optlist.h" +#include "update.h" +#include "common.h" +#include "subs.h" +#include "lost.h" +#include "gen.h" + +void +do_plague(struct sctstr *sp, struct natstr *np, int etu) +{ + int vec[I_MAX+1]; + int cvec[I_MAX+1]; + int n; + + if (opt_NO_PLAGUE) /* no plague nothing to do */ + return; + + if (getvec(VT_ITEM, vec, (s_char *)sp, EF_SECTOR) <= 0) + return; + if (getvec(VT_COND, cvec, (s_char *)sp, EF_SECTOR) <= 0) + bzero((s_char *)cvec, sizeof(cvec)); + + if (cvec[C_PSTAGE] == 0) { + cvec[C_PSTAGE] = infect_people(np, vec, sp->sct_effic, + (int)sp->sct_mobil, sp); + cvec[C_PTIME] = 0; + } else { + n = plague_people(np, vec, cvec, etu); + switch (n) { + case PLG_DYING: + wu(0, sp->sct_own, "PLAGUE deaths reported in %s.\n", + ownxy(sp)); + nreport(sp->sct_own, N_DIE_PLAGUE, 0, 1); + break; + case PLG_INFECT: + wu(0, sp->sct_own, "%s battling PLAGUE\n", ownxy(sp)); + break; + case PLG_INCUBATE: + /* Are we still incubating? */ + if (n == cvec[C_PSTAGE]) { + /* Yes. Will it turn "infectious" next time? */ + if (cvec[C_PTIME] <= etu) { + /* Yes. Report an outbreak. */ + wu(0, sp->sct_own, + "Outbreak of PLAGUE in %s!\n", + ownxy(sp)); + nreport(sp->sct_own, N_OUT_PLAGUE, 0, 1); + } + } else { + /* It has already moved on to "infectious" */ + wu(0, sp->sct_own, "%s battling PLAGUE\n", ownxy(sp)); + } + break; + case PLG_EXPOSED: + /* Has the plague moved to "incubation" yet? */ + if (n != cvec[C_PSTAGE]) { + /* Yes. Will it turn "infectious" next time? */ + if (cvec[C_PTIME] <= etu) { + /* Yes. Report an outbreak. */ + wu(0, sp->sct_own, + "Outbreak of PLAGUE in %s!\n", + ownxy(sp)); + nreport(sp->sct_own, N_OUT_PLAGUE, 0, 1); + } + } + break; + default: + break; + } + } + if (vec[I_CIVIL] == 0 && vec[I_MILIT] == 0 && + !has_units(sp->sct_x,sp->sct_y,sp->sct_own,0)) { + makelost(EF_SECTOR, sp->sct_own, 0, sp->sct_x, sp->sct_y); + sp->sct_own = 0; + sp->sct_oldown = 0; + } + putvec(VT_ITEM, vec, (s_char *)sp, EF_SECTOR); + putvec(VT_COND, cvec, (s_char *)sp, EF_SECTOR); +} + +/*ARGSUSED*/ +int +infect_people(struct natstr *np, register int *vec, u_int eff, int mobil, struct sctstr *sp) +{ + double plg_num; + double plg_denom; + double plg_chance; + double civvies = 999.0; + + if (opt_NO_PLAGUE) /* no plague nothing to do */ + return PLG_HEALTHY; + + if (np->nat_level[NAT_TLEV] <= 10.0) + return PLG_HEALTHY; + + if (opt_BIG_CITY && (sp->sct_type == SCT_CAPIT)) + civvies = 9999.0; + + /* + * make plague where there was none before... + */ + plg_num = ((vec[I_CIVIL] + vec[I_MILIT] + vec[I_UW]) / civvies) * + ((vec[I_IRON] + vec[I_OIL] + (vec[I_RAD] * 2)) / 10.0 + + np->nat_level[NAT_TLEV] + 100.0); + plg_denom = eff + mobil + 100 + np->nat_level[NAT_RLEV]; + plg_chance = ((plg_num / plg_denom) - 1.0) * 0.01; + if (chance(plg_chance)) + return PLG_EXPOSED; + return PLG_HEALTHY; +} + +/* + * Given the fact that plague exists, kill off + * people if in plague state DYING. Increment + * the plague time. Return "current" plague + * stage. No reports generated here anymore. + */ +int +plague_people(struct natstr *np, register int *vec, register int *cvec, int etus) +{ + int stage; + double plg_num; + double plg_denom; + double pct_left; + + if (opt_NO_PLAGUE) /* no plague nothing to do */ + return PLG_HEALTHY; + cvec[C_PTIME] -= etus; + stage = cvec[C_PSTAGE]; + switch (stage) { + case PLG_DYING: + plg_num = 100.0 * etus; + plg_denom = (np->nat_level[NAT_RLEV] + 100.0) * + (vec[C_PTIME] + etus + 1.0); + pct_left = 1.0 - (double)(plg_num / plg_denom); + if (pct_left < 0.2) + pct_left = 0.2; + vec[I_CIVIL] = vec[I_CIVIL] * pct_left; + vec[I_MILIT] = vec[I_MILIT] * pct_left; + vec[I_UW] = vec[I_UW] * pct_left; + break; + case PLG_INFECT: + case PLG_INCUBATE: + break; + case PLG_EXPOSED: + cvec[C_PTIME] = 0; + break; + default: + /* bad */ + cvec[C_PTIME] = 0; + break; + } + if (cvec[C_PTIME] <= 0) { + cvec[C_PSTAGE]--; + cvec[C_PTIME] = (etus / 2) + (random() % etus); + } + return stage; +} diff --git a/src/lib/update/plane.c b/src/lib/update/plane.c new file mode 100644 index 00000000..f05f63c6 --- /dev/null +++ b/src/lib/update/plane.c @@ -0,0 +1,282 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * plane.c: Do production for planes + * + * Known contributors to this file: + * Dave Pare, 1986 + * Steve McClure, 1998 + */ + +#include "misc.h" +#include "var.h" +#include "sect.h" +#include "plane.h" +#include "ship.h" +#include "nat.h" +#include "file.h" +#include "optlist.h" +#include "budg.h" +#include "player.h" +#include "update.h" +#include "lost.h" +#include "subs.h" +#include "common.h" +#include "gen.h" + +#ifndef MIN +#define MIN(x,y) ((x) > (y) ? (y) : (x)) +#endif + +int +prod_plane(int etus, int natnum, int *bp, int buildem) + + + + /* Build = 1, maintain =0 */ +{ + extern double money_mil; + extern double money_plane; + extern int plane_grow_scale; + extern long air_money[MAXNOC]; + register struct plnstr *pp; + register struct plchrstr *plp; + struct natstr *np; + float leftp, buildp; + int left, build; + int lcm_needed,hcm_needed; + int mil_needed; + int svec[I_MAX+1]; + int mvec[I_MAX+1]; + int n, k=0; + struct shpstr *shp; + struct plchrstr *desc; + struct sctstr *sp; + int delta; + int mult; + int cost; + int eff; + int avail; + int w_p_eff; + int used; + int start_money, onship=0; + + for (n=0; NULL != (pp = getplanep(n)); n++) { + if (pp->pln_own == 0) + continue; + if (pp->pln_own != natnum) + continue; + if (pp->pln_effic < PLANE_MINEFF) { + makelost(EF_PLANE, pp->pln_own, pp->pln_uid, + pp->pln_x, pp->pln_y); + pp->pln_own = 0; + continue; + } + + plp = &plchr[(int)pp->pln_type]; + if (pp->pln_flags & PLN_LAUNCHED) { + if (opt_ORBIT && (buildem == 0)) { + if ((!player->simulation) && + (plp->pl_flags & P_O) && + (pp->pln_flags & PLN_LAUNCHED) && + !(plp->pl_flags & P_M) && + !(pp->pln_flags & PLN_SYNCHRONOUS)) + move_sat(pp); + } + continue; + } + + onship = 0; + shp = (struct shpstr *)0; + if (pp->pln_ship >= 0 && (buildem == 1)) { + if (pp->pln_effic >= 80) + continue; + onship = 1; + shp = getshipp(pp->pln_ship); + if (shp == 0 || shp->shp_own != pp->pln_own) { + /* nplane is unsigned... */ + if (shp->shp_nplane > 0) + shp->shp_nplane --; + makelost(EF_PLANE, pp->pln_own, pp->pln_uid, pp->pln_x, pp->pln_y); + pp->pln_own = 0; + continue; + } + } + np = getnatp(pp->pln_own); + desc = &plchr[(int)pp->pln_type]; + sp = getsectp(pp->pln_x, pp->pln_y); + getvec(VT_ITEM, svec, (s_char *)sp, EF_SECTOR); + mult=1; + if (np->nat_level[NAT_TLEV] < pp->pln_tech * 0.85) + mult = 2; + + if (buildem == 0) { + /* flight pay is 5x the pay received by other military */ + start_money = np->nat_money; + cost = -(mult * etus * + dmin(0.0, desc->pl_cost * money_plane)); + if ((np->nat_priorities[PRI_PMAINT] == 0 || + np->nat_money < cost) && !player->simulation) { + if ((eff = pp->pln_effic - etus/5) < PLANE_MINEFF) { + wu(0, pp->pln_own, + "%s lost to lack of maintenance\n", + prplane(pp)); + makelost(EF_PLANE, pp->pln_own, pp->pln_uid, pp->pln_x, pp->pln_y); + pp->pln_own = 0; + continue; + } + wu(0, pp->pln_own, + "%s lost %d%% to lack of maintenance\n", + prplane(pp), pp->pln_effic - eff); + pp->pln_effic = eff; + } else { + np->nat_money -= cost; + } + + np->nat_money += (etus * plp->pl_crew * money_mil * 5); + + air_money[pp->pln_own] += np->nat_money - start_money; + k++; + if (player->simulation) + np->nat_money = start_money; + if ((pp->pln_flags & PLN_LAUNCHED) == PLN_LAUNCHED) + continue; + }else{ + if (sp->sct_off) + continue; + if (np->nat_priorities[PRI_PBUILD] == 0 || + np->nat_money < 0) + continue; + + start_money = np->nat_money; + left = 100 - pp->pln_effic; + if (left <= 0) + continue; + + if (!player->simulation) + avail = sp->sct_avail * 100; + else + avail = gt_bg_nmbr(bp, sp, I_MAX+1) * 100; + + if (pp->pln_ship >= 0) { + int vec[I_MAX+1]; + shp = getshipp(pp->pln_ship); + getvec(VT_ITEM, vec, (s_char *)shp, EF_SHIP); + avail += (etus * vec[I_MILIT]/2); + } + w_p_eff = 20 + (desc->pl_lcm + 2 * desc->pl_hcm); + delta = roundavg((double)avail/w_p_eff); + if (delta <= 0) + continue; + if (delta > etus*plane_grow_scale) + delta = etus*plane_grow_scale; + if (delta > left) + delta = left; + + /* delta is the max amount we can grow */ + + left = 100 - pp->pln_effic; + if (left > delta) + left = delta; + + leftp = ((float)left/100.0); + bzero((s_char *)mvec, sizeof(mvec)); + mvec[I_MILIT] = mil_needed = + ldround((double)(plp->pl_crew * leftp),1); + mvec[I_LCM] = lcm_needed = + ldround((double)(plp->pl_lcm * leftp),1); + mvec[I_HCM] = hcm_needed = + ldround((double)(plp->pl_hcm * leftp),1); + + get_materials(sp, bp, mvec, 0); + + if (mvec[I_MILIT]>=mil_needed) + buildp=leftp; + else + buildp=((float)mvec[I_MILIT]/(float)plp->pl_crew); + + if (mvec[I_LCM] < lcm_needed) + buildp = MIN(buildp,((float)mvec[I_LCM]/ + (float)plp->pl_lcm)); + + if (mvec[I_HCM] < hcm_needed) + buildp = MIN(buildp,((float)mvec[I_HCM]/ + (float)plp->pl_hcm)); + + build=ldround((double)(buildp*100.0),1); + bzero((s_char *)mvec, sizeof(mvec)); + mvec[I_MILIT] = mil_needed = + roundavg((double)(plp->pl_crew * buildp)); + mvec[I_LCM] = lcm_needed = + roundavg((double)(plp->pl_lcm * buildp)); + mvec[I_HCM] = hcm_needed = + roundavg((double)(plp->pl_hcm * buildp)); + + get_materials(sp, bp, mvec, 1); + + if (onship) build = delta; + used = build * w_p_eff; + + /* + * I didn't use roundavg here, because I want to + * penalize the player with a large number of planes. + */ + if (!player->simulation) + avail = (sp->sct_avail * 100 - used) / 100; + else + avail = (gt_bg_nmbr(bp,sp,I_MAX+1) *100 -used) / 100; + + if (avail < 0) + avail = 0; + if (!player->simulation) + sp->sct_avail = avail; + else + pt_bg_nmbr(bp,sp,I_MAX+1,avail); + + if (sp->sct_type != SCT_AIRPT) + build /= 3; + if (onship){ + if ((pp->pln_effic + build) > 80) + build = 80- pp ->pln_effic; + } + np->nat_money -= roundavg(mult * build * + desc->pl_cost / 100.0); + air_money[pp->pln_own] += np->nat_money - start_money; + + if (!player->simulation) + pp->pln_effic += (s_char)build; + else + np->nat_money = start_money; + k++; + } + } + return k; +} + + + + diff --git a/src/lib/update/populace.c b/src/lib/update/populace.c new file mode 100644 index 00000000..a2cbee46 --- /dev/null +++ b/src/lib/update/populace.c @@ -0,0 +1,141 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * populace.c: Return workforce available + * + * Known contributors to this file: + * Dave Pare, 1986 + */ + +#include "misc.h" +#include "var.h" +#include "sect.h" +#include "nat.h" +#include "news.h" +#include "var.h" +#include "file.h" +#include "path.h" +#include "xy.h" +#include "land.h" +#include "budg.h" +#include "update.h" +#include "subs.h" +#include "gen.h" +#include "common.h" +#include "lost.h" + +void +populace(struct natstr *np, register struct sctstr *sp, register int *vec, int etu) +{ + float hap; + float tech; + float edu; + float pct; + int n; + + if (vec[I_CIVIL] == 0 && vec[I_MILIT] > 0) { + sp->sct_work = 100; + sp->sct_loyal = 0; + sp->sct_oldown = sp->sct_own; + } + if (!vec[I_CIVIL] && !vec[I_MILIT] && !vec[I_UW] && + !has_units(sp->sct_x,sp->sct_y,sp->sct_own,0)) { + makelost(EF_SECTOR, sp->sct_own, 0, sp->sct_x, sp->sct_y); + sp->sct_own = 0; + sp->sct_oldown = 0; + return; + } + if (sp->sct_own != sp->sct_oldown && sp->sct_loyal == 0) { + sp->sct_oldown = sp->sct_own; + } + + hap = np->nat_level[NAT_HLEV]; + edu = np->nat_level[NAT_ELEV]; + tech = np->nat_level[NAT_TLEV]; + pct = (double)((tech - 40) / 40.0 + edu / 3.0); + if (sp->sct_own == sp->sct_oldown && hap < pct && + chance((double)(((double)pct-(double)hap)/(double)5.0))) { + /* + * zap the loyalty of unhappy civilians. + * there is a 20% chance per hap point below the + * "recommended" amount of this happening. + */ + n = roundavg(etu * 0.125); + if (n == 0) n = 1; + n = sp->sct_loyal + (random() % n) + 1; + if (n > 127) + n = 127; + sp->sct_loyal = n; + } + if (sp->sct_loyal > 65 && vec[I_MILIT] < vec[I_CIVIL]/20) { + int work_red; + + work_red = sp->sct_loyal - (50 + (random() % 15)); + n = sp->sct_work - work_red; + if (n < 0) + n = 0; + sp->sct_work = n; + if (chance((double)work_red/1000.0)) { + /* + * small chance of rebellion... + * if work_red is (max) 67, + * then revolt chance is 6.7% + */ + revolt(sp); + } else if (chance(.30) && sp->sct_own) + wu(0, sp->sct_own, "Civil unrest in %s!\n", ownxy(sp)); + } + if (sp->sct_loyal) { + n = sp->sct_loyal; + if (chance(0.75)) + n -= roundavg(etu * 0.25); + else + n += roundavg(etu * 0.125); + if (n < 0) + n = 0; + else if (n > 127) + n = 127; + sp->sct_loyal = n; + if (sp->sct_loyal == 0) { + if (sp->sct_oldown != sp->sct_own) { + wu(0, sp->sct_own, + "Sector %s is now fully yours\n", + ownxy(sp)); + sp->sct_oldown = sp->sct_own; + } + sp->sct_loyal = 0; + } + } + return; +} + +int +total_work(register int sctwork, register int etu, register int civil, register int milit, register int uw) +{ + return ((int)((((civil * sctwork) / 100.0 + + (milit * 2 / 5.0) + uw)) * etu) / 100); +} diff --git a/src/lib/update/prepare.c b/src/lib/update/prepare.c new file mode 100644 index 00000000..742b86cb --- /dev/null +++ b/src/lib/update/prepare.c @@ -0,0 +1,187 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * prepare.c: Perform prelimiary updates of sectors + * + * Known contributors to this file: + * Dave Pare, 1986 + * Thomas Ruschak, 1992 + * Steve McClure, 1997 + */ + +#include +#include "misc.h" +#include "var.h" +#include "sect.h" +#include "nat.h" +#include "item.h" +#include "news.h" +#include "file.h" +#include "xy.h" +#include "path.h" +#include "optlist.h" +#include "budg.h" +#include "player.h" +#include "ship.h" +#include "land.h" +#include "update.h" +#include "gen.h" +#include "common.h" + +extern float levels[MAXNOC][4]; + +void +prepare_sects(int etu, int *bp) +{ + extern long pops[]; + register struct sctstr *sp; + struct natstr *np; + int n, civ_tax, uw_tax, mil_pay; + + bzero((s_char *)levels, sizeof(levels)); + +/* Process all the fallout. */ + if (opt_FALLOUT) { + if (!player->simulation) { + /* First, we determine which sectors to process fallout in */ + for (n = 0; NULL != (sp = getsectid(n)); n++) { + if (getvar(V_FALLOUT, (s_char *)sp, EF_SECTOR)) + sp->sct_updated = 1; + else + sp->sct_updated = 0; + } + /* Next, we process the fallout there */ + for (n = 0; NULL != (sp = getsectid(n)); n++) + if (sp->sct_updated) + do_fallout(sp, etu); + /* Next, we spread the fallout */ + for (n = 0; NULL != (sp = getsectid(n)); n++) + if (sp->sct_updated) + spread_fallout(sp, etu); + /* Next, we decay the fallout */ + for (n = 0; NULL != (sp = getsectid(n)); n++) + if (getvar(V_FALLOUT, (s_char *)sp, EF_SECTOR)) + decay_fallout(sp, etu); + } + } + for (n=0; NULL != (sp = getsectid(n)); n++) { + sp->sct_updated = 0; + + if (sp->sct_type == SCT_WATER) + continue; + fill_update_array(bp, sp); + np = getnatp(sp->sct_own); + +#ifdef DEBUG + if (np->nat_stat & STAT_SANCT) + logerror("Prepare.c: country in sanctuary skipped production"); +#endif /* DEBUG */ + + if (!(np->nat_stat & STAT_SANCT)){ + guerrilla(sp); + do_plague(sp, np, etu); + tax(sp, np, etu, &pops[sp->sct_own], &civ_tax, &uw_tax, &mil_pay); + np->nat_money += civ_tax + uw_tax + mil_pay; + if (sp->sct_type == SCT_BANK) + np->nat_money += bank_income(sp, etu); + } + } + for (n=0; NULL != (np = getnatp(n)); n++) { + np->nat_money += upd_slmilcosts(np->nat_cnum, etu); + } +} + +void +tax(struct sctstr *sp, struct natstr *np, int etu, long *pop, int *civ_tax, int *uw_tax, int *mil_pay) +{ + int vec[I_MAX+1]; + extern double money_civ, money_mil, money_uw; + + *civ_tax = 0; + *uw_tax = 0; + *mil_pay = 0; + if (getvec(VT_ITEM, vec, (s_char *)sp, EF_SECTOR) <= 0) + return; + + if (!player->simulation) + populace(np, sp, vec, etu); + *civ_tax = (int)(0.5 + vec[I_CIVIL] * sp->sct_effic * + etu * money_civ / 100); + /* + * captured civs only pay 1/4 taxes + */ + if (sp->sct_own != sp->sct_oldown) + *civ_tax = *civ_tax / 4; + *uw_tax = (int)(0.5 + vec[I_UW] * sp->sct_effic * + etu * money_uw / 100); + *mil_pay = vec[I_MILIT] * etu * money_mil; + + /* + * only non-captured civs add to census for nation + */ + if (sp->sct_oldown == sp->sct_own) + *pop += vec[I_CIVIL]; +} + +int +upd_slmilcosts(natid n, int etu) +{ + extern double money_mil; + struct shpstr *sp; + struct lndstr *lp; + int mil = 0; + int totalmil = 0; + int mil_pay = 0; + int i; + + for (i = 0; NULL != (sp = getshipp(i)); i++) { + if (!sp->shp_own || sp->shp_own != n) + continue; + if ((mil = getvar(V_MILIT, (s_char *)sp, EF_SHIP)) > 0) + totalmil += mil; + } + for (i = 0; NULL != (lp = getlandp(i)); i++) { + if (!lp->lnd_own || lp->lnd_own != n) + continue; + if ((mil = getvar(V_MILIT, (s_char *)lp, EF_LAND)) > 0) + totalmil += mil; + } + mil_pay = totalmil * etu * money_mil; + return (mil_pay); +} + +int +bank_income(struct sctstr *sp, int etu) +{ + extern double bankint; + int vec[I_MAX+1]; + + if (getvec(VT_ITEM, vec, (s_char *)sp, EF_SECTOR) <= 0) + return 0; + else + return (int)(vec[I_BAR] * etu * bankint * sp->sct_effic / 100); +} diff --git a/src/lib/update/produce.c b/src/lib/update/produce.c new file mode 100644 index 00000000..e618a232 --- /dev/null +++ b/src/lib/update/produce.c @@ -0,0 +1,237 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * produce.c: Produce goodies + * + * Known contributors to this file: + * + */ + +#include "misc.h" +#include "var.h" +#include "sect.h" +#include "product.h" +#include "nat.h" +#include "file.h" +#include "xy.h" +#include "player.h" +#include "update.h" +#include "gen.h" +#include "subs.h" +#include "common.h" +#include "optlist.h" + +s_char *levelnames[] = { "Technology", "Research", "Education", "Happiness" }; + +int +produce(struct natstr *np, struct sctstr *sp, int *vec, int work, int sctwork, int desig, int neweff, int *cost, int *amount) +{ + extern float levels[MAXNOC][4]; + extern long tpops[]; + register struct pchrstr *product; + int vtype; + double p_e; + double level_p_e; + s_char *resource; + int output; + int actual; + int unit_work; + double depend; + int item; + int worker_limit; + int material_limit; + int material_consume; + int val; + + product = &pchr[dchr[desig].d_prd]; + if (product == &pchr[0]) + return 0; + vtype = product->p_type; + item = vtype &~ VT_ITEM; + *amount = 0; + *cost = 0; + + if ((material_limit = materials_cost(product, vec, &unit_work)) <= 0) + return 0; + /* + * calculate production efficiency. + */ + p_e = neweff / 100.0; + if (product->p_nrndx != 0) { + unit_work++; + resource = ((s_char *) sp) + product->p_nrndx; + p_e = (*resource * p_e) / 100.0; + if (product->p_nrdep > 0) { + /* XXX this looks way wrong */ + depend = (*resource * 100.0) / product->p_nrdep; + if (p_e > depend) + p_e = depend; + } + } + /* + * determine number that can be made with + * the available workforce + */ + if (unit_work == 0) + unit_work = 1; + material_consume = material_limit; + worker_limit = roundavg(work * p_e / unit_work); + if (material_consume > worker_limit) + material_consume = worker_limit; + if (material_consume == 0) + return 0; + level_p_e = 1.0; + if (product->p_nlndx >= 0) { + level_p_e = np->nat_level[product->p_nlndx] - product->p_nlmin; + if ((level_p_e < 0.0) && (!player->simulation)) { + wu(0, sp->sct_own, + "%s level too low to produce in %s (need %d)\n", + levelnames[product->p_nlndx], ownxy(sp), + product->p_nlmin); + return 0; + } + level_p_e = level_p_e / (level_p_e + product->p_nllag); + } + /* + * Adjust produced amount by commodity production ratio + */ + output = roundavg(product->p_effic * 0.01 * material_consume); + if ((vtype == 0) && (!player->simulation)) { + levels[sp->sct_own][product->p_level] += output * level_p_e; + wu((natid)0, sp->sct_own, "%s (%.2f) produced in %s\n", + product->p_name, output * level_p_e, ownxy(sp)); + } else { + if ((actual = roundavg(level_p_e * output)) <= 0) + return 0; + if (product->p_nrdep != 0) { + if(*resource*100 < product->p_nrdep*actual) + actual = *resource*100/product->p_nrdep; + } + if (actual > 999) { + actual = 999; + material_consume = (int)(actual / (product->p_effic * 0.01)); + } + vec[item] += actual; + if (vec[item] > 9999) { + material_consume = + roundavg((9999.0 - vec[item] + actual) * + material_consume / actual); + if (material_consume < 0) + material_consume = 0; + vec[item] = 9999; + if ((/* vtype != V_FOOD && */ sp->sct_own) && + (!player->simulation)) + wu(0, sp->sct_own, + "%s production backlog in %s\n", + product->p_name, ownxy(sp)); + } + } + /* + * Reset produced amount by commodity production ratio + */ + if (!player->simulation) { + materials_charge(product, vec, material_consume); + if (product->p_nrdep != 0) { + /* + * lower natural resource in sector depending on + * amount produced + */ + val = *resource - roundavg(product->p_nrdep * + material_consume / 100.0); + if (val < 0) + val = 0; + *resource = val; + } + } + *amount = actual; + *cost = product->p_cost * material_consume; + + if (opt_TECH_POP) { + if (product->p_level == NAT_TLEV) { + if (tpops[sp->sct_own] > 50000) + *cost = (double)*cost * (double)tpops[sp->sct_own] / 50000.0; + } + } + + /* The min() here is to take care of integer rounding errors */ + if (p_e > 0.0) { + return min(work, (int)(unit_work * material_consume / p_e)); + } + return 0; +} + +int +materials_cost(struct pchrstr *product, register int *vec, int *costp) +{ + register u_char *vp; + register u_short *ap; + register int count; + register int cost; + register int n; + register u_char *endp; + + count = 9999; + cost = 0; + ap = product->p_vamt; + endp = product->p_vtype + product->p_nv; + for (vp = product->p_vtype; vp < endp; vp++, ap++) { + if (!*ap) + continue; + n = vec[*vp & ~VT_ITEM] / *ap; + if (n < count) + count = n; + cost += *ap; + } + *costp = cost; + return count; +} + +void +materials_charge(struct pchrstr *product, register int *vec, register int count) +{ + register u_char *vp; + register u_short *ap; + register u_char *endp; + register int item; + register int n; + + ap = product->p_vamt; + endp = product->p_vtype + product->p_nv; + for (vp = product->p_vtype; vp < endp; vp++, ap++) { + item = *vp & ~VT_ITEM; + if (item < 0 || item > I_MAX) { + logerror("materials_charge: bad item %d", item); + continue; + } + if ((n = vec[item] - *ap * count) < 0) { + logerror("materials_charge: %d > %d item #%d", + n, vec[item], item); + n = 0; + } + vec[item] = n; + } +} diff --git a/src/lib/update/removewants.c b/src/lib/update/removewants.c new file mode 100644 index 00000000..0f7f5f91 --- /dev/null +++ b/src/lib/update/removewants.c @@ -0,0 +1,58 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * removewants.c: Remove the "I want an update" flag. + * + * Known contributors to this file: + * + */ + +#include +#include +#include +#include +#include +#include "misc.h" +#include "nat.h" +#include "file.h" +#include "update.h" + +int +update_removewants(void) +{ + natid cn; + struct natstr *natp; + + for (cn = 0; NULL != (natp=getnatp(cn)); cn++) { + if ((natp->nat_stat & STAT_INUSE) && + (natp->nat_update & WUPD_WANT) == 0){ + natp->nat_missed++; + } + natp->nat_update = natp->nat_stat & ~WUPD_WANT; + } + return 0; +} diff --git a/src/lib/update/revolt.c b/src/lib/update/revolt.c new file mode 100644 index 00000000..d734b9e1 --- /dev/null +++ b/src/lib/update/revolt.c @@ -0,0 +1,595 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * revolt.c: Have disloyal populace revolt! + * + * Known contributors to this file: + * Dave Pare, 1986 + * Steve McClure, 1997-2000 + */ + +#include "misc.h" +#include "var.h" +#include "sect.h" +#include "nat.h" +#include "news.h" +#include "var.h" +#include "file.h" +#include "path.h" +#include "xy.h" +#include "land.h" +#include "nsc.h" +#include "plane.h" +#include "update.h" +#include "common.h" +#include "gen.h" +#include "lost.h" +#include "subs.h" + +#define get_che_cnum(x) ((x) >> 8) +#define set_che_cnum(x, cn) ((x) = ((x) & 0xff) | ((cn) << 8)) +#define get_che_value(x) ((x) & 0xff) +#define set_che_value(x, n) ((x) = ((x) & 0xff00) | (n)) + +#define CHE_MAX 255 + +void +revolt(struct sctstr *sp) +{ + int che_civ; + int che_uw; + int civ; + int uw; + u_short che_combo; + int che; + int n; + int target; + + che_combo = getvar(V_CHE, (s_char *)sp, EF_SECTOR); + che = get_che_value(che_combo); + target = get_che_cnum(che_combo); + if (che_combo != 0 && (target != sp->sct_own || che >= CHE_MAX)) + return; + civ = getvar(V_CIVIL, (s_char *)sp, EF_SECTOR); + uw = getvar(V_UW, (s_char *)sp, EF_SECTOR); + if (che > (civ + uw) * 3) + return; + che_uw = 0; + che_civ = 0; + /* che due to civilian unrest */ + n = 10 - (random() % 20); + che_civ = 3 + (civ * n/500); + if (che_civ < 0) + che_civ = 0; + else if (che_civ * 3 > civ) + che_civ = civ / 3; + if (che + che_civ > CHE_MAX) + che_civ = CHE_MAX - che; + che += che_civ; + if (che < CHE_MAX) { + /* che due to uw unrest */ + n = 10 + (random() % 30); + che_uw = 5 + (uw * n/500); + if (che_uw > uw) + che_uw = uw; + if (che + che_uw > CHE_MAX) + che_uw = CHE_MAX - che_uw; + che += che_uw; + } + if (che_civ + che_uw > 0) { + civ -= che_civ; + uw -= che_uw; + set_che_cnum(che_combo, sp->sct_own); + set_che_value(che_combo, che); + putvar(V_CHE, (int)che_combo, (s_char *)sp, EF_SECTOR); + if (che_civ > 0) + putvar(V_CIVIL, civ, (s_char *)sp, EF_SECTOR); + if (che_uw > 0) + putvar(V_UW, uw, (s_char *)sp, EF_SECTOR); +#ifdef DEBUG + logerror("(#%d) %d che fired up in %s", + sp->sct_own, che, ownxy(sp)); +#endif + } +} + +/* + * summary of effects. + * if there are no military in the sector, che recruit from + * populace if pop loyalty is > 10. They spread subversion otherwise, + * trying to lower pop loyalty. + * if che outnumber military, they stay and shoot it out, kill the + * military. + * if che are outnumbered by less than 5 to 1, they blow up stuff, + * killing innocent civilians (never uw's) and damaging commodities. + * if che are outnumbered by more than 5 to 1, they try to leave the + * sector for a nearby sector with fewer military. + * + * if the military lose any attacks, the pop loyalty in the sector + * gets worse, representing military defeat. + * military can "catch" che's after bombing attacks, or after they move. + * If military catch them, then they get to shoot it out with a portion + * of the che's depending on the # of mil in the sector. Chance to contact + * is around 10% per every equal number of mil:che ratio in the sector. + * "contact" is by 20% of the military in the sector, and odds are equal. + * + * Without a doubt this routine should be broken up, if only for readabilty. + */ +void +guerrilla(struct sctstr *sp) +{ + extern s_char *effadv(); + struct sctstr *nsp; + int recruit; + int move; + int ratio; + int che; + int mil; + int cc, mc; + double odds; + int civ; + int n; + int uw; + natid target; + struct natstr *tnat; + int convert; + natid actor; + natid victim; + u_short che_combo; + int vec[I_MAX+1]; + int tmp; + int min_mil; + int val; + int oldmob; + struct lndstr *lp; + s_char *nxtitemp(struct nstr_item *np, int owner); + struct nstr_item ni; + extern double hap_fact(); + + mc = cc = 0; + recruit = 0; + convert = 0; + move = 0; + if ((n = getvar(V_CHE, (s_char *)sp, EF_SECTOR)) <= 0) + return; + che_combo = n; + if (getvec(VT_ITEM, vec, (s_char *)sp, EF_SECTOR) <= 0) + return; + civ = vec[I_CIVIL]; + + uw = vec[I_UW]; + victim = sp->sct_own; + actor = sp->sct_oldown; + che = get_che_value(che_combo); + + mil = vec[I_MILIT]; + snxtitem_xy(&ni, EF_LAND, sp->sct_x,sp->sct_y); + + while (NULL != (lp=(struct lndstr *)nxtitemp(&ni, 0))){ + if (lp->lnd_own != sp->sct_own) + continue; + + mil += lnd_getmil(lp); + + /* Security troops can now kill up to 1/2 their complement each + update, before doing anything else. */ + if (lchr[(int)lp->lnd_type].l_flags & L_SECURITY){ + int che_kill, r; + struct lchrstr *lcp; + + lcp = &lchr[(int)lp->lnd_type]; + mil += lnd_getmil(lp); + r = (((float)(lp->lnd_effic / 100) * (float)(lnd_getmil(lp))) / 2); + if (r < 2) + r = 2; + che_kill = (roll(r) - 1); + if (che_kill > che) + che_kill = che; + if (che_kill) { + wu(0, sp->sct_own, + "%s kills %d guerrilla%s in raid at %s!\n", + prland(lp), + che_kill, splur(che_kill), + ownxy(sp)); + che -= che_kill; + } + } + } + + /* Security forces killed all the che */ + if (che <= 0) { + putvar(V_CHE, 0, (s_char *)sp, EF_SECTOR); + return; + } + + target = get_che_cnum(che_combo); + if (target == 0) { + /* the deity can't be a target! */ + return; + } + tnat = getnatp(target); + if ((tnat->nat_stat & STAT_INUSE) == 0) { + /* target nation has dissolved: che's retire. */ + logerror("%d Che targeted at country %d retiring", che, target); + civ += che; + putvar(V_CHE, 0, (s_char *)sp, EF_SECTOR); + putvar(V_CIVIL, civ, (s_char *)sp, EF_SECTOR); + return; + } + + if (sp->sct_own != target) { + /*logerror("own %d != target %d", sp->sct_own, target);*/ + move++; + goto domove; + } + + ratio = mil / che; + odds = (double) che / (mil+che); + odds /= hap_fact(tnat,getnatp(sp->sct_oldown)); + if (mil == 0) { + wu(0, sp->sct_own, "Revolutionary subversion reported in %s!\n", + ownxy(sp)); + recruit++; + convert++; + } else if (che > mil && mil > 0) { + /*logerror("guerrilla shootout with military");*/ + /* + * shoot it out with the military, and kill them off. + * If loyalty bad enough, then take the sector over, + * and enlist 5% of civ as military force. + */ + while (che > 0 && mil > 0) { + if (chance(odds)) { + mc++; + mil--; + } else { + cc++; + che--; + } + } + if (mil > 0) { + /* military won. */ + n = sp->sct_loyal - (random() % 15); + if (n < 0) + n = 0; + sp->sct_loyal = n; + /*logerror("(#%d) mil beat che in %s", sp->sct_own,*/ + /*ownxy(sp));*/ + } else { + convert++; + recruit++; + /*logerror("(#%d) che beat mil in %s", sp->sct_own,*/ + /*ownxy(sp));*/ + } + take_casualties(sp,mc); + } else if (ratio < 5) { + /* + * guerrillas have to resort to blowing things up. + * Note this disrupts work in the sector. + */ + n = 0; + n = (random() % 10) + (random() % che); + if (n > 100) + n = 100; + tmp = sp->sct_work - n; + if (tmp < 0) + tmp = 0; + sp->sct_work = tmp; + wu(0, sp->sct_own, + "Production %s disrupted by terrorists in %s\n", + effadv(n), ownxy(sp)); + sect_damage(sp, n/10, 0); + /*logerror("(#%d) che blew up %s for %d", sp->sct_own,*/ + /*ownxy(sp), n);*/ + recruit++; + } else { + /* ratio >= 5 */ + /*logerror("(#%d) %d che fleeing %d mil in %s", sp->sct_own,*/ + /*che, mil, ownxy(sp));*/ + move++; + } + if (mil > 0 && che > 0) { + /* + * we only get here if we haven't had combat previously. + * Chance to catch them. + * 20% of mil involved in attacking the che's. + */ + if (chance(ratio*0.10)) { + n = (mil/5) + 1; + if ((n+che) == 0){ + logerror("n=%d che=%d\n",n,che); + if (che == 0) + return; + } + odds = (double) che / (n + che); + odds /= hap_fact(tnat,getnatp(sp->sct_oldown)); + while (che > 0 && n > 0) { + if (chance(odds)) { + mc++; + n--; + } else { + cc++; + che--; + } + } + take_casualties(sp,mc); + recruit = 0; + /*logerror("Caught che; mc: %d, cc: %d", cc, mc);*/ + } + } + if (convert && sp->sct_loyal >= 50) { + register int n; + /* new owner gets to keep the mobility there */ + oldmob = sp->sct_mobil; + /* che won, and sector converts. */ + if (sp->sct_own == sp->sct_oldown) + sp->sct_oldown = 0; + else + takeover(sp, sp->sct_oldown); + sp->sct_mobil = oldmob; + civ += uw; + uw = 0; + /* + * so we can't keep losing money by having + * our cap retaken + */ + if (sp->sct_type == SCT_CAPIT && + sp->sct_newtype == SCT_CAPIT) + sp->sct_newtype = SCT_AGRI; + n = civ / 20; + civ -= n; + putvar(V_CIVIL, civ, (s_char *)sp, EF_SECTOR); + putvar(V_UW, uw, (s_char *)sp, EF_SECTOR); + putvar(V_MILIT, n, (s_char *)sp, EF_SECTOR); + move++; + recruit = 0; + if (sp->sct_own) + wu(0, sp->sct_own, "Sector %s has been retaken!\n", + xyas(sp->sct_x, sp->sct_y, sp->sct_own)); + } + if (recruit && che > 0) { + /* loyalty drops during recruitment efforts */ + n = sp->sct_loyal; + if (n < 30) + n += (random() % 5) + 1; + else if (n < 70) + n += (random() % 10) + 4; + if (n > 127) + n = 127; + sp->sct_loyal = n; + if (sp->sct_oldown != sp->sct_own || n > 100) { + n = civ * (random() % 3) / 200; + n /= hap_fact(tnat,getnatp(sp->sct_oldown)); + if (n + che > CHE_MAX) + n = CHE_MAX - che; + che += n; + civ -= n; + putvar(V_CIVIL, civ, (s_char *)sp, EF_SECTOR); + } + n = uw * (random() % 3) / 200; + if (n + che > CHE_MAX) + n = CHE_MAX - che; + che += n; + uw -= n; + putvar(V_UW, uw, (s_char *)sp, EF_SECTOR); + } + domove: + if (move && che > 0) { + struct sctstr *maybe_sp = 0; + if (convert) + min_mil = 999; + else + min_mil = mil; + for (n=1; n<=6; n++) { + nsp = getsectp(sp->sct_x+diroff[n][0], + sp->sct_y+diroff[n][1]); + if (dchr[nsp->sct_type].d_mcst == 0) + continue; + if (nsp->sct_own != target) + continue; + if ((val = getvar(V_CHE, (s_char *)nsp, EF_SECTOR)) > 0) { + che_combo = val; + if (get_che_cnum(che_combo) != target) + continue; + if (get_che_value(che_combo) + che > CHE_MAX) + continue; + } + val = getvar(V_MILIT, (s_char *)nsp, EF_SECTOR); + if (val >= min_mil) + continue; + maybe_sp = nsp; + min_mil = val; + } + /* + * if n <= 6, we found a sector owned by TARGET which + * is a nice sector. Otherwise, we move to the first + * one we find ("maybe_sp"). + */ + if (maybe_sp != 0) { + che_combo = getvar(V_CHE, (s_char *)maybe_sp, EF_SECTOR); + che += get_che_value(che_combo); + set_che_value(che_combo, che); + set_che_cnum(che_combo, target); + putvar(V_CHE, (int) che_combo, (s_char *)maybe_sp, EF_SECTOR); + che = 0; + } + } + if (che > 0) { + set_che_value(che_combo, che); + set_che_cnum(che_combo, target); + putvar(V_CHE, (int) che_combo, (s_char *)sp, EF_SECTOR); + } else + putvar(V_CHE, 0, (s_char *)sp, EF_SECTOR); + if (mc > 0 || cc > 0) { + /* don't tell who won just to be mean */ + wu(0, target, + "Guerrilla warfare in %s\n", + xyas(sp->sct_x, sp->sct_y, target)); + wu(0, target, " body count: troops: %d, rebels: %d\n", mc, cc); + nreport(actor, N_FREEDOM_FIGHT, victim, 1); + } +} + +void +take_casualties(struct sctstr *sp, int mc) +{ + int orig_mil; + int cantake; + int nunits=0, each, deq; + struct lndstr *lp; + s_char *nxtitemp(struct nstr_item *np, int owner); + struct nstr_item ni; + + /* casualties come out of mil first */ + orig_mil = getvar(V_MILIT, (s_char *)sp, EF_SECTOR); + + if (mc <= orig_mil){ + putvar(V_MILIT, (orig_mil-mc), (s_char *)sp, EF_SECTOR); + return; + } + putvar(V_MILIT, 0, (s_char *)sp, EF_SECTOR); + + /* remaining casualites */ + mc -= orig_mil; + + /* + * Need to take total_casualties and divide + * them amongst the land units in the sector + * Do security troops first, then others. + * Try not to kill any unit. + */ + snxtitem_xy(&ni, EF_LAND, sp->sct_x,sp->sct_y); + while(NULL != (lp=(struct lndstr *)nxtitemp(&ni, 0))){ + nunits++; + if (lchr[(int)lp->lnd_type].l_flags & L_SECURITY) + nunits++; + } + + if (nunits==0) + return; + + each = (mc/nunits)+2; + + /* kill some security troops */ + snxtitem_xy(&ni, EF_LAND, sp->sct_x,sp->sct_y); + while(NULL != (lp=(struct lndstr *)nxtitemp(&ni, 0))){ + if (!(lchr[(int)lp->lnd_type].l_flags & L_SECURITY)) + continue; + + cantake = (((float)(lp->lnd_effic-40)/100.0)* + (float)lnd_getmil(lp))*2; + /* (float)lchr[lp->lnd_type].l_mil)*2;*/ + + if (cantake >= each){ + /* deq = (((float)each/(float)(lchr[lp->lnd_type].l_mil*2))*/ + deq = (((float)each/(float)(lnd_getmil(lp)*2)) + *100.0); + mc -= each; + }else if (cantake > 0){ + deq = (((float)cantake/ + (float)(lnd_getmil(lp)*2)) * 100.0); + /* (float)(lchr[lp->lnd_type].l_mil*2)) * 100.0);*/ + mc -= (((float)deq/100.0)* + (float)lnd_getmil(lp))*2; + /* (float)lchr[lp->lnd_type].l_mil)*2;*/ + }else + deq = 0; + + lp->lnd_effic -= deq; + lp->lnd_mobil -= deq/2; + deq = (double)lchr[(int)lp->lnd_type].l_mil * (deq / 100.0); + lnd_submil(lp, deq); + if (mc<=0) return; + } + + /* kill some normal troops */ + snxtitem_xy(&ni, EF_LAND, sp->sct_x,sp->sct_y); + while(NULL != (lp=(struct lndstr *)nxtitemp(&ni, 0))){ + if (lchr[(int)lp->lnd_type].l_flags & L_SECURITY) + continue; + + cantake = (((float)(lp->lnd_effic-40)/100.0)* + (float)lnd_getmil(lp)); + + if (cantake >= each){ + deq = (((float)each/(float)(lnd_getmil(lp)*2)) + *100.0); + mc -= each; + }else if (cantake > 0){ + deq = (((float)cantake/(float)lnd_getmil(lp)) + * 100.0); + mc -= (((float)deq/100.0)* + (float)lnd_getmil(lp)); + }else + deq = 0; + lp->lnd_effic -= deq; + lp->lnd_mobil -= deq/2; + deq = (double)lchr[(int)lp->lnd_type].l_mil * (deq / 100.0); + lnd_submil(lp, deq); + if (mc<=0) return; + } + + /* Hmm.. still some left.. kill off units now */ + /* kill some normal troops */ + snxtitem_xy(&ni, EF_LAND, sp->sct_x,sp->sct_y); + while(NULL != (lp=(struct lndstr *)nxtitemp(&ni, 0))){ + if (lchr[(int)lp->lnd_type].l_flags & L_SECURITY) + continue; + + mc -= (((float)lp->lnd_effic/100.0) * + (float)lnd_getmil(lp)); + lp->lnd_effic = 0; + lnd_submil(lp, 1000); /* Remove 'em all */ + wu(0,lp->lnd_own,"%s dies fighting guerrillas in %s\n", + prland(lp), + xyas(lp->lnd_x, lp->lnd_y, lp->lnd_own)); + makelost(EF_LAND, lp->lnd_own, lp->lnd_uid, lp->lnd_x, lp->lnd_y); + lp->lnd_own = 0; + if (mc<=0) return; + } + + /* Hmm.. still some left.. kill off units now */ + /* kill some security troops */ + snxtitem_xy(&ni, EF_LAND, sp->sct_x,sp->sct_y); + while(NULL != (lp = (struct lndstr *)nxtitemp(&ni, 0))){ + if (!(lchr[(int)lp->lnd_type].l_flags & L_SECURITY)) + continue; + + mc -= (((float)lp->lnd_effic / 100.0) * (float)lnd_getmil(lp)) * 2; + lp->lnd_effic = 0; + lnd_submil(lp, 1000); /* Kill 'em all */ + wu(0, lp->lnd_own, "%s dies fighting guerrillas in %s\n", + prland(lp), + xyas(lp->lnd_x, lp->lnd_y, lp->lnd_own)); + makelost(EF_LAND, lp->lnd_own, lp->lnd_uid, lp->lnd_x, lp->lnd_y); + lp->lnd_own = 0; + if (mc <= 0) + return; + } + + /* Hmm.. everyone dead.. too bad */ +} diff --git a/src/lib/update/sail.c b/src/lib/update/sail.c new file mode 100644 index 00000000..5ecba212 --- /dev/null +++ b/src/lib/update/sail.c @@ -0,0 +1,352 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * sail.c: Sail ships during the update + * + * Known contributors to this file: + * Doug Hay + * Robert Forsman + * Ken Stevens, 1995 + * Steve McClure, 1998-2000 + */ + +#include "misc.h" +#include "var.h" +#include "sect.h" +#include "path.h" +#include "ship.h" +#include "var.h" +#include "news.h" +#include "file.h" +#include "nat.h" +#include "xy.h" +#include "nsc.h" +#include "update.h" +#include "subs.h" +#include "common.h" +#include + +static void +cost_ship(struct shpstr *sp, struct fltelemstr *ep, struct fltheadstr *fp) +{ + double mobcost,ceil(double); + int howfar; + + mobcost = 0.0; + if (sp->shp_effic > 0) { + mobcost = sp->shp_effic * sp->shp_speed * 0.01; + mobcost = 480.0 / ( mobcost*(1 + (50+sp->shp_tech)/ + (double)(200+sp->shp_tech))); + } +/* the next two lines are not necessary since shp_mobquota is unsigned +and therefore cannot be less than 0. + if (sp->shp_mobquota<0) + sp->shp_mobquota=0; +*/ + + howfar = 0; + if (mobcost > 0) { + howfar = (int)sp->shp_mobil - (int)sp->shp_mobquota; + howfar = ceil((howfar / mobcost)); + } + if (howfar<0) + howfar=0; +#ifdef SAILDEBUG + wu(0,fp->own, + "Ship #%d can move %d spaces on mobility %d (cost/sect %f)\n", + sp->shp_uid, howfar, sp->shp_mobil, mobcost); +#endif + if ((unsigned int)howfar < fp->maxmoves) + fp->maxmoves = howfar; + + ep->mobil = sp->shp_mobil; + ep->mobcost = mobcost; +} + +static int +sail_find_fleet(struct fltheadstr **head, struct shpstr *sp) +{ + struct fltheadstr *fltp; + struct shpstr *ap; + struct fltelemstr *this; + int len=0; + int follow = -1; + int stop; + s_char *cp; + + if (sp->shp_own==0) + return(0); + + + + /* If this ship is following, find the head of the follow list. */ + for (ap=sp; ap; len++, ap=getshipp(follow)) { + follow = ap->shp_follow; + /* Not same owner */ + if (ap->shp_own != sp->shp_own) { + wu(0, sp->shp_own, + "Ship #%d, following #%d, which you don't own.\n", + sp->shp_uid, ap->shp_uid); + return(0); + } + /* Not a follower. */ + if (ap->shp_path[0] != 'f') + break; + /* Following itself */ + if (follow==ap->shp_uid || + follow==sp->shp_uid) + break; + } + if (!ap) { + wu(0, sp->shp_own, + "Ship #%d, following #%d, which you don't own.\n", + sp->shp_uid, follow); + return(0); + } + + /* This should prevent infinite loops. */ + if (len>=10) { + wu(0,sp->shp_own, + "Ship #%d, too many follows (circular follow?).\n", + sp->shp_uid); + return(0); + } + + for (stop=0,cp=ap->shp_path; (!stop) && (*cp); cp++) { + switch (*cp) { + case 'y': + case 'u': + case 'g': + case 'j': + case 'b': + case 'n': + case 'h': + case 't': + break; + default: + stop=1; + } + } + + /* we found a non-valid char in the path. */ + if (*cp) { + wu(0,ap->shp_own, "invalid char '\\%03o' in path of ship %d\n", + (unsigned char)*cp, ap->shp_uid); + *cp=0; + } + + /* if this ship is not sailing anywhere then ignore it. */ + if (!*ap->shp_path) + return(0); + + /* Find the fleet structure we belong to. */ + for (fltp=(*head); (fltp && fltp->leader != follow); fltp = fltp->next) + ; + + if (!fltp) { + fltp = (struct fltheadstr *) malloc(sizeof(*fltp)); + bzero((s_char *)fltp, sizeof(*fltp)); + + /* Fix the links. */ + fltp->next = (*head); + *head = fltp; + + /* Set the leader. */ + fltp->leader = ap->shp_uid; + fltp->real_q = LEADER_REAL; + fltp->x = ap->shp_x; + fltp->y = ap->shp_y; + fltp->own = ap->shp_own; + fltp->maxmoves = 500; + } + + /* If the fleet is not in the same sector as us, no go. */ + if ( ( fltp->x!=sp->shp_x ) || ( fltp->y!=sp->shp_y ) ) { + wu(0,sp->shp_own, + "Ship %d not in same sector as its sailing fleet\n", + sp->shp_uid); + fltp->real_q = LEADER_WRONGSECT; + return(0); + } + + this = (struct fltelemstr *) malloc(sizeof(*this)); + bzero((s_char *)this, sizeof(*this)); + this->num = sp->shp_uid; + this->own = sp->shp_own; + this->next = fltp->head; + fltp->head = this; + cost_ship(sp, this, fltp); + + return 1; +} + +static int +sail_nav_fleet(struct fltheadstr *fltp) +{ + struct fltelemstr *fe; + struct shpstr *sp, ship; + int vec[I_MAX+1]; + struct sctstr *sectp; + int error=0; + s_char *s, *p; + natid own; + struct emp_qelem ship_list; + int dir; + +#ifdef SAILDEBUG + switch (fltp->real_q) { + case LEADER_VIRTUAL: + s = "leaderless"; + break; + case LEADER_REAL: + s = "real"; + break; + case LEADER_WRONGSECT: + s = "scattered"; + break; + default: + s = "inconsistent"; + } + wu(0,fltp->own, + "Fleet lead by %d is %s, can go %d spaces\n contains ships:", + fltp->leader, s, fltp->maxmoves); + for (fe=fltp->head; fe; fe = fe->next) + wu(0, fltp->own, " %d", fe->num); + wu(0, fltp->own, "\n"); +#endif + sectp = getsectp(fltp->x, fltp->y); + switch (check_nav(sectp)) { + case CN_NAVIGABLE: + break; + case CN_CONSTRUCTION: + case CN_LANDLOCKED: + default: + wu(0,fltp->own, "Your fleet lead by %d is trapped by land.\n", + fltp->leader); + return(0); + } + for (fe=fltp->head; fe; fe = fe->next) { + sp = getshipp(fe->num); + getvec(VT_ITEM, vec, (s_char *)sp, EF_SHIP); + if (vec[I_MILIT]==0 && vec[I_CIVIL]==0) { + wu(0,fltp->own, + " ship #%d (%s) is crewless and can't go on\n", + fe->num, cname(fe->own)); + error = 1; + } + } + if (error) + return(0); + sp = getshipp(fltp->leader); + own = sp->shp_own; + fltp_to_list(fltp, &ship_list); /* hack -KHS 1995 */ + for (s=sp->shp_path; (*s) && (fltp->maxmoves>0); s++) { + dir = chkdir(*s, DIR_STOP, DIR_LAST); + if (0 != (error = shp_nav_one_sector(&ship_list, dir, own, 0))) + fltp->maxmoves = 1; + --(fltp->maxmoves); + } + shp_put(&ship_list, own); + getship(sp->shp_uid, &ship); + fltp->x = ship.shp_x; + fltp->y = ship.shp_y; + for (p=&ship.shp_path[0]; *s; p++,s++) + *p = *s; + *p = 0; + putship(ship.shp_uid, &ship); +#ifdef SAILDEBUG + if (sp->shp_path[0]) { + wu(0,fltp->own, + "Fleet lead by #%d nav'd to %s, path left = %s\n", + fltp->leader, xyas(fltp->x,fltp->y,fltp->own), + &sp->shp_path); + } else + wu(0,fltp->own, + "Fleet lead by #%d nav'd to %s, finished.\n", + fltp->leader, xyas(fltp->x,fltp->y,fltp->own)); + wu(0,sp->shp_own, "Ship #%d has %d mobility now.\n", + fe->num, (int)fe->mobil); +#endif + return 1; +} + +void +sail_ship(natid cn) +{ + struct shpstr *sp; + struct fltheadstr *head=0; + struct fltheadstr *fltp; + int n; + + + for (n=0; NULL != (sp = getshipp(n)); n++) if (sp->shp_own==cn) { + sail_find_fleet(&head, sp); + } + + /* see what the fleets fall out into */ + for (fltp=head; fltp; fltp = fltp->next) { + sail_nav_fleet(fltp); + wu(0,fltp->own, "Your fleet lead by ship #%d has reached %s.\n", + fltp->leader,xyas(fltp->x,fltp->y,fltp->own)); + } + + /* Free up the memory, 'cause I want to. */ + for (fltp=head; fltp!=0; ) { + struct fltelemstr *fe; + struct fltheadstr *saveh; + saveh = fltp->next; + for (fe=fltp->head; fe!=0; ) { + struct fltelemstr *saveel; + saveel = fe->next; + free(fe); + fe = saveel; + } + free(fltp); + fltp = saveh; + } +} + +/* The following is a total hack by Ken Stevens to cut down dramatically on repeated code 1995 */ + +void +fltp_to_list(struct fltheadstr *fltp, struct emp_qelem *list) +{ + struct fltelemstr *fe; + struct mlist *mlp; + struct shpstr *sp; + + emp_initque(list); + for (fe=fltp->head; fe; fe = fe->next) { + mlp = (struct mlist *) malloc(sizeof(struct mlist)); + sp = getshipp(fe->num); + mlp->mcp = mchr + sp->shp_type; + bcopy((s_char *)sp, (s_char *)&mlp->ship, + sizeof(struct shpstr)); + mlp->mobil = fe->mobil; + emp_insque(&mlp->queue, list); + } +} diff --git a/src/lib/update/sect.c b/src/lib/update/sect.c new file mode 100644 index 00000000..9d6ab2d4 --- /dev/null +++ b/src/lib/update/sect.c @@ -0,0 +1,510 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * sect.c: Do production for sectors + * + * Known contributors to this file: + * Dave Pare, 1986 + * Steve McClure, 1996 + */ + +#include +#include "misc.h" +#include "var.h" +#include "sect.h" +#include "nat.h" +#include "item.h" +#include "news.h" +#include "file.h" +#include "xy.h" +#include "path.h" +#include "product.h" +#include "distribute.h" +#include "optlist.h" +#include "budg.h" +#include "player.h" +#include "land.h" +#include "ship.h" +#include "update.h" +#include "subs.h" +#include "common.h" +#include "lost.h" +#include "gen.h" + +extern float levels[MAXNOC][4]; + +int +dodeliver(struct sctstr *sp, int *vec) +{ + register int i; + int del[I_MAX+1]; + int thresh; + int dir; + int plague; + int n; + int changed; + + if (sp->sct_mobil <= 0) + return 0; + if (getvec(VT_DEL, del, (s_char *)sp, EF_SECTOR) <= 0) + return 0; + changed = 0; + plague = getvar(V_PSTAGE, (s_char *)sp, EF_SECTOR); + for (i=1; i<=I_MAX; i++) { + if (del[i] == 0) + continue; + thresh = del[i] & ~0x7; + dir = del[i] & 0x7; + n = deliver(sp, &ichr[i], dir, thresh, vec[i], plague); + if (n > 0) { + vec[i] -= n; + changed++; + if (sp->sct_mobil <= 0) + break; + } + } + return changed; +} + +/* + * Increase sector efficiency if old type == new type. + * decrease sector efficiency if old type != new type. + * Return amount of work used. + */ +int +upd_buildeff(struct natstr *np, register struct sctstr *sp, int *workp, int *vec, int etu, int *desig, int sctwork, int *cost) +{ + register int work_cost = 0; + int buildeff_work = (int)(*workp / 2); + int n, hcms, lcms, neweff; + u_char old_type = *desig; + + *cost = 0; + neweff = sp->sct_effic; + + if (*desig != sp->sct_newtype) { + /* + * Tear down existing sector. + * Easier to destroy than to build. + */ + work_cost = (sp->sct_effic + 3) / 4; + if (work_cost > buildeff_work) + work_cost = buildeff_work; + buildeff_work -= work_cost; + n = sp->sct_effic - work_cost * 4; + if (n <= 0) { + n = 0; + *desig = sp->sct_newtype; + } + neweff = n; + *cost += work_cost; + if (opt_BIG_CITY) { + if (!n && dchr[old_type].d_pkg == UPKG && + dchr[*desig].d_pkg != UPKG) { + int maxpop = max_pop(np->nat_level[NAT_RLEV], sp); + if (vec[I_CIVIL] > maxpop) + vec[I_CIVIL] = maxpop; + if (vec[I_UW] > maxpop) + vec[I_UW] = maxpop; + *workp = (vec[I_CIVIL] * sctwork) / 100.0 + +(vec[I_MILIT] * 2 / 5.0) + vec[I_UW]; + *workp = roundavg((etu * (*workp)) / 100.0); + + buildeff_work = min((int)(*workp / 2), buildeff_work); + } + } + } + if (np->nat_priorities[*desig]) { + if (*desig == sp->sct_newtype) { + work_cost = 100 - neweff; + if (work_cost > buildeff_work) + work_cost = buildeff_work; + + if (dchr[*desig].d_lcms>0){ + lcms = vec[I_LCM]; + lcms /= dchr[*desig].d_lcms; + if (work_cost > lcms) + work_cost = lcms; + } + if (dchr[*desig].d_hcms>0){ + hcms = vec[I_HCM]; + hcms /= dchr[*desig].d_hcms; + if (work_cost > hcms) + work_cost = hcms; + } + + neweff += work_cost; + *cost += work_cost*dchr[*desig].d_build; + buildeff_work -= work_cost; + + if ((dchr[*desig].d_lcms>0) || + (dchr[*desig].d_hcms>0)){ + vec[I_LCM] -= work_cost * + dchr[*desig].d_lcms; + vec[I_HCM] -= work_cost * + dchr[*desig].d_hcms; + } + } + } + *workp = *workp/2 + buildeff_work; + + return neweff; +} + +/* + * enlistment sectors are special; they require military + * to convert civ into mil in large numbers. + * Conversion will happen much more slowly without + * some mil initially. + */ +int +enlist(register int *vec, int etu, int *cost) +{ + int maxmil; + int enlisted; + + /* Need to check treaties here */ + enlisted = 0; + maxmil = (vec[I_CIVIL] / 2) - vec[I_MILIT]; + if (maxmil > 0) { + enlisted = (etu * (10 + vec[I_MILIT]) * 0.05); + if (enlisted > maxmil) + enlisted = maxmil; + vec[I_CIVIL] -= enlisted; + vec[I_MILIT] += enlisted; + } + *cost = enlisted * 3; + return enlisted; +} + +/* Fallout is calculated here. */ + +extern int melt_item_denom[]; + +void +meltitems(int etus, int fallout, int own, int *vec, int type, int x, int y, int uid) +{ + int n; + int melt; + + for (n = 1; n <= I_MAX; n++) { + melt = roundavg(vec[n] * etus * (long)fallout / + (1000.0 * melt_item_denom[n])); + if (melt > 5 && own) { + if (type == EF_SECTOR) + wu(0, own, "Lost %d %s to radiation in %s.\n", + (melt < vec[n] ? melt : vec[n]), ichr[n].i_name, + xyas(x, y, own)); + else if (type == EF_LAND) + wu(0, own, "Unit #%d lost %d %s to radiation in %s.\n", + uid, (melt < vec[n] ? melt : vec[n]), ichr[n].i_name, + xyas(x, y, own)); + else if (type == EF_SHIP) + wu(0, own, "Ship #%d lost %d %s to radiation in %s.\n", + uid, (melt < vec[n] ? melt : vec[n]), ichr[n].i_name, + xyas(x, y, own)); + } + if (melt < vec[n]) + vec[n] -= melt; + else + vec[n] = 0; + } +} + +/* + * do_fallout - calculate fallout for sectors. + * + * This is etu based. But, do limit HUGE kill offs in large ETU + * games, the melting etus rate is limited to 24 etus. + */ + +void +do_fallout(register struct sctstr *sp, register int etus) +{ + int vec[I_MAX+1]; + int cvec[I_MAX+1]; + int tvec[I_MAX+1]; + struct shpstr *spp; + struct lndstr *lp; + int i; + + getvec(VT_ITEM, vec, (s_char *)sp, EF_SECTOR); + getvec(VT_COND, cvec, (s_char *)sp, EF_SECTOR); +/* This check shouldn't be needed, but just in case. :) */ + if (!cvec[C_FALLOUT] || !sp->sct_updated) + return; + if (etus > 24) + etus = 24; +#if 0 + wu(0,0,"Running fallout in %d,%d\n", sp->sct_x, sp->sct_y); +#endif + meltitems(etus, cvec[C_FALLOUT], sp->sct_own, vec, EF_SECTOR, + sp->sct_x, sp->sct_y, 0); + putvec(VT_ITEM, vec, (s_char *)sp, EF_SECTOR); + for (i = 0; NULL != (lp = getlandp(i)); i++) { + if (!lp->lnd_own) + continue; + if (lp->lnd_x != sp->sct_x || lp->lnd_y != sp->sct_y) + continue; + getvec(VT_ITEM, tvec, (s_char *)lp, EF_LAND); + meltitems(etus, cvec[C_FALLOUT], lp->lnd_own, tvec, EF_LAND, + lp->lnd_x, lp->lnd_y, lp->lnd_uid); + putvec(VT_ITEM, tvec, (s_char *)lp, EF_LAND); + } + for (i = 0; NULL != (spp = getshipp(i)); i++) { + if (!spp->shp_own) + continue; + if (spp->shp_x != sp->sct_x || spp->shp_y != sp->sct_y) + continue; + if (mchr[(int)spp->shp_type].m_flags & M_SUB) + continue; + getvec(VT_ITEM, tvec, (s_char *)spp, EF_SHIP); + meltitems(etus, cvec[C_FALLOUT], spp->shp_own, tvec, EF_SHIP, + spp->shp_x, spp->shp_y, spp->shp_uid); + putvec(VT_ITEM, tvec, (s_char *)spp, EF_SHIP); + } +#ifdef GODZILLA + if ((cvec[C_FALLOUT] > 20) && chance(100)) + do_godzilla(sp); +#endif /* GODZILLA */ +} + +void +spread_fallout(struct sctstr *sp, int etus) +{ + extern double fallout_spread; + struct sctstr *ap; + int tvec[I_MAX+1]; + int cvec[I_MAX+1]; + int n; + register int inc; + + if (etus > 24) + etus = 24; + getvec(VT_COND, cvec, (s_char *)sp, EF_SECTOR); + for (n = DIR_FIRST; n <= DIR_LAST; n++) { + ap = getsectp(sp->sct_x+diroff[n][0], sp->sct_y+diroff[n][1]); + getvec(VT_COND, tvec, (char *)ap, EF_SECTOR); + if (ap->sct_type == SCT_SANCT) + continue; + inc = roundavg(etus * fallout_spread * (cvec[C_FALLOUT])) - 1; +#if 0 + if (cvec[C_FALLOUT]) { + wu(0,0,"Fallout from sector %d,%d to %d,%d is %d=%d*%e*%d\n", + sp->sct_x,sp->sct_y,sp->sct_x+diroff[n][0], + sp->sct_y+diroff[n][1], inc, etus, + fallout_spread, cvec[C_FALLOUT]); + } +#endif + if (inc < 0) + inc = 0; + tvec[C_FALLOUT] += inc; + putvec(VT_COND, tvec, (char *)ap, EF_SECTOR); + } +} + +void +decay_fallout(struct sctstr *sp, int etus) +{ + extern double decay_per_etu; + extern double fallout_spread; + int cvec[I_MAX+1]; + int decay; + + if (etus > 24) + etus = 24; + getvec(VT_COND, cvec, (char *)sp, EF_SECTOR); + decay = roundavg(((decay_per_etu + 6.0) * fallout_spread) * + (double)etus * (double)cvec[C_FALLOUT]); + +#if 0 + if (decay || cvec[C_FALLOUT]) + wu(0,0,"Fallout decay in %d,%d is %d from %d\n", sp->sct_x, sp->sct_y, decay, cvec[C_FALLOUT]); +#endif + + cvec[C_FALLOUT] = (decay < cvec[C_FALLOUT]) ? (cvec[C_FALLOUT] - decay) : 0; + if (cvec[C_FALLOUT] < 0) + cvec[C_FALLOUT] = 0; + putvec(VT_COND, cvec, (s_char *)sp, EF_SECTOR); +} + +#define SHOULD_PRODUCE(sp,t) (((sp->sct_type == t) || (t == -1)) ? 1 : 0) + +/* + * Produce only a set sector type for a specific nation + * (or all, if sector_type == -1) + * + */ +void +produce_sect(int natnum, int etu, int *bp, long int (*p_sect)[2], int sector_type) +{ + register struct sctstr *sp; + register struct natstr *np; + int vec[I_MAX+1]; + int work, cost, ecost, pcost, sctwork; + int n, desig, maxpop, neweff, amount; + + for (n=0; NULL != (sp = getsectid(n)); n++) { + if (sp->sct_type == SCT_WATER) + continue; + if (sp->sct_own != natnum) + continue; + if (sp->sct_updated != 0) + continue; + if (!SHOULD_PRODUCE(sp,sector_type)) + continue; + + if ((sp->sct_type == SCT_CAPIT) && (sp->sct_effic > 60)) { + p_sect[SCT_CAPIT][0]++; + p_sect[SCT_CAPIT][1] += etu; + } + + if (getvec(VT_ITEM, vec, (s_char *)sp, EF_SECTOR) <= 0) + continue; + /* If everybody is dead, the sector reverts to unowned. + * This is also checked at the end of the production in + * they all starved or were plagued off. + */ + if (vec[I_CIVIL] == 0 && vec[I_MILIT] == 0 && + !has_units(sp->sct_x,sp->sct_y,sp->sct_own,0)) { + makelost(EF_SECTOR, sp->sct_own, 0, sp->sct_x, sp->sct_y); + sp->sct_own = 0; + sp->sct_oldown = 0; + continue; + } + + sp->sct_updated = 1; + work = 0; + + np = getnatp(natnum); + + /* do_feed trys to supply. So, we need to enable cacheing + here */ + bp_enable_cachepath(); + + sctwork = do_feed(sp, np, vec, &work, bp, etu); + + bp_disable_cachepath(); + bp_clear_cachepath(); + + if (sp->sct_off || np->nat_money < 0) { + if (!player->simulation) { + putvec(VT_ITEM, vec, (s_char *)sp, EF_SECTOR); + sp->sct_off = 0; + } + continue; + } + if ((np->nat_priorities[sp->sct_type] == 0) && + (sp->sct_type == sp->sct_newtype) && + ((pchr[dchr[sp->sct_type].d_prd].p_cost != 0) || + (sp->sct_type == SCT_ENLIST))){ + if (!player->simulation) { + putvec(VT_ITEM, vec, (s_char *)sp, EF_SECTOR); + logerror("Skipping %s production for country %s\n", + dchr[sp->sct_type].d_name,np->nat_cnam); + } + continue; + } + + neweff = sp->sct_effic; + amount = 0; + pcost = cost = ecost = 0; + + desig = sp->sct_type; + + if ((sp->sct_effic < 100 || sp->sct_type != sp->sct_newtype) && + np->nat_money > 0) { + neweff = upd_buildeff(np, sp, &work, vec, etu, &desig, sctwork, &cost); + pt_bg_nmbr(bp, sp, I_LCM, vec[I_LCM]); + pt_bg_nmbr(bp, sp, I_HCM, vec[I_HCM]); + p_sect[SCT_EFFIC][0]++; + p_sect[SCT_EFFIC][1] += cost; + if (!player->simulation) { + np->nat_money -= cost; + /* No longer tear down infrastructure + if (sp->sct_type != desig) { + sp->sct_road = 0; + sp->sct_defense = 0; + } else if (neweff < sp->sct_effic) { + sp->sct_road -= (sp->sct_road * (sp->sct_effic - neweff) / 100.0); + sp->sct_defense -= (sp->sct_defense * (sp->sct_effic - neweff) / 100.0); + if (sp->sct_road < 0) + sp->sct_road = 0; + if (sp->sct_defense < 0) + sp->sct_defense = 0; + } + */ + sp->sct_type = desig; + sp->sct_effic = neweff; + if (!opt_DEFENSE_INFRA) + sp->sct_defense = sp->sct_effic; + } + } + + if ((np->nat_priorities[desig] == 0) && + ((pchr[dchr[desig].d_prd].p_cost != 0) || + (desig == SCT_ENLIST))) { + if (!player->simulation) { + putvec(VT_ITEM, vec, (s_char *)sp, EF_SECTOR); + logerror("Skipping %s production for country %s\n", + dchr[sp->sct_type].d_name,np->nat_cnam); + } + continue; + } + + if (desig == SCT_ENLIST && neweff >= 60 && + sp->sct_own == sp->sct_oldown) { + p_sect[desig][0] += enlist(vec, etu, &ecost); + p_sect[desig][1] += ecost; + if (!player->simulation) + np->nat_money -= ecost; + } + + /* + * now do the production (if sector effic >= 60%) + */ + + if (neweff >= 60) { + if (np->nat_money > 0 && dchr[desig].d_prd) + work -= produce(np, sp, vec, work, sctwork, desig, neweff, &pcost, &amount); + } + + pt_bg_nmbr(bp, sp, I_MAX+1, work); + p_sect[desig][0] += amount; + p_sect[desig][1] += pcost; + if (!player->simulation) { + maxpop = max_pop(np->nat_level[NAT_RLEV], sp); + if (vec[I_CIVIL] > maxpop) + vec[I_CIVIL] = maxpop; + if (vec[I_UW] > maxpop) + vec[I_UW] = maxpop; + putvec(VT_ITEM, vec, (s_char *)sp, EF_SECTOR); + sp->sct_avail = work; + np->nat_money -= pcost; + } + } +} diff --git a/src/lib/update/ship.c b/src/lib/update/ship.c new file mode 100644 index 00000000..02ff1ef4 --- /dev/null +++ b/src/lib/update/ship.c @@ -0,0 +1,529 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * ship.c: Do production for ships + * + * Known contributors to this file: + * Dave Pare, 1986 + * Steve McClure, 1996 + */ + +#include "misc.h" +#include "var.h" +#include "sect.h" +#include "nat.h" +#include "ship.h" +#include "var.h" +#include "news.h" +#include "file.h" +#include "product.h" +#include "land.h" +#include "xy.h" +#include "nsc.h" +#include "optlist.h" +#include "player.h" +#include "update.h" +#include "common.h" +#include "subs.h" +#include "gen.h" +#include "lost.h" + +#ifndef MIN +#define MIN(x,y) ((x) > (y) ? (y) : (x)) +#endif + +int +prod_ship(int etus, int natnum, int *bp, int build) + /* build = 1, maintain = 0 */ +{ + register struct shpstr *sp; + struct natstr *np; + int n, k=0; + extern long sea_money[MAXNOC]; + int start_money; + int lastx = 9999, lasty = 9999; + + bp_enable_cachepath(); + for (n=0; NULL != (sp = getshipp(n)); n++) { + if (sp->shp_own == 0) + continue; + if (sp->shp_own != natnum) + continue; + np = getnatp(sp->shp_own); + start_money = np->nat_money; + if (lastx == 9999 || lasty == 9999) { + lastx = sp->shp_x; + lasty = sp->shp_y; + } + if (lastx != sp->shp_x || lasty != sp->shp_y) { + /* Reset the cache */ + bp_disable_cachepath(); + bp_clear_cachepath(); + bp_enable_cachepath(); + } + upd_ship(sp, n, etus, np, bp, build); + if (build && !player->simulation) /* make sure to only autonav once */ + nav_ship(sp); /* autonav the ship */ + sea_money[sp->shp_own] += np->nat_money - start_money; + if ((build && (np->nat_money != start_money)) || (!build)) + k++; + if (player->simulation) + np->nat_money = start_money; + } + bp_disable_cachepath(); + bp_clear_cachepath(); + + if (opt_SAIL) { + if (build && !player->simulation) /* make sure to only sail once */ + sail_ship(natnum); + } + return k; +} + +void +upd_ship(register struct shpstr *sp, int shipno, register int etus, struct natstr *np, int *bp, int build) + /* build = 1, maintain = 0 */ +{ + extern long pops[]; + struct sctstr *sectp; + struct mchrstr *mp; + int vec[I_MAX+1]; + int cvec[I_MAX+1]; + int oil_gained; + int max_oil; + int max_food; + struct pchrstr *product; + s_char *resource; + int n; + int mult; + extern double money_ship; + int needed; + int cost; + int eff; + + mp = &mchr[(int)sp->shp_type]; + getvec(VT_ITEM, vec, (s_char *)sp, EF_SHIP); + if (build == 1){ + if (np->nat_priorities[PRI_SBUILD] == 0 || + np->nat_money < 0) + return; + if (sp->shp_effic < SHIP_MINEFF || + !shiprepair(sp, vec, np, bp, etus)) { + makelost(EF_SHIP, sp->shp_own, sp->shp_uid, sp->shp_x, sp->shp_y); + sp->shp_own = 0; + return; + } + }else{ + mult = 1; + if (np->nat_level[NAT_TLEV] < sp->shp_tech * 0.85) + mult = 2; + cost = -(mult * etus * dmin(0.0, money_ship * mp->m_cost)); + if ((np->nat_priorities[PRI_SMAINT] == 0 || + np->nat_money < cost) && !player->simulation){ + if ((eff = sp->shp_effic - etus/5) < SHIP_MINEFF) { + wu(0, sp->shp_own, + "%s lost to lack of maintenance\n", + prship(sp)); + makelost(EF_SHIP, sp->shp_own, sp->shp_uid, sp->shp_x, sp->shp_y); + sp->shp_own = 0; + return; + } + wu(0, sp->shp_own, + "%s lost %d%% to lack of maintenance\n", + prship(sp), sp->shp_effic - eff); + sp->shp_effic = eff; + } else { + np->nat_money -= cost; + } + + sectp = getsectp(sp->shp_x, sp->shp_y); + if (((mp->m_flags & M_OIL) && (sectp->sct_type == SCT_WATER)) + && !player->simulation){ + /* + * take care of oil production + */ + oil_gained = roundavg((vec[I_CIVIL] * etus / 10000.0) + * sectp->sct_oil); + vec[I_OIL] += oil_gained; + max_oil = vl_find(V_OIL,mp->m_vtype,mp->m_vamt,mp->m_nv); + if (vec[I_OIL] > max_oil) + vec[I_OIL] = max_oil; + product = &pchr[P_OIL]; + if (product->p_nrdep != 0 && oil_gained > 0) { + resource = ((s_char *)sectp) + product->p_nrndx; + *resource -= roundavg(oil_gained * + product->p_nrdep / 100.0); + } + } else if (((mp->m_flags&M_FOOD)&&(sectp->sct_type==SCT_WATER)) && !player->simulation){ + sectp = getsectp(sp->shp_x, sp->shp_y); + vec[I_FOOD] += ((vec[I_CIVIL] * etus) / 1000.0) + * sectp->sct_fertil; + } +/* Military costs are now part of regular military costs, not ship costs */ +/* np->nat_money += (int) (etus * vec[I_MILIT] * money_mil);*/ + if (!player->simulation){ + if ((n = feed_ship(sp,vec,etus, &needed, 1)) > 0) { + wu(0, sp->shp_own, "%d starved on %s\n", + n, prship(sp)); + if (n > 10) + nreport(sp->shp_own, N_DIE_FAMINE, 0, 1); + } + max_food = vl_find(V_FOOD, mp->m_vtype, mp->m_vamt, mp->m_nv); + if (vec[I_FOOD] > max_food) + vec[I_FOOD] = max_food; + /* + * do plague stuff. plague can't break out on ships, + * but it can still kill people. + */ + getvec(VT_COND, cvec, (s_char *)sp, EF_SHIP); + if (cvec[C_PSTAGE] > 0) { + n = plague_people(np, vec, cvec, etus); + switch (n) { + case PLG_DYING: + wu(0, sp->shp_own, + "PLAGUE deaths reported on %s\n", + prship(sp)); + nreport(sp->shp_own, N_DIE_PLAGUE, 0, 1); + break; + case PLG_INFECT: + wu(0, sp->shp_own, "%s battling PLAGUE\n", + prship(sp)); + break; + case PLG_INCUBATE: + /* Are we still incubating? */ + if (n == cvec[C_PSTAGE]) { + /* Yes. Will it turn "infectious" next time? */ + if (cvec[C_PTIME] <= etus) { + /* Yes. Report an outbreak. */ + wu(0, sp->shp_own, + "Outbreak of PLAGUE on %s!\n", + prship(sp)); + nreport(sp->shp_own, N_OUT_PLAGUE, 0, 1); + } + } else { + /* It has already moved on to "infectious" */ + wu(0, sp->shp_own, + "%s battling PLAGUE\n", prship(sp)); + } + break; + case PLG_EXPOSED: + /* Has the plague moved to "incubation" yet? */ + if (n != cvec[C_PSTAGE]) { + /* Yes. Will it turn "infectious" next time? */ + if (cvec[C_PTIME] <= etus) { + /* Yes. Report an outbreak. */ + wu(0, sp->shp_own, + "Outbreak of PLAGUE on %s!\n", + prship(sp)); + nreport(sp->shp_own, N_OUT_PLAGUE, 0, 1); + } + } + break; + default: + break; + } + + putvec(VT_COND, cvec, (s_char *)sp, EF_SHIP); + } + putvec(VT_ITEM, vec, (s_char *)sp, EF_SHIP); + pops[sp->shp_own] += vec[I_CIVIL]; + } + } +} + +/* + * idea is: a sector full of workers can fix up eight + * battleships +8 % eff each etu. This will cost around + * 8 * 8 * $40 = $2560! + */ +int +shiprepair(register struct shpstr *ship, int *vec, struct natstr *np, int *bp, int etus) +{ + extern int ship_grow_scale; + register int delta; + struct sctstr *sp; + struct mchrstr *mp; + float leftp, buildp; + int left, build; + int lcm_needed, hcm_needed; + int wf; + int avail; + int w_p_eff; + int mult; + int svec[I_MAX+1]; + int mvec[I_MAX+1]; + int rel; + + mp = &mchr[(int)ship->shp_type]; + sp = getsectp(ship->shp_x, ship->shp_y); + + if ((sp->sct_own != ship->shp_own) && (sp->sct_own != 0)) { + rel=getrel(getnatp(sp->sct_own),ship->shp_own); + + if (rel < FRIENDLY) + return 1; + } + + wf = 0; + /* only military can work on a military boat */ + if (ship->shp_glim > 0) + wf = etus * vec[I_MILIT]/2; + else + wf = etus * (vec[I_CIVIL]/2 + vec[I_MILIT]/5); + + if (sp->sct_type != SCT_HARBR){ + wf /= 3; + avail = wf; + }else{ + if (!player->simulation) + avail = wf + sp->sct_avail * 100; + else + avail = wf + gt_bg_nmbr(bp, sp, I_MAX+1) * 100; + } + + w_p_eff = 20 + (mp->m_lcm + 2 * mp->m_hcm); + + if (sp->sct_type != SCT_HARBR){ + int abs_max, amt; + + if (ship->shp_glim > 0){ + abs_max = vl_find(V_MILIT, mp->m_vtype, + mp->m_vamt, (int) mp->m_nv); + amt = vec[I_MILIT]; + }else{ + abs_max = vl_find(V_CIVIL, mp->m_vtype, + mp->m_vamt, (int) mp->m_nv); + amt = vec[I_CIVIL]; + if (abs_max==0) { + abs_max = vl_find(V_MILIT, mp->m_vtype, mp->m_vamt, + (int) mp->m_nv); + amt = vec[I_MILIT]; + } + } + + if (abs_max == 0){ + logerror("Abs max of 0 for ship %d\n",ship->shp_uid); + abs_max = 1; + } + avail -= (etus * (100-((amt*100)/abs_max)))/7; + /* think of it as entropy in action */ + } + + if (avail <= 0){ + if (!player->simulation) { + if (opt_SHIP_DECAY) { + ship->shp_effic += avail/w_p_eff; + } + return 1; + } + } + + if ((sp->sct_off) && (sp->sct_own == ship->shp_own)) + return 1; + + getvec(VT_ITEM, svec, (s_char *)sp, EF_SECTOR); + + mult = 1; + if (np->nat_level[NAT_TLEV] < ship->shp_tech * 0.85) + mult = 2; + + if (ship->shp_effic == 100) { + /* ship is ok; no repairs needed */ + return 1; + } + + left = 100 - ship->shp_effic; + delta = roundavg((double)avail/w_p_eff); + if (delta <= 0) + return 1; + if (delta > etus*ship_grow_scale) + delta = etus*ship_grow_scale; + if (delta > left) + delta = left; + + /* delta is the max amount we can grow */ + + left = 100 - ship->shp_effic; + if (left > delta) + left = delta; + + leftp = ((float)left/100.0); + bzero((s_char *)mvec, sizeof(mvec)); + mvec[I_LCM] = lcm_needed = ldround((double)(mp->m_lcm * leftp),1); + mvec[I_HCM] = hcm_needed = ldround((double)(mp->m_hcm * leftp),1); + + get_materials(sp, bp, mvec, 0); + + if (mvec[I_LCM]>=lcm_needed) + buildp=leftp; + else + buildp=((float)mvec[I_LCM]/(float)mp->m_lcm); + if (mvec[I_HCM] < hcm_needed) + buildp = MIN(buildp,((float)mvec[I_HCM]/(float)mp->m_hcm)); + + build=ldround((double)(buildp*100.0),1); + bzero((s_char *)mvec, sizeof(mvec)); + mvec[I_LCM] = lcm_needed = roundavg((double)(mp->m_lcm * buildp)); + mvec[I_HCM] = hcm_needed = roundavg((double)(mp->m_hcm * buildp)); + + get_materials(sp, bp, mvec, 1); + + if (sp->sct_type != SCT_HARBR) + build = delta; + wf -= build * w_p_eff; + if (wf < 0) { + /* + * I didn't use roundavg here, because I want to penalize + * the player with a large number of ships. + */ + if (!player->simulation) + avail = (sp->sct_avail * 100 + wf) / 100; + else + avail = (gt_bg_nmbr(bp,sp,I_MAX+1) * 100 + wf) / 100; + if (avail < 0) + avail = 0; + if (!player->simulation) + sp->sct_avail = avail; + else + pt_bg_nmbr(bp, sp, I_MAX+1, avail); + } + if (sp->sct_type != SCT_HARBR) + if ((build+ship->shp_effic)>80){ + build = 80 - ship->shp_effic; + if (build < 0) + build = 0; + } + + np->nat_money -= mult * mp->m_cost * build / 100.0; + if (!player->simulation) + ship->shp_effic += (s_char)build; + return 1; +} + +/* + * returns the number who starved, if any. + */ +int +feed_ship(struct shpstr *sp, register int *vec, int etus, int *needed, int doit) +{ + extern double eatrate; + double food_eaten, land_eaten; + double people_left; + int ifood_eaten; + int can_eat, need; + int total_people; + int to_starve; + int starved, lvec[I_MAX+1]; + struct nstr_item ni; + struct lndstr *lp; + s_char *nxtitemp(struct nstr_item *np, int owner); + + if (opt_NOFOOD) return 0; /* no food no work to do */ + + food_eaten = (etus * eatrate) * (vec[I_CIVIL]+vec[I_MILIT]+vec[I_UW]); + ifood_eaten = (int)food_eaten; + if ((food_eaten-ifood_eaten) > 0) + ifood_eaten++; + starved = 0; + *needed = 0; + if (!player->simulation && + food_eaten > vec[I_FOOD]) + vec[I_FOOD] += supply_commod(sp->shp_own,sp->shp_x,sp->shp_y, + I_FOOD,(ifood_eaten-vec[I_FOOD])); + + if (food_eaten > vec[I_FOOD]) { +/* doit - only steal food from land units during the update */ + if (sp->shp_nland > 0 && doit) { + snxtitem_all(&ni,EF_LAND); + while((lp=(struct lndstr *)nxtitemp(&ni, 0)) && + (food_eaten > vec[I_FOOD])){ + if (lp->lnd_ship != sp->shp_uid) + continue; + need = ifood_eaten - vec[I_FOOD]; + getvec(VT_ITEM, lvec, (s_char *)lp, EF_LAND); + land_eaten = (etus * eatrate) * + (double)lnd_getmil(lp); + if (lvec[I_FOOD]-need > land_eaten){ + vec[I_FOOD] += need; + lvec[I_FOOD] -= need; + }else if ((lvec[I_FOOD]-land_eaten) > 0){ + vec[I_FOOD]+= (lvec[I_FOOD]-land_eaten); + lvec[I_FOOD]-=(lvec[I_FOOD]-land_eaten); + } + putvec(VT_ITEM, lvec, (s_char *)lp, EF_LAND); + } + } + } + + if (food_eaten > vec[I_FOOD]){ + *needed = food_eaten - vec[I_FOOD]; + if (*needed < (food_eaten - vec[I_FOOD])) + (*needed)++; + if (opt_NEW_STARVE) { + can_eat = (vec[I_FOOD] / (etus * eatrate)); + total_people = vec[I_CIVIL] + vec[I_MILIT] + vec[I_UW]; + + /* only want to starve off at most 1/2 the populace. */ + if (can_eat < (total_people/2)) + can_eat = total_people/2; + + to_starve = total_people - can_eat; + while(to_starve && vec[I_UW]){ + to_starve--; + starved++; + vec[I_UW]--; + } + while(to_starve && vec[I_CIVIL]){ + to_starve--; + starved++; + vec[I_CIVIL]--; + } + while(to_starve && vec[I_MILIT]){ + to_starve--; + starved++; + vec[I_MILIT]--; + } + + vec[I_FOOD] = 0; + } + else { /* ! opt_NEW_STARVE */ + people_left = (vec[I_FOOD] + 0.01) / (food_eaten + 0.01); + starved = vec[I_CIVIL] + vec[I_MILIT] + vec[I_UW]; + /* only want to starve off at most 1/2 the populace. */ + if (people_left < 0.5) + people_left = 0.5; + vec[I_CIVIL] = (int) (vec[I_CIVIL] * people_left); + vec[I_MILIT] = (int) (vec[I_MILIT] * people_left); + vec[I_UW] = (int) (vec[I_UW] * people_left); + starved -= vec[I_CIVIL] + vec[I_MILIT] + vec[I_UW]; + vec[I_FOOD] = 0; + } + } else { + vec[I_FOOD] -= (int)food_eaten; + } + return starved; +} diff --git a/src/make.defs b/src/make.defs new file mode 100644 index 00000000..8e939d83 --- /dev/null +++ b/src/make.defs @@ -0,0 +1,42 @@ +# +# Empire - A multi-player, client/server Internet based war game. +# Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, +# Ken Stevens, Steve McClure +# +# 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 2 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, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# --- +# +# See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the +# related information and legal notices. It is expected that any future +# projects/authors will amend these files as needed. +# +# make.defs - Wolfpack, 1996 +# +# Lots of definition stuff common to the makefiles can go here. +# Make sure that make.src is included before this one (both +# are in this directory, but make.src is auto-generated.) + +GLOBALCFLAGS = +GLOBALLFLAGS = +GLOBALIFLAGS = -I$(SRCDIR)/include + +RANLIB = ranlib + +CFLAGS = $(LOCALCFLAGS) $(GLOBALCFLAGS) +IFLAGS = $(LOCALIFLAGS) $(GLOBALIFLAGS) +LFLAGS = $(LOCALLFLAGS) $(GLOBALLFLAGS) + + diff --git a/src/make.rules b/src/make.rules new file mode 100644 index 00000000..7c4be30f --- /dev/null +++ b/src/make.rules @@ -0,0 +1,39 @@ +# +# Empire - A multi-player, client/server Internet based war game. +# Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, +# Ken Stevens, Steve McClure +# +# 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 2 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, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# --- +# +# See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the +# related information and legal notices. It is expected that any future +# projects/authors will amend these files as needed. +# +# make.rules - Wolfpack, 1996 +# +# Lots of rules stuff common to the makefiles can go here. +# Make sure that make.src is included before this one (both +# are in this directory, but make.src is auto-generated.) + +.c.obj: ; + $(CC) -c $(IFLAGS) $(CFLAGS) $*.c + +.c.o: ; + $(CC) -c $(IFLAGS) $(CFLAGS) $*.c + +depend: + $(CC) -M -I../../include -I../../../include *.c > Makedepend diff --git a/src/server/Makefile b/src/server/Makefile new file mode 100644 index 00000000..a3d048cc --- /dev/null +++ b/src/server/Makefile @@ -0,0 +1,118 @@ +# +# Empire - A multi-player, client/server Internet based war game. +# Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, +# Ken Stevens, Steve McClure +# +# 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 2 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, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# --- +# +# See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the +# related information and legal notices. It is expected that any future +# projects/authors will amend these files as needed. +# +# Makefile - Wolfpack, 1996 + +# Note that these could have been listed 1 per line, but I chose to just +# stick them all together this way to shorten the file. + +include ../../build.conf +include ../make.src +include ../make.defs + +OBJS = main.o idle.o lostitem.o marketup.o shutdown.o timestamp.o update.o + +NTOBJS = main.obj idle.obj lostitem.obj marketup.obj shutdown.obj \ + timestamp.obj update.obj + +LIBDIR = $(SRCDIR)/lib + +LIBS = $(LIBDIR)/libplayer.a \ + $(LIBDIR)/libupdate.a \ + $(LIBDIR)/libcommands.a \ + $(LIBDIR)/libsubs.a \ + $(LIBDIR)/libcommon.a \ + $(LIBDIR)/libgen.a \ + $(LIBDIR)/libglobal.a \ + $(LIBDIR)/libas.a \ + $(LIBDIR)/libempth.a \ + $(LIBDIR)/liblwp.a + +OSXLIBS = $(LIBDIR)/libplayer.a \ + $(LIBDIR)/libupdate.a \ + $(LIBDIR)/libcommands.a \ + $(LIBDIR)/libsubs.a \ + $(LIBDIR)/libcommon.a \ + $(LIBDIR)/libgen.a \ + $(LIBDIR)/libglobal.a \ + $(LIBDIR)/libas.a \ + $(LIBDIR)/libempth.a + +NTLIBS = $(LIBDIR)\libplayer.lib \ + $(LIBDIR)\libupdate.lib \ + $(LIBDIR)\libcommands.lib \ + $(LIBDIR)\libsubs.lib \ + $(LIBDIR)\libcommon.lib \ + $(LIBDIR)\libgen.lib \ + $(LIBDIR)\libglobal.lib \ + $(LIBDIR)\libas.lib \ + $(LIBDIR)\libempth.lib + +all: emp_server + +osx: empX_server + +nt: emp_server.exe + +emp_server.exe: $(NTOBJS) $(NTLIBS) + link /OUT:emp_server.exe \ + /PDB:emp_server.pdb /NOLOGO \ + /NOD /DEBUG:full /DEBUGTYPE:cv /MACHINE:IX86 /NOLOGO \ + $(NTOBJS) $(NTLIBS) \ + kernel32.lib \ + wsock32.lib \ + libcmt.lib \ + oldnames.lib + +emp_server: $(OBJS) $(LIBS) + $(CC) -o emp_server $(OBJS) $(LIBS) $(LFLAGS) $(GLOBALPFLAGS) -lm -lc + +empX_server: $(OBJS) $(OSXLIBS) + $(CC) -o emp_server $(OBJS) $(OSXLIBS) $(LFLAGS) $(GLOBALPFLAGS) -lm -lc + +clean: + -(del /q $(NTOBJS)) + -(del /q emp_server.exe) + -(del /q emp_server.ilk) + -(del /q emp_server.pdb) + -(rm -f $(OBJS)) + -(rm -f emp_server) + -(rm -f $(OSXOBJS)) + -(rm -f empX_server) + +install: + -(mkdir $(EMPDIR)/bin) + -(cp emp_server $(EMPDIR)/bin) + +OSXinstall: + -(mkdir $(EMPDIR)/bin) + -(cp empX_server $(EMPDIR)/bin) + +ntinstall: + -(mkdir $(NTINSTDIR)\bin) + -(copy emp_server.exe $(NTINSTDIR)\bin) + +include ../make.rules +include Makedepend diff --git a/src/server/idle.c b/src/server/idle.c new file mode 100644 index 00000000..b0dd6de4 --- /dev/null +++ b/src/server/idle.c @@ -0,0 +1,83 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * idle.c: Stamps out idle players. Runs at low priority + * + * Known contributors to this file: + * Dave Pare, 1994 + */ + +#include "misc.h" +#include "player.h" +#include "empio.h" +#include "empthread.h" +#include "proto.h" +#include "prototypes.h" + +/*ARGSUSED*/ +void +player_kill_idle(argv) + void *argv; +{ + extern int max_idle; + struct player *p; + time_t now; + + time(&now); + while (1) { + empth_sleep(now + 60); + time(&now); + /*if (update_pending)*/ + /*continue;*/ + for (p = player_next(0); p != 0; p = player_next(p)) { + if (p->state == PS_SHUTDOWN) { + /* no more mr. nice guy */ + p->state = PS_KILL; + p->aborted++; + empth_terminate(p->proc); + p = player_delete(p); + continue; + } + if (p->curup + max_idle * 60 < now) { + p->state = PS_SHUTDOWN; + /* giving control to another thread while + * in the middle of walking player list is + * not a good idea at all. Sasha */ + p->aborted++; + pr_flash(p, + "idle connection terminated\n"); + empth_wakeup(p->proc); + /* go to sleep because player thread + could vandalize a player list */ + + break; + } + } + } + /*NOTREACHED*/ +} + diff --git a/src/server/lostitem.c b/src/server/lostitem.c new file mode 100644 index 00000000..2cbf92ef --- /dev/null +++ b/src/server/lostitem.c @@ -0,0 +1,75 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * lostitem.c: This deletes the old lost items + * + * Known contributors to this file: + * Steve McClure, 1997 + */ + +#include "options.h" +#include "misc.h" +#include "player.h" +#include "keyword.h" +#include "empthread.h" +#include "file.h" +#include "lost.h" +#include +#include "prototypes.h" + +/*ARGSUSED*/ +void +delete_lostitems(argv) +void *argv; +{ + extern int lost_items_timeout; + time_t now; + struct loststr lost; + int n; + int ncnt; + + while (1) { + time(&now); +/* logerror("Deleting lost items at %s", ctime(&now));*/ + ncnt = 0; + for (n = 0; getlost(n, &lost); n++) { + if (!lost.lost_owner) + continue; + if (lost.lost_timestamp > (now - lost_items_timeout)) + continue; + lost.lost_owner = 0; + lost.lost_timestamp = 0; + putlost(n, &lost); + ncnt++; + } +/* logerror("Deleted %d lost items", ncnt, ctime(&now));*/ + now = now + 900; /* Every 15 minutes */ + empth_sleep(now); + } + /*NOTREACHED*/ +} + diff --git a/src/server/main.c b/src/server/main.c new file mode 100644 index 00000000..37f6da55 --- /dev/null +++ b/src/server/main.c @@ -0,0 +1,486 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * main.c: Thread and signal initialization for Empire Server + * + * Known contributors to this file: + * Dave Pare, 1994 + * Steve McClure, 1996, 1998 + * Doug Hay, 1998 + */ + +#if defined(aix) || defined(linux) +#include +#endif /* aix or linux */ + +#include +#include +#if !defined(_WIN32) +#include +#endif +#include +#include + +#if defined(_WIN32) +#include +#endif + +#include "misc.h" +#include "nat.h" +#include "file.h" +#include "player.h" +#include "empthread.h" +#include "plane.h" +#include "nuke.h" +#include "land.h" +#include "ship.h" +#include "sect.h" +#include "var.h" +#include "product.h" +#include "optlist.h" +#include "global.h" +#include "prototypes.h" + +s_char program[] = "server"; + +extern void player_accept(); +extern void player_kill_idle(); +extern void update_sched(); +extern void delete_lostitems(); +void nullify_objects(void); +void init_files(void); +void close_files(void); + +#if defined(_WIN32) +static void loc_NTInit(void); +static void loc_NTTerm(void); +#endif + +extern void mobility_init(); +extern void mobility_check(); +extern void market_update(); + +#if !defined(_WIN32) +static int mainpid = 0; +#endif + +int +main(argc, argv) +int argc; +char *argv[]; +{ + time_t now; + int hour[2]; + int flags = 0; + int debug = 0; + int op; + char *config_file = NULL; + extern s_char *datadir; + extern char *optarg; + s_char tbuf[256]; +#ifdef POSIXSIGNALS + struct sigaction act; +#endif /* POSIXSIGNALS */ + +#if !defined(_WIN32) + mainpid = getpid(); + + while ((op = getopt(argc, argv, "D:de:psh")) != EOF) { + switch (op) { + case 'D': + datadir = optarg; + break; + case 'd': + debug++; + break; + case 'e': + config_file = optarg; + break; + case 'p': + flags |= EMPTH_PRINT; + break; + case 's': + flags |= EMPTH_PRINT|EMPTH_STACKCHECK; + break; + case 'h': + default: + printf("Usage: %s -d -p -s\n",argv[0]); + return 0; + } + } +#endif + if (config_file == NULL) { + sprintf (tbuf, "%s/econfig", datadir); + config_file = tbuf; + } + + logerror("------------------------------------------------------"); +#if !defined(_WIN32) + logerror("Empire server (pid %d) started", getpid()); +#else + logerror("Empire server started"); +#endif /* _WIN32 */ + +#if defined(_WIN32) + loc_NTInit(); +#endif + emp_config (config_file); + update_policy_check(); + + nullify_objects(); + +#if !defined(_WIN32) + /* signal() should not be used with mit pthreads. Anyway if u + have a posix threads u definitly have posix signals -- Sasha */ +#if defined (POSIXSIGNALS) || defined (_EMPTH_POSIX) +#ifdef SA_SIGINFO + act.sa_flags = SA_SIGINFO; +#endif + sigemptyset (&act.sa_mask); + if (debug == 0 && flags == 0) { + disassoc(); + } + act.sa_handler = shutdwn; + /* pthreads on Linux use SIGUSR1 (*shrug*) so only catch it if not on + a Linux box running POSIX threads -- STM */ +#if !(defined(__linux__) && defined(_EMPTH_POSIX)) + sigaction (SIGUSR1, &act, NULL); +#endif + sigaction (SIGTERM, &act, NULL); + sigaction (SIGINT, &act, NULL); + act.sa_handler = panic; + sigaction (SIGBUS, &act, NULL); + sigaction (SIGSEGV, &act, NULL); + sigaction (SIGILL, &act, NULL); + sigaction (SIGFPE, &act, NULL); + act.sa_handler = SIG_IGN; + sigaction(SIGPIPE, &act, NULL); +#else + if (debug == 0 && flags == 0) { + disassoc(); + /* pthreads on Linux use SIGUSR1 (*shrug*) so only catch it if not on + a Linux box running POSIX threads -- STM */ +#if !(defined(__linux__) && defined(_EMPTH_POSIX)) + signal(SIGUSR1, shutdwn); +#endif + signal(SIGTERM, shutdwn); + signal(SIGBUS, panic); + signal(SIGSEGV, panic); + signal(SIGILL, panic); + signal(SIGFPE, panic); + signal(SIGINT, shutdwn); + } + signal(SIGPIPE, SIG_IGN); +#endif /* POSIXSIGNALS */ +#endif /* _WIN32 */ + empth_init((char **)&player, flags); + time(&now); +#if !defined(_WIN32) + srandom(now); +#else + srand(now); +#endif /* _WIN32 */ + setfdtablesize(32, 256); + global_init(); + shutdown_init(); + player_init(); + ef_init(); + init_files(); + io_init(); + gamehours(now, hour); + + if (opt_MOB_ACCESS) { + /* This fixes up mobility upon restart */ + mobility_init(); + } + + empth_create(PP_ACCEPT, player_accept, (50*1024), flags, "AcceptPlayers", + "Accept network connections", 0); + empth_create(PP_KILLIDLE, player_kill_idle, (50*1024), flags, "KillIdle", + "Kills idle player connections", 0); + empth_create(PP_SCHED, update_sched, (50*1024), flags, "UpdateSched", + "Schedules updates to occur", 0); + empth_create(PP_TIMESTAMP, delete_lostitems, (50*1024), flags, "DeleteItems", + "Deletes old lost items", 0); + if (opt_MOB_ACCESS) { + /* Start the mobility access check thread */ + empth_create(PP_TIMESTAMP, mobility_check, (50*1024), flags, "MobilityCheck", + "Writes the timestamp file", 0); + } + + if (opt_MARKET) { + empth_create(PP_TIMESTAMP, market_update, (50*1024), flags, "MarketUpdate", + "Updates the market", 0); + } +#if defined(__linux__) && defined(_EMPTH_POSIX) + strcpy(tbuf, argv[0]); + for (op = 1; op < argc; op++) { + strcat(tbuf, " "); + strcat(tbuf, argv[op]); + } + sprintf(argv[0], "%s (main pid: %d)", tbuf, getpid()); +#endif + + empth_exit(); + +/* We should never get here. But, just in case... */ + close_files(); + +#if defined(_WIN32) + loc_NTTerm(); +#endif + return 0; +} + +void +init_files(void) +{ + ef_open(EF_NATION, O_RDWR, EFF_MEM); + ef_open(EF_SECTOR, O_RDWR, EFF_MEM); + ef_open(EF_SHIP, O_RDWR, EFF_MEM); + ef_open(EF_PLANE, O_RDWR, EFF_MEM); + ef_open(EF_LAND, O_RDWR, EFF_MEM); + ef_open(EF_NEWS, O_RDWR, 0); + ef_open(EF_LOAN, O_RDWR, 0); + ef_open(EF_TREATY, O_RDWR, 0); + ef_open(EF_NUKE, O_RDWR, EFF_MEM); + ef_open(EF_POWER, O_RDWR, 0); + ef_open(EF_TRADE, O_RDWR, 0); + ef_open(EF_MAP, O_RDWR, EFF_MEM); + ef_open(EF_BMAP, O_RDWR, EFF_MEM); + ef_open(EF_COMM, O_RDWR, 0); + ef_open(EF_LOST, O_RDWR, 0); +} + +void +close_files(void) +{ + ef_close(EF_NATION); + ef_close(EF_SECTOR); + ef_close(EF_SHIP); + ef_close(EF_PLANE); + ef_close(EF_LAND); + ef_close(EF_NEWS); + ef_close(EF_LOAN); + ef_close(EF_TREATY); + ef_close(EF_NUKE); + ef_close(EF_POWER); + ef_close(EF_TRADE); + ef_close(EF_MAP); + ef_close(EF_COMM); + ef_close(EF_BMAP); + ef_close(EF_LOST); +} + +/* we're going down. try to close the files at least */ +emp_sig_t +panic(int sig) +{ +#if !defined(_WIN32) +#ifdef POSIXSIGNALS + struct sigaction act; + + act.sa_flags = 0; + sigemptyset (&act.sa_mask); + act.sa_handler = SIG_DFL; + sigaction (SIGBUS, &act, NULL); + sigaction (SIGSEGV, &act, NULL); + sigaction (SIGILL, &act, NULL); + sigaction (SIGFPE, &act, NULL); +#else + signal(SIGBUS, SIG_DFL); + signal(SIGSEGV, SIG_DFL); + signal(SIGILL, SIG_DFL); + signal(SIGFPE, SIG_DFL); +#endif /* POSIXSIGNALS */ +#endif /* _WIN32 */ + logerror("server received fatal signal %d", sig); + log_last_commands(); + close_files(); + _exit(0); +} + +emp_sig_t +shutdwn(int sig) +{ + struct player *p; + time_t now; + +#if defined(__linux__) && defined(_EMPTH_POSIX) +/* This is a hack to get around the way pthreads work on Linux. This + may be useful on other platforms too where threads are turned into + processes. */ + if (getpid() != mainpid) { + empth_t *me; + + me = empth_self(); + if (me && me->name) { + if (strlen(me->name) > 5) { + /* Player threads are cleaned up below, so just have + them return. This should work. */ + if (!strncmp("Player", me->name, 6)) { + return; + } + } + } + /* Not a player thread - must be server thread, so exit */ + empth_exit(); + return; + } +#endif + + logerror("Shutdown commencing (cleaning up threads.)"); + + for (p = player_next(0); p != 0; p = player_next(p)) { + if (p->state != PS_PLAYING) + continue; + pr_flash(p, "Server shutting down...\n"); + p->state = PS_SHUTDOWN; + p->aborted++; + if (p->command) { + pr_flash(p, "Shutdown aborting command\n"); + } + empth_wakeup(p->proc); + } + + if (!sig) { + /* Sleep and let some cleanup happen - note this doesn't work + when called from a signal handler, since we may or may not + be in the right thread. So we just pass by and kill 'em + all. */ + time(&now); + empth_sleep(now + 1); + } + + for (p = player_next(0); p != 0; p = player_next(p)) { + p->state = PS_KILL; + p->aborted++; + empth_terminate(p->proc); + p = player_delete(p); + } + if (sig) + logerror("Server shutting down on signal %d", sig); + else + logerror("Server shutting down at Deity's request"); + close_files(); + _exit(0); +} + + +void +nullify_objects(void) +{ + int i, j; + + if (opt_BIG_CITY) { + dchr[SCT_CAPIT].d_flg = bigcity_dchr.d_flg; + dchr[SCT_CAPIT].d_pkg = bigcity_dchr.d_pkg; + dchr[SCT_CAPIT].d_build = bigcity_dchr.d_build; + dchr[SCT_CAPIT].d_lcms = bigcity_dchr.d_lcms; + dchr[SCT_CAPIT].d_hcms = bigcity_dchr.d_hcms; + dchr[SCT_CAPIT].d_name = bigcity_dchr.d_name; + } + for (i = 0; i < pln_maxno; i++) { + if (opt_NO_HCMS) + plchr[i].pl_hcm = 0; + if (opt_NO_LCMS) + plchr[i].pl_lcm = 0; + if (opt_NO_OIL) + plchr[i].pl_fuel = 0; + if (opt_PLANENAMES) + plchr[i].pl_name = plchr[i].pl_planename; + } + for (i = 0; i < lnd_maxno; i++) { + if (opt_NO_HCMS) + lchr[i].l_hcm = 0; + if (opt_NO_LCMS) + lchr[i].l_lcm = 0; + /* Fix up the military values */ + for (j = 0; j < lchr[i].l_nv; j++) { + if (lchr[i].l_vtype[j] == V_MILIT) + lchr[i].l_mil = lchr[i].l_vamt[j]; + } + } + for (i = 0; i < shp_maxno; i++) { + if (opt_NO_HCMS) + mchr[i].m_hcm = 0; + if (opt_NO_LCMS) + mchr[i].m_lcm = 0; + if (opt_NO_OIL) { + if (mchr[i].m_flags & M_OIL) + mchr[i].m_name = 0; + } + } + for (i = 0; i < nuk_maxno; i++) { + if (opt_NO_HCMS) + nchr[i].n_hcm = 0; + if (opt_NO_LCMS) + nchr[i].n_lcm = 0; + } + for (i = 0; i < sct_maxno; i++) { + if (opt_NO_HCMS) + dchr[i].d_hcms = 0; + if (opt_NO_LCMS) + dchr[i].d_lcms = 0; + } + for (i = 0; i < prd_maxno; i++) { + for (j = 0; j < pchr[i].p_nv; j++) { + if (opt_NO_HCMS && pchr[i].p_vtype[j] == V_HCM) + pchr[i].p_vamt[j] = 0; + if (opt_NO_LCMS && pchr[i].p_vtype[j] == V_LCM) + pchr[i].p_vamt[j] = 0; + if (opt_NO_OIL && pchr[i].p_vtype[j] == V_OIL) + pchr[i].p_vamt[j] = 0; + } + } +} + +#if defined(_WIN32) +static void +loc_NTInit() +{ + int rc; + WORD wVersionRequested; + WSADATA wsaData; + + wVersionRequested = MAKEWORD(2, 0); + rc = WSAStartup(wVersionRequested, &wsaData); + if (rc != 0) { + logerror("WSAStartup failed. %d", rc); + _exit(1); + } +} +#endif + +#if defined(_WIN32) +static void +loc_NTTerm() +{ + WSACleanup(); +} +#endif + diff --git a/src/server/marketup.c b/src/server/marketup.c new file mode 100644 index 00000000..73d6791f --- /dev/null +++ b/src/server/marketup.c @@ -0,0 +1,87 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * marketup.c: Market updater thread + * + * Known contributors to this file: + * Steve McClure, 1996 + */ + +#include "options.h" +#include "misc.h" +#include "player.h" +#include "keyword.h" +#include "empthread.h" +#include "file.h" +#include +#include "prototypes.h" + +/*ARGSUSED*/ +void +check_all_markets(argv) +void *argv; +{ + player->proc = empth_self(); + player->cnum = 0; + player->god = 1; + + check_market(); + check_trade(); + + ef_flush(EF_NATION); + ef_flush(EF_SECTOR); + ef_flush(EF_PLANE); + ef_flush(EF_SHIP); + ef_flush(EF_LAND); + ef_flush(EF_COMM); + ef_flush(EF_TRADE); + + player_delete(player); + empth_exit(); + /*NOTREACHED*/ +} + +/*ARGSUSED*/ +void +market_update(argv) +void *argv; +{ + time_t now; + struct player *dp; + + while (1) { + time(&now); +/* logerror("Checking the world markets at %s", ctime(&now));*/ + dp = player_new(0, 0); + empth_create(PP_UPDATE, check_all_markets, (50*1024), 0, + "MarketCheck", "Checks the world markets", dp); + now = now + 300; /* Every 5 minutes */ + empth_sleep(now); + } + /*NOTREACHED*/ +} + diff --git a/src/server/shutdown.c b/src/server/shutdown.c new file mode 100644 index 00000000..78f2179c --- /dev/null +++ b/src/server/shutdown.c @@ -0,0 +1,96 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * shutdown.c: Shuts down server. Runs at low priority. + * + * Known contributors to this file: + * Ken Stevens, 1995 + */ + +#include "misc.h" +#include "player.h" +#include "empio.h" +#include "empthread.h" +#include "proto.h" +#include "nat.h" +#include "file.h" +#include +#include "prototypes.h" + +int shutdown_pending; + +void +shutdown_init(void) +{ + shutdown_pending = 0; +} + +void +shutdown_sequence(argc, argv) + int argc; + s_char **argv; +{ + struct natstr *god; + struct tm *tm; + time_t now; + s_char header[100]; + + if (shutdown_pending <= 0) { + shutdown_pending = 0; + logerror("shutdown called with 0 shutdown_pending"); + empth_exit(); + return; + } + god = getnatp(0); + while (shutdown_pending > 0) { + --shutdown_pending; + time(&now); + if (shutdown_pending <= 1440) { /* one day */ + tm = localtime(&now); + sprintf(header, "BROADCAST from %s @ %02d:%02d: ", + god->nat_cnam, tm->tm_hour, tm->tm_min); + if (!shutdown_pending) { + pr_wall("%sServer shutting down NOW!\n", header); + shutdwn(0); + } else if (shutdown_pending == 1) { + pr_wall("%sServer shutting down in 1 minute!\n", header); + } else if (shutdown_pending <= 5) { + pr_wall("%sServer shutting down in %d minutes!\n", header, shutdown_pending); + } else if (shutdown_pending <= 60 && + shutdown_pending%10 == 0) { + pr_wall("%sThe server will be shutting down in %d minutes!\n", header, shutdown_pending); + } else if (shutdown_pending%60 == 0) { + pr_wall("%sThe server will be shutting down %d hours from now.\n", header, (int)(shutdown_pending/60)); + } + } + empth_sleep(now + 60); + } + empth_exit(); +} + + + diff --git a/src/server/timestamp.c b/src/server/timestamp.c new file mode 100644 index 00000000..f6456033 --- /dev/null +++ b/src/server/timestamp.c @@ -0,0 +1,141 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * timestamp.c: Timestamp writer/maintainer thread + * + * Known contributors to this file: + * Steve McClure, 1996 + * Doug Hay, 1998 + */ + +#include "options.h" +#include "misc.h" +#include "player.h" +#include "keyword.h" +#include "empthread.h" +#include +#include "prototypes.h" + +/*ARGSUSED*/ +void +mobility_check(argv) +void *argv; + +{ + extern s_char *timestampfil; + extern int updating_mob; + struct mob_acc_globals timestamps; + time_t now; + FILE *fp; + int hour[2]; + + while (1) { + time(&now); +/* logerror("Updating timestamp file at %s", ctime(&now));*/ +#if !defined(_WIN32) + if ((fp = fopen(timestampfil, "r+")) == NULL) { +#else + if ((fp = fopen(timestampfil, "r+b")) == NULL) { +#endif + logerror("Unable to edit timestamp file."); + continue; + } + rewind(fp); + fread(×tamps, sizeof(timestamps), 1, fp); + timestamps.timestamp = now; + rewind(fp); + fwrite(×tamps, sizeof(timestamps), 1, fp); + fclose(fp); + if (!gamehours(now, hour)) { + if (updating_mob == 1) { + update_all_mob(); + logerror("Turning off mobility updating (gamehours)."); + updating_mob = 0; + } + } else if (updating_mob == 1 && now < timestamps.starttime) { + logerror("Turning off mobility updating at %s", ctime(&now)); + update_all_mob(); + updating_mob = 0; + } else if (updating_mob == 0 && now >= timestamps.starttime) { + logerror("Turning on mobility updating at %s", ctime(&now)); + update_all_mob(); + updating_mob = 1; + } + now = now + 180; /* Every 3 minutes */ + empth_sleep(now); + + } + /*NOTREACHED*/ +} + +void +mobility_init() +{ + extern s_char *timestampfil; + extern int updating_mob; + struct mob_acc_globals timestamps; + time_t now; + time_t lastsavedtime; + FILE *fp; + int hour[2]; + + /* During downtime, we don't want mobility to accrue. So, we look + at the timestamp file, and determine how far forward to push + mobility */ + + time(&now); +#if !defined(_WIN32) + if ((fp = fopen(timestampfil, "r+")) == NULL) { +#else + if ((fp = fopen(timestampfil, "r+b")) == NULL) { +#endif + logerror("Unable to edit timestamp file."); + } else { + rewind(fp); + fread(×tamps, sizeof(timestamps), 1, fp); + lastsavedtime = timestamps.timestamp; + timestamps.timestamp = now; + rewind(fp); + fwrite(×tamps, sizeof(timestamps), 1, fp); + fclose(fp); + } + time(&now); + logerror("Adjusting timestamps at %s",ctime(&now)); + logerror("(was %s)",ctime(&lastsavedtime)); + /* Update the timestamps to this point in time */ + update_timestamps(lastsavedtime); + time(&now); + logerror("Done at %s", ctime(&now)); + + if (now >= timestamps.starttime && gamehours(now, hour)) { + logerror("Turning on mobility updating."); + updating_mob = 1; + } else { + logerror("Turning off mobility updating."); + updating_mob = 0; + } +} diff --git a/src/server/update.c b/src/server/update.c new file mode 100644 index 00000000..22818fde --- /dev/null +++ b/src/server/update.c @@ -0,0 +1,152 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * update.c: Update scheduler + * + * Known contributors to this file: + * Dave Pare, 1994 + * Steve McClure, 1996 + */ + +#include "misc.h" +#include "player.h" +#include "keyword.h" +#include "empthread.h" +#include "prototypes.h" +#include "optlist.h" + +empth_sem_t *update_sem; + +extern void update_main(); +extern void update_wait(); +time_t update_time; + +/*ARGSUSED*/ +void +update_sched(argv) +void *argv; +{ + extern int s_p_etu; + extern int etu_per_update; + extern int adj_update; + extern int update_window; + s_char *kw; + int hour[2]; + int wind; + time_t now, delta; + + update_sem = empth_sem_create("Update", 0); + empth_create(PP_SCHED, update_wait, (50*1024), 0, "UpdateWait", + "Waits until players idle", 0); + time(&now); + (void) gamehours(now, hour); + if (NULL != (kw = kw_find("s_p_etu"))) + kw_parse(CF_VALUE, kw, &s_p_etu); + if (NULL != (kw = kw_find("etu_per_update"))) + kw_parse(CF_VALUE, kw, &etu_per_update); + if (NULL != (kw = kw_find("adj_update"))) + kw_parse(CF_VALUE, kw, &adj_update); + if (NULL != (kw = kw_find("update_window"))) + kw_parse(CF_VALUE, kw, &update_window); + if (s_p_etu <= 0) { + logerror("bad value for s_p_etu (%d)", s_p_etu); + s_p_etu = 2 * 60; + logerror("setting s_p_etu to %d", s_p_etu); + } + while (1) { + time(&now); + next_update_time(&now, &update_time, &delta); + if (update_window > 0) { + wind = (random() % update_window); + update_time += wind; + delta += wind; + } + logerror("Next update at %s", ctime(&update_time)); + logerror("Next update in %d seconds", delta); + /* sleep until update is scheduled to go off */ + empth_sleep(update_time); + time(&now); + now += adj_update; + if (!gamehours(now, hour)) { + logerror("No update permitted (hours restriction)"); + continue; + } + if (!updatetime(&now)) { + logerror("No update wanted"); + continue; + } + if (updates_disabled()) { + logerror("Updates disabled...skipping update"); + continue; + } + empth_sem_signal(update_sem); + } + /*NOTREACHED*/ +} + +/*ARGSUSED*/ +void +update_wait(argv) + void *argv; +{ + struct player *p; + int running; + time_t now; + int stacksize; + struct player *dp; + + while (1) { + empth_sem_wait(update_sem); + running = 0; + for (p = player_next(0); p != 0; p = player_next(p)) { + if (p->state != PS_PLAYING) + continue; + if (p->command) { + pr_flash(p, "Update aborting command\n"); + p->aborted = 1; + empth_wakeup(p->proc); + running++; + } + } + time(&now); + if (running) { + /* sleep a few, wait for aborts to take effect */ + empth_sleep(now + 2); + } + /* + * we rely on the fact that update's priority is the highest + * in the land so it can finish before it yields. + */ + dp = player_new(0, 0); + stacksize= 100000 + +/* finish_sects */ WORLD_X*WORLD_Y*(2*sizeof(double)+sizeof(s_char *)); + + empth_create(PP_UPDATE, update_main, stacksize, 0, + "UpdateRun", "Updates the world", dp); + } + /*NOTREACHED*/ +} diff --git a/src/util/Makefile b/src/util/Makefile new file mode 100644 index 00000000..e1ecccb9 --- /dev/null +++ b/src/util/Makefile @@ -0,0 +1,127 @@ +# +# Empire - A multi-player, client/server Internet based war game. +# Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, +# Ken Stevens, Steve McClure +# +# 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 2 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, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# --- +# +# See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the +# related information and legal notices. It is expected that any future +# projects/authors will amend these files as needed. +# +# Makefile - Wolfpack, 1996 + +# Note that these could have been listed 1 per line, but I chose to just +# stick them all together this way to shorten the file. + +include ../../build.conf +include ../make.src +include ../make.defs + +LIBDIR = $(SRCDIR)/lib + +LIBS = $(LIBDIR)/libsubs.a \ + $(LIBDIR)/libcommon.a \ + $(LIBDIR)/libgen.a \ + $(LIBDIR)/libglobal.a + +NTLIBS = $(LIBDIR)\libsubs.lib \ + $(LIBDIR)\libcommon.lib \ + $(LIBDIR)\libgen.lib \ + $(LIBDIR)\libglobal.lib + +OBJS = fairland.o files.o land.o ore.o pconfig.o perfect.o + +NTOBJS = fairland.obj files.obj land.obj ore.obj pconfig.obj perfect.obj + +nt: ntfairland ntfiles ntpconfig + +all: fairland files pconfig + +osx: fairland files pconfig + +# all: $(OBJS) fairland files land ore pconfig perfect + +ntfiles: files.obj + link /OUT:files.exe \ + /NOD /DEBUG:full /DEBUGTYPE:cv /MACHINE:IX86 /NOLOGO \ + files.obj $(NTLIBS) \ + kernel32.lib \ + wsock32.lib \ + libcmt.lib \ + oldnames.lib + +files: files.o + $(CC) -o files $(IFLAGS) $(CFLAGS) files.o $(LIBS) $(LFLAGS) -lc + +land: land.o + $(CC) -o land $(IFLAGS) $(CFLAGS) land.o $(LIBS) $(LFLAGS) -lc + +ore: ore.o + $(CC) -o ore $(IFLAGS) $(CFLAGS) ore.o $(LIBS) $(LFLAGS) -lc + +fairland: fairland.o + $(CC) -o fairland $(IFLAGS) $(CFLAGS) fairland.o $(LIBS) $(LFLAGS) -lc + +ntfairland: fairland.obj + link /OUT:fairland.exe \ + /NOD /DEBUG:full /DEBUGTYPE:cv /MACHINE:IX86 /NOLOGO \ + fairland.obj $(NTLIBS) \ + kernel32.lib \ + wsock32.lib \ + libcmt.lib \ + oldnames.lib + +perfect: perfect.o + $(CC) -o perfect $(IFLAGS) $(CFLAGS) perfect.o $(LIBS) $(LFLAGS) -lc + +pconfig: pconfig.o + $(CC) -o pconfig $(IFLAGS) $(CFLAGS) pconfig.o $(LIBS) $(LFLAGS) -lc + +ntpconfig: pconfig.o + link /OUT:pconfig.exe \ + /NOD /DEBUG:full /DEBUGTYPE:cv /MACHINE:IX86 /NOLOGO \ + pconfig.obj $(NTLIBS) \ + kernel32.lib \ + wsock32.lib \ + libcmt.lib \ + oldnames.lib + +clean: + -(rm -f files land ore fairland perfect pconfig $(OBJS)) + -(del /q *.exe *.pdb *.ilk $(NTOBJS)) + +install: + -(mkdir $(EMPDIR)/bin) + -(cp files $(EMPDIR)/bin) +# -(cp land $(EMPDIR)/bin) +# -(cp ore $(EMPDIR)/bin) + -(cp fairland $(EMPDIR)/bin) +# -(cp perfect $(EMPDIR)/bin) + -(cp pconfig $(EMPDIR)/bin) + +ntinstall: + -(mkdir $(NTINSTDIR)\bin) + -(copy files.exe $(NTINSTDIR)\bin) +# -(copy land.exe $(NTINSTDIR)\bin) +# -(copy ore.exe $(NTINSTDIR)\bin) + -(copy fairland.exe $(NTINSTDIR)\bin) +# -(copy perfect.exe $(NTINSTDIR)\bin) + -(copy pconfig.exe $(NTINSTDIR)\bin) + +include ../make.rules +include Makedepend diff --git a/src/util/README b/src/util/README new file mode 100644 index 00000000..70af3270 --- /dev/null +++ b/src/util/README @@ -0,0 +1,4 @@ +As of today (October 20, 1998) land, ore and perfect don't work. They +need to be fixed to deal with run-time configurable world sizes, and +have been commented out in the Makefile. + diff --git a/src/util/fairland.c b/src/util/fairland.c new file mode 100644 index 00000000..d9630d2b --- /dev/null +++ b/src/util/fairland.c @@ -0,0 +1,1252 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * fairland.c: Create a nice, new world + * + * Known contributors to this file: + * Ken Stevens, 1995 + * Steve McClure, 1998 + */ + +/* define ORE 1 to add resources, define ORE 0 if you want to use another + program to add the resources */ +static int ORE = 1; +static int quiet = 0; + +/* If you don't specify these command line arguments, then these are the + defaults */ +#define DEFAULT_SPIKE 10 +#define DEFAULT_MOUNTAIN 0 +#define DEFAULT_CONTDIST 2 +#define DEFAULT_ISLDIST 1 + +/* The following five numbers refer to elevation under which (in the case of + fertility or oil) or over which (in the case of iron, gold, and uranium) + sectors with that elevation will contain that resource. Elevation ranges + from 0 to 100 */ + +/* raise FERT_MAX for more fertility */ +#define FERT_MAX 56 + +/* raise OIL_MAX for more oil */ +#define OIL_MAX 33 + +/* lower IRON_MIN for more iron */ +#define IRON_MIN 22 + +/* lower GOLD_MIN for more gold */ +#define GOLD_MIN 36 + +/* lower URAN_MIN for more uranium */ +#define URAN_MIN 56 + +#if defined(aix) || defined(linux) || defined(solaris) +#include +#endif /* aix or linux */ + +#include +#include +#include "var.h" +#include "misc.h" +#include "power.h" +#include "nat.h" +#include "sect.h" +#include "gamesdef.h" +#include "file.h" +#include "xy.h" +#include "optlist.h" +#include "prototypes.h" + +/* do not change these 4 defines */ +#define LANDMIN 1 /* plate altitude for normal land */ +#define HILLMIN 34 /* plate altitude for hills */ +#define PLATMIN 36 /* plate altitude for plateau */ +#define HIGHMIN 98 /* plate altitude for mountains */ + +static void qprint _PROTO((const char *str)); + +static const char *outfile = "newcap_script"; +/* mark the continents with a * so you can tell them + from the islands 1 = mark, 0 = don't mark. */ +static int AIRPORT_MARKER = 0; + +/* don't let the islands crash into each other. + 1 = don't merge, 0 = merge. */ +static int DISTINCT_ISLANDS = 1; + +#define XSIZE ((WORLD_X) / 2) /* basically world x-y size */ +#define YSIZE (WORLD_Y) +#define STABLE_CYCLE 4 /* stability required for perterbed capitals */ +#define INFINITY 999 /* a number which means "BIG" */ + +/* these defines prevent infinite loops: +*/ + +#define COAST_SEARCH_MAX 200 /* how many times do we look for a coast sector + when growing continents and islands */ +#define DRIFT_BEFORE_CHECK ((WORLD_X + WORLD_Y)/2) +#define DRIFT_MAX ((WORLD_X + WORLD_Y)*2) +#define MOUNTAIN_SEARCH_MAX 1000 /* how long do we try to place mountains */ + +/* handy macros: +*/ + +#define new_x(newx) (((newx) + WORLD_X) % WORLD_X) +#define new_y(newy) (((newy) + WORLD_Y) % WORLD_Y) +#if !defined(_WIN32) +#define max(a,b) (a>b?a:b) +#endif +#define rnd(x) (random() % (x)) + +int secs; /* number of sectors grown */ +int ctot; /* total number of continents and islands grown */ +int *isecs; /* array of how large each island is */ + +int nc, sc, di, sp, pm, ni, is, id; /* the 8 arguments to this program */ +int *capx, *capy; /* location of the nc capitals */ +int *mc, mcc; /* array and counter used for stability + check when perturbing */ +int spike; /* are we spiking? */ +int mind; /* the final distance between capitals that + we achieved */ +int dirx[] = {-2, -1, 1, 2, 1, -1}; /* gyujnb */ +int diry[] = {0, -1, -1, 0, 1, 1}; + +int **own; /* owner of the sector. -1 means water */ +int **elev; /* elevation of the sectors */ +int **sectx, **secty; /* the sectors for each continent */ +int **sectc; /* which sectors are on the coast? */ +int *vector; /* used for measuring distances */ +int *weight; /* used for placing mountains */ +int *dsea, *dmoun; /* the dist to the ocean and mountain */ +int the_file; /* the file we write everything to */ +struct sctstr **sects; +struct sctstr *sectsbuf; +int fl_status; /* is anything wrong? */ +#define STATUS_NO_ROOM (1) /* there was no room to grow */ +#define NUMTRIES 10 /* keep trying to grow this many times */ + +const char *numletter = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; + +void parse_args(int argc, char *argv[]); +int allocate_memory(void); +void init(void); +int drift(void); +void grow_continents(void); +void create_elevations(void); +void write_sects(void); +int write_file(void); +void output(void); +int write_newcap_script(void); +int stable(void); +void elevate_land(void); +void elevate_sea(void); +void translate_continents(void); +int map_symbol(int x, int y); +static void fl_sct_init(coord x, coord y, s_char *ptr); + +void print_vars(); +void fl_move(int); +void next_coast(); +void grow_islands(); + +/**************************************************************************** + MAIN +****************************************************************************/ + +int +main(int argc, char *argv[]) +{ + int opt; + extern int optind; + extern char *optarg; + extern s_char *datadir; + char *config_file = NULL; + char tbuf[512]; + int i = 0; + +#if !defined(_WIN32) + while ((opt = getopt(argc, argv, "ae:ioqs:")) != EOF) { + switch (opt) { + case 'a': + AIRPORT_MARKER = 1; + break; + case 'i': + DISTINCT_ISLANDS = 0; + break; + case 'e': + config_file = optarg; + break; + case 'o': + ORE = 0; + break; + case 'q': + quiet = 1; + break; + case 's': + outfile = optarg; + break; + } + } +#endif + if (config_file == NULL) { + sprintf (tbuf, "%s/econfig", datadir); + config_file = tbuf; + } + emp_config (config_file); + +#if !defined(_WIN32) + parse_args(argc - optind, argv + optind); +#else + parse_args(argc - 1, argv + 1); +#endif + if (allocate_memory() == -1) + exit(-1); + print_vars(); + + do { + init(); + if (!quiet && i) + printf("\ntry #%d (out of %d)...", i + 1, NUMTRIES); + qprint ("\n\n #*# ...fairland rips open a rift in the datumplane... #*#\n\n"); + qprint ("placing capitals...\n"); + if (!drift()) + qprint ("fairland: unstable drift -- try increasisg DRIFT_MAX\n"); + qprint ("growing continents...\n"); + grow_continents(); + } while (fl_status && ++i < NUMTRIES); + if (fl_status) { + fputs("ERROR: World not large enough to hold continents\n", stderr); + exit(1); + } + qprint ("growing islands:"); + grow_islands(); + qprint ("\nelevating land...\n"); + create_elevations(); + qprint ("designating sectors...\n"); + if (ORE) + qprint ("adding resources...\n"); + write_sects(); + qprint ("writing to sectors file...\n"); + if (write_file() == -1) + exit (-1); + output(); + write_newcap_script(); + exit(0); +} + +void +print_vars() +{ + if (quiet) + return; + puts("Creating a planet with:\n"); + printf("%d continents\n", nc); + printf("continent size: %d\n", sc); + printf("number of islands: %d\n", ni); + printf("average size of islands: %d\n", is); + printf("spike: %d%%\n", sp); + printf("%d%% of land is mountain (each continent will have %d mountains)\n", + pm, (pm*sc)/100); + printf("minimum distance between continents: %d\n", di); + printf("minimum distance from islands to continents: %d\n", id); + printf("World dimensions: %dx%d\n", WORLD_X, WORLD_Y); +} + +int +my_sqrt(n) +int n; +{ + int i; + + for (i = 1; i*i < n*10000; ++i); + return (i+50)/100; +} + +/**************************************************************************** + PARSE COMMAND LINE ARGUMENTS +****************************************************************************/ + +void +parse_args(int argc, char *argv[]) +{ + if (argc < 2 || argc > 8) { + puts("fairland syntax:\n"); + puts("fairland [-e config] [-aiqo] [-s script] [] [] [] [] [] []"); + puts ("-q = quiet, -o = no ore produced"); + puts ("-a = Airport marker for continents, -i = islands not distinct"); + printf ("-e = read config file, -s = name of script (default %s)\n", + outfile); + puts("nc = number of continents [MANDATORY]"); + puts("sc = continent size [MANDATORY]"); + puts("ni = number of islands (default = nc)"); + puts("is = average size of islands (default = sc/2)"); + printf("sp = spike percentage: 0 = round, 100 = snake (default = %d)\n", DEFAULT_SPIKE); + printf("pm = the percentage of land that is mountain (default = %d)\n", DEFAULT_MOUNTAIN); + printf("di = the minimum distance between continents (default = %d)\n", DEFAULT_CONTDIST); + printf("id = minimum distance from islands to continents (default = %d)\n", DEFAULT_ISLDIST); + exit (1); + } + nc = atoi(argv[0]); + if (nc < 1) { + puts("fairland: error -- number of continents must be > 0"); + exit (1); + } + + sc = atoi(argv[1]); + if (sc < 1) { + puts("fairland: error -- size of continents must be > 0"); + exit (1); + } + + if (argc > 2) + ni = atoi(argv[2]); + else + ni = nc; + + if (argc > 3) + is = atoi(argv[3]); + else + is = sc/2; + if (is < 0) + is = 0; + + if (argc > 4) + sp = atoi(argv[4]); + else + sp = DEFAULT_SPIKE; + if (sp < 0) + sp = 0; + if (sp > 100) + sp = 100; + + if (argc > 5) + pm = atoi(argv[5]); + else + pm = DEFAULT_MOUNTAIN; + if (pm < 0) + pm = 0; + + if (argc > 6) + di = atoi(argv[6]); + else + di = DEFAULT_CONTDIST; + + if (di < 0) { + puts("fairland: error -- distance between continents must be >= 0"); + exit (1); + } + if (di > WORLD_X/2 || di > WORLD_Y/2) { + puts("fairland: error -- distance between continents too large"); + exit (1); + } + + if (argc > 7) + id = atoi(argv[7]); + else + id = DEFAULT_ISLDIST; + if (id < 0) { + puts("fairland: error -- distance from islands to continents must be >= 0"); + exit (1); + } + if (id > WORLD_X || id > WORLD_Y) { + puts("fairland: error -- distance from islands to continents too large"); + exit (1); + } + if (nc*sc + nc*my_sqrt(sc)*2*(di+1) > WORLD_X * WORLD_Y) { + puts("fairland: error -- world not big enough to fit continents."); + puts("arguments must satisfy:"); + puts("nc*sc*sc + nc*sqrt(sc)*2*(di+1) < WORLD_X * WORLD_Y"); + exit (1); + } +} + +/**************************************************************************** + VARIABLE INITIALIZATION +****************************************************************************/ + +int +allocate_memory(void) +{ + int i; + time_t now; + +#if !defined(_WIN32) + the_file = open(empfile[EF_SECTOR].file, O_RDWR|O_CREAT|O_TRUNC, 0660); +#else + the_file = open(empfile[EF_SECTOR].file, O_RDWR|O_CREAT|O_TRUNC|O_BINARY, 0660); +#endif + if (the_file < 0) { + perror(empfile[EF_SECTOR].file); + return -1; + } + sectsbuf = (struct sctstr *)calloc((YSIZE * XSIZE), sizeof(struct sctstr)); + sects = (struct sctstr **)calloc(YSIZE, sizeof(struct sctstr *)); + for (i = 0; i < YSIZE; i++) + sects[i] = §sbuf[XSIZE * i]; + time(&now); +#if !defined(_WIN32) + srandom(now+getpid()); +#else + srandom(now); +#endif + capx = (int *)calloc(nc, sizeof(int)); + capy = (int *)calloc(nc, sizeof(int)); + vector = (int *)calloc(WORLD_X+WORLD_Y, sizeof(int)); + mc = (int *)calloc(STABLE_CYCLE, sizeof(int)); + own = (int **)calloc(WORLD_X, sizeof(int*)); + elev = (int **)calloc(WORLD_X, sizeof(int*)); + for (i = 0; i < WORLD_X; ++i) { + own[i] = (int *)calloc(WORLD_Y, sizeof(int)); + elev[i] = (int *)calloc(WORLD_Y, sizeof(int)); + } + sectx = (int **)calloc(nc+ni, sizeof(int*)); + secty = (int **)calloc(nc+ni, sizeof(int*)); + sectc = (int **)calloc(nc+ni, sizeof(int*)); + isecs = (int *)calloc(nc+ni, sizeof(int)); + weight = (int *)calloc(max(sc,is*2), sizeof(int)); + dsea = (int *)calloc(max(sc,is*2), sizeof(int)); + dmoun = (int *)calloc(max(sc,is*2), sizeof(int)); + for (i = 0; i < nc; ++i) { + sectx[i] = (int *)calloc(sc, sizeof(int)); + secty[i] = (int *)calloc(sc, sizeof(int)); + sectc[i] = (int *)calloc(sc, sizeof(int)); + } + for (i = nc; i < nc+ni; ++i) { + sectx[i] = (int *)calloc(is*2, sizeof(int)); + secty[i] = (int *)calloc(is*2, sizeof(int)); + sectc[i] = (int *)calloc(is*2, sizeof(int)); + } + + return 0; +} + +void +init(void) +{ + int i, j, xx = 0, yy = 0; + + mcc = 0; + fl_status = 0; + + for (i = 0; i < WORLD_X; ++i) { + for (j = 0; j < WORLD_Y; ++j) { + own[i][j] = -1; + elev[i][j] = -INFINITY; + } + } + + for (i = 0; i < nc; ++i, xx += 2) { + if (xx >= WORLD_X) { + ++yy; + xx = yy%2; + if (yy == WORLD_Y) { + puts("fairland error: world not big enough for all the continents.\n"); + exit(1); + } + } + capx[i] = xx; + capy[i] = yy; + } + for (i = 0; i < STABLE_CYCLE; ++i) + mc[i] = i; +} + +/**************************************************************************** + DRIFT THE CAPITALS UNTIL THEY ARE AS FAR AWAY FROM EACH OTHER AS POSSIBLE +****************************************************************************/ + +/* How isolated is capital j? +*/ +int +iso(j, newx, newy) +int j, newx, newy; +{ + int i, md, d = WORLD_X + WORLD_Y; + + for (i = 0; i < nc; ++i) { + if (i == j) + continue; + md = mapdist(capx[i], capy[i], newx, newy); + if (md < d) + d = md; + } + + return d; +} + +/* Drift all the capitals +*/ +int +drift(void) +{ + int i, turns; + + for (turns = 0; turns < DRIFT_MAX; ++turns) { + if (turns > DRIFT_BEFORE_CHECK && (mind = stable())) + return 1; + for (i = 0; i < nc; ++i) + fl_move(i); + } + return 0; +} + +/* Check to see if we have stabilized--can we stop drifting the capitals? +*/ + +int +stable(void) +{ + int i, isod, d = 0, stab = 1; + + for (i = 0; i < nc; ++i) { + isod = iso(i, capx[i], capy[i]); + if (isod > d) + d = isod; + } + for (i = 0; i < STABLE_CYCLE; ++i) + if (d != mc[i]) + stab = 0; + mc[mcc] = d; + mcc = (mcc + 1) % STABLE_CYCLE; + return stab?d:0; +} + +/* This routine does the actual drifting +*/ + +void +fl_move(j) +int j; +{ + int i, n, newx, newy; + + for (i = rnd(6), n = 0; n < 6; i = (i + 1)%6, ++n) { + newx = new_x(capx[j] + dirx[i]); + newy = new_y(capy[j] + diry[i]); + if (iso(j, newx, newy) >= iso(j, capx[j], capy[j])) { + capx[j] = newx; + capy[j] = newy; + return; + } + } +} + +/**************************************************************************** + GROW THE CONTINENTS +****************************************************************************/ + +/* Look for a coastal sector of continent c +*/ + +void +find_coast(c) +int c; +{ + int i, j; + + for (i = 0; i < secs; ++i) { + sectc[c][i] = 0; + for (j = 0; j < 6; ++j) + if (own[new_x(sectx[c][i] + dirx[j])][new_y(secty[c][i] + diry[j])] == -1) + sectc[c][i] = 1; + } +} + +/* Used for measuring distances +*/ +int +next_vector(n) +int n; +{ + int i; + + if (n == 1) { + vector[0] += 1; + vector[0] %= 6; + return vector[0]; + } + for (i = 1; i < n && vector[i] == vector[i-1]; ++i); + vector[i-1] += 1; + vector[i-1] %= 6; + return i > 1 || vector[0] > 0; +} + +/* Test to see if we're allowed to grow there: the arguments di and id +*/ +int +try_to_grow(c, newx, newy, d) +int c, newx, newy, d; +{ + int i, j, px, py; + + for (i = 1; i <= d; ++i) { + for (j = 0; j < i; ++j) + vector[j] = 0; + do { + px = newx; + py = newy; + for (j = 0; j < i; ++j) { + px = new_x(px + dirx[vector[j]]); + py = new_y(py + diry[vector[j]]); + } + if (own[px][py] != -1 && + own[px][py] != c && + (DISTINCT_ISLANDS || own[px][py] < nc)) + return 0; + } while (next_vector(i)); + } + sectx[c][secs] = newx; + secty[c][secs] = newy; + own[newx][newy] = c; + return 1; +} + +/* Move along the coast in a clockwise direction. +*/ + +void +next_coast(c, x, y, xp, yp) +int c, x, y, *xp, *yp; +{ + int i, nx, ny, wat = 0; + + if (secs == 1) { + *xp = x; + *yp = y; + return; + } + + for (i = 0; i < 12; ++i) { + nx = new_x(x+dirx[i%6]); + ny = new_y(y+diry[i%6]); + if (own[nx][ny] == -1) + wat = 1; + if (wat && own[nx][ny] == c) { + *xp = nx; + *yp = ny; + return; + } + } +} + +/* Choose a sector to grow from +*/ + +int +new_try(int c) +{ + int i, starti; + + if (secs == 1) { + if (sectc[c][0]) + return 0; + } + else { + i = starti = (spike && sectc[c][secs-1])?secs-1:rnd(secs); + do { + if (sectc[c][i]) + return i; + i = (i + 1)%secs; + } while (i != starti); + if (c < nc) { + printf("fairland: BUG -- couldn't find coast for continent %c, sector %d.\nPlease mail stevens@math.utoronto.ca.\n", c + 'a', secs); + exit (1); + } + else + return -1; + } + return -1; +} + +/* Grow continent c by 1 sector +*/ + +int +grow_one_sector(c) +int c; +{ + int done, coast_search, try1, x, y, newx, newy, i, n, sx, sy; + + spike = rnd(100) < sp; + if ((try1 = new_try(c)) == -1) + return 0; + x = sx = sectx[c][try1]; + y = sy = secty[c][try1]; + coast_search = 0; + done = 0; + do { + if (spike) { + for (i = rnd(6), n = 0; n < 12 && !done; i = (i + 1)%6, ++n) { + newx = new_x(x+dirx[i]); + newy = new_y(y+diry[i]); + if (own[newx][newy] == -1 && + (n > 5 || + (own[new_x(x+dirx[(i+5)%6])][new_y(y+diry[(i+5)%6])] == -1 && + own[new_x(x+dirx[(i+1)%6])][new_y(y+diry[(i+1)%6])] == -1))) + if (try_to_grow(c, newx, newy, c WORLD_X - 2) + ssx = new_x(ssx + 2); + for (d = di + id; d >= id; --d) { + sx = ssx; + sy = ssy; + *xp = new_x(sx + 2); + for (*yp = sy; *xp != sx || *yp != sy; *xp += 2) { + if (*xp >= WORLD_X) { + *yp = new_y(*yp + 1); + *xp = (*yp)%2; + if (*xp == sx && *yp == sy) + break; + } + if (own[*xp][*yp] == -1 && try_to_grow(c, *xp, *yp, d)) + return 1; + } + } + return 0; +} + +/* Grow all the islands +*/ + +void +grow_islands() +{ + int c, x, y, isiz; + + for (c = nc; c < nc+ni; ++c) { + secs = 0; + if (!place_island(c, &x, &y)) + return; + isiz = 1 + rnd(2*is - 1); + do { + ++secs; + find_coast(c); + } while (secs < isiz && grow_one_sector(c)); + if (quiet == 0) printf(" %d(%d)", c - nc + 1, secs); + isecs[c] = secs; + ctot = c; + } +} + +/**************************************************************************** + CREATE ELEVATIONS +****************************************************************************/ +void +create_elevations(void) +{ + elevate_land(); + elevate_sea(); +} + +/* Generic function for finding the distance to the closest sea, land, or + mountain +*/ +int +distance_to_what(x,y,flag) +int x, y, flag; +{ + int j, d, px, py; + + for (d = 1; d < 5; ++d) { + for (j = 0; j < d; ++j) + vector[j] = 0; + do { + px = x; + py = y; + for (j = 0; j < d; ++j) { + px = new_x(px + dirx[vector[j]]); + py = new_y(py + diry[vector[j]]); + } + switch(flag) { + case 0: /* distance to sea */ + if (own[px][py] == -1) + return d; + break; + case 1: /* distance to land */ + if (own[px][py] != -1) + return d; + break; + case 2: /* distance to mountain */ + if (elev[px][py] == INFINITY) + return d; + break; + } + } while (next_vector(d)); + } + return d; +} + +#define ELEV elev[sectx[c][i]][secty[c][i]] +#define distance_to_sea() (sectc[c][i]?1:distance_to_what(sectx[c][i], secty[c][i], 0)) +#define distance_to_mountain() distance_to_what(sectx[c][i], secty[c][i], 2) + +/* Decide where the mountains go +*/ +void +elevate_land(void) +{ + int i, mountain_search, k, c, total, ns, nm, highest, where, h, newk, r, dk; + + for (c = 0; c < ctot; ++c) { + total = 0; + ns = (c < nc)?sc:isecs[c]; + nm = (pm*ns)/100; + +/* Place the mountains */ + + for (i = 0; i < ns; ++i) { + dsea[i] = distance_to_sea(); + weight[i] = (total += (dsea[i]*dsea[i])); + } + + for (k = nm, mountain_search = 0; + k && mountain_search < MOUNTAIN_SEARCH_MAX; + ++mountain_search) { + r = rnd(total); + for (i = 0; i < ns; ++i) + if (r < weight[i] && ELEV == -INFINITY && (c >= nc || + ((!(capx[c] == sectx[c][i] && capy[c] == secty[c][i])) && + (!(new_x(capx[c] + 2) == sectx[c][i] && capy[c] == secty[c][i]))))) { + ELEV = INFINITY; + break; + } + --k; + } + +/* Elevate land that is not mountain and not capital */ + + for (i = 0; i < ns; ++i) + dmoun[i] = distance_to_mountain(); + dk=(ns-nm-((c0)?(100*(HIGHMIN-LANDMIN))/(ns-nm-((c= nc || + ((!(capx[c] == sectx[c][i] && capy[c] == secty[c][i])) && + (!(new_x(capx[c] + 2) == sectx[c][i] && capy[c] == secty[c][i]))))) + { + h = 3*(5 - dmoun[i]) + dsea[i]; + if (h > highest) { + highest = h; + where = i; + } + } + } + if (where == -1) + break; + newk = k/100; + if (newk >= HILLMIN && newk < PLATMIN) + newk = PLATMIN; + if (newk < LANDMIN) + newk = LANDMIN; + elev[sectx[c][where]][secty[c][where]] = newk; + dsea[where] = -INFINITY; + dmoun[where] = INFINITY; + } + +/* Elevate the mountains and capitals */ + + for (i = 0; i < ns; ++i) { + if (ELEV == INFINITY) { + if (dsea[i] == 1) + ELEV = HILLMIN + rnd(PLATMIN - HILLMIN); + else + ELEV = HIGHMIN + rnd((256-HIGHMIN)/2) + rnd((256-HIGHMIN)/2); + } + else if ((c < nc && + ((capx[c] == sectx[c][i] && capy[c] == secty[c][i]))) || + ((new_x(capx[c] + 2) == sectx[c][i] && capy[c] == secty[c][i]))) + ELEV = PLATMIN; + } + } +} + +#define distance_to_land() distance_to_what(x, y, 1) + +void +elevate_sea(void) +{ + int x, y; + + for (y = 0; y < WORLD_Y; ++y) { + for (x = y%2; x < WORLD_X; x +=2) { + if (elev[x][y] == -INFINITY) + elev[x][y] = - rnd((distance_to_land()*20 + 27)) - 1; + } + } +} + +/**************************************************************************** + ADD THE RESOURCES +****************************************************************************/ + +int +set_fert(e) +int e; +{ + int fert = 0; + if (e < LANDMIN) + fert = LANDMIN - e + 40; + else if (e < FERT_MAX) + fert = (140*(FERT_MAX - e))/(FERT_MAX - LANDMIN); + if (fert > 120) + fert = 120; + return fert; +} + +int +set_oil(e) +int e; +{ + int oil = 0; + if (e < LANDMIN) + oil = (LANDMIN - e)*2 + rnd(2); + else if (e <= OIL_MAX) + oil = (120*(OIL_MAX - e + 1))/(OIL_MAX - LANDMIN + 1); + if (oil > 100) + oil = 100; + return oil; +} + +int +set_iron(e) +int e; +{ + int iron = 0; + if (e >= IRON_MIN && e < HIGHMIN) + iron = (120*(e - IRON_MIN + 1))/(HIGHMIN - IRON_MIN); + if (iron > 100) + iron = 100; + return iron; +} + +int +set_gold(e) +int e; +{ + int gold = 0; + if (e >= GOLD_MIN) { + if (e < HIGHMIN) + gold = (80*(e - GOLD_MIN + 1))/(HIGHMIN - GOLD_MIN); + else + gold = 100 - 20 * HIGHMIN / e; + } + if (gold > 100) + gold = 100; + return gold; +} + +int +set_uran(e) +int e; +{ + int uran = 0; + if (e >= URAN_MIN && e < HIGHMIN) + uran = (120*(e - URAN_MIN + 1))/(HIGHMIN - URAN_MIN); + if (uran > 100) + uran = 100; + return uran; +} + +void +add_resources(sct) +struct sctstr *sct; +{ + sct->sct_fertil = set_fert(sct->sct_elev); + sct->sct_oil = set_oil(sct->sct_elev); + sct->sct_min = set_iron(sct->sct_elev); + sct->sct_gmin = set_gold(sct->sct_elev); + sct->sct_uran = set_uran(sct->sct_elev); +} + +/**************************************************************************** + DESIGNATE THE SECTORS +****************************************************************************/ + +void +write_sects(void) +{ + register struct sctstr *sct; + int c, x, y, total; + + /* sct = §s[0][0];*/ + sct = sectsbuf; + for (y = 0; y < YSIZE; y++) { + for (x = 0; x < XSIZE; x++, sct++) { + fl_sct_init(x*2 + (y & 01), y, (s_char *) sct); + total = elev[sct->sct_x][y]; + if (total < LANDMIN) { + sct->sct_type = SCT_WATER; + } else if (total < HILLMIN) + sct->sct_type = SCT_RURAL; + else if (total < PLATMIN) + sct->sct_type = SCT_MOUNT; + else if (total < HIGHMIN) + sct->sct_type = SCT_RURAL; + else + sct->sct_type = SCT_MOUNT; + sct->sct_elev = total; + sct->sct_newtype = sct->sct_type; + if (ORE) + add_resources(sct); + } + } + if (AIRPORT_MARKER) + for (c = 0; c < nc; ++c) { + sects[capy[c]][capx[c]/2 + capy[c]%2].sct_type = SCT_AIRPT; + sects[capy[c]][capx[c]/2 + capy[c]%2].sct_newtype = SCT_AIRPT; + } +} + +/**************************************************************************** + WRITE ALL THIS STUFF TO THE FILE +****************************************************************************/ +int +write_file(void) +{ + int n; + + /* if ((n = write(the_file, sects, sizeof(sects))) < 0) {*/ + if ((n = write(the_file, sectsbuf, YSIZE * XSIZE * sizeof(struct sctstr))) < 0) { + perror(empfile[EF_SECTOR].file); + return -1; + } + if (n != (int)(YSIZE * XSIZE * sizeof(struct sctstr))) { + printf("%s:partial write\n", empfile[EF_SECTOR].file); + return -1; + } + close(the_file); + return 0; +} + +/**************************************************************************** + PRINT A PICTURE OF THE MAP TO YOUR SCREEN +****************************************************************************/ +void +output(void) +{ + int i, j; + if (opt_BLITZ) + translate_continents(); + if (quiet == 0) { + for (i = 0; i < WORLD_Y; ++i) { + puts(""); + if (i%2) + printf(" "); + for (j = i%2; j < WORLD_X; j += 2) { + if (own[j][i] == -1) + printf(". "); + else { + printf("%c ", map_symbol(j,i)); + } + } + } + } + if (AIRPORT_MARKER) + printf("\n\nEach continent is marked by a \"*\" on the map (to distinguish them from\nthe islands). You can redesignate these airfields to wilderness sectors\none at a time, each time you add a new country to the game.\n"); +} + +/* Reorder the continents from top left to bottom right */ +void +translate_continents(void) +{ + int i, j, n = 0, k, gotit, c; + int *trans, *trans_cont, *oldcapx, *oldcapy; + + trans = (int *)calloc(nc, sizeof(int)); + trans_cont = (int *)calloc(nc, sizeof(int)); + oldcapx = (int *)calloc(nc, sizeof(int)); + oldcapy = (int *)calloc(nc, sizeof(int)); + + for (i = 0; i < WORLD_Y; ++i) { + for (j = i%2; j < WORLD_X; j += 2) { + if (own[j][i] >-1 && own[j][i] < nc) { + gotit = 0; + for (k = 0; k < n; ++k) { + if (trans[k] == own[j][i]) + gotit = 1; + } + if (!gotit) { + if (n > nc) { + printf("fairland: BUG in translate continents! mail stevens@math.utoronto.ca\n"); + exit (2); + } + trans[n] = own[j][i]; + trans_cont[own[j][i]] = n; + ++n; + } + } + } + } + for (i = 0; i < WORLD_Y; ++i) { + for (j = i%2; j < WORLD_X; j += 2) { + if (own[j][i] >-1 && own[j][i] < nc) { + own[j][i] = trans_cont[own[j][i]]; + } + } + } + for (c = 0; c < nc; ++c) { + oldcapx[c] = capx[c]; + oldcapy[c] = capy[c]; + } + for (c = 0; c < nc; ++c) { + capx[c] = oldcapx[trans[c]]; + capy[c] = oldcapy[trans[c]]; + } +} + +int +map_symbol(int x, int y) +{ + int c, iscap = 0; + + for (c = 0; c < nc; ++c) + if ((x == capx[c] && y == capy[c]) || (x == new_x(capx[c]+2) && y == capy[c])) + iscap = 1; + if ((elev[x][y] >= HILLMIN && elev[x][y] < PLATMIN) || elev[x][y] >= HIGHMIN) + return '^'; + return own[x][y]>=nc?'%':iscap?'#':numletter[own[x][y] % 62]; +} + +/*************************************************************************** + WRITE A SCRIPT FOR PLACING CAPITALS +****************************************************************************/ +int +write_newcap_script(void) +{ + int c; + FILE *script = fopen(outfile, "w"); + + if (!script) { + printf("fairland: error, unable to write to %s.\n", outfile); + return -1; + } + + for (c = 0; c < nc; ++c) { + fprintf(script, "add %d %d %d n i\n", c+1, c+1, c+1); + if (AIRPORT_MARKER) + fprintf(script, "des %d,%d -\n", capx[c], capy[c]); + fprintf(script, "newcap %d %d,%d\n", c+1, capx[c], capy[c]); + } + fprintf(script, "add %d visitor visitor v i\n", c+1); + ++c; + fclose (script); + if (quiet == 0) + printf("\n\nA script for adding all the countries can be found in \"%s\".\n", + outfile); + if (ORE && quiet == 0) + printf("\t***IMPORTANT: Resources have already been added***\n\tYou do NOT need to run the ore program.\n"); + return 0; +} + +static void qprint (str) +const char *str; +{ + if (quiet == 0) + fputs (str, stdout); +} + +void +fl_sct_init(coord x, coord y, s_char *ptr) +{ + struct sctstr *sp = (struct sctstr *) ptr; + + sp->ef_type = EF_SECTOR; + sp->sct_x = x; + sp->sct_y = y; + sp->sct_dist_x = x; + sp->sct_dist_y = y; + sp->sct_road = 0; + sp->sct_rail = 0; + sp->sct_defense = 0; +} diff --git a/src/util/files.c b/src/util/files.c new file mode 100644 index 00000000..a0a67cae --- /dev/null +++ b/src/util/files.c @@ -0,0 +1,262 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * files.c: Create all the misc files + * + * Known contributors to this file: + * Thomas Ruschak + * Ken Stevens, 1995 + * Steve McClure, 1998 + */ + +#if defined(aix) || defined(linux) || defined(solaris) +#include +#endif /* aix or linux */ + +#include +#include +#if !defined(_WIN32) +#include +#include +#else +#include +#endif +#include + +#include "options.h" +#include "misc.h" +#include "var.h" +#include "sect.h" +#include "nat.h" +#include "ship.h" +#include "land.h" +#include "plane.h" +#include "nuke.h" +#include "power.h" +#include "trade.h" +#include "file.h" +#include "tel.h" +#include "prototypes.h" +#include "optlist.h" + +s_char program[] = "file"; + +static void comminit(int fd); +static int make(char *filename); +static void file_sct_init(coord x, coord y, s_char *ptr); + +int +main(int argc, char *argv[]) +{ + extern s_char *annfil; + extern s_char *timestampfil; + extern s_char *infodir; + extern s_char *commfil; + extern s_char *datadir; + s_char buf[255]; + s_char tbuf[512]; + s_char *filename; + int x,y; + struct natstr nat; + struct sctstr sct; + int i; + s_char *map; + extern char *optarg; + int opt; + char *config_file = NULL; + +#if !defined(_WIN32) + while ((opt = getopt (argc, argv, "e:")) != EOF) { + switch (opt) { + case 'e': + config_file = optarg; + break; + } + } +#endif + + /* Try to use the existing data directory */ + if (config_file == NULL) { + sprintf (tbuf, "%s/econfig", datadir); + config_file = tbuf; + } + emp_config (config_file); + empfile[EF_MAP].size = (WORLD_X * WORLD_Y) / 2; + empfile[EF_BMAP].size = (WORLD_X * WORLD_Y) / 2; + +#if !defined(_WIN32) + if (access(datadir, F_OK) < 0 && mkdir(datadir, 0750) < 0) { +#else + if (_access(datadir, 06) < 0 && _mkdir(datadir) < 0) { +#endif + perror(datadir); + printf("Can't make game directory\n"); + exit(1); + } + printf("WARNING: this blasts the existing game in %s (if any)\n", datadir); + printf("continue? "); + fgets(buf, sizeof(buf) - 1, stdin); + if (*buf != 'y' && *buf != 'Y') + exit(1); + for (i=0; i < EF_MAX; i++) { + if (ef_open(i, O_RDWR|O_CREAT|O_TRUNC, 0) < 0) { + perror("ef_open"); + exit(1); + } + } + bzero((s_char *)&nat, sizeof(nat)); + nat.ef_type = EF_NATION; + if (nat.nat_cnam[0] == 0) + strcpy(nat.nat_cnam,"POGO"); + if (nat.nat_pnam[0] == 0) + strcpy(nat.nat_pnam,"peter"); + nat.nat_stat = STAT_INUSE|STAT_NORM|STAT_GOD|STAT_ABS; + nat.nat_btu = 255; + nat.nat_money = 123456789; + nat.nat_cnum = 0; + nat.nat_flags |= NF_FLASH; + for(x=0;x= 0; x--) { + filename = mailbox(buf, x); + close(creat(filename, 0600)); + chmod(filename, 0600); + } + close(creat(timestampfil, 0600)); + close(creat(annfil, 0600)); + chmod(infodir, 0750); + chmod(datadir, 0770); + chmod(teldir, 0770); + + /* create a zero-filled sector file */ + bzero((s_char *)&sct,sizeof(sct)); + for (y=0;yef_type = EF_SECTOR; + sp->sct_x = x; + sp->sct_y = y; + sp->sct_dist_x = x; + sp->sct_dist_y = y; +} + +void +log_last_commands(void) {} diff --git a/src/util/land.c b/src/util/land.c new file mode 100644 index 00000000..45745547 --- /dev/null +++ b/src/util/land.c @@ -0,0 +1,410 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * land.c: New version of empcre - Create the land masses in the game + * + * Known contributors to this file: + * James Anderson, 1987 + * Dave Pare, 1989 + */ + +#include +#include +#include "var.h" +#include "misc.h" +#include "power.h" +#include "nat.h" +#include "sect.h" +#include "gamesdef.h" +#include "file.h" +#include "xy.h" +#include "prototypes.h" + +#define rnd(x) (random() % (x)) + +#define XPLATES ((WORLD_X) / 2) /* basically world x-y size */ +#define YPLATES (WORLD_Y) +#define XSIZE (XPLATES) +#define YSIZE (YPLATES) + +#define BIGV 256 /* used in making altitude */ +#define SMALLV 128 /* ex-ocean: rnd(SMALLV) - rnd(BIGV) */ + +typedef enum plates { + OCEAN, ISLAND, CONTINENT +} plate_e; + +#define LANDMIN 1 /* plate altitude for normal land */ +#define HILLMIN 34 /* plate altitude for hills */ +#define PLATMIN 36 /* plate altitude for plateau */ +#define HIGHMIN 98 /* plate altitude for mountains */ + +#define LANDCH 60 /* land plate percentage */ +#define NUMLAND (YPLATES * XPLATES * LANDCH)/100 +#define NUMISLE NUMLAND/5 /* 1 isle for 5 land */ +#define NUMWATER (XPLATES * YPLATES) - (NUMLAND + NUMISLE) + +#define SECTRANGE 3 /* smoothing area */ +#define MINCONTDIST 2 /* minimum continent distance */ +#define CHUNKSIZE 2 /* basic land block size */ +#define NEWCONTDIST (rnd(mincontdist) + mincontdist) + /* dist away from others for newcont */ +#define NUMCHUNKS 70 /* number of CHUNKS per cont */ + +struct sctstr sects[YSIZE][XSIZE]; + +plate_e plates[YPLATES][XPLATES]; +int world[YSIZE][XSIZE]; + +int sectrange = SECTRANGE; +int mincontdist = MINCONTDIST; +int chunksize = CHUNKSIZE; +int numchunks = NUMCHUNKS; +int numisle = NUMISLE; + +static void initworld(); +static void growcont(); +static void newcont(); +static int verify(); +static int makeland(); +static void make_altitude(); +static int total_land(); +static void make_sects(); +static void land_sct_init(coord x, coord y, s_char *ptr); + + +int +main(argc, argv) + int argc; + s_char **argv; +{ + extern struct empfile empfile[]; + register int n; + int x, y; + int i, j; + time_t now; + int fd; + int left; + int big; + + if (argc > 1 && argc != 6) { + printf("usage: %s sectrange mincontdist chunksize numchunks numisle\n", + *argv); + return -1; + } + if (argc == 6) { + sectrange = atoi(argv[1]); + mincontdist = atoi(argv[2]); + chunksize = atoi(argv[3]); + numchunks = atoi(argv[4]); + numisle = atoi(argv[5]); + } + printf("sectrange: %d\n", sectrange); + printf("mincontdist: %d\n", mincontdist); + printf("chunksize: %d\n", chunksize); + printf("numchunks: %d\n", numchunks); + printf("numisle: %d\n", numisle); + fd = open(empfile[EF_SECTOR].file, O_RDWR|O_CREAT|O_TRUNC, 0660); + if (fd < 0) { + perror(empfile[EF_SECTOR].file); + return -1; + } + time(&now); + srandom(now+getpid()); + initworld((plate_e *)plates); + left = NUMLAND; + printf("Creating continents"); + while (left > 0) { + big = (left / (numchunks * 3 * chunksize*chunksize)) + 1; + for (n=0; nsct_type = SCT_WATER; + } else if (total < HILLMIN) + sct->sct_type = SCT_RURAL; + else if (total < PLATMIN) + sct->sct_type = SCT_MOUNT; + else if (total < HIGHMIN) + sct->sct_type = SCT_RURAL; + else + sct->sct_type = SCT_MOUNT; + sct->sct_elev = total; + sct->sct_newtype = sct->sct_type; + sum += total; + if (total < -129) + elev[0]++; + else + if (total > 129) + elev[26]++; + else + elev[13+total/10]++; + } + } + for (i = 0; i < 12+12+3; i++) + if (elev[i] != 0) + printf("%4d sectors elevation %4d to %4d\n", + elev[i], 10*i - 140, 10*i - 130); +} + +static void +land_sct_init(coord x, coord y, s_char *ptr) +{ + struct sctstr *sp = (struct sctstr *) ptr; + + sp->ef_type = EF_SECTOR; + sp->sct_x = x; + sp->sct_y = y; + sp->sct_dist_x = x; + sp->sct_dist_y = y; +} diff --git a/src/util/ore.c b/src/util/ore.c new file mode 100644 index 00000000..a254cb9f --- /dev/null +++ b/src/util/ore.c @@ -0,0 +1,409 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * ore.c: Create a world + * + * Known contributors to this file: + * Thomas Ruschak + */ + +/* + * In the oceans, it puts oil = (2d6-4)*10+d10, fert = (2d6-2)*10+d10 + * (max of 127 in both cases) + * + * For islands smaller than ISLANDSIZE, it puts in normal + * resources. (These are assumed to be small non-start islands) + * For islands at least ISLANDSIZE big, it makes normal fert, + * but it uses the MIN, OIL, GOLD, and URAN arrays to find out + * what resources to put there. The intent is to find all start + * islands, and give them all a pre-determined spread of stuff. + * To change the stuff, just change the MIN, OIL, GOLD, and URAN arrays. + * + * For example, if the GOLD array is 90,80,70,60, it'll try to put 1 + * sector with 90 gold, 1 with 80 gold, 1 with 70, and 1 with 60 gold + * on each island of at least ISLANDSIZE. It will not overrun start + * sectors, and should be run AFTER you have placed capitals. + */ + + */ + +#if defined(aix) || defined(linux) || defined(solaris) +#include +#endif /* aix or linux */ + +#include +#include +#include "misc.h" +#include "var.h" +#include "sect.h" +#include "gamesdef.h" +#include "file.h" +#include "path.h" +#include "xy.h" +#include "prototypes.h" + +#define XPLATES WORLD_X/2 +#define YPLATES WORLD_Y +#define YbyX (YPLATES*XPLATES/8) +#define ISLANDSIZE 25 +#define ISLANDMAX 1000 + +int MIN[] = { 90,85,85,85,70,70,70,70,70 }; +int OIL[] = { 90,80,70,60,50 }; +int GOLD[] = { 90,80,70,60,50 }; +int URAN[] = { 90,80,70,60,50 }; + +#define MIN_TYPE 0 +#define OIL_TYPE 1 +#define GOLD_TYPE 2 +#define URAN_TYPE 3 + +struct sctstr sects[YPLATES*XPLATES]; +u_char s[WORLD_Y][WORLD_X]; +short c[WORLD_Y][WORLD_X]; +short e[WORLD_Y][WORLD_X]; +int size[YbyX]; +int goldchance[YbyX]; +int ironchance[YbyX]; +int oilchance[YbyX]; +int fertchance[YbyX]; +int urchance[YbyX]; +int ix[ISLANDMAX],iy[ISLANDMAX],ic[ISLANDMAX],in=0; +int cont = 0; + +void makec(); +void makeore(); +int place(); +int nearelev(); + +int +main(argc, argp) + int argc; + s_char **argp; +{ + register struct sctstr *sp; + register int y; + register int x; + int sectf; + time_t now; + s_char *sectfil = NULL; + int xx,x1,y1; + extern char *optarg; + int opt; + char *config_file = NULL; + + + while ((opt = getopt (argc, argp, "e:s:")) != EOF) { + switch (opt) { + case 'e': + config_file = optarg; + break; + case 's': + sectfil = optarg; + break; + } + } + + emp_config (config_file); + + if (sectfil == NULL) + sectfil = empfile[EF_SECTOR].file; + time(&now); + srandom((unsigned int)now); + sectf = open(sectfil, O_RDWR, 0); + if (sectf < 0) { + perror(sectfil); + exit(1); + } + read(sectf, sects, sizeof(sects)); + sp = sects; + for (y = 0; y < WORLD_Y; y++) { + for (x = 0; x < WORLD_X; x++) { + if (((x ^ y) & 1)) + continue; + c[sp->sct_y][sp->sct_x] = 0; + s[sp->sct_y][sp->sct_x] = sp->sct_type; + e[sp->sct_y][sp->sct_x] = sp->sct_elev; + sp++; + } + } + for (y = 0; y < WORLD_Y; y++) { + for (x = 0; x < WORLD_X; x++) { + if (((x ^ y) & 1)) + continue; + if (c[y][x] != 0) + continue; + if (s[y][x] == SCT_WATER) + continue; + + makec(x, y, 0); + + for(y1=0;y1= ISLANDSIZE){ + xx = ISLANDSIZE/2; + for(y1=0;y1 y ? y : x) +#define MAXIMUM(x,y) (x > y ? x : y) + +void +makeore(sp) + register struct sctstr *sp; +{ + int elev; + int oil, gmin, iron, fertil, ur; + int lev; + int i; + int x,y; + + if (sp->sct_type == SCT_SANCT) + return; + + y = sp->sct_y; + x = sp->sct_x; + + elev = e[y][x]; + lev = (elev*12 + nearelev(x, y))/18; + i = c[y][x]; + oil = 0; + iron = 0; + gmin = 0; + fertil = 0; + ur = 0; + + if (sp->sct_type == SCT_WATER){ + oil = MAXIMUM(((roll(6)+roll(6)-4)*10+roll(10)),0); + sp->sct_oil = MINIMUM(oil,127); + fertil = MAXIMUM(((roll(6)+roll(6)-2)*12+roll(10)),0); + sp->sct_fertil = MINIMUM(fertil,127); + return; + } + iron = roll(100) + 100-roll(100); + oil = roll(100) + 100-roll(100); + ur = roll(100) + 100-roll(100); + gmin = roll(100) + 100-roll(100); + fertil = 85 + 100-roll(100); + + iron = MAXIMUM(iron,0); + oil = MAXIMUM(oil,0); + ur = MAXIMUM(ur,0); + gmin = MAXIMUM(gmin,0); + fertil = MAXIMUM(fertil,0); + iron = MINIMUM(iron,127); + oil = MINIMUM(oil,127); + ur = MINIMUM(ur,127); + gmin = MINIMUM(gmin,127); + fertil = MINIMUM(fertil,127); + + sp->sct_fertil = fertil; + if (i > ISLANDMAX){ + sp->sct_oil = oil; + sp->sct_min = iron; + sp->sct_gmin = gmin; + sp->sct_uran = ur; + } + else{ + fertil -= 20; + fertil = MAXIMUM(fertil,0); + fertil = MINIMUM(fertil,127); + sp->sct_fertil = fertil; + } +} + +int +nearelev(x, y) + int x; + int y; +{ + int dir; + int dx; + int dy; + int level; + + level = 0; + for (dir = 1; dir <= 6; dir++) { + dx = (diroff[dir][0] + x + WORLD_X) % WORLD_X; + dy = (diroff[dir][1] + y + WORLD_Y) % WORLD_Y; + level += e[dy][dx]; + } + return level; +} + +/* Already in libgen.a +roll(n) + int n; +{ + return random() % n; +} +*/ + +int +min(a, b) + int a; + int b; +{ + if (a < b) + return a; + return b; +} + +int +place(island,res,num,offset,restype) +int island, res[], num, offset; +s_char *restype; +{ + int x1,y1,x2,y2,x3,y3,j,k; + int tried[WORLD_Y][WORLD_X]; + int numtried, there; + struct sctstr *foo; + + x1=ix[island]; + y1=iy[island]; + + for(k=0;k 0) || + (sects[y2*XPLATES+x2/2].sct_type==SCT_MOUNT)){ + + there = *((u_char *)(((s_char *)& + sects[y2*XPLATES+x2/2])+offset)); + + foo = §s[y2*XPLATES+x2/2]; + + if (sects[y2*XPLATES+x2/2].sct_type==SCT_RURAL){ + if (!tried[y2][x2]){ + tried[y2][x2]=1; + numtried++; + if (numtried == ISLANDSIZE){ + int a,b; +printf("*** %d) couldn't place %s %d (%d)\n",island,restype,k,res[k]); +for(a=0;a +#include +#include "prototypes.h" + +int +main (argc, argv) +int argc; +char *argv[]; +{ + if (argc > 1) + emp_config (argv[1]); + else emp_config (NULL); + + print_config (stdout); + exit (0); +} diff --git a/src/util/perfect.c b/src/util/perfect.c new file mode 100644 index 00000000..9097c00e --- /dev/null +++ b/src/util/perfect.c @@ -0,0 +1,288 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * perfect.c: Create a perfect world + * + * Known contributors to this file: + * James Anderson, 1986 + * Dave Pare, 1986 + */ + +#if defined(aix) || defined(linux) || defined(solaris) +#include +#endif /* aix or linux */ + +#include +#include +#include "misc.h" +#include "var.h" +#include "sect.h" +#include "gamesdef.h" +#include "file.h" +#include "path.h" +#include "xy.h" +#include "prototypes.h" + +#define XPLATES (WORLD_X / 2) +#define YPLATES WORLD_Y +#define YbyX (YPLATES*XPLATES/8) + +struct sctstr sects[YPLATES*XPLATES]; +u_char s[YPLATES][XPLATES]; +short c[YPLATES][XPLATES]; +short e[YPLATES][XPLATES]; +int size[YbyX]; +int goldchance[YbyX]; +int ironchance[YbyX]; +int oilchance[YbyX]; +int fertchance[YbyX]; +int urchance[YbyX]; + +void makec(); +void makeore(); +int nearelev(); + +int +main(argc, argp) + int argc; + s_char **argp; +{ + register struct sctstr *sp; + register int y; + register int x; + int sectf; + int i; + time_t now; + s_char *sectfil = NULL; + extern char *optarg; + int opt; + char *config_file = NULL; + + + while ((opt = getopt (argc, argp, "e:s:")) != EOF) { + switch (opt) { + case 'e': + config_file = optarg; + break; + case 's': + sectfil = optarg; + break; + } + } + + emp_config (config_file); + + if (sectfil == NULL) + sectfil = empfile[EF_SECTOR].file; + + time(&now); + srandom((unsigned int)now); + sectf = open(sectfil, O_RDWR, 0); + if (sectf < 0) { + perror(sectfil); + exit(1); + } + read(sectf, sects, sizeof(sects)); + sp = sects; + for (y = 0; y < WORLD_Y; y++) { + for (x = 0; x < WORLD_X; x++) { + if (((x ^ y) & 1)) + continue; + c[y][x/2] = 0; + s[y][x/2] = sp->sct_type; + e[y][x/2] = sp->sct_elev; + sp++; + } + } + for (y = 0; y < WORLD_Y; y++) { + for (x = 0; x < WORLD_X; x++) { + if (((x ^ y) & 1)) + continue; + if (c[y][x/2] != 0) + continue; + makec(x, y, 0); + } + } + printf("size oil gold fert iron\n"); + for (i=1; i 10) { + printf("%3d %3d %3d %3d %3d\n", + size[i], oilchance[i], goldchance[i], + fertchance[i], ironchance[i]); + } + } + if (i == YbyX) + printf("Oops. YbyX not big enough\n"); + sp = sects; + for (y = 0; y < WORLD_Y; y++) { + for (x = 0; x < WORLD_X; x++) { + if (((x ^ y) & 1)) + continue; + makeore(sp++); + } + } + lseek(sectf, 0L, 0); + write(sectf, sects, sizeof(sects)); + close(sectf); + exit(0); +} + +int cont = 0; + +#define max(a,b) (a < b ? b : a) + +void +makec(x, y, n) + int x; + int y; + int n; +{ + register int dy; + register int dx; + register int dir; + register short *cp; + + if (s[y][x/2] == SCT_WATER) + return; + cp = &c[y][x/2]; + if (*cp != 0) + return; + if (n == 0) + n = ++cont; + *cp = n; + size[n]++; + for (dir = 1; dir <= 6; dir++) { + dx = (diroff[dir][0] + x + WORLD_X) % WORLD_X; + dy = (diroff[dir][1] + y + WORLD_Y) % WORLD_Y; + makec(dx, dy, n); + } +} + +void +makeore(sp) + register struct sctstr *sp; +{ + int elev; + int oil, gmin, iron, fertil, ur; + int lev; + int i; + int x,y; + + y = sp->sct_y; + x = sp->sct_x; + elev = e[y][x/2]; + lev = (elev*12 + nearelev(x, y))/18; + i = c[y][x/2]; + oil = 0; + iron = 0; + gmin = 0; + fertil = 0; + ur = 0; + if (lev < 20 && lev > -15 && roll(100) < 30+oilchance[i]+lev) { + oil = (45 - lev) + roll(50); + if (oil > 100) + oil = 100; + if (oil < 10) + oil = 0; + } + if (lev > 15 && roll(20+lev) < lev+ironchance[i]) { + iron = lev + roll(55); + if (iron > 100) + iron = 100; + if (iron < 10) + iron = 0; + } + if (lev > 16 && roll(35+lev) < lev+goldchance[i]) { + gmin = (lev - 5) + roll(45); + if (gmin > 100) + gmin = 100; + if (gmin < 10) + gmin = 0; + } + if (lev > 14 && roll(35+lev) < lev+urchance[i]) { + ur = (lev - 5) + roll(45); + if (ur > 100) + ur = 100; + if (ur < 10) + ur = 0; + } + fertil = (85 + fertchance[i] - lev) - (((iron + gmin)/2) - oil/3); + if (fertil > 120) + fertil = 120; + if (fertil < 0) + fertil = 0; + sp->sct_oil = 100; + sp->sct_min = 100; + sp->sct_gmin = 100; + sp->sct_fertil = 100; + sp->sct_uran = 100; +} + +int +nearelev(x, y) + int x; + int y; +{ + int dir; + int dx; + int dy; + int level; + + level = 0; + for (dir = 1; dir <= 6; dir++) { + dx = (diroff[dir][0] + x + WORLD_X) % WORLD_X; + dy = (diroff[dir][1] + y + WORLD_Y) % WORLD_Y; + level += e[dy][dx/2]; + } + return level; +} + +/* Already in libgen.a +roll(n) + int n; +{ + return random() % n; +} +*/ + +int +min(a, b) + int a; + int b; +{ + if (a < b) + return a; + return b; +}