Custom games may want to tweak how items contribute to the power
factor, in particular when products are also customized. Add ichrstr
member i_power and item selector power for that.
"info power" doesn't reflect this change, yet. It'll be updated in
the next commit.
The current item power values are problematic. This will be addressed
later.
For straightforward configurations, reasonable item power values could
perhaps be derived from the configuration automatically. However,
this is surprisingly hard in the general case: since producing things
should not decrease power, the efficiency of processing products into
other products needs to be considered, and estimating these
efficiencies can be difficult.
Deities can create multiple products making the same item, or multiple
sector types with the same product, but different process efficiency
(sect-chr selector peffic). Providing differently efficient ways to
make the same item can be reasonable when the sector types involved
have different terrain. To average them, you'd need to know the map.
The stock game has one example: gold mines produce dust with 100%
process efficiency, mountains produce it with 75%. Mountains are
normally rare enough not to matter.
Level p.e. (product selectors nlmin, nllag) may have to be considered.
In the stock game, level p.e. variations are minor, because it reaches
0.9 pretty quickly. In games where it doesn't, you might have to
increase the power value of the product.
Resources (sect selectors min, gold, fert, ocontent, uran) and
resource depletion (product selectors nrndx and nrdep) further
complicate things: you might want to increase the power value of
products depending on unusually scarce resources, but you can't know
what's scarce without understanding the map.
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
Actual abilities of ships, planes and land units depend almost
completely on the individual unit's tech, not the nation's tech. The
power factor should reflect that.
The power value of a unit is of the form
base value * (20 + nation's tech level) / 500
Change it to
base value * (20 + unit's tech level) / 500
Note that a plane's base value still depends on the nation's tech
level. This commit merely makes the absurdity stand out a bit more.
To be fixed later.
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
In the old times, power didn't consider tech at all. Chainsaw's
option NEWPOWER (mandatory since v4.2.14, on by default before)
changed this dramatically: the power factor gets multiplied by
max(1, tech) / 500.
In the early game, small absolute tech differences yield large power
factor differences. For instance, if country A has tech level 10, and
B has 5, then A gets a factor two boost.
As the game progresses, tech differences between viable countries tend
to grow, but only slowly. The influence on power diminishes. For
instance, if C has tech level 270 and D has 240 (quite a respectable
tech lead), then C gets a modest 1.125x boost over D.
Change the factor to (20 + tech) / 500. Now A's advantage is only
1.2, and C's is 1.115.
You might think that's rather low. However, tech is not power unless
you project it, and then it manifests itself as sectors, population
and other stuff power counts.
The same tech term occurs in plane power, except with just tech
instead of max(1, tech) . Change it there as well, for consistency.
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
If option RES_POP is enabled, the power factor is multiplied by a
"research factor" of 1.0 + maxpop / 10000.0, where maxpop is the
maximum population of a mine sector.
Back when this code was written (Chainsaw 3), all sectors had the same
population limit, so using a mine sector was as good as any. Since
then, it has become configurable, and the stock game has both sector
types with lower (mountains, plains) and with higher (cities)
population limits.
Space for people is worth considering for power, but multiplying total
power by a fudge factor based on the most common sector type's maximum
population is silly. Drop it.
Adjusting each sector's value for maximum population would make more
sense, with and without RES_POP. Perhaps later.
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
Item power value is basically number of items times the item power
weight. For some item types, we add up the item numbers, then apply
the weight. For lcms and hcms, we apply the weight, then add up the
weighted numbers.
Adopt the latter method for all types: change addtopow() to tally the
power value for all types instead of just lcms and hcms, and drop
gen_power()'s item power value computation.
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
Use a single array member instead of multiple scalar members. Only
the array elements that replace scalar members are can be non-zero for
now.
This is a first step to permitting more build materials.
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
The work required for build and repairs is traditionally a function of
build materials: 20 + lcm + 2*hcm for ships, planes and land units,
and (lcm + 2*hcm + oil + rad)/5 for nukes. Make it independently
configurable instead, via new ship-chr, plane-chr, land-chr, nuke-chr
selector bwork, backed by new struct mchrstr member m_bwork, struct
plchrstr member pl_bwork, struct lchrstr member l_bwork, struct
nchrstr member n_bwork. Keep the required work exactly the same for
now.
Clients that compute work from materials need to be updated. Easy,
since build work is now exposed in xdump.
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
Notable gaps in its coverage are fallout, most of guerrilla, delivery,
distribution, ALL_BLEED and LOSE_CONTACT.
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
Add edit u keys 'A' for plague stage, and 'b' for plague time.
Admittedly unobvious, but at least they match edit s keys 'a' and 'b'.
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
Exercise version, show and xdump, except for xdump of game state.
The xdump part is mostly factored out of tests/smoke.
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
One-way sorties (fly, recon and sweep) reject mountain destinations
with a "Nowhere to land" message. However, planes can land there just
fine when they return to base (bomb, drop, paradrop, missions).
Already inconsistent in BSD Empire 1.1.
Fix the inconsistency by changing pln_where_to_land() to permit only
helicopters to land in mountains, and pln_airbase_ok() to permit only
helicopters and missiles to take off there, i.e. reject fixed-wing
aircraft.
The flying commands now reject fixed-wing planes based in mountains
with an "is in a mountain and can't take off" message.
Commands flying to a mountain now select only helicopters and silently
ignore the rest, exactly like they select only VTOL planes for flying
to a non-airfield. If no planes can be selected, the command fails
with a "No planes could be equipped" message. This is admittedly less
clear than the "Nowhere to land" message we got before.
Missions now ignore fixed-wing planes based in mountains, exactly like
they ignore non-VTOL planes outside airfields. This may make players
wonder why the fixed-wing VTOL planes they transported up that
mountain don't obey missions. Missions are always quiet unless they
execute.
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
The two "while it is carrying a nuclear weapon" messages lack
newlines. Add them. Screwed up in commit a269cdd, v4.3.23.
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
When bombing land units, the bombers get a chance to spot spies. They
can target one even when it wasn't spotted. This makes no sense.
Screwed up when spy units were added in 4.0.0. Hide them completely.
They can still be killed via collateral damage.
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
This reverts commit 9b33a4c598.
Parameter only_count was introduced so would_abandon() could use
unitsatxy(), but that was a flawed idea, fixed in the previous commit.
No callers passing non-zero remain, so get rid of it.
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
sct_prewrite() makes an owned sector revert to the deity when there
are no civilians, military or own land units.
would_abandon() tries to predict that, but gets it wrong: it ignores
land units that evade spy detection or are loaded on ships, and it
fails to ignore land units loaded on land units marching out.
Broken in commit 7c1b166, v4.3.33. Fix by counting manually rather
than with unitsatxy().
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
Set the application name to "Empire" to support Empire-specific
customization of readline. Use in .inputrc looks like this:
$if Empire
set bell-style audible
set history-size 500
else
set bell-style visible
$endif
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
Make -H take an argument. Default it to ~/.empire_history, except in
-r restricted mode, where history is off unless you specify -H.
That's because restricted mode restricts the player's access to the
local system, and that includes the history file. If you want to
grant access to a history file, you have to do so explicitly.
Thanks to the previous commit, there is no need to suppress saving to
~/.empire_history in the test suite.
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
Readline is for interactive use. For non-interactive use, it merely
complicates things. Case in point: it slows down "make check" by almost
10% for me.
Interactive use should always involve a TTY, so use readline only when
standard input is a TTY. This supresses readline in "make check".
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
We truncate the user's home directory name to 1000 characters when
constructing the history file name. Use fnameat() to fix that.
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
AX_LIB_READLINE tries to cope with systems where readline lacks
history support, or lacks headers, or needs headers included in
unorthodox ways. It puts six HAVE_ macros into config.h, and its
usage example takes 24 lines of code just to include two headers.
Way too complicated for my taste. Replace with new MY_LIB_READLINE,
which succeeds only when you have a sane readline, and then defines
*one* macro: HAVE_LIBREADLINE.
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
Two out of three callers want an extra newline. Letting the callers
do that is simpler, especially now that readline added another case to
prompt().
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
If recv_input() can't stuff the whole line into @inbuf, it leaves its
tail in @input_from_rl. If send_input() then empties @inbuf, the next
iteration will select @input_fd for reading instead of @sock for
writing, because @inbuf is empty. Since @has_rl_input is still set,
recv_input() will do nothing, and the client hangs.
Fix as follows. Factor ring_from_rl() out of recv_input(). Also call
it in send_input() to refill @inbuf from @input_from_rl.
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
Document readline in more detail in man/empire.6.
Make @history_file local to main().
main() silently truncates the home directory name to 1000 characters
when constructing the history file name; mark FIXME.
Set @rl_already_prompted just once.
Write history file on unsuccessful exit, too.
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
Readline provides fancy command line editing such as <Arrow Up> for
previous commands and CTRL+A to jump to the beginning of the line.
This patch does not add any completion on <tab> key, a TODO, if you
will.
A new command line flag, -H, turns on saving the history to disk.
This may have security implications on shared computers, as all
commands are saved as-is. Thus "change re 1234" would be logged
directly to the file.
Signed-off-by: Martin Haukeli <martin.haukeli@gmail.com>
Rebase on top of preparatory work, fix a few bugs, and tidy up:
* Update the standalone client build, too.
* Fix the Windows build.
* Keep command line options sorted case-insensitively.
* Error out when $HOME is unset and getpwuid() fails, just like we do
for $LOGNAME.
* Give @input_from_rl, @has_rl_input static linkage.
* @has_rl_input is a flag, not a counter, set and test it accordingly.
* Save all input in history, not just commands. Martin's attempt to
recognize commands works only as long as the server sends prompts
faster than the user sends input. Drop that part, and update commit
message accordingly.
* Fix recv_input() not to truncate value of strlen() to int, and to
use memmove() for updating @input_from_rl in place.
* Clean up whitespace in a few places.
* Tweak commit message.
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
We need to copy input to @auxfp to implement command line option -2,
and pass it to save_input() to enable protection against a rogue
server exploiting redirection and execute. We currently do this right
when input enters the ring buffer, in recv_input().
Calling save_input() before sending input to the server is sloppy: it
can make the client accept "future" redirections and executes.
Delay save_input() until after input is sent. For simplicity, delay
copying to @auxfp as well.
This is actually pretty close to how things worked before commit
8b7d0b9 (v4.3.11).
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
On successful execute, servercmd() sets @input_fd to the batch file
descriptor. Return the file descriptor instead, and let its caller
recv_output() set @input_fd. This permits giving @input_fd static
linkage.
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
recv_input(input_fd, &inbuf) returns zero when @inbuf is full or
@input_fd is at EOF. We avoid the former by putting @input_fd in
@rdfd only when @inbuf has space, so we can detect EOF easily. But we
missed the case where adding a cookie fills up @inbuf. We
misinterpret "can't read into full buffer" as "EOF on input" then.
Fix by checking for space again.
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
The client can send an interrupt cookie after the EOF cookie.
Harmless, as the server throws away input after the EOF cookie. Clean
it up anyway.
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
We increment @send_eof only when read() returns zero, and we read()
only when it's zero. Therefore, we never increment it beyond one.
Change it from counter to flag.
This effectively reverts commit 51846ec (v4.3.11). Possible only
because the previous commit got rid of the @send_eof increment on
failed execute.
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
The server doesn't currently care for the difference, but interrupt is
more accurate than EOF. The change also enables the next commit.
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
recv_input() passes full lines to save_input(). Pass characters
instead. Simpler, and doesn't truncate long lines.
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
To protect against a rogue server reading your files, the client
honors C_EXECUTE only when it matches recent player input.
This has a somewhat troubled history, detailed in the previous commit.
The remaining major issue comes from commit 8b7d0b9 (v4.3.11): any
suffix of a recent line of input is accepted as C_EXECUTE text.
Before, only text that looked like an argument of an execute command
or a redirection was accepted.
Fix by again requiring the text to be preceded by something that looks
like an execute command. But do it more carefully: don't break
execute with a prompted for argument, and prevent abuse of
redirections for execute.
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
Redirections let the server write files and run pipelines, and execute
lets it read files.
Before 4.2.0, the client simply trusted the server. 4.2.0 added
fairly complex code to recognize redirections and execute, replace the
filenames and pipelines by tag strings, remember tag string and
replaced text, and honor redirection and execute only when their text
is a known tag string. Tag and replaced text were freed on use.
Broken by design because the client cannot know whether a line will
actually be read as a command by the server. Issues included:
(1) Non-command lines could be messed up.
(2) The memory used for remembering their tags was never freed.
(3) execute prompting for its argument was incorrectly rejected.
(4) A rogue server could use a tag for the wrong purpose. For
instance, "execute fire" creates a tag for "fire", which a rogue
server could use for a pipeline to command "ire".
4.2.10 dropped the tag strings, and used the actual text as key. This
took care of (1).
Commit 17d6997 and commit 2456a71 (both v4.3.11) tightened checking of
redirections, which took care of (4) for redirections, but not
execute. Relatively harmless, because redirection text always starts
with '>' or '|', but filenames rarely do.
Commit 8b7d0b9 (v4.3.11) replaced the protection code wholesale.
Instead of attempting to recognize redirections and execute, we now
save everything in a ring buffer, and require redirections and execute
to match at a line end in the ring buffer. Much simpler, takes care
of issues (2) and (3), but adds new issues:
(5) When sent-ahead input exceeds the ring buffer, good redirections
and executes get rejected. Could be avoided by limiting send-ahead,
or remembering input until its output arrives. However, bogus
rejections haven't been a problem in practice even with a tiny 4KiB
ring buffer.
(6) The protection against rogue execute is *much* weaker, because we
now accept any line suffix. Before, we accepted any tag,
i.e. anything that looks like a redirection or an execute command.
(7) When we find a match in the ring buffer, we used to drop
everything up to that line right away. This broke redirected execute
commands. Commit 02a9af0 (v4.3.11) fixed it by delaying the drop
until the next prompt, but that's overly complicated.
This commit addresses (7): don't drop on use, simply let new input
push old input out of the ring buffer.
The next commit will address (6) and the remainder of (4).
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
Use a "Warning: " prefix for server output violating the protocol and
for rogue redirections and executes. Don't shout "WARNING!"
In redir_authorized(), check for server issues (conflicting
redirections, rogue redirections and executes) before enforcing
restrictions (restricted mode, executing batch file), so server issues
aren't masked.
Surprisingly, popen() may not set errno on failure. Avoid reporting a
bogus errno in dopipe().
doexecute() complains about an "execute file". We call that a "batch
file" elsewhere. Reword for consistency.
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
Peeking beyond either end of the ring buffer must return EOF. We
first compute the index, then check whether it's in range.
Unfortunately, the index computation r->prod - -n can wrap around
while r->prod is still <= RING_SIZE. If it happens, ring_peek()
returns r->buf[(r->prod - -n) % RING_SIZE] instead of EOF.
Currently harmless, because no caller peeks out of range.
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
quiet_bigdef() runs for each attacker. It lets each eligible defender
fire at most once. The first time a defender is eligible, it fires
and is saved in the list of defenders, along with its firing damage.
If it's eligible again for a later attacker, it's found in the list of
defenders, and the damage is reused. The list of defenders searched
with search_flist(). Unfortunately, search_flist() compares only uid,
not type, and therefore can return a previously found defender of
another type.
If there are multiple attackers and multiple defenders with the same
uid, total damage can be off, damage can be spread to attackers out of
range, and defenders may not be charged shells. Abuse is possible,
but complicated to set up, and probably not worth the trouble.
Broken in commit f89edc7, v4.3.12. Fix by comparing the type as well.
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
The "loaded on ship" condition was useless from the start (v4.2.0).
The "loaded on land" condition became useless in commit 45d090b,
v4.3.28.
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>