From d8b7fdfae1c42f6ab23e74a011d3ed12c4c78f16 Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Sat, 23 Aug 2003 12:23:04 +0000 Subject: [PATCH] Import of Empire 4.2.12 --- COPYING | 3 + CREDITS | 154 ++ LEGAL | 26 + LICENSE | 340 +++ Make.sysdefs | 152 ++ Makefile | 561 +++++ README | 82 + build.conf | 72 + doc/CHANGES | 691 ++++++ doc/CHANGES2.3 | 335 +++ doc/CHANGES3.0 | 449 ++++ doc/CHANGES4.X | 1294 ++++++++++++ doc/README | 54 + doc/WACKY_IDEAS | 171 ++ doc/WISH_LIST | 208 ++ doc/backups | 14 + doc/bug-reports | 42 + doc/coding | 143 ++ doc/compiling | 42 + doc/configuration | 23 + doc/debugging | 12 + doc/disk_space | 15 + doc/econfig | 141 ++ doc/files | 33 + doc/message | 16 + doc/pthreads | 98 + doc/threads | 161 ++ doc/troubleshooting | 13 + include/bit.h | 71 + include/budg.h | 40 + include/com.h | 51 + include/combat.h | 107 + include/commands.h | 60 + include/commodity.h | 60 + include/common.h | 49 + include/damage.h | 48 + include/deity.h | 41 + include/distribute.h | 40 + include/empio.h | 77 + include/empthread.h | 137 ++ include/event.h | 51 + include/file.h | 117 + include/gen.h | 45 + include/genitem.h | 72 + include/global.h | 38 + include/io_mask.h | 53 + include/ioqueue.h | 69 + include/item.h | 60 + include/keyword.h | 51 + include/land.h | 235 ++ include/loan.h | 66 + include/lost.h | 55 + include/lwp.h | 105 + include/map.h | 64 + include/match.h | 48 + include/misc.h | 222 ++ include/mission.h | 68 + include/nat.h | 206 ++ include/news.h | 173 ++ include/nsc.h | 167 ++ include/nuke.h | 79 + include/options.h | 127 ++ include/optlist.h | 128 ++ include/path.h | 87 + include/plane.h | 206 ++ include/player.h | 106 + include/power.h | 65 + include/product.h | 75 + include/proto.h | 68 + include/prototype.h | 44 + include/prototypes.h | 997 +++++++++ include/queue.h | 48 + include/retreat.h | 50 + include/sect.h | 202 ++ include/ship.h | 229 ++ include/struct.h | 41 + include/subs.h | 55 + include/tel.h | 61 + include/trade.h | 88 + include/treaty.h | 84 + include/update.h | 49 + include/user.h | 53 + include/var.h | 148 ++ include/version.h | 47 + include/wantupd.h | 101 + include/xy.h | 71 + info/Blank.awk | 10 + info/CRT.MAC | 27 + info/Commands/MakeSrcs | 1 + info/Commands/Makefile | 62 + info/Commands/accept.t | 23 + info/Commands/add.t | 17 + info/Commands/announce.t | 34 + info/Commands/anti.t | 35 + info/Commands/apropos.t | 24 + info/Commands/arm.t | 21 + info/Commands/army.t | 43 + info/Commands/assault.t | 81 + info/Commands/attack.t | 9 + info/Commands/bdes.t | 35 + info/Commands/bestdistpath.t | 27 + info/Commands/bestpath.t | 27 + info/Commands/bmap.t | 94 + info/Commands/board.t | 48 + info/Commands/bomb.t | 117 + info/Commands/break.t | 14 + info/Commands/budget.t | 88 + info/Commands/build.t | 303 +++ info/Commands/buy.t | 41 + info/Commands/bye.t | 15 + info/Commands/capital.t | 48 + info/Commands/cargo.t | 61 + info/Commands/cede.t | 47 + info/Commands/census.t | 86 + info/Commands/change.t | 29 + info/Commands/coastwatch.t | 28 + info/Commands/collect.t | 47 + info/Commands/commodity.t | 89 + info/Commands/consider.t | 37 + info/Commands/convert.t | 40 + info/Commands/country.t | 26 + info/Commands/cutoff.t | 83 + info/Commands/declare.t | 54 + info/Commands/deliver.t | 51 + info/Commands/demobilize.t | 57 + info/Commands/designate.t | 40 + info/Commands/disable.t | 7 + info/Commands/disarm.t | 9 + info/Commands/dissolve.t | 21 + info/Commands/distribute.t | 98 + info/Commands/drop.t | 44 + info/Commands/dump.t | 125 ++ info/Commands/echo.t | 24 + info/Commands/edit.t | 7 + info/Commands/enable.t | 6 + info/Commands/enlist.t | 52 + info/Commands/execute.t | 8 + info/Commands/explore.t | 93 + info/Commands/financial.t | 26 + info/Commands/fire.t | 158 ++ info/Commands/flash.t | 33 + info/Commands/fleetadd.t | 43 + info/Commands/fly.t | 43 + info/Commands/follow.t | 23 + info/Commands/force.t | 6 + info/Commands/fortify.t | 33 + info/Commands/fuel.t | 41 + info/Commands/give.t | 6 + info/Commands/grind.t | 10 + info/Commands/harden.t | 19 + info/Commands/headlines.t | 19 + info/Commands/hidden.t | 5 + info/Commands/improve.t | 19 + info/Commands/info.t | 30 + info/Commands/land.t | 61 + info/Commands/launch.t | 127 ++ info/Commands/lboard.t | 30 + info/Commands/lcargo.t | 61 + info/Commands/ldump.t | 85 + info/Commands/ledger.t | 26 + info/Commands/level.t | 75 + info/Commands/list.t | 34 + info/Commands/lload.t | 46 + info/Commands/llookout.t | 35 + info/Commands/lmap.t | 67 + info/Commands/lmine.t | 46 + info/Commands/load.t | 73 + info/Commands/lookout.t | 41 + info/Commands/lost.t | 62 + info/Commands/lradar.t | 28 + info/Commands/lrange.t | 11 + info/Commands/lretreat.t | 90 + info/Commands/lstat.t | 68 + info/Commands/ltend.t | 8 + info/Commands/lunload.t | 14 + info/Commands/map.t | 65 + info/Commands/march.t | 110 + info/Commands/market.t | 52 + info/Commands/mine.t | 40 + info/Commands/mission.t | 315 +++ info/Commands/mobupdate.t | 14 + info/Commands/morale.t | 30 + info/Commands/motd.t | 9 + info/Commands/move.t | 120 ++ info/Commands/mquota.t | 8 + info/Commands/mult.t | 47 + info/Commands/name.t | 7 + info/Commands/nation.t | 50 + info/Commands/navigate.t | 119 ++ info/Commands/ndump.t | 44 + info/Commands/newcap.t | 7 + info/Commands/neweff.t | 21 + info/Commands/newspaper.t | 110 + info/Commands/nmap.t | 65 + info/Commands/nuke.t | 23 + info/Commands/offer.t | 74 + info/Commands/offset.t | 6 + info/Commands/order.t | 167 ++ info/Commands/origin.t | 15 + info/Commands/paradrop.t | 43 + info/Commands/path.t | 42 + info/Commands/payoff.t | 37 + info/Commands/pboard.t | 19 + info/Commands/pdump.t | 67 + info/Commands/plane.t | 54 + info/Commands/players.t | 27 + info/Commands/pmap.t | 65 + info/Commands/power.t | 101 + info/Commands/pray.t | 45 + info/Commands/production.t | 90 + info/Commands/pstat.t | 52 + info/Commands/qorder.t | 27 + info/Commands/quit.t | 8 + info/Commands/radar.t | 124 ++ info/Commands/range.t | 21 + info/Commands/read.t | 22 + info/Commands/realm.t | 36 + info/Commands/recon.t | 51 + info/Commands/reject.t | 25 + info/Commands/relations.t | 109 + info/Commands/repay.t | 30 + info/Commands/report.t | 59 + info/Commands/reset.t | 13 + info/Commands/resource.t | 68 + info/Commands/retreat.t | 91 + info/Commands/route.t | 61 + info/Commands/sabotage.t | 17 + info/Commands/sail.t | 55 + info/Commands/satellite.t | 58 + info/Commands/scrap.t | 24 + info/Commands/scuttle.t | 19 + info/Commands/sdump.t | 80 + info/Commands/sect.t | 40 + info/Commands/sell.t | 42 + info/Commands/set.t | 24 + info/Commands/setresource.t | 5 + info/Commands/setsector.t | 6 + info/Commands/sharebmap.t | 35 + info/Commands/shark.t | 15 + info/Commands/ship.t | 61 + info/Commands/shoot.t | 36 + info/Commands/show.t | 41 + info/Commands/shutdown.t | 17 + info/Commands/sinfrastructure.t | 62 + info/Commands/skywatch.t | 18 + info/Commands/smap.t | 67 + info/Commands/sonar.t | 98 + info/Commands/sorder.t | 35 + info/Commands/spy.t | 60 + info/Commands/sstat.t | 52 + info/Commands/start.t | 17 + info/Commands/starvation.t | 59 + info/Commands/stop.t | 21 + info/Commands/strength.t | 51 + info/Commands/supply.t | 98 + info/Commands/survey.t | 37 + info/Commands/swapsector.t | 15 + info/Commands/sweep.t | 55 + info/Commands/telegram.t | 45 + info/Commands/tend.t | 30 + info/Commands/territory.t | 38 + info/Commands/test.t | 23 + info/Commands/threshold.t | 46 + info/Commands/toggle.t | 45 + info/Commands/torpedo.t | 71 + info/Commands/trade.t | 40 + info/Commands/transport.t | 32 + info/Commands/treaty.t | 32 + info/Commands/turn.t | 9 + info/Commands/unload.t | 17 + info/Commands/unsail.t | 7 + info/Commands/update.t | 8 + info/Commands/upgrade.t | 19 + info/Commands/version.t | 72 + info/Commands/wait.t | 25 + info/Commands/wall.t | 25 + info/Commands/wingadd.t | 43 + info/Commands/wipe.t | 42 + info/Commands/wire.t | 17 + info/Commands/work.t | 19 + info/Commands/zdone.t | 30 + info/Concepts/Attack.t | 388 ++++ info/Concepts/Autofeed.t | 76 + info/Concepts/Autonav.t | 48 + info/Concepts/BTU.t | 74 + info/Concepts/Bridges.t | 34 + info/Concepts/Citizens.t | 56 + info/Concepts/Damage.t | 103 + info/Concepts/Education.t | 70 + info/Concepts/Fallout.t | 35 + info/Concepts/Flak.t | 151 ++ info/Concepts/Food.t | 149 ++ info/Concepts/Guerrilla.t | 74 + info/Concepts/Happiness.t | 34 + info/Concepts/Hitchance.t | 121 ++ info/Concepts/Infrastructure.t | 62 + info/Concepts/Innards.t | 248 +++ info/Concepts/Interception.t | 126 ++ info/Concepts/Land-units.t | 344 +++ info/Concepts/Maintenance.t | 31 + info/Concepts/MakeSrcs | 1 + info/Concepts/Makefile | 62 + info/Concepts/Mobility.t | 230 ++ info/Concepts/Move.t | 36 + info/Concepts/Nuke-types.t | 79 + info/Concepts/Plague.t | 113 + info/Concepts/Plane-types.t | 309 +++ info/Concepts/Products.t | 133 ++ info/Concepts/Quick-ref.t | 42 + info/Concepts/Research.t | 37 + info/Concepts/Sector-ownership.t | 31 + info/Concepts/Sector-types.t | 397 ++++ info/Concepts/Selector.t | 261 +++ info/Concepts/Ship-types.t | 311 +++ info/Concepts/Spies.t | 38 + info/Concepts/Syntax.t | 153 ++ info/Concepts/Taxes.t | 36 + info/Concepts/Technology.t | 92 + info/Concepts/Time.t | 30 + info/Concepts/Trade-ships.t | 92 + info/Concepts/Unit-types.t | 235 ++ info/Concepts/Update-sequence.t | 98 + info/INFO.MAC | 133 ++ info/Introduction/Basics.t | 41 + info/Introduction/Clients.t | 56 + info/Introduction/Expert.t | 219 ++ info/Introduction/Guide.t | 3408 ++++++++++++++++++++++++++++++ info/Introduction/Hints.t | 177 ++ info/Introduction/Kill.t | 35 + info/Introduction/MakeSrcs | 1 + info/Introduction/Makefile | 62 + info/Introduction/Novice.t | 585 +++++ info/Introduction/Overview.t | 236 +++ info/Introduction/Suggestions.t | 46 + info/Makefile | 53 + info/README | 135 ++ info/Server/Bugs.t | 169 ++ info/Server/CHANGES.CHAINSAW.t | 663 ++++++ info/Server/Empire2.t | 652 ++++++ info/Server/Empire3.t | 174 ++ info/Server/Empire4.t | 1306 ++++++++++++ info/Server/God.t | 101 + info/Server/Hidden.t | 36 + info/Server/History.t | 229 ++ info/Server/MakeSrcs | 1 + info/Server/Makefile | 62 + info/Server/Merc.t | 92 + info/Server/Old-empire.t | 331 +++ info/Server/Options.t | 70 + info/Server/Wolfpack.t | 13 + info/Subjects/MakeSrcs | 1 + info/Subjects/Makefile | 62 + info/TROFF.MAC | 41 + info/checklist.pl | 69 + info/deity.list | 111 + info/emp2html.pl | 167 ++ info/info.pl | 329 +++ info/ls2html.pl | 8 + info/player.list | 148 ++ info/subj2html.pl | 198 ++ man/emp_client.6 | 77 + man/emp_server.6 | 64 + man/fairland.1 | 106 + man/files.1 | 24 + man/land.1 | 35 + man/ore.1 | 31 + man/pconfig.1 | 29 + man/perfect.1 | 31 + scripts/README | 41 + scripts/bigstart | 86 + scripts/blitz/README | 6 + scripts/blitz/crontab.config | 3 + scripts/blitz/motd | 18 + scripts/blitz/setup-blitz | 37 + scripts/blitz/start-blitz | 14 + scripts/crontab.config | 2 + scripts/keepitup | 156 ++ scripts/mapper/Makefile | 24 + scripts/mapper/README | 66 + scripts/mapper/archive.pl | 51 + scripts/mapper/cleanup | 6 + scripts/mapper/crontab.config | 4 + scripts/mapper/default.param | 41 + scripts/mapper/makeframe | 7 + scripts/mapper/makempeg | 27 + scripts/mapper/map.param | 180 ++ scripts/mapper/mapper | 41 + scripts/mapper/over.awk | 85 + scripts/mapper/over2.pbm | 3 + scripts/mapper/param.pl | 41 + scripts/mapper/pgmmap.awk | 66 + scripts/mapper/randppm.awk | 15 + scripts/mapper/text.pbm | 3 + scripts/mapper/text.size | 1 + scripts/postresults | 66 + scripts/saveass | 42 + src/client/Makefile | 99 + src/client/Makefile.server | 96 + src/client/Makefile.standalone | 81 + src/client/README | 47 + src/client/bit.c | 232 ++ src/client/bit.h | 61 + src/client/dtable.c | 73 + src/client/empire.6 | 77 + src/client/expect.c | 175 ++ src/client/fnlist.h | 45 + src/client/globals.c | 51 + src/client/h.h | 39 + src/client/handle.c | 52 + src/client/host.c | 133 ++ src/client/hpux.c | 95 + src/client/ioqueue.c | 322 +++ src/client/ioqueue.h | 49 + src/client/login.c | 126 ++ src/client/main.c | 362 ++++ src/client/misc.h | 136 ++ src/client/proto.h | 68 + src/client/queue.c | 80 + src/client/queue.h | 44 + src/client/saveargv.c | 53 + src/client/servcmd.c | 373 ++++ src/client/serverio.c | 92 + src/client/tags.c | 89 + src/client/tags.h | 42 + src/client/termio.c | 310 +++ src/client/termlib.c | 96 + src/doconfig/Makefile | 73 + src/doconfig/doconfig.c | 276 +++ src/lib/as/COPYRIGHT | 41 + src/lib/as/Makefile | 62 + src/lib/as/README | 300 +++ src/lib/as/as.h | 180 ++ src/lib/as/as_cache.c | 196 ++ src/lib/as/as_costcomp.c | 49 + src/lib/as/as_delete.c | 88 + src/lib/as/as_extend.c | 74 + src/lib/as/as_hash.c | 85 + src/lib/as/as_init.c | 62 + src/lib/as/as_merge.c | 84 + src/lib/as/as_search.c | 149 ++ src/lib/as/as_stats.c | 73 + src/lib/as/as_winnow.c | 177 ++ src/lib/commands/Makefile | 98 + src/lib/commands/acce.c | 92 + src/lib/commands/add.c | 231 ++ src/lib/commands/anti.c | 172 ++ src/lib/commands/arm.c | 164 ++ src/lib/commands/army.c | 88 + src/lib/commands/assa.c | 231 ++ src/lib/commands/atta.c | 163 ++ src/lib/commands/bdes.c | 78 + src/lib/commands/best.c | 88 + src/lib/commands/boar.c | 187 ++ src/lib/commands/bomb.c | 976 +++++++++ src/lib/commands/brea.c | 56 + src/lib/commands/budg.c | 477 +++++ src/lib/commands/buil.c | 1120 ++++++++++ src/lib/commands/buy.c | 374 ++++ src/lib/commands/capi.c | 79 + src/lib/commands/carg.c | 153 ++ src/lib/commands/cede.c | 393 ++++ src/lib/commands/cens.c | 179 ++ src/lib/commands/chan.c | 135 ++ src/lib/commands/coas.c | 179 ++ src/lib/commands/coll.c | 181 ++ src/lib/commands/comm.c | 141 ++ src/lib/commands/cons.c | 414 ++++ src/lib/commands/conv.c | 187 ++ src/lib/commands/coun.c | 116 + src/lib/commands/cuto.c | 117 + src/lib/commands/decl.c | 114 + src/lib/commands/deli.c | 124 ++ src/lib/commands/demo.c | 137 ++ src/lib/commands/desi.c | 239 +++ src/lib/commands/disa.c | 49 + src/lib/commands/diss.c | 265 +++ src/lib/commands/dist.c | 136 ++ src/lib/commands/drop.c | 152 ++ src/lib/commands/dump.c | 474 +++++ src/lib/commands/echo.c | 44 + src/lib/commands/edit.c | 1176 +++++++++++ src/lib/commands/enab.c | 47 + src/lib/commands/enli.c | 147 ++ src/lib/commands/expl.c | 343 +++ src/lib/commands/fina.c | 120 ++ src/lib/commands/flash.c | 197 ++ src/lib/commands/flee.c | 87 + src/lib/commands/fly.c | 152 ++ src/lib/commands/foll.c | 112 + src/lib/commands/forc.c | 72 + src/lib/commands/fort.c | 160 ++ src/lib/commands/fuel.c | 498 +++++ src/lib/commands/give.c | 105 + src/lib/commands/grin.c | 96 + src/lib/commands/hard.c | 121 ++ src/lib/commands/head.c | 258 +++ src/lib/commands/hidd.c | 92 + src/lib/commands/improve.c | 202 ++ src/lib/commands/info.c | 575 +++++ src/lib/commands/land.c | 118 ++ src/lib/commands/laun.c | 453 ++++ src/lib/commands/lboard.c | 157 ++ src/lib/commands/ldump.c | 299 +++ src/lib/commands/ledg.c | 68 + src/lib/commands/leve.c | 98 + src/lib/commands/load.c | 1229 +++++++++++ src/lib/commands/look.c | 321 +++ src/lib/commands/lost.c | 85 + src/lib/commands/lstat.c | 109 + src/lib/commands/lten.c | 175 ++ src/lib/commands/map.c | 145 ++ src/lib/commands/marc.c | 201 ++ src/lib/commands/mark.c | 165 ++ src/lib/commands/mfir.c | 1072 ++++++++++ src/lib/commands/mine.c | 175 ++ src/lib/commands/miss.c | 342 +++ src/lib/commands/mobq.c | 123 ++ src/lib/commands/mobu.c | 116 + src/lib/commands/mora.c | 84 + src/lib/commands/move.c | 436 ++++ src/lib/commands/mult.c | 122 ++ src/lib/commands/name.c | 86 + src/lib/commands/nati.c | 125 ++ src/lib/commands/navi.c | 311 +++ src/lib/commands/ndump.c | 92 + src/lib/commands/new.c | 396 ++++ src/lib/commands/newe.c | 170 ++ src/lib/commands/news.c | 215 ++ src/lib/commands/nuke.c | 110 + src/lib/commands/offe.c | 245 +++ src/lib/commands/offs.c | 80 + src/lib/commands/orde.c | 536 +++++ src/lib/commands/orig.c | 65 + src/lib/commands/para.c | 213 ++ src/lib/commands/path.c | 128 ++ src/lib/commands/payo.c | 131 ++ src/lib/commands/pboa.c | 56 + src/lib/commands/pdump.c | 218 ++ src/lib/commands/plan.c | 108 + src/lib/commands/play.c | 129 ++ src/lib/commands/powe.c | 441 ++++ src/lib/commands/prod.c | 428 ++++ src/lib/commands/pstat.c | 97 + src/lib/commands/rada.c | 150 ++ src/lib/commands/rang.c | 108 + src/lib/commands/rea.c | 243 +++ src/lib/commands/real.c | 151 ++ src/lib/commands/reco.c | 145 ++ src/lib/commands/reje.c | 116 + src/lib/commands/rela.c | 102 + src/lib/commands/repa.c | 146 ++ src/lib/commands/repo.c | 256 +++ src/lib/commands/rese.c | 150 ++ src/lib/commands/reso.c | 106 + src/lib/commands/retr.c | 301 +++ src/lib/commands/rout.c | 141 ++ src/lib/commands/sabo.c | 130 ++ src/lib/commands/sail.c | 183 ++ src/lib/commands/sate.c | 109 + src/lib/commands/scra.c | 341 +++ src/lib/commands/scut.c | 364 ++++ src/lib/commands/sdump.c | 274 +++ src/lib/commands/sect.c | 138 ++ src/lib/commands/sell.c | 203 ++ src/lib/commands/set.c | 186 ++ src/lib/commands/setres.c | 169 ++ src/lib/commands/setsect.c | 388 ++++ src/lib/commands/shar.c | 80 + src/lib/commands/shark.c | 131 ++ src/lib/commands/shi.c | 121 ++ src/lib/commands/shoo.c | 136 ++ src/lib/commands/show.c | 123 ++ src/lib/commands/shut.c | 100 + src/lib/commands/sinf.c | 97 + src/lib/commands/skyw.c | 176 ++ src/lib/commands/sona.c | 402 ++++ src/lib/commands/spy.c | 361 ++++ src/lib/commands/sstat.c | 98 + src/lib/commands/star.c | 102 + src/lib/commands/stop.c | 102 + src/lib/commands/stre.c | 161 ++ src/lib/commands/strv.c | 271 +++ src/lib/commands/supp.c | 77 + src/lib/commands/surv.c | 166 ++ src/lib/commands/swap.c | 111 + src/lib/commands/tele.c | 135 ++ src/lib/commands/tend.c | 378 ++++ src/lib/commands/terr.c | 100 + src/lib/commands/thre.c | 109 + src/lib/commands/togg.c | 110 + src/lib/commands/torp.c | 487 +++++ src/lib/commands/trad.c | 601 ++++++ src/lib/commands/tran.c | 344 +++ src/lib/commands/trea.c | 63 + src/lib/commands/turn.c | 89 + src/lib/commands/upda.c | 187 ++ src/lib/commands/upgr.c | 386 ++++ src/lib/commands/vers.c | 258 +++ src/lib/commands/wai.c | 60 + src/lib/commands/wing.c | 77 + src/lib/commands/wipe.c | 64 + src/lib/commands/work.c | 190 ++ src/lib/commands/zdon.c | 145 ++ src/lib/common/Makefile | 67 + src/lib/common/bestpath.c | 322 +++ src/lib/common/bridgefall.c | 167 ++ src/lib/common/check.c | 165 ++ src/lib/common/damage.c | 199 ++ src/lib/common/file.c | 494 +++++ src/lib/common/fsize.c | 92 + src/lib/common/getvar.c | 118 ++ src/lib/common/hap_fact.c | 66 + src/lib/common/hours.c | 100 + src/lib/common/keyword.c | 199 ++ src/lib/common/land.c | 98 + src/lib/common/log.c | 164 ++ src/lib/common/mailbox.c | 45 + src/lib/common/maps.c | 420 ++++ src/lib/common/move.c | 75 + src/lib/common/nat.c | 170 ++ src/lib/common/nstr_subs.c | 159 ++ src/lib/common/path.c | 541 +++++ src/lib/common/res_pop.c | 71 + src/lib/common/sectdamage.c | 141 ++ src/lib/common/snxtit_subs.c | 156 ++ src/lib/common/snxtsct_subs.c | 159 ++ src/lib/common/stmtch.c | 82 + src/lib/common/tfact.c | 89 + src/lib/common/type.c | 101 + src/lib/common/vlist.c | 284 +++ src/lib/common/wantupd.c | 399 ++++ src/lib/common/xy.c | 212 ++ src/lib/empthread/Makefile | 60 + src/lib/empthread/lwp.c | 147 ++ src/lib/empthread/ntthread.c | 728 +++++++ src/lib/empthread/pthread.c | 518 +++++ src/lib/gen/Makefile | 68 + src/lib/gen/atoip.c | 59 + src/lib/gen/atopi.c | 55 + src/lib/gen/bit.c | 206 ++ src/lib/gen/chance.c | 87 + src/lib/gen/copy.c | 83 + src/lib/gen/disassoc.c | 72 + src/lib/gen/dtable.c | 65 + src/lib/gen/emp_config.c | 679 ++++++ src/lib/gen/getstarg.c | 50 + src/lib/gen/getstring.c | 45 + src/lib/gen/hpux.c | 90 + src/lib/gen/iceil.c | 52 + src/lib/gen/inet.c | 53 + src/lib/gen/io.c | 535 +++++ src/lib/gen/io_mask.c | 113 + src/lib/gen/ioqueue.c | 456 ++++ src/lib/gen/lock.c | 140 ++ src/lib/gen/mapdist.c | 118 ++ src/lib/gen/minmax.c | 71 + src/lib/gen/numstr.c | 74 + src/lib/gen/onearg.c | 52 + src/lib/gen/parse.c | 96 + src/lib/gen/plur.c | 59 + src/lib/gen/queue.c | 65 + src/lib/gen/round.c | 52 + src/lib/gen/same.c | 45 + src/lib/gen/scthash.c | 44 + src/lib/gen/signal.c | 105 + src/lib/gen/strdup.c | 48 + src/lib/gen/strscan.c | 57 + src/lib/gen/vsprintf.c | 185 ++ src/lib/global/Makefile | 64 + src/lib/global/constants.c | 251 +++ src/lib/global/dir.c | 71 + src/lib/global/file.c | 106 + src/lib/global/init.c | 95 + src/lib/global/item.c | 63 + src/lib/global/land.c | 266 +++ src/lib/global/misc.c | 72 + src/lib/global/news.c | 229 ++ src/lib/global/nsc.c | 370 ++++ src/lib/global/nuke.c | 57 + src/lib/global/numnames.c | 48 + src/lib/global/options.c | 380 ++++ src/lib/global/path.c | 71 + src/lib/global/plane.c | 344 +++ src/lib/global/product.c | 98 + src/lib/global/sect.c | 97 + src/lib/global/ship.c | 326 +++ src/lib/global/treaty.c | 53 + src/lib/lwp/Makefile | 64 + src/lib/lwp/arch.c | 428 ++++ src/lib/lwp/lwp.c | 625 ++++++ src/lib/lwp/lwpInit.s | 76 + src/lib/lwp/lwpRestore.s | 62 + src/lib/lwp/lwpSave.s | 66 + src/lib/lwp/lwpint.h | 105 + src/lib/lwp/mipsarch.s | 71 + src/lib/lwp/misc/echo.c | 115 + src/lib/lwp/misc/lwp.h | 90 + src/lib/lwp/misc/lwp.tar.gz | Bin 0 -> 11247 bytes src/lib/lwp/misc/lwp.tex | 189 ++ src/lib/lwp/queue.c | 51 + src/lib/lwp/sel.c | 250 +++ src/lib/lwp/sem.c | 90 + src/lib/lwp/status.c | 69 + src/lib/player/Makefile | 62 + src/lib/player/accept.c | 268 +++ src/lib/player/dispatch.c | 114 + src/lib/player/empdis.c | 234 ++ src/lib/player/empmod.c | 433 ++++ src/lib/player/init_nats.c | 133 ++ src/lib/player/login.c | 327 +++ src/lib/player/nat.c | 68 + src/lib/player/player.c | 426 ++++ src/lib/player/recvclient.c | 72 + src/lib/subs/Makefile | 76 + src/lib/subs/aircombat.c | 1196 +++++++++++ src/lib/subs/askyn.c | 83 + src/lib/subs/aswplnsubs.c | 176 ++ src/lib/subs/attsub.c | 2647 +++++++++++++++++++++++ src/lib/subs/bigmap.c | 105 + src/lib/subs/border.c | 98 + src/lib/subs/bsanct.c | 78 + src/lib/subs/caploss.c | 129 ++ src/lib/subs/chkmoney.c | 76 + src/lib/subs/cnumb.c | 66 + src/lib/subs/comsub.c | 173 ++ src/lib/subs/control.c | 72 + src/lib/subs/detonate.c | 332 +++ src/lib/subs/disloan.c | 115 + src/lib/subs/distrea.c | 94 + src/lib/subs/fileinit.c | 94 + src/lib/subs/fortdef.c | 281 +++ src/lib/subs/getbit.c | 175 ++ src/lib/subs/getele.c | 115 + src/lib/subs/land.c | 173 ++ src/lib/subs/landgun.c | 88 + src/lib/subs/list.c | 314 +++ src/lib/subs/lndsub.c | 1341 ++++++++++++ src/lib/subs/lostsub.c | 118 ++ src/lib/subs/mission.c | 1712 +++++++++++++++ src/lib/subs/move.c | 375 ++++ src/lib/subs/mslsub.c | 424 ++++ src/lib/subs/mtch.c | 90 + src/lib/subs/natarg.c | 81 + src/lib/subs/neigh.c | 53 + src/lib/subs/nreport.c | 200 ++ src/lib/subs/nstr.c | 176 ++ src/lib/subs/nuke.c | 150 ++ src/lib/subs/nxtitem.c | 118 ++ src/lib/subs/nxtsct.c | 81 + src/lib/subs/paths.c | 332 +++ src/lib/subs/plane.c | 147 ++ src/lib/subs/plnsub.c | 1172 ++++++++++ src/lib/subs/pr.c | 341 +++ src/lib/subs/radmap.c | 214 ++ src/lib/subs/rej.c | 167 ++ src/lib/subs/retreat.c | 567 +++++ src/lib/subs/sarg.c | 228 ++ src/lib/subs/satmap.c | 360 ++++ src/lib/subs/sect.c | 168 ++ src/lib/subs/ship.c | 134 ++ src/lib/subs/show.c | 786 +++++++ src/lib/subs/shpsub.c | 1052 +++++++++ src/lib/subs/snxtitem.c | 136 ++ src/lib/subs/snxtsct.c | 102 + src/lib/subs/supply.c | 688 ++++++ src/lib/subs/takeover.c | 342 +++ src/lib/subs/trdsub.c | 327 +++ src/lib/subs/trechk.c | 134 ++ src/lib/subs/whatitem.c | 54 + src/lib/subs/wire.c | 89 + src/lib/subs/wu.c | 194 ++ src/lib/update/Makefile | 67 + src/lib/update/age.c | 102 + src/lib/update/anno.c | 137 ++ src/lib/update/bp.c | 97 + src/lib/update/deliver.c | 119 ++ src/lib/update/distribute.c | 223 ++ src/lib/update/finish.c | 270 +++ src/lib/update/human.c | 326 +++ src/lib/update/land.c | 439 ++++ src/lib/update/main.c | 252 +++ src/lib/update/material.c | 93 + src/lib/update/mobility.c | 563 +++++ src/lib/update/move_sat.c | 93 + src/lib/update/nat.c | 309 +++ src/lib/update/nav_ship.c | 373 ++++ src/lib/update/nav_util.c | 310 +++ src/lib/update/nxtitemp.c | 119 ++ src/lib/update/nxtsctp.c | 76 + src/lib/update/plague.c | 200 ++ src/lib/update/plane.c | 282 +++ src/lib/update/populace.c | 141 ++ src/lib/update/prepare.c | 187 ++ src/lib/update/produce.c | 237 +++ src/lib/update/removewants.c | 58 + src/lib/update/revolt.c | 595 ++++++ src/lib/update/sail.c | 352 +++ src/lib/update/sect.c | 510 +++++ src/lib/update/ship.c | 529 +++++ src/make.defs | 42 + src/make.rules | 39 + src/server/Makefile | 118 ++ src/server/idle.c | 83 + src/server/lostitem.c | 75 + src/server/main.c | 486 +++++ src/server/marketup.c | 87 + src/server/shutdown.c | 96 + src/server/timestamp.c | 141 ++ src/server/update.c | 152 ++ src/util/Makefile | 127 ++ src/util/README | 4 + src/util/fairland.c | 1252 +++++++++++ src/util/files.c | 262 +++ src/util/land.c | 410 ++++ src/util/ore.c | 409 ++++ src/util/pconfig.c | 49 + src/util/perfect.c | 288 +++ 817 files changed, 126589 insertions(+) create mode 100644 COPYING create mode 100644 CREDITS create mode 100644 LEGAL create mode 100644 LICENSE create mode 100644 Make.sysdefs create mode 100644 Makefile create mode 100644 README create mode 100644 build.conf create mode 100644 doc/CHANGES create mode 100644 doc/CHANGES2.3 create mode 100644 doc/CHANGES3.0 create mode 100644 doc/CHANGES4.X create mode 100644 doc/README create mode 100644 doc/WACKY_IDEAS create mode 100644 doc/WISH_LIST create mode 100644 doc/backups create mode 100644 doc/bug-reports create mode 100644 doc/coding create mode 100644 doc/compiling create mode 100644 doc/configuration create mode 100644 doc/debugging create mode 100644 doc/disk_space create mode 100644 doc/econfig create mode 100644 doc/files create mode 100644 doc/message create mode 100644 doc/pthreads create mode 100644 doc/threads create mode 100644 doc/troubleshooting create mode 100644 include/bit.h create mode 100644 include/budg.h create mode 100644 include/com.h create mode 100644 include/combat.h create mode 100644 include/commands.h create mode 100644 include/commodity.h create mode 100644 include/common.h create mode 100644 include/damage.h create mode 100644 include/deity.h create mode 100644 include/distribute.h create mode 100644 include/empio.h create mode 100644 include/empthread.h create mode 100644 include/event.h create mode 100644 include/file.h create mode 100644 include/gen.h create mode 100644 include/genitem.h create mode 100644 include/global.h create mode 100644 include/io_mask.h create mode 100644 include/ioqueue.h create mode 100644 include/item.h create mode 100644 include/keyword.h create mode 100644 include/land.h create mode 100644 include/loan.h create mode 100644 include/lost.h create mode 100644 include/lwp.h create mode 100644 include/map.h create mode 100644 include/match.h create mode 100644 include/misc.h create mode 100644 include/mission.h create mode 100644 include/nat.h create mode 100644 include/news.h create mode 100644 include/nsc.h create mode 100644 include/nuke.h create mode 100644 include/options.h create mode 100644 include/optlist.h create mode 100644 include/path.h create mode 100644 include/plane.h create mode 100644 include/player.h create mode 100644 include/power.h create mode 100644 include/product.h create mode 100644 include/proto.h create mode 100644 include/prototype.h create mode 100644 include/prototypes.h create mode 100644 include/queue.h create mode 100644 include/retreat.h create mode 100644 include/sect.h create mode 100644 include/ship.h create mode 100644 include/struct.h create mode 100644 include/subs.h create mode 100644 include/tel.h create mode 100644 include/trade.h create mode 100644 include/treaty.h create mode 100644 include/update.h create mode 100644 include/user.h create mode 100644 include/var.h create mode 100644 include/version.h create mode 100644 include/wantupd.h create mode 100644 include/xy.h create mode 100644 info/Blank.awk create mode 100644 info/CRT.MAC create mode 100644 info/Commands/MakeSrcs create mode 100644 info/Commands/Makefile create mode 100644 info/Commands/accept.t create mode 100644 info/Commands/add.t create mode 100644 info/Commands/announce.t create mode 100644 info/Commands/anti.t create mode 100644 info/Commands/apropos.t create mode 100644 info/Commands/arm.t create mode 100644 info/Commands/army.t create mode 100644 info/Commands/assault.t create mode 100644 info/Commands/attack.t create mode 100644 info/Commands/bdes.t create mode 100644 info/Commands/bestdistpath.t create mode 100644 info/Commands/bestpath.t create mode 100644 info/Commands/bmap.t create mode 100644 info/Commands/board.t create mode 100644 info/Commands/bomb.t create mode 100644 info/Commands/break.t create mode 100644 info/Commands/budget.t create mode 100644 info/Commands/build.t create mode 100644 info/Commands/buy.t create mode 100644 info/Commands/bye.t create mode 100644 info/Commands/capital.t create mode 100644 info/Commands/cargo.t create mode 100644 info/Commands/cede.t create mode 100644 info/Commands/census.t create mode 100644 info/Commands/change.t create mode 100644 info/Commands/coastwatch.t create mode 100644 info/Commands/collect.t create mode 100644 info/Commands/commodity.t create mode 100644 info/Commands/consider.t create mode 100644 info/Commands/convert.t create mode 100644 info/Commands/country.t create mode 100644 info/Commands/cutoff.t create mode 100644 info/Commands/declare.t create mode 100644 info/Commands/deliver.t create mode 100644 info/Commands/demobilize.t create mode 100644 info/Commands/designate.t create mode 100644 info/Commands/disable.t create mode 100644 info/Commands/disarm.t create mode 100644 info/Commands/dissolve.t create mode 100644 info/Commands/distribute.t create mode 100644 info/Commands/drop.t create mode 100644 info/Commands/dump.t create mode 100644 info/Commands/echo.t create mode 100644 info/Commands/edit.t create mode 100644 info/Commands/enable.t create mode 100644 info/Commands/enlist.t create mode 100644 info/Commands/execute.t create mode 100644 info/Commands/explore.t create mode 100644 info/Commands/financial.t create mode 100644 info/Commands/fire.t create mode 100644 info/Commands/flash.t create mode 100644 info/Commands/fleetadd.t create mode 100644 info/Commands/fly.t create mode 100644 info/Commands/follow.t create mode 100644 info/Commands/force.t create mode 100644 info/Commands/fortify.t create mode 100644 info/Commands/fuel.t create mode 100644 info/Commands/give.t create mode 100644 info/Commands/grind.t create mode 100644 info/Commands/harden.t create mode 100644 info/Commands/headlines.t create mode 100644 info/Commands/hidden.t create mode 100644 info/Commands/improve.t create mode 100644 info/Commands/info.t create mode 100644 info/Commands/land.t create mode 100644 info/Commands/launch.t create mode 100644 info/Commands/lboard.t create mode 100644 info/Commands/lcargo.t create mode 100644 info/Commands/ldump.t create mode 100644 info/Commands/ledger.t create mode 100644 info/Commands/level.t create mode 100644 info/Commands/list.t create mode 100644 info/Commands/lload.t create mode 100644 info/Commands/llookout.t create mode 100644 info/Commands/lmap.t create mode 100644 info/Commands/lmine.t create mode 100644 info/Commands/load.t create mode 100644 info/Commands/lookout.t create mode 100644 info/Commands/lost.t create mode 100644 info/Commands/lradar.t create mode 100644 info/Commands/lrange.t create mode 100644 info/Commands/lretreat.t create mode 100644 info/Commands/lstat.t create mode 100644 info/Commands/ltend.t create mode 100644 info/Commands/lunload.t create mode 100644 info/Commands/map.t create mode 100644 info/Commands/march.t create mode 100644 info/Commands/market.t create mode 100644 info/Commands/mine.t create mode 100644 info/Commands/mission.t create mode 100644 info/Commands/mobupdate.t create mode 100644 info/Commands/morale.t create mode 100644 info/Commands/motd.t create mode 100644 info/Commands/move.t create mode 100644 info/Commands/mquota.t create mode 100644 info/Commands/mult.t create mode 100644 info/Commands/name.t create mode 100644 info/Commands/nation.t create mode 100644 info/Commands/navigate.t create mode 100644 info/Commands/ndump.t create mode 100644 info/Commands/newcap.t create mode 100644 info/Commands/neweff.t create mode 100644 info/Commands/newspaper.t create mode 100644 info/Commands/nmap.t create mode 100644 info/Commands/nuke.t create mode 100644 info/Commands/offer.t create mode 100644 info/Commands/offset.t create mode 100644 info/Commands/order.t create mode 100644 info/Commands/origin.t create mode 100644 info/Commands/paradrop.t create mode 100644 info/Commands/path.t create mode 100644 info/Commands/payoff.t create mode 100644 info/Commands/pboard.t create mode 100644 info/Commands/pdump.t create mode 100644 info/Commands/plane.t create mode 100644 info/Commands/players.t create mode 100644 info/Commands/pmap.t create mode 100644 info/Commands/power.t create mode 100644 info/Commands/pray.t create mode 100644 info/Commands/production.t create mode 100644 info/Commands/pstat.t create mode 100644 info/Commands/qorder.t create mode 100644 info/Commands/quit.t create mode 100644 info/Commands/radar.t create mode 100644 info/Commands/range.t create mode 100644 info/Commands/read.t create mode 100644 info/Commands/realm.t create mode 100644 info/Commands/recon.t create mode 100644 info/Commands/reject.t create mode 100644 info/Commands/relations.t create mode 100644 info/Commands/repay.t create mode 100644 info/Commands/report.t create mode 100644 info/Commands/reset.t create mode 100644 info/Commands/resource.t create mode 100644 info/Commands/retreat.t create mode 100644 info/Commands/route.t create mode 100644 info/Commands/sabotage.t create mode 100644 info/Commands/sail.t create mode 100644 info/Commands/satellite.t create mode 100644 info/Commands/scrap.t create mode 100644 info/Commands/scuttle.t create mode 100644 info/Commands/sdump.t create mode 100644 info/Commands/sect.t create mode 100644 info/Commands/sell.t create mode 100644 info/Commands/set.t create mode 100644 info/Commands/setresource.t create mode 100644 info/Commands/setsector.t create mode 100644 info/Commands/sharebmap.t create mode 100644 info/Commands/shark.t create mode 100644 info/Commands/ship.t create mode 100644 info/Commands/shoot.t create mode 100644 info/Commands/show.t create mode 100644 info/Commands/shutdown.t create mode 100644 info/Commands/sinfrastructure.t create mode 100644 info/Commands/skywatch.t create mode 100644 info/Commands/smap.t create mode 100644 info/Commands/sonar.t create mode 100644 info/Commands/sorder.t create mode 100644 info/Commands/spy.t create mode 100644 info/Commands/sstat.t create mode 100644 info/Commands/start.t create mode 100644 info/Commands/starvation.t create mode 100644 info/Commands/stop.t create mode 100644 info/Commands/strength.t create mode 100644 info/Commands/supply.t create mode 100644 info/Commands/survey.t create mode 100644 info/Commands/swapsector.t create mode 100644 info/Commands/sweep.t create mode 100644 info/Commands/telegram.t create mode 100644 info/Commands/tend.t create mode 100644 info/Commands/territory.t create mode 100644 info/Commands/test.t create mode 100644 info/Commands/threshold.t create mode 100644 info/Commands/toggle.t create mode 100644 info/Commands/torpedo.t create mode 100644 info/Commands/trade.t create mode 100644 info/Commands/transport.t create mode 100644 info/Commands/treaty.t create mode 100644 info/Commands/turn.t create mode 100644 info/Commands/unload.t create mode 100644 info/Commands/unsail.t create mode 100644 info/Commands/update.t create mode 100644 info/Commands/upgrade.t create mode 100644 info/Commands/version.t create mode 100644 info/Commands/wait.t create mode 100644 info/Commands/wall.t create mode 100644 info/Commands/wingadd.t create mode 100644 info/Commands/wipe.t create mode 100644 info/Commands/wire.t create mode 100644 info/Commands/work.t create mode 100644 info/Commands/zdone.t create mode 100644 info/Concepts/Attack.t create mode 100644 info/Concepts/Autofeed.t create mode 100644 info/Concepts/Autonav.t create mode 100644 info/Concepts/BTU.t create mode 100644 info/Concepts/Bridges.t create mode 100644 info/Concepts/Citizens.t create mode 100644 info/Concepts/Damage.t create mode 100644 info/Concepts/Education.t create mode 100644 info/Concepts/Fallout.t create mode 100644 info/Concepts/Flak.t create mode 100644 info/Concepts/Food.t create mode 100644 info/Concepts/Guerrilla.t create mode 100644 info/Concepts/Happiness.t create mode 100644 info/Concepts/Hitchance.t create mode 100644 info/Concepts/Infrastructure.t create mode 100644 info/Concepts/Innards.t create mode 100644 info/Concepts/Interception.t create mode 100644 info/Concepts/Land-units.t create mode 100644 info/Concepts/Maintenance.t create mode 100644 info/Concepts/MakeSrcs create mode 100644 info/Concepts/Makefile create mode 100644 info/Concepts/Mobility.t create mode 100644 info/Concepts/Move.t create mode 100644 info/Concepts/Nuke-types.t create mode 100644 info/Concepts/Plague.t create mode 100644 info/Concepts/Plane-types.t create mode 100644 info/Concepts/Products.t create mode 100644 info/Concepts/Quick-ref.t create mode 100644 info/Concepts/Research.t create mode 100644 info/Concepts/Sector-ownership.t create mode 100644 info/Concepts/Sector-types.t create mode 100644 info/Concepts/Selector.t create mode 100644 info/Concepts/Ship-types.t create mode 100644 info/Concepts/Spies.t create mode 100644 info/Concepts/Syntax.t create mode 100644 info/Concepts/Taxes.t create mode 100644 info/Concepts/Technology.t create mode 100644 info/Concepts/Time.t create mode 100644 info/Concepts/Trade-ships.t create mode 100644 info/Concepts/Unit-types.t create mode 100644 info/Concepts/Update-sequence.t create mode 100644 info/INFO.MAC create mode 100644 info/Introduction/Basics.t create mode 100644 info/Introduction/Clients.t create mode 100644 info/Introduction/Expert.t create mode 100644 info/Introduction/Guide.t create mode 100644 info/Introduction/Hints.t create mode 100644 info/Introduction/Kill.t create mode 100644 info/Introduction/MakeSrcs create mode 100644 info/Introduction/Makefile create mode 100644 info/Introduction/Novice.t create mode 100644 info/Introduction/Overview.t create mode 100644 info/Introduction/Suggestions.t create mode 100644 info/Makefile create mode 100644 info/README create mode 100644 info/Server/Bugs.t create mode 100644 info/Server/CHANGES.CHAINSAW.t create mode 100644 info/Server/Empire2.t create mode 100644 info/Server/Empire3.t create mode 100644 info/Server/Empire4.t create mode 100644 info/Server/God.t create mode 100644 info/Server/Hidden.t create mode 100644 info/Server/History.t create mode 100644 info/Server/MakeSrcs create mode 100644 info/Server/Makefile create mode 100644 info/Server/Merc.t create mode 100644 info/Server/Old-empire.t create mode 100644 info/Server/Options.t create mode 100644 info/Server/Wolfpack.t create mode 100644 info/Subjects/MakeSrcs create mode 100644 info/Subjects/Makefile create mode 100644 info/TROFF.MAC create mode 100644 info/checklist.pl create mode 100644 info/deity.list create mode 100644 info/emp2html.pl create mode 100644 info/info.pl create mode 100644 info/ls2html.pl create mode 100644 info/player.list create mode 100644 info/subj2html.pl create mode 100644 man/emp_client.6 create mode 100644 man/emp_server.6 create mode 100644 man/fairland.1 create mode 100644 man/files.1 create mode 100644 man/land.1 create mode 100644 man/ore.1 create mode 100644 man/pconfig.1 create mode 100644 man/perfect.1 create mode 100644 scripts/README create mode 100644 scripts/bigstart create mode 100644 scripts/blitz/README create mode 100644 scripts/blitz/crontab.config create mode 100644 scripts/blitz/motd create mode 100644 scripts/blitz/setup-blitz create mode 100644 scripts/blitz/start-blitz create mode 100644 scripts/crontab.config create mode 100644 scripts/keepitup create mode 100644 scripts/mapper/Makefile create mode 100644 scripts/mapper/README create mode 100644 scripts/mapper/archive.pl create mode 100644 scripts/mapper/cleanup create mode 100644 scripts/mapper/crontab.config create mode 100644 scripts/mapper/default.param create mode 100644 scripts/mapper/makeframe create mode 100644 scripts/mapper/makempeg create mode 100644 scripts/mapper/map.param create mode 100644 scripts/mapper/mapper create mode 100644 scripts/mapper/over.awk create mode 100644 scripts/mapper/over2.pbm create mode 100644 scripts/mapper/param.pl create mode 100644 scripts/mapper/pgmmap.awk create mode 100644 scripts/mapper/randppm.awk create mode 100644 scripts/mapper/text.pbm create mode 100644 scripts/mapper/text.size create mode 100644 scripts/postresults create mode 100644 scripts/saveass create mode 100644 src/client/Makefile create mode 100644 src/client/Makefile.server create mode 100644 src/client/Makefile.standalone create mode 100644 src/client/README create mode 100644 src/client/bit.c create mode 100644 src/client/bit.h create mode 100644 src/client/dtable.c create mode 100644 src/client/empire.6 create mode 100644 src/client/expect.c create mode 100644 src/client/fnlist.h create mode 100644 src/client/globals.c create mode 100644 src/client/h.h create mode 100644 src/client/handle.c create mode 100644 src/client/host.c create mode 100644 src/client/hpux.c create mode 100644 src/client/ioqueue.c create mode 100644 src/client/ioqueue.h create mode 100644 src/client/login.c create mode 100644 src/client/main.c create mode 100644 src/client/misc.h create mode 100644 src/client/proto.h create mode 100644 src/client/queue.c create mode 100644 src/client/queue.h create mode 100644 src/client/saveargv.c create mode 100644 src/client/servcmd.c create mode 100644 src/client/serverio.c create mode 100644 src/client/tags.c create mode 100644 src/client/tags.h create mode 100644 src/client/termio.c create mode 100644 src/client/termlib.c create mode 100644 src/doconfig/Makefile create mode 100644 src/doconfig/doconfig.c create mode 100644 src/lib/as/COPYRIGHT create mode 100644 src/lib/as/Makefile create mode 100644 src/lib/as/README create mode 100644 src/lib/as/as.h create mode 100644 src/lib/as/as_cache.c create mode 100644 src/lib/as/as_costcomp.c create mode 100644 src/lib/as/as_delete.c create mode 100644 src/lib/as/as_extend.c create mode 100644 src/lib/as/as_hash.c create mode 100644 src/lib/as/as_init.c create mode 100644 src/lib/as/as_merge.c create mode 100644 src/lib/as/as_search.c create mode 100644 src/lib/as/as_stats.c create mode 100644 src/lib/as/as_winnow.c create mode 100644 src/lib/commands/Makefile create mode 100644 src/lib/commands/acce.c create mode 100644 src/lib/commands/add.c create mode 100644 src/lib/commands/anti.c create mode 100644 src/lib/commands/arm.c create mode 100644 src/lib/commands/army.c create mode 100644 src/lib/commands/assa.c create mode 100644 src/lib/commands/atta.c create mode 100644 src/lib/commands/bdes.c create mode 100644 src/lib/commands/best.c create mode 100644 src/lib/commands/boar.c create mode 100644 src/lib/commands/bomb.c create mode 100644 src/lib/commands/brea.c create mode 100644 src/lib/commands/budg.c create mode 100644 src/lib/commands/buil.c create mode 100644 src/lib/commands/buy.c create mode 100644 src/lib/commands/capi.c create mode 100644 src/lib/commands/carg.c create mode 100644 src/lib/commands/cede.c create mode 100644 src/lib/commands/cens.c create mode 100644 src/lib/commands/chan.c create mode 100644 src/lib/commands/coas.c create mode 100644 src/lib/commands/coll.c create mode 100644 src/lib/commands/comm.c create mode 100644 src/lib/commands/cons.c create mode 100644 src/lib/commands/conv.c create mode 100644 src/lib/commands/coun.c create mode 100644 src/lib/commands/cuto.c create mode 100644 src/lib/commands/decl.c create mode 100644 src/lib/commands/deli.c create mode 100644 src/lib/commands/demo.c create mode 100644 src/lib/commands/desi.c create mode 100644 src/lib/commands/disa.c create mode 100644 src/lib/commands/diss.c create mode 100644 src/lib/commands/dist.c create mode 100644 src/lib/commands/drop.c create mode 100644 src/lib/commands/dump.c create mode 100644 src/lib/commands/echo.c create mode 100644 src/lib/commands/edit.c create mode 100644 src/lib/commands/enab.c create mode 100644 src/lib/commands/enli.c create mode 100644 src/lib/commands/expl.c create mode 100644 src/lib/commands/fina.c create mode 100644 src/lib/commands/flash.c create mode 100644 src/lib/commands/flee.c create mode 100644 src/lib/commands/fly.c create mode 100644 src/lib/commands/foll.c create mode 100644 src/lib/commands/forc.c create mode 100644 src/lib/commands/fort.c create mode 100644 src/lib/commands/fuel.c create mode 100644 src/lib/commands/give.c create mode 100644 src/lib/commands/grin.c create mode 100644 src/lib/commands/hard.c create mode 100644 src/lib/commands/head.c create mode 100644 src/lib/commands/hidd.c create mode 100644 src/lib/commands/improve.c create mode 100644 src/lib/commands/info.c create mode 100644 src/lib/commands/land.c create mode 100644 src/lib/commands/laun.c create mode 100644 src/lib/commands/lboard.c create mode 100644 src/lib/commands/ldump.c create mode 100644 src/lib/commands/ledg.c create mode 100644 src/lib/commands/leve.c create mode 100644 src/lib/commands/load.c create mode 100644 src/lib/commands/look.c create mode 100644 src/lib/commands/lost.c create mode 100644 src/lib/commands/lstat.c create mode 100644 src/lib/commands/lten.c create mode 100644 src/lib/commands/map.c create mode 100644 src/lib/commands/marc.c create mode 100644 src/lib/commands/mark.c create mode 100644 src/lib/commands/mfir.c create mode 100644 src/lib/commands/mine.c create mode 100644 src/lib/commands/miss.c create mode 100644 src/lib/commands/mobq.c create mode 100644 src/lib/commands/mobu.c create mode 100644 src/lib/commands/mora.c create mode 100644 src/lib/commands/move.c create mode 100644 src/lib/commands/mult.c create mode 100644 src/lib/commands/name.c create mode 100644 src/lib/commands/nati.c create mode 100644 src/lib/commands/navi.c create mode 100644 src/lib/commands/ndump.c create mode 100644 src/lib/commands/new.c create mode 100644 src/lib/commands/newe.c create mode 100644 src/lib/commands/news.c create mode 100644 src/lib/commands/nuke.c create mode 100644 src/lib/commands/offe.c create mode 100644 src/lib/commands/offs.c create mode 100644 src/lib/commands/orde.c create mode 100644 src/lib/commands/orig.c create mode 100644 src/lib/commands/para.c create mode 100644 src/lib/commands/path.c create mode 100644 src/lib/commands/payo.c create mode 100644 src/lib/commands/pboa.c create mode 100644 src/lib/commands/pdump.c create mode 100644 src/lib/commands/plan.c create mode 100644 src/lib/commands/play.c create mode 100644 src/lib/commands/powe.c create mode 100644 src/lib/commands/prod.c create mode 100644 src/lib/commands/pstat.c create mode 100644 src/lib/commands/rada.c create mode 100644 src/lib/commands/rang.c create mode 100644 src/lib/commands/rea.c create mode 100644 src/lib/commands/real.c create mode 100644 src/lib/commands/reco.c create mode 100644 src/lib/commands/reje.c create mode 100644 src/lib/commands/rela.c create mode 100644 src/lib/commands/repa.c create mode 100644 src/lib/commands/repo.c create mode 100644 src/lib/commands/rese.c create mode 100644 src/lib/commands/reso.c create mode 100644 src/lib/commands/retr.c create mode 100644 src/lib/commands/rout.c create mode 100644 src/lib/commands/sabo.c create mode 100644 src/lib/commands/sail.c create mode 100644 src/lib/commands/sate.c create mode 100644 src/lib/commands/scra.c create mode 100644 src/lib/commands/scut.c create mode 100644 src/lib/commands/sdump.c create mode 100644 src/lib/commands/sect.c create mode 100644 src/lib/commands/sell.c create mode 100644 src/lib/commands/set.c create mode 100644 src/lib/commands/setres.c create mode 100644 src/lib/commands/setsect.c create mode 100644 src/lib/commands/shar.c create mode 100644 src/lib/commands/shark.c create mode 100644 src/lib/commands/shi.c create mode 100644 src/lib/commands/shoo.c create mode 100644 src/lib/commands/show.c create mode 100644 src/lib/commands/shut.c create mode 100644 src/lib/commands/sinf.c create mode 100644 src/lib/commands/skyw.c create mode 100644 src/lib/commands/sona.c create mode 100644 src/lib/commands/spy.c create mode 100644 src/lib/commands/sstat.c create mode 100644 src/lib/commands/star.c create mode 100644 src/lib/commands/stop.c create mode 100644 src/lib/commands/stre.c create mode 100644 src/lib/commands/strv.c create mode 100644 src/lib/commands/supp.c create mode 100644 src/lib/commands/surv.c create mode 100644 src/lib/commands/swap.c create mode 100644 src/lib/commands/tele.c create mode 100644 src/lib/commands/tend.c create mode 100644 src/lib/commands/terr.c create mode 100644 src/lib/commands/thre.c create mode 100644 src/lib/commands/togg.c create mode 100644 src/lib/commands/torp.c create mode 100644 src/lib/commands/trad.c create mode 100644 src/lib/commands/tran.c create mode 100644 src/lib/commands/trea.c create mode 100644 src/lib/commands/turn.c create mode 100644 src/lib/commands/upda.c create mode 100644 src/lib/commands/upgr.c create mode 100644 src/lib/commands/vers.c create mode 100644 src/lib/commands/wai.c create mode 100644 src/lib/commands/wing.c create mode 100644 src/lib/commands/wipe.c create mode 100644 src/lib/commands/work.c create mode 100644 src/lib/commands/zdon.c create mode 100644 src/lib/common/Makefile create mode 100644 src/lib/common/bestpath.c create mode 100644 src/lib/common/bridgefall.c create mode 100644 src/lib/common/check.c create mode 100644 src/lib/common/damage.c create mode 100644 src/lib/common/file.c create mode 100644 src/lib/common/fsize.c create mode 100644 src/lib/common/getvar.c create mode 100644 src/lib/common/hap_fact.c create mode 100644 src/lib/common/hours.c create mode 100644 src/lib/common/keyword.c create mode 100644 src/lib/common/land.c create mode 100644 src/lib/common/log.c create mode 100644 src/lib/common/mailbox.c create mode 100644 src/lib/common/maps.c create mode 100644 src/lib/common/move.c create mode 100644 src/lib/common/nat.c create mode 100644 src/lib/common/nstr_subs.c create mode 100644 src/lib/common/path.c create mode 100644 src/lib/common/res_pop.c create mode 100644 src/lib/common/sectdamage.c create mode 100644 src/lib/common/snxtit_subs.c create mode 100644 src/lib/common/snxtsct_subs.c create mode 100644 src/lib/common/stmtch.c create mode 100644 src/lib/common/tfact.c create mode 100644 src/lib/common/type.c create mode 100644 src/lib/common/vlist.c create mode 100644 src/lib/common/wantupd.c create mode 100644 src/lib/common/xy.c create mode 100644 src/lib/empthread/Makefile create mode 100644 src/lib/empthread/lwp.c create mode 100644 src/lib/empthread/ntthread.c create mode 100644 src/lib/empthread/pthread.c create mode 100644 src/lib/gen/Makefile create mode 100644 src/lib/gen/atoip.c create mode 100644 src/lib/gen/atopi.c create mode 100644 src/lib/gen/bit.c create mode 100644 src/lib/gen/chance.c create mode 100644 src/lib/gen/copy.c create mode 100644 src/lib/gen/disassoc.c create mode 100644 src/lib/gen/dtable.c create mode 100644 src/lib/gen/emp_config.c create mode 100644 src/lib/gen/getstarg.c create mode 100644 src/lib/gen/getstring.c create mode 100644 src/lib/gen/hpux.c create mode 100644 src/lib/gen/iceil.c create mode 100644 src/lib/gen/inet.c create mode 100644 src/lib/gen/io.c create mode 100644 src/lib/gen/io_mask.c create mode 100644 src/lib/gen/ioqueue.c create mode 100644 src/lib/gen/lock.c create mode 100644 src/lib/gen/mapdist.c create mode 100644 src/lib/gen/minmax.c create mode 100644 src/lib/gen/numstr.c create mode 100644 src/lib/gen/onearg.c create mode 100644 src/lib/gen/parse.c create mode 100644 src/lib/gen/plur.c create mode 100644 src/lib/gen/queue.c create mode 100644 src/lib/gen/round.c create mode 100644 src/lib/gen/same.c create mode 100644 src/lib/gen/scthash.c create mode 100644 src/lib/gen/signal.c create mode 100644 src/lib/gen/strdup.c create mode 100644 src/lib/gen/strscan.c create mode 100644 src/lib/gen/vsprintf.c create mode 100644 src/lib/global/Makefile create mode 100644 src/lib/global/constants.c create mode 100644 src/lib/global/dir.c create mode 100644 src/lib/global/file.c create mode 100644 src/lib/global/init.c create mode 100644 src/lib/global/item.c create mode 100644 src/lib/global/land.c create mode 100644 src/lib/global/misc.c create mode 100644 src/lib/global/news.c create mode 100644 src/lib/global/nsc.c create mode 100644 src/lib/global/nuke.c create mode 100644 src/lib/global/numnames.c create mode 100644 src/lib/global/options.c create mode 100644 src/lib/global/path.c create mode 100644 src/lib/global/plane.c create mode 100644 src/lib/global/product.c create mode 100644 src/lib/global/sect.c create mode 100644 src/lib/global/ship.c create mode 100644 src/lib/global/treaty.c create mode 100644 src/lib/lwp/Makefile create mode 100644 src/lib/lwp/arch.c create mode 100644 src/lib/lwp/lwp.c create mode 100644 src/lib/lwp/lwpInit.s create mode 100644 src/lib/lwp/lwpRestore.s create mode 100644 src/lib/lwp/lwpSave.s create mode 100644 src/lib/lwp/lwpint.h create mode 100644 src/lib/lwp/mipsarch.s create mode 100644 src/lib/lwp/misc/echo.c create mode 100644 src/lib/lwp/misc/lwp.h create mode 100644 src/lib/lwp/misc/lwp.tar.gz create mode 100644 src/lib/lwp/misc/lwp.tex create mode 100644 src/lib/lwp/queue.c create mode 100644 src/lib/lwp/sel.c create mode 100644 src/lib/lwp/sem.c create mode 100644 src/lib/lwp/status.c create mode 100644 src/lib/player/Makefile create mode 100644 src/lib/player/accept.c create mode 100644 src/lib/player/dispatch.c create mode 100644 src/lib/player/empdis.c create mode 100644 src/lib/player/empmod.c create mode 100644 src/lib/player/init_nats.c create mode 100644 src/lib/player/login.c create mode 100644 src/lib/player/nat.c create mode 100644 src/lib/player/player.c create mode 100644 src/lib/player/recvclient.c create mode 100644 src/lib/subs/Makefile create mode 100644 src/lib/subs/aircombat.c create mode 100644 src/lib/subs/askyn.c create mode 100644 src/lib/subs/aswplnsubs.c create mode 100644 src/lib/subs/attsub.c create mode 100644 src/lib/subs/bigmap.c create mode 100644 src/lib/subs/border.c create mode 100644 src/lib/subs/bsanct.c create mode 100644 src/lib/subs/caploss.c create mode 100644 src/lib/subs/chkmoney.c create mode 100644 src/lib/subs/cnumb.c create mode 100644 src/lib/subs/comsub.c create mode 100644 src/lib/subs/control.c create mode 100644 src/lib/subs/detonate.c create mode 100644 src/lib/subs/disloan.c create mode 100644 src/lib/subs/distrea.c create mode 100644 src/lib/subs/fileinit.c create mode 100644 src/lib/subs/fortdef.c create mode 100644 src/lib/subs/getbit.c create mode 100644 src/lib/subs/getele.c create mode 100644 src/lib/subs/land.c create mode 100644 src/lib/subs/landgun.c create mode 100644 src/lib/subs/list.c create mode 100644 src/lib/subs/lndsub.c create mode 100644 src/lib/subs/lostsub.c create mode 100644 src/lib/subs/mission.c create mode 100644 src/lib/subs/move.c create mode 100644 src/lib/subs/mslsub.c create mode 100644 src/lib/subs/mtch.c create mode 100644 src/lib/subs/natarg.c create mode 100644 src/lib/subs/neigh.c create mode 100644 src/lib/subs/nreport.c create mode 100644 src/lib/subs/nstr.c create mode 100644 src/lib/subs/nuke.c create mode 100644 src/lib/subs/nxtitem.c create mode 100644 src/lib/subs/nxtsct.c create mode 100644 src/lib/subs/paths.c create mode 100644 src/lib/subs/plane.c create mode 100644 src/lib/subs/plnsub.c create mode 100644 src/lib/subs/pr.c create mode 100644 src/lib/subs/radmap.c create mode 100644 src/lib/subs/rej.c create mode 100644 src/lib/subs/retreat.c create mode 100644 src/lib/subs/sarg.c create mode 100644 src/lib/subs/satmap.c create mode 100644 src/lib/subs/sect.c create mode 100644 src/lib/subs/ship.c create mode 100644 src/lib/subs/show.c create mode 100644 src/lib/subs/shpsub.c create mode 100644 src/lib/subs/snxtitem.c create mode 100644 src/lib/subs/snxtsct.c create mode 100644 src/lib/subs/supply.c create mode 100644 src/lib/subs/takeover.c create mode 100644 src/lib/subs/trdsub.c create mode 100644 src/lib/subs/trechk.c create mode 100644 src/lib/subs/whatitem.c create mode 100644 src/lib/subs/wire.c create mode 100644 src/lib/subs/wu.c create mode 100644 src/lib/update/Makefile create mode 100644 src/lib/update/age.c create mode 100644 src/lib/update/anno.c create mode 100644 src/lib/update/bp.c create mode 100644 src/lib/update/deliver.c create mode 100644 src/lib/update/distribute.c create mode 100644 src/lib/update/finish.c create mode 100644 src/lib/update/human.c create mode 100644 src/lib/update/land.c create mode 100644 src/lib/update/main.c create mode 100644 src/lib/update/material.c create mode 100644 src/lib/update/mobility.c create mode 100644 src/lib/update/move_sat.c create mode 100644 src/lib/update/nat.c create mode 100644 src/lib/update/nav_ship.c create mode 100644 src/lib/update/nav_util.c create mode 100644 src/lib/update/nxtitemp.c create mode 100644 src/lib/update/nxtsctp.c create mode 100644 src/lib/update/plague.c create mode 100644 src/lib/update/plane.c create mode 100644 src/lib/update/populace.c create mode 100644 src/lib/update/prepare.c create mode 100644 src/lib/update/produce.c create mode 100644 src/lib/update/removewants.c create mode 100644 src/lib/update/revolt.c create mode 100644 src/lib/update/sail.c create mode 100644 src/lib/update/sect.c create mode 100644 src/lib/update/ship.c create mode 100644 src/make.defs create mode 100644 src/make.rules create mode 100644 src/server/Makefile create mode 100644 src/server/idle.c create mode 100644 src/server/lostitem.c create mode 100644 src/server/main.c create mode 100644 src/server/marketup.c create mode 100644 src/server/shutdown.c create mode 100644 src/server/timestamp.c create mode 100644 src/server/update.c create mode 100644 src/util/Makefile create mode 100644 src/util/README create mode 100644 src/util/fairland.c create mode 100644 src/util/files.c create mode 100644 src/util/land.c create mode 100644 src/util/ore.c create mode 100644 src/util/pconfig.c create mode 100644 src/util/perfect.c diff --git a/COPYING b/COPYING new file mode 100644 index 000000000..4e19bc563 --- /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 000000000..992647e64 --- /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 000000000..ca0fef50a --- /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 000000000..60549be51 --- /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 000000000..33674ba68 --- /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 000000000..49f44e375 --- /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 000000000..733988709 --- /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 000000000..aa0a18e5d --- /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 000000000..625343ac7 --- /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 000000000..babcbec4e --- /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 000000000..fa0975795 --- /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 000000000..1115ce116 --- /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 000000000..1807db71d --- /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 000000000..faa8ebc9c --- /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 000000000..664fc43dc --- /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 000000000..53f99fd05 --- /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 000000000..db4120d81 --- /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 000000000..7083c3b2c --- /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 000000000..275392b4b --- /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 000000000..d18e2663c --- /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 000000000..357b6ce00 --- /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 000000000..91faaba5f --- /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 000000000..b9902cc2f --- /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 000000000..b4b1d55fb --- /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 000000000..a476998b5 --- /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 000000000..ecdd4108e --- /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 000000000..be5b50b74 --- /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 000000000..781d8e1ab --- /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 000000000..de0eaf68d --- /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 000000000..06150cfb9 --- /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 000000000..ab56d63dc --- /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 000000000..d99404fe0 --- /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 000000000..87df3e126 --- /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 000000000..b3f05c905 --- /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 000000000..2271ec4c1 --- /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 000000000..38ce260ee --- /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 000000000..c0f1d6d52 --- /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 000000000..5cdba4862 --- /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 000000000..cad53004c --- /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 000000000..2ca7e5b13 --- /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 000000000..90993221d --- /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 000000000..e9045c227 --- /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 000000000..ad9380e0d --- /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 000000000..1a9282073 --- /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 000000000..e61a3425d --- /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 000000000..425f38f1a --- /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 000000000..b92909df5 --- /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 000000000..c9ca0c96b --- /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 000000000..620fbcbba --- /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 000000000..d60999dbf --- /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 000000000..7cd1844c3 --- /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 000000000..e0a53270b --- /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 000000000..61395a559 --- /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 000000000..b627904b9 --- /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 000000000..dc9fa45f8 --- /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 000000000..dcfb7f929 --- /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 000000000..a2a5d2b80 --- /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 000000000..cbb4200dc --- /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 000000000..f933e717c --- /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 000000000..d323b7947 --- /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 000000000..2c86e085b --- /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 000000000..dc081f936 --- /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 000000000..eff0ad14b --- /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 000000000..1c0e6841c --- /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 000000000..e7bdbc18b --- /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 000000000..cae5093aa --- /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 000000000..43f414656 --- /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 000000000..2b1b6ed6d --- /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 000000000..08f24bda8 --- /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 000000000..68ec07f56 --- /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 000000000..9c1c70b93 --- /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 000000000..bbc9337f2 --- /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 000000000..b0c5ac215 --- /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 000000000..49d398896 --- /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 000000000..bebffbbd0 --- /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 000000000..ad0994a4f --- /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 000000000..1a3539f15 --- /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 000000000..91883c7e5 --- /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 000000000..28be53fed --- /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 000000000..de6dcfc6d --- /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 000000000..4f5634e81 --- /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 000000000..f2bb00fa5 --- /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 000000000..dd5ddfc19 --- /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 000000000..bb105ea35 --- /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 000000000..913361368 --- /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 000000000..81ec32dd2 --- /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 000000000..52cb1bf93 --- /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 000000000..966ce43ca --- /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 000000000..aa56267d2 --- /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 000000000..d2224a610 --- /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 000000000..3c9c0f208 --- /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 000000000..b036af35a --- /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 000000000..533f06195 --- /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 000000000..4a2bb01a4 --- /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 000000000..44fa016e2 --- /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 000000000..684892ae1 --- /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 000000000..c22d2c0d1 --- /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 000000000..4137147a0 --- /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 000000000..841d4cc9a --- /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 000000000..eda649b11 --- /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 000000000..a7781496e --- /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 000000000..68bb384ec --- /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 000000000..a9f89c6a1 --- /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 000000000..18771f3e8 --- /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 000000000..a5f8ad341 --- /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 000000000..245772a5b --- /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 000000000..ce0572b0d --- /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 000000000..7f3169a8d --- /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 000000000..2f3745d8c --- /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 000000000..f1be03a8d --- /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 000000000..13cc64736 --- /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 000000000..2a3573512 --- /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 000000000..c3a83d5fd --- /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 000000000..060ac0ab6 --- /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 000000000..74ee10bdb --- /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 000000000..4de64d919 --- /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 000000000..665307b99 --- /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 000000000..6fabb140d --- /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 000000000..cf50c8544 --- /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 000000000..1a8914512 --- /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 000000000..9d35f7c77 --- /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 000000000..ec9ee2a77 --- /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 000000000..9f50fb243 --- /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 000000000..1149ed9df --- /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 000000000..a4469d293 --- /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 000000000..2f23cb944 --- /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 000000000..169374aa7 --- /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 000000000..7b0b383ae --- /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 000000000..d40ab5dce --- /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 000000000..fc3d55107 --- /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 000000000..56837b52f --- /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 000000000..bd88392ff --- /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 000000000..e56d7ab9f --- /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 000000000..b0a368705 --- /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 000000000..7c672d398 --- /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 000000000..fd2202e71 --- /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 000000000..803fc6709 --- /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 000000000..98186dd8f --- /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 000000000..07a78460c --- /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 000000000..2aec09e92 --- /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 000000000..ba21d1e56 --- /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 000000000..eaf923276 --- /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 000000000..82d41725b --- /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 000000000..4a8857199 --- /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 000000000..3be565aea --- /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 000000000..9a1e59c58 --- /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 000000000..c0e09c5ab --- /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 000000000..f391243a1 --- /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 000000000..32a9f85ab --- /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 000000000..813e805a9 --- /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 000000000..77fa474fe --- /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 000000000..41edd3c96 --- /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 000000000..3b4705071 --- /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 000000000..d5d157c10 --- /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 000000000..4ebaabc0c --- /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 000000000..a697158fa --- /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 000000000..cf8165210 --- /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 000000000..31772e33c --- /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 000000000..ebb711ea5 --- /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 000000000..68fb58a66 --- /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 000000000..2ab35fff6 --- /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 000000000..01790ef56 --- /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 000000000..9a0d6c121 --- /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 000000000..5bb0fe1a9 --- /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 000000000..b39d53ad7 --- /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 000000000..9527c7ff4 --- /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 000000000..5cdd29dbd --- /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 000000000..eaaa0005a --- /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 000000000..23cd5c5fd --- /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 000000000..33a316e31 --- /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 000000000..a8c475a56 --- /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 000000000..2011c6eee --- /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 000000000..d728137cf --- /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 000000000..440c4ff60 --- /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 000000000..f808fe6e2 --- /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 000000000..54011d703 --- /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 000000000..d17035716 --- /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 000000000..60fe957b3 --- /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 000000000..32c358574 --- /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 000000000..85c16359a --- /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 000000000..b8c507723 --- /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 000000000..60cf29cc7 --- /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 000000000..b0368b007 --- /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 000000000..0f3f6b414 --- /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 000000000..92abe9301 --- /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 000000000..f2048c9fb --- /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 000000000..bcc1500a7 --- /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 000000000..4eb826faf --- /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 000000000..30030ce75 --- /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 000000000..a2b2adb6d --- /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 000000000..d3bf3b172 --- /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 000000000..20ffb481d --- /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 000000000..cef7361d3 --- /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 000000000..151bde1c0 --- /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 000000000..a7b24ca9b --- /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 000000000..49f8b0aef --- /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 000000000..c6326e7f0 --- /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 000000000..4c985a309 --- /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 000000000..3300d08a2 --- /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 000000000..49ff2833a --- /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 000000000..6a7fc5500 --- /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 000000000..134371c8b --- /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 000000000..48638e794 --- /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 000000000..94dd56710 --- /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 000000000..7f6e7deb5 --- /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 000000000..900ff2ca0 --- /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 000000000..70adc4c21 --- /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 000000000..bee2b58d5 --- /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 000000000..ea873f9d6 --- /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 000000000..d74d03fa0 --- /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 000000000..371eea2de --- /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 000000000..31111f27d --- /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 000000000..e0ba41aae --- /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 000000000..51fe71af0 --- /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 000000000..e4d78e2d1 --- /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 000000000..5167ba8bb --- /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 000000000..178749bc8 --- /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 000000000..95029df36 --- /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 000000000..425b3aa67 --- /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 000000000..a30643d3c --- /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 000000000..319b0c6d7 --- /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 000000000..5db5fc302 --- /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 000000000..cdbb6317a --- /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 000000000..f7305dfad --- /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 000000000..0e57fda60 --- /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 000000000..d317a0207 --- /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 000000000..7feb5d5bd --- /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 000000000..f4bf98df6 --- /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 000000000..df8589c6f --- /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 000000000..da8a2f955 --- /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 000000000..7c1d7a638 --- /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 000000000..a6b31f1dd --- /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 000000000..bdddd730c --- /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 000000000..6cda40677 --- /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 000000000..a1dbc6f62 --- /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 000000000..37e1755a9 --- /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 000000000..744fa7b5d --- /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 000000000..dc0c42e75 --- /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 000000000..662e390fa --- /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 000000000..8c5aea689 --- /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 000000000..b4ec55dc2 --- /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 000000000..4e9853d88 --- /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 000000000..f9f5129e7 --- /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 000000000..d176f35a4 --- /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 000000000..3ce26a7c6 --- /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 000000000..74afc8e5c --- /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 000000000..644c2352c --- /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 000000000..aa7d52562 --- /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 000000000..b4833f9e7 --- /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 000000000..877f9fcd2 --- /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 000000000..4b4814aec --- /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 000000000..2159309ab --- /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 000000000..721f57321 --- /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 000000000..cb424685f --- /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 000000000..7c492e749 --- /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 000000000..063c8fc96 --- /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 000000000..f68aac3e4 --- /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 000000000..3da462228 --- /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 000000000..be05ebccd --- /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 000000000..26fde1c4b --- /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 000000000..1a5f0e771 --- /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 000000000..bca4161ae --- /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 000000000..2af069cb2 --- /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 000000000..616bc649d --- /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 000000000..0f677d573 --- /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 000000000..fd7ccca3a --- /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 000000000..14388902a --- /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 000000000..cad63e9af --- /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 000000000..cb621b788 --- /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 000000000..40b03c51f --- /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 000000000..678a0928b --- /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 000000000..ac7341190 --- /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 000000000..53f85f1b4 --- /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 000000000..f3d65dfcb --- /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 000000000..c488fb4c6 --- /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 000000000..2bfbd60f3 --- /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 000000000..617022845 --- /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 000000000..ea86e71e5 --- /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 000000000..721f92a4c --- /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 000000000..991ff47f7 --- /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 000000000..d37a2f736 --- /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 000000000..24a6e0770 --- /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 000000000..12e36abe3 --- /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 000000000..acd638016 --- /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 000000000..23bd06f43 --- /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 000000000..f5e69aada --- /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 000000000..a7e04e3c5 --- /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 000000000..c66b5a5a7 --- /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 000000000..647e9f9bc --- /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 000000000..a52f98a5e --- /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 000000000..28e8414d8 --- /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 000000000..ba82b0955 --- /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 000000000..eb8680c7e --- /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 000000000..6e03220d2 --- /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 000000000..2a5605d06 --- /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 000000000..688275ada --- /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 000000000..65f0f5621 --- /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 000000000..ba280d0a2 --- /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 000000000..3b27d539b --- /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 000000000..5e63d1afa --- /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 000000000..8573cca49 --- /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 000000000..d2224a610 --- /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 000000000..8ace4f23f --- /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 000000000..24f05b27e --- /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 000000000..20d970d37 --- /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 000000000..88211a62b --- /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 000000000..5a8cfdd8a --- /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 000000000..0c7d4d4d6 --- /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 000000000..b8e91af0c --- /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 000000000..4a1175214 --- /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 000000000..d60dbc512 --- /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 000000000..75d7b0c3e --- /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 000000000..ebb4e75bc --- /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 000000000..36fb7f81b --- /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 000000000..8df64e7c5 --- /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 000000000..3b1c95e3a --- /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 000000000..fe8024f06 --- /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 000000000..86bb22921 --- /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 000000000..133f82aed --- /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 000000000..95034546a --- /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 000000000..8c3335163 --- /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 000000000..9f21755ff --- /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 000000000..eef2f8688 --- /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 000000000..a9a94a073 --- /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 000000000..f69cb09dc --- /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 000000000..7f74878c9 --- /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 000000000..0f7995dbb --- /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 000000000..8a12aac99 --- /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 000000000..02da30aa2 --- /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 000000000..57b48365b --- /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 000000000..d2224a610 --- /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 000000000..ee27b46c4 --- /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 000000000..c06bf655d --- /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 000000000..47a2fd96f --- /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 000000000..45573a1e7 --- /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 000000000..f0ce4b926 --- /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 000000000..92b408ba8 --- /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 000000000..1aa136531 --- /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 000000000..b8f69f7c4 --- /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 000000000..56c4cfbcb --- /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 000000000..5e68f2bc3 --- /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 000000000..ab9676988 --- /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 000000000..e3f07e4ed --- /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 000000000..c980b591c --- /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 000000000..f7997b1d9 --- /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 000000000..d2224a610 --- /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 000000000..24c8d81a0 --- /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 000000000..4248cafd6 --- /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 000000000..728f7460c --- /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 000000000..3e11b2090 --- /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 000000000..1ff4c6eb1 --- /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 000000000..032035e5a --- /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 000000000..40c5e68eb --- /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 000000000..7a2471dcb --- /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 000000000..61a79d7fe --- /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 000000000..249c4180f --- /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 000000000..1b51ba4be --- /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 000000000..6a5be1b6b --- /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 000000000..f3bef86b9 --- /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 000000000..034e09ef2 --- /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 000000000..b7093ea83
--- /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 000000000..4f45f8f97
--- /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 000000000..3ff8ad022
--- /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 000000000..d939ea2b8
--- /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 000000000..d95c95c58
--- /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 000000000..984e75572
--- /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 000000000..1fb8482bd
--- /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 000000000..f51265e0b
--- /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 000000000..0f6494670
--- /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 000000000..4d7d04a52
--- /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 000000000..cd39dde5d
--- /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 000000000..2b26cbb5f
--- /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 000000000..1879be90c
--- /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 000000000..22f78ea5e
--- /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 000000000..ca86e2f3b
--- /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 000000000..23dfb2730
--- /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 000000000..93ac18e01
--- /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 000000000..3e513cfef
--- /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 000000000..06cf79382
--- /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 000000000..8d77a09a9
--- /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 000000000..5790f2228 --- /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 000000000..a2457b842 --- /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 000000000..7c64fc9e4 --- /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 000000000..36d410e13 --- /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 000000000..abde651b2 --- /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 000000000..c9bec4158 --- /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 000000000..773184439 --- /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 000000000..46741a583 --- /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 000000000..0397c9ed5 --- /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 000000000..eb03f2bc3 --- /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 000000000..f551021b1 --- /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 000000000..88111df6a --- /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 000000000..bcb7abc77 --- /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 000000000..b35171abe --- /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 000000000..448978a18 --- /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 000000000..c5f6796b4 --- /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 000000000..dae6bb1bb --- /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 000000000..272f842f5 --- /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 000000000..8cb19edbe --- /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 000000000..a05f1ea6b --- /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 000000000..500b13dee --- /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 000000000..b7093ea83 --- /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 000000000..96dac3c9f --- /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 000000000..5de583000 --- /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 000000000..9f754f7f5 --- /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 000000000..014f10eff --- /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 000000000..e9e4ccd8f --- /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 000000000..ab3da133c --- /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 000000000..422b20cba --- /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 000000000..b1eecb332 --- /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 000000000..4fe67dc89 --- /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 000000000..b3ca3609f --- /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 000000000..cb539c60b --- /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 000000000..b5f3de6be --- /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 000000000..c79035659 --- /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 000000000..896035b88 --- /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 000000000..2d6fcc802 --- /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 000000000..d2d43adf3 --- /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 000000000..919950e24 --- /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 000000000..f6fb8abec --- /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 000000000..0d79835bc --- /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 000000000..2296f18b9 --- /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 000000000..822b4c8e0 --- /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 000000000..d08ca6258 --- /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 000000000..1e327f964 --- /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 000000000..bf3e1ab9d --- /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 000000000..ff73f2252 --- /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 000000000..00069f4bd --- /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 000000000..88362195c --- /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 000000000..737300f98 --- /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 000000000..7e50db9df --- /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 000000000..24b7a193c --- /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 000000000..8e097ef68 --- /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 000000000..8e4b97135 --- /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 000000000..926b3b15c --- /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 000000000..531b474cd --- /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 000000000..c81ed78a7 --- /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 000000000..6c93fd128 --- /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 000000000..03b01c64a --- /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 000000000..5586b8942 --- /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 000000000..3c68874bf --- /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 000000000..1d87bd1e4 --- /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 000000000..1d01d5528 --- /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 000000000..30e6b6661 --- /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 000000000..e5e087cf8 --- /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 000000000..3351569d8 --- /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 000000000..83fdfcfe2 --- /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 000000000..4a2ae0e43 --- /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 000000000..9c02e211f --- /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 000000000..4352cc02c --- /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 000000000..1e62f4c9a --- /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 000000000..fa03cdbb5 --- /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 000000000..1f53961f2 --- /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 000000000..257593ed4 --- /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 000000000..c891dec7d --- /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 000000000..d351526d1 --- /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 000000000..582839fa7 --- /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 000000000..3439c8e55 --- /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 000000000..f808e52d9 --- /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 000000000..a1b452b5a --- /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 000000000..fab689ae8 --- /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 000000000..496e23a63 --- /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 000000000..87c223cdb --- /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 000000000..37bb99db2 --- /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 000000000..f4ccdedf2 --- /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 000000000..2e2780439 --- /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 000000000..6afbc74d6 --- /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 000000000..80340552f --- /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 000000000..0cb55b988 --- /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 000000000..515cdffe8 --- /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 000000000..1e03db675 --- /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 000000000..a711a7ca5 --- /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 000000000..4736d156a --- /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 000000000..e751245c9 --- /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 000000000..41236005f --- /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 000000000..c1890caee --- /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 000000000..b0d58efaf --- /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 000000000..fc7292d5d --- /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 000000000..f0cdb4495 --- /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 000000000..519169e28 --- /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 000000000..ce4cd1f6c --- /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 000000000..bed9cf3f6 --- /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 000000000..094b62754 --- /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 000000000..2a84e0f69 --- /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 000000000..52965e153 --- /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 000000000..a0d52a3a7 --- /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 000000000..26d81eaef --- /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 000000000..ca683f14c --- /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 000000000..44c24cae8 --- /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 000000000..0c65e4a5a --- /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 000000000..d437578d2 --- /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 000000000..48a069f05 --- /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 000000000..b84a13fab --- /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 000000000..7064eb836 --- /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 000000000..643ea5f8f --- /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 000000000..4874e2824 --- /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 000000000..cb285f24f --- /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 000000000..ed67b2c9f --- /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 000000000..faa71d281 --- /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 000000000..2d6f728bc --- /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 000000000..e964c93cd --- /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 000000000..bb3d655f1 --- /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 000000000..17b31bd53 --- /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 000000000..57447ee28 --- /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 000000000..f4cb4356c --- /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 000000000..f6a7d5f62 --- /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 000000000..6bcee531d --- /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 000000000..02c38b2bf --- /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 000000000..5a235dd30 --- /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 000000000..7be9e5f8e --- /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 000000000..c18eb5452 --- /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 000000000..8aae81cea --- /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 000000000..98c42a4ae --- /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 000000000..b33ae6bd4 --- /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 000000000..ad51e1189 --- /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 000000000..055ec1425 --- /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 000000000..fe67a8ee7 --- /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 000000000..3c22642e0 --- /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 000000000..ba12fa194 --- /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 000000000..f79eb0598 --- /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 000000000..1bb684ed9 --- /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 000000000..b02663cf5 --- /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 000000000..409b4bbab --- /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 000000000..dc72a667a --- /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 000000000..7ebadf047 --- /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 000000000..c10923098 --- /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 000000000..3af0c4c4a --- /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 000000000..c2698a1d8 --- /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 000000000..d2378137c --- /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 000000000..c50eb7d43 --- /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 000000000..58fe59982 --- /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 000000000..ccd2f80db --- /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 000000000..3c82204f2 --- /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 000000000..975c921a8 --- /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 000000000..d87e6eea2 --- /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 000000000..729b6779b --- /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 000000000..b842ab978 --- /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 000000000..3be73665a --- /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 000000000..6c66f187c --- /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 000000000..5e581c14f --- /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 000000000..4cadf25b7 --- /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 000000000..ef9d59d85 --- /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 000000000..d65b38e09 --- /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 000000000..8e084e396 --- /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 000000000..df6902a40 --- /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 000000000..999340452 --- /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 000000000..94223c9e5 --- /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 000000000..ddf2c1276 --- /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 000000000..f577565b8 --- /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 000000000..69f3df375 --- /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 000000000..48ec36854 --- /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 000000000..8754192b2 --- /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 000000000..43fd42e57 --- /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 000000000..950f0ba69 --- /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 000000000..ad6ed7e9b --- /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 000000000..a28960738 --- /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 000000000..034972662 --- /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 000000000..70875c34e --- /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 000000000..6b91c90d0 --- /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 000000000..c946d1e59 --- /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 000000000..da1263455 --- /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 000000000..17af37946 --- /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 000000000..9ece4d007 --- /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 000000000..076ac34c1 --- /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 000000000..49d41b13b --- /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 000000000..80749b331 --- /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 000000000..63f76c30b --- /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 000000000..10ef40794 --- /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 000000000..ed0ea562d --- /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 000000000..0e696e289 --- /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 000000000..f98a4a30e --- /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 000000000..56868799e --- /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 000000000..a4468cd7f --- /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 000000000..1a59cdb87 --- /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 000000000..e3949ca1f --- /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 000000000..21f464892 --- /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 000000000..4e47322f3 --- /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 000000000..cf890157b --- /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 000000000..75e3b2df5 --- /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 000000000..a432f1baa --- /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 000000000..04472c818 --- /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 000000000..7aab1ee9b --- /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 000000000..669e2b4a0 --- /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 000000000..db5cad06d --- /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 000000000..0510bd4c2 --- /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 000000000..d821291cb --- /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 000000000..ff4b65378 --- /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 000000000..8ad43b539 --- /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 000000000..920493307 --- /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 000000000..8baaa09dd --- /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 000000000..3d45b8767 --- /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 000000000..90fc698ed --- /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 000000000..a381af8b3 --- /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 000000000..98bc4c47b --- /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 000000000..04645b9a7 --- /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 000000000..913b8a556 --- /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 000000000..f30165b06 --- /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 000000000..d58283610 --- /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 000000000..89212fc16 --- /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 000000000..27af2a9de --- /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 000000000..785b9f0f7 --- /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 000000000..9d4b039a9 --- /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 000000000..f9c165115 --- /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 000000000..9e7a64022 --- /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 000000000..0705f9e29 --- /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 000000000..1b24ac419 --- /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 000000000..2b6990d82 --- /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 000000000..3a5499f86 --- /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 000000000..5e0819b79 --- /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 000000000..98565382d --- /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 000000000..af263b881 --- /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 000000000..5947a34f7 --- /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 000000000..e34ed2bc8 --- /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 000000000..c7b363aa1 --- /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 000000000..6be004359 --- /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 000000000..76df8e8ec --- /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 000000000..efff7479e --- /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 000000000..5cb2bc218 --- /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 000000000..990ffc2e2 --- /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 000000000..828fbf41e --- /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 000000000..01ff7031f --- /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 000000000..7c3cf52cb --- /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 000000000..958a13abb --- /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 000000000..dfdd847ca --- /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 000000000..e01a5aaf0 --- /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 000000000..3bfd9d0b3 --- /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 000000000..038cda62b --- /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 000000000..2ba3c2cdc --- /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 000000000..6c3940a3c --- /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 000000000..7e876409c --- /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 000000000..a373a25c7 --- /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 000000000..cc6d41bc5 --- /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 000000000..eb18783cc --- /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 000000000..5e13dd826 --- /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 000000000..5807b6097 --- /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 000000000..47ea9e370 --- /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 000000000..ebed92966 --- /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 000000000..b4559f566 --- /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 000000000..0f07a6657 --- /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 000000000..7aa228df8 --- /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 000000000..a6c12a0a5 --- /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 000000000..56a7706df --- /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 000000000..b5cf0812a --- /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 000000000..6b3c45d2c --- /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 000000000..a888a54da --- /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 000000000..fae8b84ad --- /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 000000000..d96e3a248 --- /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 000000000..123607a53 --- /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 000000000..cc08b25ea --- /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 000000000..f728bc6d7 --- /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 000000000..ae98726a8 --- /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 000000000..b50d4b477 --- /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 000000000..7146b2fbc --- /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 000000000..b688564fd --- /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 000000000..97b199422 --- /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 000000000..c454ebd0b --- /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 000000000..db7116540 --- /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 000000000..dc4604760 --- /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 000000000..391cf6137 --- /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 000000000..3dc64ff3a --- /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 000000000..59165b26d --- /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 000000000..838571cb8 --- /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 000000000..858579fea --- /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 000000000..a886e838c --- /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 000000000..a69c920e8 --- /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 000000000..eef55bce6 --- /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 000000000..a00cb9acd --- /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 000000000..240ceb7a7 --- /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 000000000..13b256612 --- /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 000000000..ec6482011 --- /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 000000000..616b5a3d7 --- /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 000000000..c65849417 --- /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 000000000..8dbd3f531 --- /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 000000000..7bea0852f --- /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 000000000..b9f180061 --- /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 000000000..89bb0faf0 --- /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 000000000..2ec2df250 --- /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 000000000..7636416c6 --- /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 000000000..6b551d410 --- /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 000000000..b2a166cc0 --- /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 000000000..8a14dfab9 --- /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 000000000..176fb9176 --- /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 000000000..baa60e1c2 --- /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 000000000..a1966ae8a --- /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 000000000..f6b3b12fd --- /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 000000000..62d69de41 --- /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 000000000..6e0a55bc9 --- /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 000000000..b4bc69495 --- /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 000000000..0d8226606 --- /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 000000000..29e143b21 --- /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 000000000..6c2a949f5 --- /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 000000000..06d49dd0b --- /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 0000000000000000000000000000000000000000..72e71fb6f79873d5757175fa78c54cc6d381411d GIT binary patch literal 11247 zcmVQyeY;18jG2E_7jX0PH+#bK6LAzAs6UsmiB($j4bJs|9I_B1MVX zH7(!CwCq(POIlGb-)8MnLBNp283ZUiL@_>9t1L2krx{0R-)Kx0cg?r`;j?Z+EwM+MAo$eQUe@NdK?#8JzY9yUdQ9 zanoTRs+9^bgnYV8dCKK;%zgbdX*$*F@ymZ#<3c?yG{%K`T&Tx|)z#J2su=W)Z3H~o zn0W5Yo^RM2lW2Vyg`*8VnR*f5=np#0t&Q;pPCI7suNNfEag|p2bwedsziu$?;I|9SE+PyVqPjl(#Jfx5q&Lfij7`PV1^)C`>@O5@0xpp^ga zzoGsApzlAR{L?%S$YUhX%jJK2v%9I}e|rZyz!%U1kMjRDJ{$Eat24n#>+5V9g-Mvq zr#xnM;IbHa#!1o$z7E5P`QB)p%sBpwJslp$JjU_;a5|5u+3MF=`-dOe>m4>o_;kzz z){pFfH=!H$JR5s4%ySXh(VW5KFyfrW;V_xm5$~~im@>x>Sj1fq7WXdFgflNeU^c=C zCzyn;H=JWz8n`@S$(XZ*N0XR^L;3>Nj2+4a-td4&w$Dz|3*U2a_@U?UAm+@D*%TY& zF?ZR;oJPJzSOyXn_Bw5Gx`?&|5lW_=d`4tyad6TK{!OXBRAVx9=;Bkhx`=|XMVaVRggTsTfpK%MX z56+JE2Ltx{_>}FjlfBckgZ{h2y;FAb?)2n%u-{~Cz_~)Sz-Sq+HKLJkCL!R{<%#Y2 zvBtp9K?y9cQ$Tq1EYI={ zX8kF4{@{jA({q}((@a0r8tfIH+EFs$L4rH%hm&cVc)^G$dN7&t$b${`L*M5kjy(pB z#{&l@JLAqc2>oz0C((Qh65@EcO8fg3`zhr-_>N@p4e(oo9fpAmY&v+q!!}?3XM^nr zBOit#z#G+7ZwRt8Wao$PPtJd=uEI0Sq`qdaPfm}|j`1sfJ9nmj8sq=j2R{;pE`U4XNj-R@mJ&$?vrwOQ@7iQZ$-blO&$JXjbT`3x1iXe$X5CT7R zJ^>rLA*%yv>&zM3!AP*=G>ko@A|ej^^XmlnE7TZjxf7U-eXdqu)$@yVSdpE2m24s4 zS2Yw^!^ZKItI%^R_4p#0^eWi(B21ESf~&-d?R;W(0)J4G0E2n7WCd(8S-05xFVJh* z2S#I4HdfDX)qyFZdCjU3IP?W}gcHdLD=xQP0l{p{Q6-68D-40+yg)&U5th^kc+|jY z`@L@%Ym4|QVDRgvCvS$H+1Ek zL@r!NPL7@IXyk})UI6q0hKH6EWg@0NK+&jDuS4TiPa!{*6N3Vb7|5z1Oo6iX0Et<> z=@I9Mt>x(d6E%Ha95_bIE;gge(({3DW>3ec%W`uL_ylLfjX9u4lH4?6!AmiR5)PEJ z*RRe`_xD~^TG#Dj`}@;_vwe86nIG|X?~fo=2gjA~s|Aj()ZyU(P&t^#2|y!-&jOHY zwO(20K5%xz&5jL*cxF}|_^-jJf&M{SuzFp-uH$?}5OnzWuYuXs9N3zBdj?k73(RGT z*v)nS+2ddemd-ZtIiJ3EO^|`f2uL>c?NPkg`yFtwuLqEYK&JL{J>T1(cxq0(97sgm z8=ky-b-xV_Ztbcti$jogID|UjiZy zsu$2?kovZc1MYJt$&m@gT{992H31Bg%ArY<64S4&{G3JCE}JH9lGX$HDwhNrs1!yijQDa$&78!onDI zVh7$d_33T%F%R^Z2YSo{{igCjX4WNfy|9poq39srHUSd}`!L&9D0#e+Z=e&2m1;5a zu7Gzx!0_d#U(AU1BfvSEzJd_^r^RU13$;}$5ZAq` z2=>_=W~xLyNg;~4W-pi}Bjh!Baf6FU&1yt!pkej14g8219I0kOpk~Ow0K0$<1qSmy zIEzlUGZ?{%?xZkbf{7p{t({xUsv)2YQI<$ZWOVpQ=?cAPpHdiXmmT(x-yNOxaEBw% zNdRbBu4QU=!0{d;1%%D|W_?}ERm0>6A#BQaSw70OOfFb&Ls$qg+3xx;F^uWwPF_SMSuqp{%bFa6KgF) zlJ~JDx{Iw*@AVf*of7LNJgW9iM~cN~g>oB37^$y8vs&MRJRxa5-DPHKK zlyMRgd5{V=6Q%@s1Vc<4r^u4j)@BXRDq>F24_2PpI4{a>7zlkghJUb&myn@_7OPXk zX%>KR>@=ozj70>oq@GhW!)*&{k&@{3zEo8KxKmh+YgHr}%^WsWtffvrG}dJf7Vs`3 zQd`@CYRRcZmeRA-RvUsJ8+4-3ka;%Z1(u>_l9_+%+gm(k5FO}%!pO_3^gGT&)J5>2QHID7^$r zdl%N)b?x_zKzK?i+PJp1z6kv@CSS^JnEc3|?`rZ*KK6`goz^k3wnf>tCnR)|%!w5P$ z!`dNm;Hf5IU1e{QXW$Km6II1TM_74JsHYt@wLB<8r3REOM&YY1axXR$>*GVl47exJ zlDfICk_WH>eKbq7BD!k2k3^pCW684s0-@+VqVh!(lx87$7)YfoikcXOH=xZx`r|mA zaOMbv7JWlR_q1$}_m=JZ_>)r1$PYo5&rJYB_FVT2LO|2O5)24&z|`Enq!}LheHYWA zU$!587<0>pZUIBF!&Dkdy(ZX`@&(n2jy09qwPa1HI;F0>WqDICnA8@BU_k9TJs79E zV4=XIs-PhmBmMK_rLn@EEtjplROqGAW{PNDa*k#-SoDIk>_l0FB|cXf*sdlY@3?$(k4C7wnG z>YY3ydl#IE0*_#rCJmz5tegx&Aw`+#WHOg&8`MNA6Wa?`$mEw~02Y=p{1KHGFu-rH z%Uw-;nI*V<`V^tRTz@eZW8n$&ml?2>wra|^`n%BwGgN7upz0E$?FB}}gkqkGP=_*> zpl@d(s6>%Qry3XTi)ci8|E&ho=j;vkefx*a25X7`31jRcfg=amBLiH zf}T8BD0)}m*U>{w9%y7vypcx7EH36M@+i#h80!lE0{dNGS3A!3Yi1g7Yi7zk+h#6F zgs}g8<^RzClNbFS%*VLH|J&S_{$FQnyVLD#VfW3=&ZGbLH9kU6)m2Y$|3uNe>Gv@i zZpV)f;G+Zh=m7pk9l(2*>FCUvb_*_RMQ zONmEDBXfr}%A#N5Q9)^Oijjg_TDoE!56Fe{Nghn)({(ltm`+jQs|?tw$mM70tDEZI zCi$27|04h6KY0GziH)jECx}m#I}FV|>>!xE|i5U1o`J*-HC` z))7zKgvxp#l%eP<>!T0=-4Fo~CL=b5=n*3XFIb`az}qvs@HnOy-JRg1&mARrO`lFc8TSUE6aokPhABC9Dt8Qi3)HN zK=pxJD$6v@GjxNzwG1bCD9j4L$)m1<+yYhlM zeYwBTn7Ea9+c7UACi$CXGrv$RW5Q9)XO;2EMt$$}&EVZ&|CP+SRkaL+qX=9{dt5q#I#3k=>yhM=0hN!!hRgU=Of7g$zfn45oe8#-Xce8F zGrc2$(%cRe^NPLGutM2>NDfD~$!J%ScrX;c2E-F?jee2tH$KX=CA17!j4 z$p3A%k>)`Et*x!@))wCX?*hL((*J9GHpB@{%%dwF=^P-Y@+{*RS*2sPVZvhn6xtRO zdn!Su?huxoYou`&KOii&>qh5Z!0@jTrHG#iGXgFwuSEmd2OL_Zx3kJZuKa~7v1~=( zaCDMu!xHG`nkX@#i7wLNFYVUm*2gT8D#j}Es^^OGlGL?MBUc3r$q3)b`SgsjXalLF zJ)}*lDd_MA{ZwqsW&xlY>P{9s<8998%I4~TLrpyj6ZWl3KN$tnHdt^Ma3ZI)1Uhm7 zOz^0o09sJfuJ-~svnWjXB0x7)-9twH8{nQmH*{A8QX5RJg8dyojP)Ue_HE3j zVU*DJ#qWI~GV?cviAyj^AY|LxdwqUzw13uMgX8{xoDUEaZ?T}cmIW(Q88@KV%VA}A zkzun<`2T!pPdpzhVC2-j>=i759iRN(LT_#efV(0>QL6Az-1(`*P<%B}8 zf>_UJ>Jh_$(JjGmV`5Ci=6R5Wwq?>={FuN}9h-NzQ8e^`^%s&+gs@elm}9|VtiMxQ z%-5Ct+AuY=naCIP;{r>f1yT=q`{CY-!OvZXX-fr^fgaH}=n?4u-`=w}w~ZXBN?oPG`FtPp5tZ}Cq?d2%wc5*7$&b5Ltt`7N`F5`?oeY8? zg~0dzD^hjE-mz$I?>FWn%-eHZNx zX=S-dbMzN9JanTtx*lV^5;e>wyc>m&m~&NPV*QQoz|76XK{DLHoNK&Df z{k0*4)jjJ84xR;6L(I5@gjUUPP@b7L!nHY21& zu`YwzRP&B|0g)m_D_e>y+DIu(nqW#6(;3A%NpphaSRm9!f}J!;cq@cDQH4+^+@oG^ zc8?3FTI`bIreK_ufpRkmJ93rTK}BfvyjjSg!fP6AKti7BM@=Ia#5&q=*tls~Z@lme zD?Q&*j4L4QD*uh9CD)O60hAM@vR!(X{3$hM+lem$oj5QfXRA2hYCdvTNzv1g7(trv zD(t$tmP2xsx&p_euF|#5IHui-Mt5VA4C|Rg$50mg$}^LYNKEpb?@oxl*en$QP&7V6 zpF9*~ywEpuD55Cc;p3DMQkOO4I{IKm+ja92;#f8)&SP{cKW8vl9OMqMR#+UYIwCI2 z(QXvUI3k-dV4vi;*407ntWSW^Ww^9F&x75sL?WQ@Ww zbeZ~w3UOUTae_ya*T((WT9}p%J^-L{hC<9?iezzfnq`g&W>}l?l@14Gq!_aVhOq>L z!7J32$&3*lqDd@uHDS1BAPet*5Bwy3jH!eqOr+ApK*Ivf7`MVyxL`~%Qy7R?LR1xI z0*M_bFi7;>WJ=)p(c+L~%dFeBO!OMm5ESXl+{beF1!s`N6VR(EUND9P7Lgw#x}=$* zX@zZR*Gc&};o9sBlsn1j=3{r@7j_@BaurDfA#4Gm9u;YHH0MCrFtc9j%x5WZfCb`C zHH`p2s13u^V9%OLSnC6HLpMNyNN)XUdYuP&DrNP-hXS1J>Ce*ubY)pHP@VxW zOsyQNcLrcxT_?GhBH)$!5@dXO?efypJh4;BRo;TH2Y>vJX#e`l#h@ zwNJmI)q=a~(4B^v^cl#~X>?{yT>I0$Uj7FWhU-IOfDYi#nVNs%@Kj_R^%I~TGf9!W zTSrEvL$Y0K%qtvwswpo&nBpmT8wFQ0nXbB!8*ka<#e=H}!xpF|B1oN1TqyQ5yuqPZ zY?@@O_|&*S@wi8gSXr*;LO9J1F^HV=SjJ{Be+y<-6j$p+R7d0H2*Mb(>&7Q7F zNSH2Zu8BLrJ8Na}NvsB}RC_8HgoV3E1hn&0R~W_3$O3pfVD|6o6QJr^t`?~$REQO8 zwswV=Hp}IJ{4HLX*l$@70dUt4ETbDVumX1wlivnnNT$S0z3denJu1L;iNvi){}2{3 z)3`Ax#;LHTXe!;2`oegi-A74yJ)GLPDliDyjyNkDCxj!$fjpaxhW(88gy}>vNn8dV zMR3E2>ml(z9%kk{#px6-Zta9@HLuL!qJf=xy0%Wy;;t|XQPA`yp6DgY<)Fb@FM}6W z4TS$CxlCuFs4f2v?ruOj`W&~)_^S~!JM4`E_ z-7@_^25jlL*yUZQT5IT`du<(?L`$d*r%vD^KrBrK28$4|GMhOesC?OJYsT6m@<{_% zQ<2QatMxB_60eZm9OpTL#H$of4oP(LNo{czTToLNg1R9&CIc-1J&GQgx1vZo4!i^i z7UpcgqgBjp0urmjU>uOL0*r~oP7J?>=C7XLv?R9IelkQc3TD}e;Cw_qdv}rb&-617 zVNFbx%-bLk)cn6q%z;Bdx9r%vNq$Ho7>Wb+! z>N!xO*WSgiot<6$(durttxCP!?S4AI^3Luyer;}V(%0^GtJf>`Mg`w+tsZ?Hy#8^n z3OwBU2L9=Gx>(_O;wE0BW4|%PdjYJrjo|Ed`DKmgKXzMNcD-=`vJt|yga7Vs;lIy) zkK%0u@6RhT*$K+jspn4SaW4zjx-W35EFi$VSreVsnnJ~9Lhy&o*cu%QQGG^&7%17- zOYgCa%4F2hG2lj+i7JM<2l~vF{b=*diuf}h5TDa%ro1RniqJ9%r$Hro2RSZ1!-Hr2 z(5w+wb72L%UJ5B4)!;6k_#vq`u-$_mczMm^+e0QUvP4R%hY={2fZ>RDuAfME@&JeWZ(G(!%n=8H@Kp`aVlQ|;_=qQ%MXynDDSlh2fX2Dd28Cap!2WCYAk`C{_xnTPxXTJ-l&GW*|`{soV zOU9GZfW|J;jNcIM?m2WS8Zg-lx(}AF8fRhEz+Uq><6xRFGQy2?uc|mZ{*{aCN)!*o zRG1}*t6SC|=VwXjN`|DGVdA2?;3IN>nvN%u2N*}>AWKV01RfU73t@4A(1`BqWJI?X^fYtPX9J?dX%0^C8E!dm<$yBFKJaBVLFox}cF-{Z^qjo)&fhmF6M^4|l< zf9U_?j?zy_W4EmT-e#|@jG@PXB!H{YTsO*+&D{^+h~j7Beo#^hAL_I<-5d_w|nGG7Tqmtr+c+ComH zQp3arC{)X%1r)l&yHZRNm&{d`rvd>e&k0?-UD@q`RV=iEXT>(fx5aZU;%wO%<03S1 zvL0`7(wnP)=UKv&p+Z}HFb@)%P@jPOrKyUdf#`=sUM7Aj+Avd{RjC`Ha_&%Fkyw|y z&-s{gT$xomtLKkR#bxz!?2juHV!zPQs+h_A{yd$WfniyuIjIb2S*%8el-aq!)9#aXs?IUO|(`&}4lR|dA?>L$<50swXf9_GWc{2x2*b{YTqvwWH__rHH}{=YBY93Q+o+N;PPjZU+Ti>Vp!Ra(~`~&b0eHxsC80$o&B%)v|fFz#e=2-?Jm>L{*@T(-=8ULyj}( zz@p(fgi=p6pT0dfJUKtyKR!7p!hiGjXiwp`qEVxJlsKeL;UU6XD7fFqAB1R@QDC9$ zI)zzF;-!TYKlK3s;E<~i(UBKrp$Gfk!=S~@fbwsj^k2_QbYR*0@+7xGwf^Z=6h*^z zg7_STJHweCh9%vbTNZiI`gvZ%8aVhdUAsZW2N~fPwdpYJT1|Ho(fnEbCq0h0ffV`89(Od-Q|nf|Lx|5c{{ z`WH+8HH5V@bj}Zdcztkma{iqOikUxAttZa=5S^vaKa(9MeHbE{IT{BtpR8rxM~|J$ zAVp(e!LYs~OYn8j69&QAGp=!x)STR<*iB>Jzl{1|AG5w#Gjc~%5g;8714IlLEwiY> zValM`4Xx7XV4TmPBQEvTmj|zpYf3It@fOZGfBojw$*XD=_QrFHM)oabN2ug?dCRK& zhaXzK9=|=>tRbXqXo~il+Od$r0k9#VhTprk0M&3*uWFTZ-lE}8GYsoS5i5u(Q1uEZ zpoT!C{<4m4>u0{32-vF?IQ8Ivj`k0aD=-4GSb*RAhi_iiltMipX=o5n(XA&>NlM{P z^S#0tBTK3YJB+!(=0cvf`a)s}#B}jl#lD_i-IbZeVthK&0L$j;pwHQ2e>ohc>MIzb zn~WFw%4=A6-7CASJCgm??mEBFUkz!VpJ`>^sUHptZJu+afRzpC(iDflq<}%l=)Hq-`?5mY@+_Z-R_q5zn|sPlAM1?0VV-pZm|ng zNnsGI;0SsP#-rrL7~pHu<=K1k)8ps8-R+uMYbvxDiW`e0L^iNI&g02>wgs+t-80T? zkkznwuCQ$i3yha?B^7t~!-J!@Ki1Se;HxZ!ukl~!=adM15jrgDuP&N+R{HP{=mfn4 zY!-DS|N0Pv1c+ErV_R*J0cysV5nA!ac}XNt+6C&8P`EIHemjigOpmPO{yZ| zlJira#%}6L2xZL7f`XC>s@qZ(Hyu0GKcpWjk9wWDvs-<%iFseJs^qS~IHpK?bCuh5 zXVa?8ZaA6+7VD-kUu~-{^Xnyb2bD*iZ4i*UR%P-e=7dp>PAQwtH`=WOcauhTK^LIx z?k+3n)`1I}0-dJAAgq`L&9X3Ci{lRCSUiQ6pgEkwhW*^eXyLgvEy@(kqpDD_3?1Pr zbc74&nB8aLtzZnDb&MhB8mm?oi2J=yzz^2*tKOaY6>B5+0nflEOI=gh6K_KKknfUZ zuTQqTg)x|@&xNNHH+vOtCPV-gQ;3WNxy58c@*Ik4Hc8|2KRJIa^rN%fXuaytO8jSD zt`qmM6gby!rNV{7aGGAst$3l>%&oMq+C2^_4OPF2+s=PBu%C%t4G8<)SHsEI?W@hr zvpUwYT6A=a0t)6^$8BoZF%1ReaS#c|1LdD$KoLu`nj^oeK+AgL8(5}arIS1Wwm}Xc zkdg%DO6D?jN$_pk@|eP3&$RBKO8Ng^RQ~@*%b(?^{FI-6+^4+%|FS>j{eOA?U*7+J zxu5d>zr6o1@BhpD|MLF7y#Fun|I7RT^8WwJI{z#0|G(@{dH-MD|Cjgw<^6wo|6kt! Zm-qkW{eOA?|7FSle+P*!&M*Mr0043%FbMzv literal 0 HcmV?d00001 diff --git a/src/lib/lwp/misc/lwp.tex b/src/lib/lwp/misc/lwp.tex new file mode 100644 index 000000000..2cfb2b532 --- /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 000000000..1aa5ad481 --- /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 000000000..af9526945 --- /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 000000000..ee8199acf --- /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 000000000..045c30146 --- /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 000000000..95bd786a8 --- /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 000000000..4c50a62d7 --- /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 000000000..3e2ceecf6 --- /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 000000000..3c54dcdd8 --- /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 000000000..24b28700d --- /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 000000000..5f92b4608 --- /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 000000000..2bc15df19 --- /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 000000000..73005d6fb --- /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 000000000..b175279b8 --- /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 000000000..fa8baa533 --- /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 000000000..828b8439c --- /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 000000000..cff1e3882 --- /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 000000000..f4ed15cbf --- /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 000000000..1b6d9d9fb --- /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 000000000..39bef2c34 --- /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 000000000..ea3b55539 --- /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 000000000..4dbb2b478 --- /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 000000000..f784091bd --- /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 000000000..9f8d2e808 --- /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 000000000..fa8bb8209 --- /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 000000000..044e4adbe --- /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 000000000..ba35fe11d --- /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 000000000..5edb9ba29 --- /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 000000000..4c58387ef --- /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 000000000..62d90c54d --- /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 000000000..87489a454 --- /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 000000000..1477b04d4 --- /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 000000000..e4bab65fa --- /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 000000000..263a0c4f3 --- /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 000000000..4041980a6 --- /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 000000000..2d5a06aff --- /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 000000000..afad0b565 --- /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 000000000..defb1f6ef --- /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 000000000..5311c7de2 --- /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 000000000..ce875f85d --- /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 000000000..c92f9cdbc --- /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 000000000..ea35d85cd --- /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 000000000..8f76405da --- /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 000000000..d45e229a0 --- /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 000000000..13e27034e --- /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 000000000..426b7878d --- /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 000000000..356be274a --- /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 000000000..57a8b2a92 --- /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 000000000..31ff09a92 --- /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 000000000..d3cb14264 --- /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 000000000..12265ff08 --- /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 000000000..59bd0f96a --- /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 000000000..f5338d98d --- /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 000000000..8a7d48730 --- /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 000000000..dc0c69a28 --- /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 000000000..d2eec4724 --- /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 000000000..31ba58ef9 --- /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 000000000..9d4a6d4cd --- /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 000000000..128a03f8b --- /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 000000000..2d723e111 --- /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 000000000..71fb2a78f --- /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 000000000..dba03716a --- /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 000000000..d55a342a3 --- /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 000000000..d11138892 --- /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 000000000..510e6a434 --- /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 000000000..99a57ee15 --- /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 000000000..c1bac9465 --- /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 000000000..cf4d947c4 --- /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 000000000..e301f45ce --- /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 000000000..e531739c4 --- /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 000000000..12e5482ef --- /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 000000000..6f516db2e --- /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 000000000..54b86cd20 --- /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 000000000..2e1c78962 --- /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 000000000..763951724 --- /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 000000000..e608f7204 --- /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 000000000..025b4a01b --- /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 000000000..95b2d3d82 --- /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 000000000..6811602d7 --- /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 000000000..45812a832 --- /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 000000000..2ba16105f --- /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 000000000..7f90e93d2 --- /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 000000000..15067e924 --- /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 000000000..369832523 --- /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 000000000..b4345dc86 --- /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 000000000..fc09f052d --- /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 000000000..d2e5c5b20 --- /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 000000000..30293b969 --- /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 000000000..f6268badf --- /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 000000000..fb9e7e923 --- /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 000000000..6f0f24548 --- /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 000000000..f05f63c6c --- /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 000000000..a2cbee46c --- /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 000000000..742b86cb4 --- /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 000000000..e618a232b --- /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 000000000..0f7f5f91f --- /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 000000000..d734b9e17 --- /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 000000000..5ecba2129 --- /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 000000000..9d6ab2d47 --- /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 000000000..02ff1ef46 --- /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 000000000..8e939d839 --- /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 000000000..7c4be30fc --- /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 000000000..a3d048cc6 --- /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 000000000..b0dd6de48 --- /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 000000000..2cbf92ef0 --- /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 000000000..37f6da55d --- /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 000000000..73d6791f0 --- /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 000000000..78f2179cc --- /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 000000000..f64560339 --- /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 000000000..22818fde6 --- /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 000000000..e1ecccb95 --- /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 000000000..70af32705 --- /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 000000000..d9630d2b9 --- /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 000000000..a0a67cae6 --- /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 000000000..457455474 --- /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 000000000..a254cb9fc --- /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 000000000..9097c00e8 --- /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; +} -- 2.43.0