Merge branch 'duke' into danger
This commit is contained in:
@@ -3,12 +3,12 @@ AC_PREREQ([2.60])
|
||||
define(_CLIENT_VERSION_MAJOR, 3)
|
||||
dnl Must be kept in sync with src/clientversion.h , ugh!
|
||||
define(_CLIENT_VERSION_MINOR, 10)
|
||||
define(_CLIENT_VERSION_REVISION, 0)
|
||||
define(_CLIENT_VERSION_REVISION, 1)
|
||||
define(_CLIENT_VERSION_BUILD, 50)
|
||||
define(_ZC_BUILD_VAL, m4_if(m4_eval(_CLIENT_VERSION_BUILD < 25), 1, m4_incr(_CLIENT_VERSION_BUILD), m4_eval(_CLIENT_VERSION_BUILD < 50), 1, m4_eval(_CLIENT_VERSION_BUILD - 24), m4_eval(_CLIENT_VERSION_BUILD == 50), 1, , m4_eval(_CLIENT_VERSION_BUILD - 50)))
|
||||
define(_CLIENT_VERSION_SUFFIX, m4_if(m4_eval(_CLIENT_VERSION_BUILD < 25), 1, _CLIENT_VERSION_REVISION-beta$1, m4_eval(_CLIENT_VERSION_BUILD < 50), 1, _CLIENT_VERSION_REVISION-rc$1, m4_eval(_CLIENT_VERSION_BUILD == 50), 1, _CLIENT_VERSION_REVISION, _CLIENT_VERSION_REVISION-$1)))
|
||||
define(_CLIENT_VERSION_IS_RELEASE, true)
|
||||
define(_COPYRIGHT_YEAR, 2023)
|
||||
define(_COPYRIGHT_YEAR, 2024)
|
||||
AC_INIT([Hush],[_CLIENT_VERSION_MAJOR._CLIENT_VERSION_MINOR._CLIENT_VERSION_SUFFIX(_ZC_BUILD_VAL)],[https://git.hush.is/hush/hush3],[hush])
|
||||
AC_CONFIG_SRCDIR([src/main.cpp])
|
||||
AC_CONFIG_HEADERS([src/config/bitcoin-config.h])
|
||||
|
||||
@@ -7,14 +7,18 @@ use strict;
|
||||
|
||||
# Given a block time, estimate when it will happen
|
||||
my $block = shift || die "Usage: $0 123";
|
||||
my $coin = shift || '';
|
||||
my $hush = "./src/hush-cli";
|
||||
unless (-e $hush) {
|
||||
die "$hush does not exist, aborting";
|
||||
}
|
||||
if ($coin) {
|
||||
$hush .= " -ac_name=$coin";
|
||||
}
|
||||
my $blockcount = qx{$hush getblockcount};
|
||||
|
||||
unless ($blockcount = int($blockcount)) {
|
||||
print "Invalid response from hush-cli\n";
|
||||
print "Invalid response from $hush\n";
|
||||
exit 1;
|
||||
}
|
||||
|
||||
@@ -22,13 +26,24 @@ if ($block <= $blockcount) {
|
||||
die "That block has already happened!";
|
||||
} else {
|
||||
my $diff = $block - $blockcount;
|
||||
my $minutes = $diff*1.25; # 75s in minutes
|
||||
my $minpb = 1.25; # 75s in minutes for HUSH3
|
||||
if ($coin eq 'DRAGONX') {
|
||||
$minpb = 0.6; # minutes per block
|
||||
} elsif ($coin) {
|
||||
# TODO: support custom bloctimes
|
||||
$minpb = 1; # assumes default blocktime of 60s
|
||||
}
|
||||
my $minutes = $diff*$minpb;
|
||||
my $seconds = $minutes*60;
|
||||
my $now = time;
|
||||
my $then = $now + $seconds;
|
||||
my $ldate = localtime($then);
|
||||
my $gmdate = gmtime($then);
|
||||
print "Hush Block $block will happen at roughly:\n";
|
||||
if ($coin) {
|
||||
print "$coin Block $block will happen at roughly:\n";
|
||||
} else {
|
||||
print "Hush Block $block will happen at roughly:\n";
|
||||
}
|
||||
print "$ldate Eastern # $then\n";
|
||||
print "$gmdate GMT # $then\n";
|
||||
}
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
package=boost
|
||||
|
||||
$(package)_version=1_72_0
|
||||
$(package)_download_path=https://boostorg.jfrog.io/artifactory/main/release/$(subst _,.,$($(package)_version))/source/
|
||||
#$(package)_download_path=https://boostorg.jfrog.io/artifactory/main/release/$(subst _,.,$($(package)_version))/source/
|
||||
#$(package)_file_name=$(package)_$($(package)_version).tar.bz2
|
||||
$(package)_sha256_hash=59c9b274bc451cf91a9ba1dd2c7fdcaf5d60b1b3aa83f2c9fa143417cc660722
|
||||
$(package)_file_name=$(package)_$($(package)_version).tar.bz2
|
||||
$(package)_download_path=https://git.hush.is/attachments
|
||||
$(package)_file_name=7b13759e-8623-4e48-ae08-f78502f4b6a5
|
||||
$(package)_download_file=7b13759e-8623-4e48-ae08-f78502f4b6a5
|
||||
$(package)_patches=fix-Solaris.patch
|
||||
|
||||
define $(package)_set_vars
|
||||
|
||||
@@ -14,7 +14,7 @@ $(package)_dependencies=wolfssl
|
||||
$(package)_download_path=https://curl.haxx.se/download
|
||||
$(package)_config_opts_linux=--disable-shared --enable-static --without-ssl --prefix=$(host_prefix) --host=$(host)
|
||||
$(package)_config_opts_mingw32=--enable-mingw --disable-shared --enable-static --with-wolfssl --without-ssl --prefix=$(host_prefix) --host=x86_64-w64-mingw32
|
||||
$(package)_config_opts_darwin=--disable-shared --enable-static --with-wolfssl --without-ssl --prefix=$(host_prefix)
|
||||
$(package)_config_opts_darwin=--disable-shared --enable-static --without-ssl --prefix=$(host_prefix)
|
||||
$(package)_cflags_darwin=-mmacosx-version-min=10.9
|
||||
$(package)_conf_tool=./configure
|
||||
|
||||
|
||||
115
doc/cjdns.md
Normal file
115
doc/cjdns.md
Normal file
@@ -0,0 +1,115 @@
|
||||
# CJDNS support in Hush
|
||||
|
||||
It is possible to run Hush over CJDNS, an encrypted IPv6 network that
|
||||
uses public-key cryptography for address allocation and a distributed hash table
|
||||
for routing.
|
||||
|
||||
## What is CJDNS?
|
||||
|
||||
CJDNS is like a distributed, shared VPN with multiple entry points where every
|
||||
participant can reach any other participant. All participants use addresses from
|
||||
the `fc00::/8` network (reserved IPv6 range). Installation and configuration is
|
||||
done outside of Hush, similarly to a VPN (either in the host/OS or on
|
||||
the network router). See https://github.com/cjdelisle/cjdns#readme and
|
||||
https://github.com/hyperboria/docs#hyperboriadocs for more information.
|
||||
|
||||
Compared to IPv4/IPv6, CJDNS provides end-to-end encryption and protects nodes
|
||||
from traffic analysis and filtering.
|
||||
|
||||
Used with Tor and I2P, CJDNS is a complementary option that can enhance network
|
||||
redundancy and robustness for both the Hush network and individual nodes.
|
||||
|
||||
Each network has different characteristics. For instance, Tor is widely used but
|
||||
somewhat centralized. I2P connections have a source address and I2P is slow.
|
||||
CJDNS is fast but does not hide the sender and the recipient from intermediate
|
||||
routers.
|
||||
|
||||
## Installing CJDNS and finding a peer to connect to the network
|
||||
|
||||
To install and set up CJDNS, follow the instructions at
|
||||
https://github.com/cjdelisle/cjdns#how-to-install-cjdns.
|
||||
|
||||
You need to initiate an outbound connection to a peer on the CJDNS network
|
||||
before it will work with your Hush node. This is described in steps
|
||||
["2. Find a friend"](https://github.com/cjdelisle/cjdns#2-find-a-friend) and
|
||||
["3. Connect your node to your friend's
|
||||
node"](https://github.com/cjdelisle/cjdns#3-connect-your-node-to-your-friends-node)
|
||||
in the CJDNS documentation.
|
||||
|
||||
One quick way to accomplish these two steps is to query for available public
|
||||
peers on [Hyperboria](https://github.com/hyperboria) by running the following:
|
||||
|
||||
```
|
||||
git clone https://github.com/hyperboria/peers hyperboria-peers
|
||||
cd hyperboria-peers
|
||||
./testAvailable.py
|
||||
```
|
||||
|
||||
For each peer, the `./testAvailable.py` script prints the filename of the peer's
|
||||
credentials followed by the ping result.
|
||||
|
||||
Choose one or several peers, copy their credentials from their respective files,
|
||||
paste them into the relevant IPv4 or IPv6 "connectTo" JSON object in the
|
||||
`cjdroute.conf` file you created in step ["1. Generate a new configuration
|
||||
file"](https://github.com/cjdelisle/cjdns#1-generate-a-new-configuration-file),
|
||||
and save the file.
|
||||
|
||||
## Launching CJDNS
|
||||
|
||||
Typically, CJDNS might be launched from its directory with
|
||||
`sudo ./cjdroute < cjdroute.conf` and it sheds permissions after setting up the
|
||||
[TUN](https://en.wikipedia.org/wiki/TUN/TAP) interface. You may also [launch it as an
|
||||
unprivileged user](https://github.com/cjdelisle/cjdns/blob/master/doc/non-root-user.md)
|
||||
with some additional setup.
|
||||
|
||||
The network connection can be checked by running `./tools/peerStats` from the
|
||||
CJDNS directory.
|
||||
|
||||
## Run Hush with CJDNS
|
||||
|
||||
Once you are connected to the CJDNS network, the following Hush
|
||||
configuration option makes CJDNS peers automatically reachable:
|
||||
|
||||
```
|
||||
-cjdnsreachable
|
||||
```
|
||||
|
||||
When enabled, this option tells Hush that it is running in an
|
||||
environment where a connection to an `fc00::/8` address will be to the CJDNS
|
||||
network instead of to an [RFC4193](https://datatracker.ietf.org/doc/html/rfc4193)
|
||||
IPv6 local network. This helps Hush perform better address management:
|
||||
- Your node can consider incoming `fc00::/8` connections to be from the CJDNS
|
||||
network rather than from an IPv6 private one.
|
||||
- If one of your node's local addresses is `fc00::/8`, then it can choose to
|
||||
gossip that address to peers.
|
||||
|
||||
## Additional configuration options related to CJDNS
|
||||
|
||||
```
|
||||
-onlynet=cjdns
|
||||
```
|
||||
|
||||
Make automatic outbound connections only to CJDNS addresses. Inbound and manual
|
||||
connections are not affected by this option. It can be specified multiple times
|
||||
to allow multiple networks, e.g. onlynet=cjdns, onlynet=i2p, onlynet=onion.
|
||||
|
||||
CJDNS support was added to Hush in version 3.9.3 and there may be fewer
|
||||
CJDNS peers than Tor or IP ones. You can use `hush-cli -addrinfo` to see the
|
||||
number of CJDNS addresses known to your node.
|
||||
|
||||
In general, a node can be run with both an onion service and CJDNS (or any/all
|
||||
of IPv4/IPv6/onion/I2P/CJDNS), which can provide a potential fallback if one of
|
||||
the networks has issues. There are a number of ways to configure this; see
|
||||
[doc/tor.md](https://git.hush.is/hush/hush3/src/branch/master/doc/tor.md) for
|
||||
details.
|
||||
|
||||
## CJDNS-related information in Hush
|
||||
|
||||
There are several ways to see your CJDNS address in Hush:
|
||||
- in the "Local addresses" output of CLI `-netinfo`
|
||||
- in the "localaddresses" output of RPC `getnetworkinfo`
|
||||
|
||||
To see which CJDNS peers your node is connected to, use `hush-cli -netinfo 4`
|
||||
or the `getpeerinfo` RPC (i.e. `hush-cli getpeerinfo`).
|
||||
|
||||
You can use the `getnodeaddresses` RPC to fetch a number of CJDNS peers known to your node; run `hush-cli help getnodeaddresses` for details.
|
||||
@@ -38,10 +38,30 @@ Defaults to 1. This is a default option that should not be changed or things wil
|
||||
|
||||
Defaults to 0. This option enables the "shielded index" which also calculates the "anonset" (anonymity set) also known as the "shielded pool". This data is avaailable in the getchaintxstats RPC, if zindex is enabled. Enabling this feature requires a full rescan or full sync from scratch, which is not done by default. If you don't do one of those things, your zindex stats will be incorrect.
|
||||
|
||||
# Mining options
|
||||
# Mining and Stratum server options
|
||||
|
||||
These options are only of interest to solo miners and mining pool operators....
|
||||
|
||||
## stratum
|
||||
|
||||
Defaults to off. This option enables a Stratum server.
|
||||
|
||||
## stratumaddress=<address>
|
||||
|
||||
Defaults to none. This option sets a Stratum Mining address to use when special address of 'x' is sent by miner.
|
||||
|
||||
## stratumbind=<ipaddr>
|
||||
|
||||
Defaults to: bind to all interfaces. This option Binds to given address to listen for Stratum work requests. Use [host]:port notation for IPv6. This option can be specified multiple times.
|
||||
|
||||
## stratumport=<port>
|
||||
|
||||
Defaults to 19031 or 19031 for testnet. This option sets the <port> to listen for Stratum work requests on.
|
||||
|
||||
## stratumallowip=<ip>
|
||||
|
||||
No default. This option allows Stratum work requests from specified source. Valid for <ip> are a single IP (e.g. 1.2.3.4), a network/netmask (e.g. 1.2.3.4/255.255.255.0) or a network/CIDR (e.g. 1.2.3.4/24). This option can be specified multiple times.
|
||||
|
||||
# Other options
|
||||
|
||||
These options are not commonly used and likely on for advanced users and/or developers...
|
||||
@@ -56,4 +76,4 @@ Defaults to 0 in hushd, defaults to 1 in some GUI wallets. Maintain a timestamp
|
||||
|
||||
## spentindex=1
|
||||
|
||||
Defaults to 0 in hushd, defaults to 1 in some GUI wallets. Maintain a full spent index, used to query the spending txid and input index for an outpoint
|
||||
Defaults to 0 in hushd, defaults to 1 in some GUI wallets. Maintain a full spent index, used to query the spending txid and input index for an outpoint
|
||||
|
||||
73
doc/i2p.md
73
doc/i2p.md
@@ -33,12 +33,10 @@ configuration options:
|
||||
none)
|
||||
|
||||
-i2pacceptincoming
|
||||
If set and -i2psam is also set then incoming I2P connections are
|
||||
accepted via the SAM proxy. If this is not set but -i2psam is set
|
||||
then only outgoing connections will be made to the I2P network.
|
||||
Ignored if -i2psam is not set. Listening for incoming I2P
|
||||
connections is done through the SAM proxy, not by binding to a
|
||||
local address and port (default: 1)
|
||||
Whether to accept inbound I2P connections (default: 1). Ignored if
|
||||
-i2psam is not set. Listening for inbound I2P connections is
|
||||
done through the SAM proxy, not by binding to a local address and
|
||||
port.
|
||||
```
|
||||
|
||||
In a typical situation, this suffices:
|
||||
@@ -56,6 +54,36 @@ connections if `-i2pacceptincoming=1`. If `-i2pacceptincoming=0` then only
|
||||
outbound I2P connections are made and a different transient I2P address is used
|
||||
for each connection to improve privacy.
|
||||
|
||||
## Additional configuration options related to I2P
|
||||
|
||||
```
|
||||
-debug=i2p
|
||||
```
|
||||
|
||||
Set the `debug=i2p` config logging option to see additional information in the
|
||||
debug log about your I2P configuration and connections.
|
||||
|
||||
```
|
||||
-onlynet=i2p
|
||||
```
|
||||
|
||||
Make automatic outbound connections only to I2P addresses. Inbound and manual
|
||||
connections are not affected by this option. It can be specified multiple times
|
||||
to allow multiple networks, e.g. onlynet=onion, onlynet=i2p.
|
||||
|
||||
I2P support was added to Hush in version 3.9.3 and there may be fewer I2P
|
||||
peers than Tor or IP ones. Therefore, using I2P alone without other networks may
|
||||
make a node more susceptible to [Sybil
|
||||
attacks](https://en.bitcoin.it/wiki/Weaknesses#Sybil_attack).
|
||||
|
||||
Another consideration with `onlynet=i2p` is that the initial blocks download
|
||||
phase when syncing up a new node can be very slow. This phase can be sped up by
|
||||
using other networks, for instance `onlynet=onion`, at the same time.
|
||||
|
||||
In general, a node can be run with both onion and I2P hidden services (or
|
||||
any/all of IPv4/IPv6/onion/I2P/CJDNS), which can provide a potential fallback if
|
||||
one of the networks has issues.
|
||||
|
||||
## Persistent vs transient I2P addresses
|
||||
|
||||
In I2P connections, the connection receiver sees the I2P address of the
|
||||
@@ -136,14 +164,19 @@ port (`TO_PORT`) is always set to 0 and is not in the control of Hush.
|
||||
|
||||
## Bandwidth
|
||||
|
||||
I2P routers may route a large amount of general network traffic with their
|
||||
default settings. Check your router's configuration to limit the amount of this
|
||||
traffic relayed, if desired.
|
||||
By default, your node shares bandwidth and transit tunnels with the I2P network
|
||||
in order to increase your anonymity with cover traffic, help the I2P router used
|
||||
by your node integrate optimally with the network, and give back to the network.
|
||||
It's important that the nodes of a popular application like Hush contribute
|
||||
as much to the I2P network as they consume.
|
||||
|
||||
With `i2pd`, the amount of bandwidth being shared with the wider network can be
|
||||
adjusted with the `bandwidth`, `share` and `transittunnels` options in your
|
||||
`i2pd.conf` file. For example, to limit total I2P traffic to 256KB/s and share
|
||||
50% of this limit for a maximum of 20 transit tunnels:
|
||||
It is possible, though strongly discouraged, to change your I2P router
|
||||
configuration to limit the amount of I2P traffic relayed by your node.
|
||||
|
||||
With `i2pd`, this can be done by adjusting the `bandwidth`, `share` and
|
||||
`transittunnels` options in your `i2pd.conf` file. For example, to limit total
|
||||
I2P traffic to 256KB/s and share 50% of this limit for a maximum of 20 transit
|
||||
tunnels:
|
||||
|
||||
```
|
||||
bandwidth = 256
|
||||
@@ -153,9 +186,15 @@ share = 50
|
||||
transittunnels = 20
|
||||
```
|
||||
|
||||
If you prefer not to relay any public I2P traffic and only permit I2P traffic
|
||||
from programs which are connecting via the SAM proxy, e.g. Hush, you
|
||||
can set the `notransit` option to `true`.
|
||||
|
||||
Similar bandwidth configuration options for the Java I2P router can be found in
|
||||
`http://127.0.0.1:7657/config` under the "Bandwidth" tab.
|
||||
|
||||
Before doing this, please see the "Participating Traffic Considerations" section
|
||||
in [Embedding I2P in your Application](https://geti2p.net/en/docs/applications/embedding).
|
||||
|
||||
In most cases, the default router settings should work fine.
|
||||
|
||||
## Bundling I2P in a Hush application
|
||||
|
||||
Please see the "General Guidance for Developers" section in https://geti2p.net/en/docs/api/samv3
|
||||
if you are developing a downstream application that may be bundling I2P with Hush.
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.6.
|
||||
.TH HUSH-CLI "1" "June 2023" "hush-cli v3.9.4" "User Commands"
|
||||
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.13.
|
||||
.TH HUSH-CLI "1" "January 2024" "hush-cli v3.10.1" "User Commands"
|
||||
.SH NAME
|
||||
hush-cli \- manual page for hush-cli v3.9.4
|
||||
hush-cli \- manual page for hush-cli v3.10.1
|
||||
.SH DESCRIPTION
|
||||
Hush RPC client version v3.9.4\-44595d5ab
|
||||
Hush RPC client version v3.10.1\-05ee31891\-dirty
|
||||
.PP
|
||||
In order to ensure you are adequately protecting your privacy when using Hush,
|
||||
please see <https://hush.is/security/>.
|
||||
@@ -75,7 +75,7 @@ Read extra arguments from standard input, one per line until EOF/Ctrl\-D
|
||||
In order to ensure you are adequately protecting your privacy when using Hush,
|
||||
please see <https://hush.is/security/>.
|
||||
|
||||
Copyright (C) 2016-2023 Duke Leto and The Hush Developers
|
||||
Copyright (C) 2016-2024 Duke Leto and The Hush Developers
|
||||
|
||||
Copyright (C) 2016-2020 jl777 and SuperNET developers
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.6.
|
||||
.TH HUSH-TX "1" "June 2023" "hush-tx v3.9.4" "User Commands"
|
||||
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.13.
|
||||
.TH HUSH-TX "1" "January 2024" "hush-tx v3.10.1" "User Commands"
|
||||
.SH NAME
|
||||
hush-tx \- manual page for hush-tx v3.9.4
|
||||
hush-tx \- manual page for hush-tx v3.10.1
|
||||
.SH DESCRIPTION
|
||||
hush\-tx utility version v3.9.4\-44595d5ab
|
||||
hush\-tx utility version v3.10.1\-05ee31891\-dirty
|
||||
.SS "Usage:"
|
||||
.TP
|
||||
hush\-tx [options] <hex\-tx> [commands]
|
||||
@@ -89,7 +89,7 @@ Set register NAME to given JSON\-STRING
|
||||
In order to ensure you are adequately protecting your privacy when using Hush,
|
||||
please see <https://hush.is/security/>.
|
||||
|
||||
Copyright (C) 2016-2023 Duke Leto and The Hush Developers
|
||||
Copyright (C) 2016-2024 Duke Leto and The Hush Developers
|
||||
|
||||
Copyright (C) 2016-2020 jl777 and SuperNET developers
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.6.
|
||||
.TH HUSHD "1" "June 2023" "hushd v3.9.4" "User Commands"
|
||||
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.13.
|
||||
.TH HUSHD "1" "January 2024" "hushd v3.10.1" "User Commands"
|
||||
.SH NAME
|
||||
hushd \- manual page for hushd v3.9.4
|
||||
hushd \- manual page for hushd v3.10.1
|
||||
.SH DESCRIPTION
|
||||
Hush Daemon version v3.9.4\-44595d5ab
|
||||
Hush Daemon version v3.10.1\-05ee31891\-dirty
|
||||
.PP
|
||||
In order to ensure you are adequately protecting your privacy when using Hush,
|
||||
please see <https://hush.is/security/>.
|
||||
@@ -78,7 +78,7 @@ applied)
|
||||
.HP
|
||||
\fB\-par=\fR<n>
|
||||
.IP
|
||||
Set the number of script verification threads (\fB\-6\fR to 16, 0 = auto, <0 =
|
||||
Set the number of script verification threads (\fB\-8\fR to 16, 0 = auto, <0 =
|
||||
leave that many cores free, default: 0)
|
||||
.HP
|
||||
\fB\-pid=\fR<file>
|
||||
@@ -336,6 +336,10 @@ Set key pool size to <n> (default: 100)
|
||||
.IP
|
||||
Enable auto Sapling note consolidation (default: false)
|
||||
.HP
|
||||
\fB\-consolidationinterval\fR
|
||||
.IP
|
||||
Block interval between consolidations (default: 25)
|
||||
.HP
|
||||
\fB\-consolidatesaplingaddress=\fR<zaddr>
|
||||
.IP
|
||||
Specify Sapling Address to Consolidate. (default: all)
|
||||
@@ -767,7 +771,7 @@ Enforce transaction\-rate limit, default 0
|
||||
In order to ensure you are adequately protecting your privacy when using Hush,
|
||||
please see <https://hush.is/security/>.
|
||||
|
||||
Copyright (C) 2016-2023 Duke Leto and The Hush Developers
|
||||
Copyright (C) 2016-2024 Duke Leto and The Hush Developers
|
||||
|
||||
Copyright (C) 2016-2020 jl777 and SuperNET developers
|
||||
|
||||
|
||||
@@ -14,7 +14,24 @@ Equihash (200,9) (ASIC)
|
||||
|
||||
## P2P
|
||||
|
||||
TLS1.3 via WolfSSL is enforced for all network connections as of v3.6.1
|
||||
TLS1.3 via WolfSSL is enforced for all network connections as of v3.6.1 .
|
||||
Many ciphersuites are technically supported by TLS1.3 but many of them
|
||||
are ancient, proved to be less secure than intended or likely backdoored.
|
||||
Hush only uses what are widely considered to be the most secure and [best ciphersuites](https://ciphersuite.info/cs/).
|
||||
|
||||
New Hush P2P connections randomly choose between these two ciphersuites each
|
||||
time a new connection to a peer is created:
|
||||
|
||||
* `TLS_AES_256_GCM_SHA384`
|
||||
* `TLS_CHACHA20_POLY1305_SHA256`
|
||||
|
||||
Encrypted P2P connections are important because it means passive network spies,
|
||||
such as ISPs, cannot tell what nodes are communicating to each other and also
|
||||
prevents certain attacks against privacy at the network level, such as looking
|
||||
for which node was the first to relay a transaction. Bitcoin has no protection
|
||||
against this which is why it's trivial for network spies to tell which node
|
||||
(and hence which IP address) created a certain transaction and hence which
|
||||
IP address owns which addresses.
|
||||
|
||||
## RPC
|
||||
|
||||
|
||||
@@ -26,7 +26,8 @@ If the last command has no output, congrats, there is nothing to do. If the last
|
||||
```
|
||||
git checkout master
|
||||
git merge --no-ff dev # using the default commit message is fine
|
||||
git push origin master
|
||||
git tag vX.Y.Z # this creates a tag vX.Y.Z on current master, or you can let gitea do it later
|
||||
git push --tags origin master
|
||||
git checkout dev
|
||||
git merge master
|
||||
git push origin dev
|
||||
@@ -129,4 +130,4 @@ Use `./util/build-debian-package.sh aarch64` to build a Debian package for aarch
|
||||
|
||||
### Updating RandomX
|
||||
|
||||
If you need to update the source code of our in tree copy of RandomX, see issue https://git.hush.is/hush/hush3/issues/337#issuecomment-5114 for details. Currently we use RandomX v1.2.1 from the official repo at https://github.com/tevador/RandomX/releases/tag/v1.2.1
|
||||
If you need to update the source code of our in tree copy of RandomX, see issue https://git.hush.is/hush/hush3/issues/337#issuecomment-5114 for details. Currently we use RandomX v1.2.1 from the official repo at https://github.com/tevador/RandomX/releases/tag/v1.2.1
|
||||
|
||||
@@ -10,12 +10,35 @@ and no longer on Github, since they banned Duke Leto and
|
||||
also because they censor many people around the world and work with
|
||||
evil organizations.
|
||||
|
||||
# Hush 3.10.0 ""
|
||||
# Hush 3.10.1 "Oneiric Octopus"
|
||||
|
||||
This is a MANDATORY release for Hush and nodes must upgrade by block height X, which will happen
|
||||
on approximately Y. This is an OPTIONAL release for DragonX but it is highly recommended for
|
||||
exchanges, solo miners and mining pools to update to this release.
|
||||
This is an OPTIONAL but RECOMMENDED release for Hush full nodes. It fixes an important bug
|
||||
that affects new Hush nodes. It also makes syncing faster for both Hushd and DragonX nodes.
|
||||
|
||||
```
|
||||
26 files changed, 257 insertions(+), 429 deletions(-)
|
||||
```
|
||||
|
||||
* Fix the bug which causes "payment to wrong pubkey" error when syncing a new node
|
||||
* Faster syncing of Hush and DragonX full nodes
|
||||
* Slightly less memory usage in each Equihash/RandomX mining thread
|
||||
* Fixed compiling issues related to RandomX v1.2.1
|
||||
* Improved RPC docs for `getblocktemplate`
|
||||
* Removed the `getdeprecationinfo` RPC
|
||||
|
||||
|
||||
# Hush 3.10.0 "Sassy Siphonophore"
|
||||
|
||||
```
|
||||
132 files changed, 6387 insertions(+), 2084 deletions(-)
|
||||
```
|
||||
|
||||
This is a MANDATORY release for Hush and *ALL* nodes must upgrade by block height 1605555, which will happen
|
||||
on approximately Dec 16th 2023. YOU MUST UPGRADE YOUR HUSH FULL NODE TO THIS RELEASE BY DEC 15th 2023.
|
||||
If you do not, your node will not work correctly and will require a fresh sync to fix.
|
||||
|
||||
This is an OPTIONAL release for DragonX but it is highly recommended for miners and exchanges
|
||||
to update to this release.
|
||||
|
||||
* Hush and all Hush Smart Chains now use less RAM https://git.hush.is/hush/hush3/issues/283
|
||||
* Hush full nodes will use ~2GB less RAM
|
||||
@@ -26,8 +49,11 @@ exchanges, solo miners and mining pools to update to this release.
|
||||
* Fix a bug where `hush-cli stop` would not stop the node during the "Building Witnesses" rescan phase https://git.hush.is/hush/hush3/issues/330
|
||||
* Fix bugs where `abortrescan` couldn't be used when node is start up (RPC warmup) and where it could not abort the rescan if it was in the "Building Witnesses" phase https://git.hush.is/hush/hush3/issues/331
|
||||
* Fix bug in `z_mergetoaddress` where docs said you could use `ANY_ZADDR` but you couldn't https://git.hush.is/hush/hush3/commit/7eb9d75b94469c3fc8c028f29b35be9ac764a10c
|
||||
* RPC `z_listunspent` now returns the text representation of a memo in `memoStr` key
|
||||
* Upgraded curl to 8.4.0 https://git.hush.is/hush/hush3/issues/325
|
||||
* This fixes CVE-2023-38545 which affects very few or potentially no Hush/DragonX users. It could only affect people who compile Hush full node software (not those who use binaries or packages) and who use a malicious SOCKS5 proxy for all network traffic via the operating system.
|
||||
* New documentation about using CJDNS with Hush: https://git.hush.is/hush/hush3/src/branch/dev/doc/cjdns.md
|
||||
* Decentralized Devtax for improved scalability and operational security. This is a consensus change.
|
||||
* DragonX specific changes:
|
||||
* Updated to latest RandomX v1.2.1 which includes mining optimizations https://git.hush.is/hush/hush3/commit/6029b3d571009991ae9c4aea0397f4d00be6a817 https://git.hush.is/hush/hush3/issues/337
|
||||
* Fix RandomX mining memory leak and crash https://git.hush.is/hush/hush3/issues/324
|
||||
@@ -38,7 +64,6 @@ exchanges, solo miners and mining pools to update to this release.
|
||||
* For instance, many RPCs such as `dragonx z_sendmany ...` would not previously work because the arguments to the RPC were not quoted correctly.
|
||||
|
||||
|
||||
|
||||
# Hush 3.9.4 "Maniacal Manticore"
|
||||
|
||||
```
|
||||
|
||||
@@ -221,7 +221,7 @@ class WalletTest (BitcoinTestFramework):
|
||||
for uTx in unspentTxs:
|
||||
if uTx['txid'] == zeroValueTxid:
|
||||
found = True
|
||||
assert_equal(uTx['amount'], Decimal('0.00000000'))
|
||||
assert_equal(uTx['amount'], Decimal('0'))
|
||||
assert(found)
|
||||
|
||||
#do some -walletbroadcast tests
|
||||
|
||||
@@ -165,7 +165,6 @@ BITCOIN_CORE_H = \
|
||||
consensus/validation.h \
|
||||
core_io.h \
|
||||
core_memusage.h \
|
||||
deprecation.h \
|
||||
fs.h \
|
||||
hash.h \
|
||||
httprpc.h \
|
||||
@@ -273,26 +272,15 @@ libbitcoin_server_a_SOURCES = \
|
||||
asyncrpcqueue.cpp \
|
||||
bloom.cpp \
|
||||
cc/eval.cpp \
|
||||
cc/import.cpp \
|
||||
cc/importgateway.cpp \
|
||||
cc/CCassetsCore.cpp \
|
||||
cc/CCcustom.cpp \
|
||||
cc/CCtx.cpp \
|
||||
cc/CCutils.cpp \
|
||||
cc/CCtokens.cpp \
|
||||
cc/assets.cpp \
|
||||
cc/faucet.cpp \
|
||||
cc/rewards.cpp \
|
||||
cc/dice.cpp \
|
||||
cc/lotto.cpp \
|
||||
cc/fsm.cpp \
|
||||
cc/heir.cpp \
|
||||
cc/oracles.cpp \
|
||||
cc/prices.cpp \
|
||||
cc/pegs.cpp \
|
||||
cc/payments.cpp \
|
||||
cc/gateways.cpp \
|
||||
cc/channels.cpp \
|
||||
cc/auction.cpp \
|
||||
cc/betprotocol.cpp \
|
||||
chain.cpp \
|
||||
@@ -300,7 +288,6 @@ libbitcoin_server_a_SOURCES = \
|
||||
fs.cpp \
|
||||
crosschain.cpp \
|
||||
crosschain_authority.cpp \
|
||||
deprecation.cpp \
|
||||
httprpc.cpp \
|
||||
httpserver.cpp \
|
||||
i2p.cpp \
|
||||
@@ -349,7 +336,6 @@ libbitcoin_wallet_a_SOURCES = \
|
||||
zcash/Note.cpp \
|
||||
transaction_builder.cpp \
|
||||
wallet/rpcdump.cpp \
|
||||
cc/CCtokens.cpp \
|
||||
cc/CCassetsCore.cpp \
|
||||
cc/CCassetstx.cpp \
|
||||
cc/CCtx.cpp \
|
||||
@@ -416,7 +402,6 @@ libbitcoin_common_a_SOURCES = \
|
||||
core_read.cpp \
|
||||
core_write.cpp \
|
||||
hash.cpp \
|
||||
importcoin.cpp \
|
||||
key.cpp \
|
||||
key_io.cpp \
|
||||
keystore.cpp \
|
||||
@@ -473,10 +458,6 @@ if GLIBC_BACK_COMPAT
|
||||
libbitcoin_util_a_SOURCES += compat/glibc_compat.cpp
|
||||
endif
|
||||
|
||||
if ENABLE_TESTS
|
||||
libbitcoin_server_a_SOURCES += rpc/testtransactions.cpp
|
||||
endif
|
||||
|
||||
|
||||
# cli
|
||||
libbitcoin_cli_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
|
||||
@@ -723,7 +704,7 @@ endif
|
||||
$(AM_V_GEN) $(PROTOC) --cpp_out=$(@D) --proto_path=$(abspath $(<D) $<)
|
||||
|
||||
if ENABLE_TESTS
|
||||
include Makefile.test-hush.include
|
||||
#include Makefile.test-hush.include
|
||||
#include Makefile.test.include
|
||||
#include Makefile.gtest.include
|
||||
endif
|
||||
|
||||
@@ -96,7 +96,7 @@ function(add_flag flag)
|
||||
endfunction()
|
||||
|
||||
# x86-64
|
||||
if ((CMAKE_SIZEOF_VOID_P EQUAL 8) AND (ARCH_ID STREQUAL "x86_64" OR ARCH_ID STREQUAL "x86-64" OR ARCH_ID STREQUAL "amd64"))
|
||||
if (ARCH_ID STREQUAL "x86_64" OR ARCH_ID STREQUAL "x86-64" OR ARCH_ID STREQUAL "amd64")
|
||||
list(APPEND randomx_sources
|
||||
src/jit_compiler_x86.cpp)
|
||||
|
||||
|
||||
@@ -148,9 +148,9 @@ void* allocMemoryPages(size_t bytes) {
|
||||
mem = NULL;
|
||||
#if defined(USE_PTHREAD_JIT_WP) && defined(MAC_OS_VERSION_11_0) \
|
||||
&& MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_VERSION_11_0
|
||||
if (__builtin_available(macOS 11.0, *)) {
|
||||
//if (__builtin_available(macOS 11.0, *)) {
|
||||
pthread_jit_write_protect_np(0);
|
||||
}
|
||||
//}
|
||||
#endif
|
||||
#endif
|
||||
return mem;
|
||||
@@ -173,11 +173,11 @@ void setPagesRW(void* ptr, size_t bytes) {
|
||||
char *errfunc;
|
||||
#if defined(USE_PTHREAD_JIT_WP) && defined(MAC_OS_VERSION_11_0) \
|
||||
&& MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_VERSION_11_0
|
||||
if (__builtin_available(macOS 11.0, *)) {
|
||||
//if (__builtin_available(macOS 11.0, *)) {
|
||||
pthread_jit_write_protect_np(0);
|
||||
} else {
|
||||
pageProtect(ptr, bytes, PAGE_READWRITE, &errfunc);
|
||||
}
|
||||
//} else {
|
||||
// pageProtect(ptr, bytes, PAGE_READWRITE, &errfunc);
|
||||
//}
|
||||
#else
|
||||
pageProtect(ptr, bytes, PAGE_READWRITE, &errfunc);
|
||||
#endif
|
||||
@@ -187,12 +187,12 @@ void setPagesRX(void* ptr, size_t bytes) {
|
||||
char *errfunc;
|
||||
#if defined(USE_PTHREAD_JIT_WP) && defined(MAC_OS_VERSION_11_0) \
|
||||
&& MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_VERSION_11_0
|
||||
if (__builtin_available(macOS 11.0, *)) {
|
||||
//if (__builtin_available(macOS 11.0, *)) {
|
||||
pthread_jit_write_protect_np(1);
|
||||
__builtin___clear_cache((char*)ptr, ((char*)ptr) + bytes);
|
||||
} else {
|
||||
pageProtect(ptr, bytes, PAGE_EXECUTE_READ, &errfunc);
|
||||
}
|
||||
//} else {
|
||||
// pageProtect(ptr, bytes, PAGE_EXECUTE_READ, &errfunc);
|
||||
//}
|
||||
#else
|
||||
pageProtect(ptr, bytes, PAGE_EXECUTE_READ, &errfunc);
|
||||
#endif
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
// Copyright (c) 2016-2023 The Hush developers
|
||||
// Distributed under the GPLv3 software license, see the accompanying
|
||||
// file COPYING or https://www.gnu.org/licenses/gpl-3.0.en.html
|
||||
/******************************************************************************
|
||||
* Copyright © 2014-2019 The SuperNET Developers. *
|
||||
* *
|
||||
* See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at *
|
||||
* the top-level directory of this distribution for the individual copyright *
|
||||
* holder information and the developer policies on copyright and licensing. *
|
||||
* *
|
||||
* Unless otherwise agreed in a custom licensing agreement, no part of the *
|
||||
* SuperNET software, including this file may be copied, modified, propagated *
|
||||
* or distributed except according to the terms contained in the LICENSE file *
|
||||
* *
|
||||
* Removal or modification of this copyright notice is prohibited. *
|
||||
* *
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef CC_GATEWAYS_H
|
||||
#define CC_GATEWAYS_H
|
||||
|
||||
#include "CCinclude.h"
|
||||
|
||||
bool GatewaysValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn);
|
||||
UniValue GatewaysBind(const CPubKey& pk, uint64_t txfee,std::string coin,uint256 tokenid,int64_t totalsupply,uint256 oracletxid,uint8_t M,uint8_t N,std::vector<CPubKey> pubkeys,uint8_t p1,uint8_t p2,uint8_t p3,uint8_t p4);
|
||||
UniValue GatewaysDeposit(const CPubKey& pk, uint64_t txfee,uint256 bindtxid,int32_t height,std::string refcoin,uint256 cointxid,int32_t claimvout,std::string deposithex,std::vector<uint8_t>proof,CPubKey destpub,int64_t amount);
|
||||
UniValue GatewaysClaim(const CPubKey& pk, uint64_t txfee,uint256 bindtxid,std::string refcoin,uint256 deposittxid,CPubKey destpub,int64_t amount);
|
||||
UniValue GatewaysWithdraw(const CPubKey& pk, uint64_t txfee,uint256 bindtxid,std::string refcoin,CPubKey withdrawpub,int64_t amount);
|
||||
UniValue GatewaysPartialSign(const CPubKey& pk, uint64_t txfee,uint256 txidaddr,std::string refcoin,std::string hex);
|
||||
UniValue GatewaysCompleteSigning(const CPubKey& pk, uint64_t txfee,uint256 txidaddr,std::string refcoin,std::string hex);
|
||||
UniValue GatewaysMarkDone(const CPubKey& pk, uint64_t txfee,uint256 withdrawtxid,std::string refcoin);
|
||||
UniValue GatewaysPendingDeposits(const CPubKey& pk, uint256 bindtxid,std::string refcoin);
|
||||
UniValue GatewaysPendingWithdraws(const CPubKey& pk, uint256 bindtxid,std::string refcoin);
|
||||
UniValue GatewaysProcessedWithdraws(const CPubKey& pk, uint256 bindtxid,std::string refcoin);
|
||||
|
||||
// CCcustom
|
||||
UniValue GatewaysInfo(uint256 bindtxid);
|
||||
UniValue GatewaysExternalAddress(uint256 bindtxid,CPubKey pubkey);
|
||||
UniValue GatewaysDumpPrivKey(uint256 bindtxid,CKey privkey);
|
||||
UniValue GatewaysList();
|
||||
|
||||
#endif
|
||||
@@ -1,46 +0,0 @@
|
||||
// Copyright (c) 2016-2023 The Hush developers
|
||||
// Distributed under the GPLv3 software license, see the accompanying
|
||||
// file COPYING or https://www.gnu.org/licenses/gpl-3.0.en.html
|
||||
/******************************************************************************
|
||||
* Copyright © 2014-2019 The SuperNET Developers. *
|
||||
* *
|
||||
* See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at *
|
||||
* the top-level directory of this distribution for the individual copyright *
|
||||
* holder information and the developer policies on copyright and licensing. *
|
||||
* *
|
||||
* Unless otherwise agreed in a custom licensing agreement, no part of the *
|
||||
* SuperNET software, including this file may be copied, modified, propagated *
|
||||
* or distributed except according to the terms contained in the LICENSE file *
|
||||
* *
|
||||
* Removal or modification of this copyright notice is prohibited. *
|
||||
* *
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
#ifndef CC_PAYMENTS_H
|
||||
#define CC_PAYMENTS_H
|
||||
|
||||
#include "CCinclude.h"
|
||||
#include <gmp.h>
|
||||
#include <key_io.h>
|
||||
|
||||
#define PAYMENTS_TXFEE 10000
|
||||
#define PAYMENTS_MERGEOFSET 60 // 1H extra.
|
||||
extern std::vector <std::pair<CAmount, CTxDestination>> vAddressSnapshot;
|
||||
extern int32_t lastSnapShotHeight;
|
||||
|
||||
bool PaymentsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn);
|
||||
|
||||
// CCcustom
|
||||
UniValue PaymentsRelease(struct CCcontract_info *cp,char *jsonstr);
|
||||
UniValue PaymentsFund(struct CCcontract_info *cp,char *jsonstr);
|
||||
UniValue PaymentsMerge(struct CCcontract_info *cp,char *jsonstr);
|
||||
UniValue PaymentsTxidopret(struct CCcontract_info *cp,char *jsonstr);
|
||||
UniValue PaymentsCreate(struct CCcontract_info *cp,char *jsonstr);
|
||||
UniValue PaymentsAirdrop(struct CCcontract_info *cp,char *jsonstr);
|
||||
UniValue PaymentsAirdropTokens(struct CCcontract_info *cp,char *jsonstr);
|
||||
UniValue PaymentsInfo(struct CCcontract_info *cp,char *jsonstr);
|
||||
UniValue PaymentsList(struct CCcontract_info *cp,char *jsonstr);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -16,24 +16,3 @@
|
||||
* *
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
#ifndef CC_PEGS_H
|
||||
#define CC_PEGS_H
|
||||
|
||||
#include "CCinclude.h"
|
||||
|
||||
bool PegsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn);
|
||||
|
||||
// CCcustom
|
||||
UniValue PegsCreate(const CPubKey& pk,uint64_t txfee,int64_t amount,std::vector<uint256> bindtxids);
|
||||
UniValue PegsFund(const CPubKey& pk,uint64_t txfee,uint256 pegstxid, uint256 tokenid, int64_t amount);
|
||||
UniValue PegsGet(const CPubKey& pk,uint64_t txfee,uint256 pegstxid, uint256 tokenid, int64_t amount);
|
||||
UniValue PegsRedeem(const CPubKey& pk,uint64_t txfee,uint256 pegstxid, uint256 tokenid);
|
||||
UniValue PegsLiquidate(const CPubKey& pk,uint64_t txfee,uint256 pegstxid, uint256 tokenid, uint256 liquidatetxid);
|
||||
UniValue PegsExchange(const CPubKey& pk,uint64_t txfee,uint256 pegstxid, uint256 tokenid, int64_t amount);
|
||||
UniValue PegsAccountHistory(const CPubKey& pk,uint256 pegstxid);
|
||||
UniValue PegsAccountInfo(const CPubKey& pk,uint256 pegstxid);
|
||||
UniValue PegsWorstAccounts(uint256 pegstxid);
|
||||
UniValue PegsInfo(uint256 pegstxid);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
// Copyright (c) 2016-2023 The Hush developers
|
||||
// Distributed under the GPLv3 software license, see the accompanying
|
||||
// file COPYING or https://www.gnu.org/licenses/gpl-3.0.en.html
|
||||
/******************************************************************************
|
||||
* Copyright © 2014-2019 The SuperNET Developers. *
|
||||
* *
|
||||
* See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at *
|
||||
* the top-level directory of this distribution for the individual copyright *
|
||||
* holder information and the developer policies on copyright and licensing. *
|
||||
* *
|
||||
* Unless otherwise agreed in a custom licensing agreement, no part of the *
|
||||
* SuperNET software, including this file may be copied, modified, propagated *
|
||||
* or distributed except according to the terms contained in the LICENSE file *
|
||||
* *
|
||||
* Removal or modification of this copyright notice is prohibited. *
|
||||
* *
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
#ifndef CC_CHANNELS_H
|
||||
#define CC_CHANNELS_H
|
||||
|
||||
#include "CCinclude.h"
|
||||
#define CHANNELS_MAXPAYMENTS 1000
|
||||
|
||||
bool ChannelsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn);
|
||||
UniValue ChannelOpen(const CPubKey& pk,uint64_t txfee,CPubKey destpub,int32_t numpayments,int64_t payment,uint256 tokenid);
|
||||
UniValue ChannelPayment(const CPubKey& pk,uint64_t txfee,uint256 opentxid,int64_t amount, uint256 secret);
|
||||
UniValue ChannelClose(const CPubKey& pk,uint64_t txfee,uint256 opentxid);
|
||||
UniValue ChannelRefund(const CPubKey& pk,uint64_t txfee,uint256 opentxid,uint256 closetxid);
|
||||
UniValue ChannelsList(const CPubKey& pk);
|
||||
// CCcustom
|
||||
UniValue ChannelsInfo(const CPubKey& pk,uint256 opentxid);
|
||||
|
||||
#endif
|
||||
@@ -20,20 +20,13 @@
|
||||
#include "CCinclude.h"
|
||||
#include "CCassets.h"
|
||||
#include "CCfaucet.h"
|
||||
#include "CCrewards.h"
|
||||
#include "CCdice.h"
|
||||
#include "CCauction.h"
|
||||
#include "CClotto.h"
|
||||
#include "CCfsm.h"
|
||||
#include "CCHeir.h"
|
||||
#include "CCchannels.h"
|
||||
#include "CCOracles.h"
|
||||
#include "CCPrices.h"
|
||||
#include "CCPegs.h"
|
||||
#include "CCPayments.h"
|
||||
#include "CCGateways.h"
|
||||
#include "CCtokens.h"
|
||||
#include "CCImportGateway.h"
|
||||
|
||||
/*
|
||||
CCcustom has most of the functions that need to be extended to create a new CC contract.
|
||||
@@ -318,24 +311,24 @@ struct CCcontract_info *CCinit(struct CCcontract_info *cp, uint8_t evalcode)
|
||||
strcpy(cp->normaladdr,RewardsNormaladdr);
|
||||
strcpy(cp->CChexstr,RewardsCChexstr);
|
||||
memcpy(cp->CCpriv,RewardsCCpriv,32);
|
||||
cp->validate = RewardsValidate;
|
||||
cp->ismyvin = IsRewardsInput;
|
||||
//cp->validate = RewardsValidate;
|
||||
//cp->ismyvin = IsRewardsInput;
|
||||
break;
|
||||
case EVAL_DICE:
|
||||
strcpy(cp->unspendableCCaddr,DiceCCaddr);
|
||||
strcpy(cp->normaladdr,DiceNormaladdr);
|
||||
strcpy(cp->CChexstr,DiceCChexstr);
|
||||
memcpy(cp->CCpriv,DiceCCpriv,32);
|
||||
cp->validate = DiceValidate;
|
||||
cp->ismyvin = IsDiceInput;
|
||||
//cp->validate = DiceValidate;
|
||||
//cp->ismyvin = IsDiceInput;
|
||||
break;
|
||||
case EVAL_LOTTO:
|
||||
strcpy(cp->unspendableCCaddr,LottoCCaddr);
|
||||
strcpy(cp->normaladdr,LottoNormaladdr);
|
||||
strcpy(cp->CChexstr,LottoCChexstr);
|
||||
memcpy(cp->CCpriv,LottoCCpriv,32);
|
||||
cp->validate = LottoValidate;
|
||||
cp->ismyvin = IsLottoInput;
|
||||
//cp->validate = LottoValidate;
|
||||
//cp->ismyvin = IsLottoInput;
|
||||
break;
|
||||
case EVAL_FSM:
|
||||
strcpy(cp->unspendableCCaddr,FSMCCaddr);
|
||||
@@ -366,8 +359,8 @@ struct CCcontract_info *CCinit(struct CCcontract_info *cp, uint8_t evalcode)
|
||||
strcpy(cp->normaladdr,ChannelsNormaladdr);
|
||||
strcpy(cp->CChexstr,ChannelsCChexstr);
|
||||
memcpy(cp->CCpriv,ChannelsCCpriv,32);
|
||||
cp->validate = ChannelsValidate;
|
||||
cp->ismyvin = IsChannelsInput;
|
||||
//cp->validate = ChannelsValidate;
|
||||
//cp->ismyvin = IsChannelsInput;
|
||||
break;
|
||||
case EVAL_ORACLES:
|
||||
strcpy(cp->unspendableCCaddr,OraclesCCaddr);
|
||||
@@ -382,32 +375,32 @@ struct CCcontract_info *CCinit(struct CCcontract_info *cp, uint8_t evalcode)
|
||||
strcpy(cp->normaladdr,PricesNormaladdr);
|
||||
strcpy(cp->CChexstr,PricesCChexstr);
|
||||
memcpy(cp->CCpriv,PricesCCpriv,32);
|
||||
cp->validate = PricesValidate;
|
||||
cp->ismyvin = IsPricesInput;
|
||||
//cp->validate = PricesValidate;
|
||||
//cp->ismyvin = IsPricesInput;
|
||||
break;
|
||||
case EVAL_PEGS:
|
||||
strcpy(cp->unspendableCCaddr,PegsCCaddr);
|
||||
strcpy(cp->normaladdr,PegsNormaladdr);
|
||||
strcpy(cp->CChexstr,PegsCChexstr);
|
||||
memcpy(cp->CCpriv,PegsCCpriv,32);
|
||||
cp->validate = PegsValidate;
|
||||
cp->ismyvin = IsPegsInput;
|
||||
//cp->validate = PegsValidate;
|
||||
//cp->ismyvin = IsPegsInput;
|
||||
break;
|
||||
case EVAL_PAYMENTS:
|
||||
strcpy(cp->unspendableCCaddr,PaymentsCCaddr);
|
||||
strcpy(cp->normaladdr,PaymentsNormaladdr);
|
||||
strcpy(cp->CChexstr,PaymentsCChexstr);
|
||||
memcpy(cp->CCpriv,PaymentsCCpriv,32);
|
||||
cp->validate = PaymentsValidate;
|
||||
cp->ismyvin = IsPaymentsInput;
|
||||
//cp->validate = PaymentsValidate;
|
||||
//cp->ismyvin = IsPaymentsInput;
|
||||
break;
|
||||
case EVAL_GATEWAYS:
|
||||
strcpy(cp->unspendableCCaddr,GatewaysCCaddr);
|
||||
strcpy(cp->normaladdr,GatewaysNormaladdr);
|
||||
strcpy(cp->CChexstr,GatewaysCChexstr);
|
||||
memcpy(cp->CCpriv,GatewaysCCpriv,32);
|
||||
cp->validate = GatewaysValidate;
|
||||
cp->ismyvin = IsGatewaysInput;
|
||||
//cp->validate = GatewaysValidate;
|
||||
//cp->ismyvin = IsGatewaysInput;
|
||||
break;
|
||||
|
||||
case EVAL_TOKENS:
|
||||
@@ -415,16 +408,16 @@ struct CCcontract_info *CCinit(struct CCcontract_info *cp, uint8_t evalcode)
|
||||
strcpy(cp->normaladdr, TokensNormaladdr);
|
||||
strcpy(cp->CChexstr, TokensCChexstr);
|
||||
memcpy(cp->CCpriv, TokensCCpriv, 32);
|
||||
cp->validate = TokensValidate;
|
||||
cp->ismyvin = IsTokensInput;
|
||||
//cp->validate = TokensValidate;
|
||||
//cp->ismyvin = IsTokensInput;
|
||||
break;
|
||||
case EVAL_IMPORTGATEWAY:
|
||||
strcpy(cp->unspendableCCaddr, ImportGatewayCCaddr);
|
||||
strcpy(cp->normaladdr, ImportGatewayNormaladdr);
|
||||
strcpy(cp->CChexstr, ImportGatewayCChexstr);
|
||||
memcpy(cp->CCpriv, ImportGatewayCCpriv, 32);
|
||||
cp->validate = ImportGatewayValidate;
|
||||
cp->ismyvin = IsImportGatewayInput;
|
||||
//cp->validate = ImportGatewayValidate;
|
||||
//cp->ismyvin = IsImportGatewayInput;
|
||||
break;
|
||||
default:
|
||||
if ( CClib_initcp(cp,evalcode) < 0 )
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
// Copyright (c) 2016-2023 The Hush developers
|
||||
// Distributed under the GPLv3 software license, see the accompanying
|
||||
// file COPYING or https://www.gnu.org/licenses/gpl-3.0.en.html
|
||||
/******************************************************************************
|
||||
* Copyright © 2014-2019 The SuperNET Developers. *
|
||||
* *
|
||||
* See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at *
|
||||
* the top-level directory of this distribution for the individual copyright *
|
||||
* holder information and the developer policies on copyright and licensing. *
|
||||
* *
|
||||
* Unless otherwise agreed in a custom licensing agreement, no part of the *
|
||||
* SuperNET software, including this file may be copied, modified, propagated *
|
||||
* or distributed except according to the terms contained in the LICENSE file *
|
||||
* *
|
||||
* Removal or modification of this copyright notice is prohibited. *
|
||||
* *
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
#ifndef CC_DICE_H
|
||||
#define CC_DICE_H
|
||||
|
||||
#include "CCinclude.h"
|
||||
|
||||
#define EVAL_DICE 0xe6
|
||||
|
||||
bool DiceValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn);
|
||||
|
||||
std::string DiceBet(uint64_t txfee,char *planstr,uint256 fundingtxid,int64_t bet,int32_t odds);
|
||||
std::string DiceBetFinish(uint8_t &funcid,uint256 &entropyused,int32_t &entropyvout,int32_t *resultp,uint64_t txfee,char *planstr,uint256 fundingtxid,uint256 bettxid,int32_t winlosetimeout,uint256 vin0txid,int32_t vin0vout);
|
||||
double DiceStatus(uint64_t txfee,char *planstr,uint256 fundingtxid,uint256 bettxid);
|
||||
std::string DiceCreateFunding(uint64_t txfee,char *planstr,int64_t funds,int64_t minbet,int64_t maxbet,int64_t maxodds,int64_t timeoutblocks);
|
||||
std::string DiceAddfunding(uint64_t txfee,char *planstr,uint256 fundingtxid,int64_t amount);
|
||||
UniValue DiceInfo(uint256 diceid);
|
||||
UniValue DiceList();
|
||||
int64_t DicePlanFunds(uint64_t &entropyval,uint256 &entropytxid,uint64_t refsbits,struct CCcontract_info *cp,CPubKey dicepk,uint256 reffundingtxid, int32_t &entropytxs,bool random);
|
||||
|
||||
#endif
|
||||
@@ -1,34 +0,0 @@
|
||||
// Copyright (c) 2016-2023 The Hush developers
|
||||
// Distributed under the GPLv3 software license, see the accompanying
|
||||
// file COPYING or https://www.gnu.org/licenses/gpl-3.0.en.html
|
||||
/******************************************************************************
|
||||
* Copyright © 2014-2019 The SuperNET Developers. *
|
||||
* *
|
||||
* See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at *
|
||||
* the top-level directory of this distribution for the individual copyright *
|
||||
* holder information and the developer policies on copyright and licensing. *
|
||||
* *
|
||||
* Unless otherwise agreed in a custom licensing agreement, no part of the *
|
||||
* SuperNET software, including this file may be copied, modified, propagated *
|
||||
* or distributed except according to the terms contained in the LICENSE file *
|
||||
* *
|
||||
* Removal or modification of this copyright notice is prohibited. *
|
||||
* *
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
#ifndef CC_LOTTO_H
|
||||
#define CC_LOTTO_H
|
||||
|
||||
#include "CCinclude.h"
|
||||
|
||||
#define EVAL_LOTTO 0xe9
|
||||
|
||||
bool LottoValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn);
|
||||
|
||||
UniValue LottoInfo(uint256 lottoid);
|
||||
UniValue LottoList();
|
||||
std::string LottoTicket(uint64_t txfee,int64_t numtickets);
|
||||
std::string LottoWinner(uint64_t txfee);
|
||||
|
||||
#endif
|
||||
@@ -1,38 +0,0 @@
|
||||
// Copyright (c) 2016-2023 The Hush developers
|
||||
// Distributed under the GPLv3 software license, see the accompanying
|
||||
// file COPYING or https://www.gnu.org/licenses/gpl-3.0.en.html
|
||||
/******************************************************************************
|
||||
* Copyright © 2014-2019 The SuperNET Developers. *
|
||||
* *
|
||||
* See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at *
|
||||
* the top-level directory of this distribution for the individual copyright *
|
||||
* holder information and the developer policies on copyright and licensing. *
|
||||
* *
|
||||
* Unless otherwise agreed in a custom licensing agreement, no part of the *
|
||||
* SuperNET software, including this file may be copied, modified, propagated *
|
||||
* or distributed except according to the terms contained in the LICENSE file *
|
||||
* *
|
||||
* Removal or modification of this copyright notice is prohibited. *
|
||||
* *
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
#ifndef CC_REWARDS_H
|
||||
#define CC_REWARDS_H
|
||||
|
||||
#include "CCinclude.h"
|
||||
#include <gmp.h>
|
||||
|
||||
#define EVAL_REWARDS 0xe5
|
||||
#define REWARDSCC_MAXAPR (COIN * 25)
|
||||
|
||||
bool RewardsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn);
|
||||
UniValue RewardsInfo(uint256 rewardid);
|
||||
UniValue RewardsList();
|
||||
|
||||
std::string RewardsCreateFunding(uint64_t txfee,char *planstr,int64_t funds,int64_t APR,int64_t minseconds,int64_t maxseconds,int64_t mindeposit);
|
||||
std::string RewardsAddfunding(uint64_t txfee,char *planstr,uint256 fundingtxid,int64_t amount);
|
||||
std::string RewardsLock(uint64_t txfee,char *planstr,uint256 fundingtxid,int64_t amount);
|
||||
std::string RewardsUnlock(uint64_t txfee,char *planstr,uint256 fundingtxid,uint256 locktxid);
|
||||
|
||||
#endif
|
||||
1059
src/cc/CCtokens.cpp
1059
src/cc/CCtokens.cpp
File diff suppressed because it is too large
Load Diff
@@ -1,38 +0,0 @@
|
||||
SHELL = /bin/sh
|
||||
CC = gcc
|
||||
CC_DARWIN = g++-8
|
||||
CC_WIN = x86_64-w64-mingw32-gcc-posix
|
||||
CFLAGS_DARWIN = -DBUILD_ROGUE -std=c++11 -arch x86_64 -I../../depends/$(shell echo `../..//depends/config.guess`/include) -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I.. -I. -fPIC -Wl,-undefined -Wl,dynamic_lookup -Wno-write-strings -shared -dynamiclib
|
||||
CFLAGS = -Wno-write-strings -DBUILD_ROGUE -std=c++11 -I../../depends/$(shell echo `../..//depends/config.guess`/include) -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I.. -I. -fPIC -shared
|
||||
CFLAGS_WIN = -Wno-write-strings -DBUILD_ROGUE -std=c++11 -I./rogue/x86_64-w64-mingw32/include -I./rogue/x86_64-w64-mingw32/include/ncursesw -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I.. -I. -fPIC -shared
|
||||
DEBUGFLAGS = -O0 -D _DEBUG
|
||||
RELEASEFLAGS = -O2 -D NDEBUG -combine -fwhole-program
|
||||
$(info $(OS))
|
||||
OS := $(shell uname -s)
|
||||
$(info $(OS))
|
||||
TARGET = librogue.so
|
||||
TARGET_DARWIN = librogue.dylib
|
||||
TARGET_WIN = librogue.dll
|
||||
SOURCES = cclib.cpp
|
||||
#HEADERS = $(shell echo ../cryptoconditions/include/*.h) -I/usr/local/Cellar/gcc\@8/8.3.0/include/c++/8.3.0/
|
||||
|
||||
all: $(TARGET)
|
||||
|
||||
$(TARGET): $(SOURCES)
|
||||
$(info Building cclib to src/)
|
||||
ifeq ($(OS),Darwin)
|
||||
$(CC_DARWIN) $(CFLAGS_DARWIN) $(DEBUGFLAGS) -o $(TARGET_DARWIN) -c $(SOURCES)
|
||||
cp $(TARGET_DARWIN) ../libcc.dylib
|
||||
else ifeq ($(HOST),x86_64-w64-mingw32)
|
||||
$(info WINDOWS)
|
||||
$(CC_WIN) $(CFLAGS_WIN) $(DEBUGFLAGS) -o $(TARGET_WIN) -c $(SOURCES)
|
||||
cp $(TARGET_WIN) ../libcc.dll
|
||||
#else ifeq ($(WIN_HOST),True) - todo: pass ENV var from build.sh if WIN host
|
||||
else
|
||||
$(info LINUX)
|
||||
$(CC) $(CFLAGS) $(DEBUGFLAGS) -o $(TARGET) -c $(SOURCES)
|
||||
cp $(TARGET) ../libcc.so
|
||||
endif
|
||||
|
||||
clean:
|
||||
rm -rf $(TARGET)
|
||||
@@ -19,448 +19,8 @@
|
||||
#include "CCassets.h"
|
||||
#include "CCtokens.h"
|
||||
|
||||
/*
|
||||
Assets can be created or transferred.
|
||||
|
||||
native coins are also locked in the EVAL_ASSETS address, so we need a strict rule on when utxo in the special address are native coins and when they are assets. The specific rule that must not be violated is that vout0 for 'b'/'B' funcid are native coins. All other utxo locked in the special address are assets.
|
||||
|
||||
To create an asset use CC EVAL_ASSETS to create a transaction where vout[0] funds the assets. Externally each satoshi can be interpreted to represent 1 asset, or 100 million satoshis for one asset with 8 decimals, and the other decimals in between. The interpretation of the number of decimals is left to the higher level usages.
|
||||
|
||||
Once created, the assetid is the txid of the create transaction and using the assetid/0 it can spend the assets to however many outputs it creates. The restriction is that the last output must be an opreturn with the assetid. The sum of all but the first output needs to add up to the total assetoshis input. The first output is ignored and used for change from txfee.
|
||||
|
||||
What this means is that vout 0 of the creation txid and vouts 1 ... n-2 for transfer vouts are assetoshi outputs.
|
||||
|
||||
There is a special type of transfer to an unspendable address, that locks the asset and creates an offer for all. The details specified in the opreturn. In order to be compatible with the signing restrictions, the "unspendable" address is actually an address whose privkey is known to all. Funds sent to this address can only be spent if the swap parameters are fulfilled, or if the original pubkey cancels the offer by spending it.
|
||||
|
||||
Types of transactions:
|
||||
create name:description -> txid for assetid
|
||||
transfer <pubkey> <assetid> -> [{address:amount}, ... ] // like withdraw api
|
||||
selloffer <pubkey> <txid/vout> <amount> -> cancel or fillsell -> mempool txid or rejected, might not confirm
|
||||
buyoffer <amount> <assetid> <required> -> cancelbuy or fillbuy -> mempool txid or rejected, might not confirm
|
||||
exchange <pubkey> <txid/vout> <required> <required assetid> -> cancel or fillexchange -> mempool txid or rejected, might not confirm
|
||||
|
||||
assetsaddress <pubkey> // all assets end up in a special address for each pubkey
|
||||
assetbalance <pubkey> <assetid>
|
||||
assetutxos <pubkey> <assetid>
|
||||
assetsbalances <pubkey>
|
||||
asks <assetid>
|
||||
bids <assetid>
|
||||
swaps <assetid>
|
||||
|
||||
valid CC output: create or transfer or buyoffer or selloffer or exchange or cancel or fill
|
||||
|
||||
|
||||
buyoffer:
|
||||
vins.*: normal inputs (bid + change)
|
||||
vout.0: amount of bid to unspendable
|
||||
vout.1: CC output for marker
|
||||
vout.2: normal output for change (if any)
|
||||
vout.n-1: opreturn [EVAL_ASSETS] ['b'] [assetid] [amount of asset required] [origpubkey]
|
||||
|
||||
cancelbuy:
|
||||
vin.0: normal input
|
||||
vin.1: unspendable.(vout.0 from buyoffer) buyTx.vout[0]
|
||||
vin.2: CC marker from buyoffer for txfee
|
||||
vout.0: vin.1 value to original pubkey buyTx.vout[0].nValue -> [origpubkey]
|
||||
vout.1: vin.2 back to users pubkey
|
||||
vout.2: normal output for change (if any)
|
||||
vout.n-1: opreturn [EVAL_ASSETS] ['o'] [assetid] 0 0 [origpubkey]
|
||||
|
||||
fillbuy:
|
||||
vin.0: normal input
|
||||
vin.1: unspendable.(vout.0 from buyoffer) buyTx.vout[0]
|
||||
vin.2+: valid CC output satisfies buyoffer (*tx.vin[2])->nValue
|
||||
vout.0: remaining amount of bid to unspendable
|
||||
vout.1: vin.1 value to signer of vin.2
|
||||
vout.2: vin.2 assetoshis to original pubkey
|
||||
vout.3: CC output for assetoshis change (if any)
|
||||
vout.4: normal output for change (if any)
|
||||
vout.n-1: opreturn [EVAL_ASSETS] ['B'] [assetid] [remaining asset required] [origpubkey]
|
||||
|
||||
selloffer:
|
||||
vin.0: normal input
|
||||
vin.1+: valid CC output for sale
|
||||
vout.0: vin.1 assetoshis output to CC to unspendable
|
||||
vout.1: CC output for marker
|
||||
vout.2: CC output for change (if any)
|
||||
vout.3: normal output for change (if any)
|
||||
vout.n-1: opreturn [EVAL_ASSETS] ['s'] [assetid] [amount of native coin required] [origpubkey]
|
||||
|
||||
exchange:
|
||||
vin.0: normal input
|
||||
vin.1+: valid CC output
|
||||
vout.0: vin.1 assetoshis output to CC to unspendable
|
||||
vout.1: CC output for change (if any)
|
||||
vout.2: normal output for change (if any)
|
||||
vout.n-1: opreturn [EVAL_ASSETS] ['e'] [assetid] [assetid2] [amount of asset2 required] [origpubkey]
|
||||
|
||||
cancel:
|
||||
vin.0: normal input
|
||||
vin.1: unspendable.(vout.0 from exchange or selloffer) sellTx/exchangeTx.vout[0] inputTx
|
||||
vin.2: CC marker from selloffer for txfee
|
||||
vout.0: vin.1 assetoshis to original pubkey CC sellTx/exchangeTx.vout[0].nValue -> [origpubkey]
|
||||
vout.1: vin.2 back to users pubkey
|
||||
vout.2: normal output for change (if any)
|
||||
vout.n-1: opreturn [EVAL_ASSETS] ['x'] [assetid]
|
||||
|
||||
fillsell:
|
||||
vin.0: normal input
|
||||
vin.1: unspendable.(vout.0 assetoshis from selloffer) sellTx.vout[0]
|
||||
vin.2+: normal output that satisfies selloffer (*tx.vin[2])->nValue
|
||||
vout.0: remaining assetoshis -> unspendable
|
||||
vout.1: vin.1 assetoshis to signer of vin.2 sellTx.vout[0].nValue -> any
|
||||
vout.2: vin.2 value to original pubkey [origpubkey]
|
||||
vout.3: CC asset for change (if any)
|
||||
vout.4: CC asset2 for change (if any) 'E' only
|
||||
vout.5: normal output for change (if any)
|
||||
vout.n-1: opreturn [EVAL_ASSETS] ['S'] [assetid] [amount of coin still required] [origpubkey]
|
||||
|
||||
fillexchange:
|
||||
vin.0: normal input
|
||||
vin.1: unspendable.(vout.0 assetoshis from exchange) exchangeTx.vout[0]
|
||||
vin.2+: valid CC assetid2 output that satisfies exchange (*tx.vin[2])->nValue
|
||||
vout.0: remaining assetoshis -> unspendable
|
||||
vout.1: vin.1 assetoshis to signer of vin.2 exchangeTx.vout[0].nValue -> any
|
||||
vout.2: vin.2 assetoshis2 to original pubkey [origpubkey]
|
||||
vout.3: normal output for change (if any)
|
||||
vout.n-1: opreturn [EVAL_ASSETS] ['E'] [assetid vin0+1] [assetid vin2] [remaining asset2 required] [origpubkey]
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
// tx validation
|
||||
bool AssetsValidate(struct CCcontract_info *cpAssets,Eval* eval,const CTransaction &tx, uint32_t nIn)
|
||||
{
|
||||
static uint256 zero;
|
||||
CTxDestination address;
|
||||
CTransaction vinTx, createTx;
|
||||
uint256 hashBlock, assetid, assetid2;
|
||||
int32_t i,starti, numvins, numvouts, preventCCvins, preventCCvouts;
|
||||
int64_t remaining_price, nValue, assetoshis, outputsDummy,inputs,tmpprice,totalunits,ignore;
|
||||
std::vector<uint8_t> origpubkey, tmporigpubkey, ignorepubkey, vopretNonfungible, vopretNonfungibleDummy;
|
||||
uint8_t funcid, evalCodeInOpret;
|
||||
char destaddr[64], origNormalAddr[64], origTokensCCaddr[64], origCCaddrDummy[64];
|
||||
char tokensDualEvalUnspendableCCaddr[64], origAssetsCCaddr[64];
|
||||
|
||||
//return true;
|
||||
|
||||
numvins = tx.vin.size();
|
||||
numvouts = tx.vout.size();
|
||||
outputsDummy = inputs = 0;
|
||||
preventCCvins = preventCCvouts = -1;
|
||||
|
||||
if (numvouts == 0)
|
||||
return eval->Invalid("AssetValidate: no vouts");
|
||||
|
||||
if((funcid = DecodeAssetTokenOpRet(tx.vout[numvouts-1].scriptPubKey, evalCodeInOpret, assetid, assetid2, remaining_price, origpubkey)) == 0 )
|
||||
return eval->Invalid("AssetValidate: invalid opreturn payload");
|
||||
|
||||
// non-fungible tokens support:
|
||||
GetNonfungibleData(assetid, vopretNonfungible);
|
||||
if (vopretNonfungible.size() > 0)
|
||||
cpAssets->additionalTokensEvalcode2 = vopretNonfungible.begin()[0];
|
||||
|
||||
// find dual-eval tokens unspendable addr:
|
||||
GetTokensCCaddress(cpAssets, tokensDualEvalUnspendableCCaddr, GetUnspendable(cpAssets, NULL));
|
||||
// this is for marker validation:
|
||||
GetCCaddress(cpAssets, origAssetsCCaddr, origpubkey);
|
||||
|
||||
// we need this for validating single-eval tokens' vins/vous:
|
||||
struct CCcontract_info *cpTokens, tokensC;
|
||||
cpTokens = CCinit(&tokensC, EVAL_TOKENS);
|
||||
|
||||
// find single-eval token user cc addr:
|
||||
//GetCCaddress(cpTokens, signleEvalTokensCCaddr, pubkey2pk(origpubkey));
|
||||
|
||||
//fprintf(stderr,"AssetValidate (%c)\n",funcid);
|
||||
|
||||
if( funcid != 'o' && funcid != 'x' && eval->GetTxUnconfirmed(assetid, createTx, hashBlock) == 0 )
|
||||
return eval->Invalid("cant find asset create txid");
|
||||
else if( funcid != 'o' && funcid != 'x' && assetid2 != zero && eval->GetTxUnconfirmed(assetid2, createTx, hashBlock) == 0 )
|
||||
return eval->Invalid("cant find asset2 create txid");
|
||||
else if( IsCCInput(tx.vin[0].scriptSig) != 0 ) // vin0 should be normal vin
|
||||
return eval->Invalid("illegal asset vin0");
|
||||
else if( numvouts < 2 )
|
||||
return eval->Invalid("too few vouts"); // it was if(numvouts < 1) but it refers at least to vout[1] below
|
||||
else if( funcid != 'c' )
|
||||
{
|
||||
/* if( funcid == 't' )
|
||||
starti = 0;
|
||||
else
|
||||
starti = 1; */
|
||||
|
||||
if( assetid == zero )
|
||||
return eval->Invalid("illegal assetid");
|
||||
|
||||
else if (!AssetCalcAmounts(cpAssets, inputs, outputsDummy/*outputsDummy is calculated incorrectly but not used*/, eval, tx, assetid)) { // Only set inputs and outputs. NOTE: we do not need to check cc inputs == cc outputs
|
||||
return false; // returns false if some problems with reading vintxes
|
||||
}
|
||||
}
|
||||
|
||||
switch( funcid )
|
||||
{
|
||||
case 'c': // create wont be called to be verified as it has no CC inputs
|
||||
//vin.0: normal input
|
||||
//vout.0: issuance assetoshis to CC
|
||||
//vout.1: normal output for change (if any)
|
||||
//vout.n-1: opreturn [EVAL_ASSETS] ['c'] [{"<assetname>":"<description>"}]
|
||||
//if (evalCodeInOpret == EVAL_ASSETS)
|
||||
// return eval->Invalid("unexpected AssetValidate for createasset");
|
||||
// return
|
||||
return eval->Invalid("invalid asset funcid \'c\'");
|
||||
break;
|
||||
case 't': // transfer
|
||||
//vin.0: normal input
|
||||
//vin.1 .. vin.n-1: valid CC outputs
|
||||
//vout.0 to n-2: assetoshis output to CC
|
||||
//vout.n-2: normal output for change (if any)
|
||||
//vout.n-1: opreturn [EVAL_ASSETS] ['t'] [assetid]
|
||||
//if (inputs == 0)
|
||||
// return eval->Invalid("no asset inputs for transfer");
|
||||
//fprintf(stderr,"transfer preliminarily validated %.8f -> %.8f (%d %d)\n",(double)inputs/COIN,(double)outputs/COIN,preventCCvins,preventCCvouts);
|
||||
return eval->Invalid("invalid asset funcid \'t\'");
|
||||
break;
|
||||
|
||||
case 'b': // buyoffer
|
||||
//vins.*: normal inputs (bid + change)
|
||||
//vout.0: amount of bid to unspendable
|
||||
//vout.1: CC output for marker
|
||||
//vout.2: normal output for change (if any)
|
||||
// vout.n-1: opreturn [EVAL_ASSETS] ['b'] [assetid] [amount of asset required] [origpubkey]
|
||||
|
||||
// as we don't use tokenconvert we should not be here:
|
||||
return eval->Invalid("invalid asset funcid (b)");
|
||||
|
||||
if( remaining_price == 0 )
|
||||
return eval->Invalid("illegal null amount for buyoffer");
|
||||
else if( ConstrainVout(tx.vout[0], 1, cpAssets->unspendableCCaddr,0) == 0 ) // coins to assets unspendable cc addr
|
||||
return eval->Invalid("invalid vout for buyoffer");
|
||||
preventCCvins = 1;
|
||||
preventCCvouts = 1;
|
||||
fprintf(stderr,"buy offer validated to destaddr.(%s)\n",cpAssets->unspendableCCaddr);
|
||||
break;
|
||||
|
||||
case 'o': // cancelbuy
|
||||
//vin.0: normal input
|
||||
//vin.1: unspendable.(vout.0 from buyoffer) buyTx.vout[0]
|
||||
//vin.2: CC marker from buyoffer for txfee
|
||||
//vout.0: vin.1 value to original pubkey buyTx.vout[0].nValue -> [origpubkey]
|
||||
//vout.1: vin.2 back to users pubkey
|
||||
//vout.2: normal output for change (if any)
|
||||
//vout.n-1: opreturn [EVAL_ASSETS] ['o']
|
||||
if( (nValue= AssetValidateBuyvin(cpAssets, eval, tmpprice, tmporigpubkey, origCCaddrDummy, origNormalAddr, tx, assetid)) == 0 )
|
||||
return(false);
|
||||
else if( ConstrainVout(tx.vout[0],0, origNormalAddr, nValue) == 0 )
|
||||
return eval->Invalid("invalid refund for cancelbuy");
|
||||
preventCCvins = 3;
|
||||
preventCCvouts = 0;
|
||||
//fprintf(stderr,"cancelbuy validated to origaddr.(%s)\n",origNormalAddr);
|
||||
break;
|
||||
|
||||
case 'B': // fillbuy:
|
||||
//vin.0: normal input
|
||||
//vin.1: unspendable.(vout.0 from buyoffer) buyTx.vout[0]
|
||||
//vin.2+: valid CC output satisfies buyoffer (*tx.vin[2])->nValue
|
||||
//vout.0: remaining amount of bid to unspendable
|
||||
//vout.1: vin.1 value to signer of vin.2
|
||||
//vout.2: vin.2 assetoshis to original pubkey
|
||||
//vout.3: CC output for assetoshis change (if any)
|
||||
//vout.4: normal output for change (if any)
|
||||
//vout.n-1: opreturn [EVAL_ASSETS] ['B'] [assetid] [remaining asset required] [origpubkey]
|
||||
preventCCvouts = 4;
|
||||
|
||||
if( (nValue = AssetValidateBuyvin(cpAssets, eval, totalunits, tmporigpubkey, origTokensCCaddr, origNormalAddr, tx, assetid)) == 0 )
|
||||
return(false);
|
||||
else if( numvouts < 4 )
|
||||
return eval->Invalid("not enough vouts for fillbuy");
|
||||
else if( tmporigpubkey != origpubkey )
|
||||
return eval->Invalid("mismatched origpubkeys for fillbuy");
|
||||
else
|
||||
{
|
||||
if( nValue != tx.vout[0].nValue + tx.vout[1].nValue )
|
||||
return eval->Invalid("locked value doesnt match vout0+1 fillbuy");
|
||||
else if( tx.vout[4].scriptPubKey.IsPayToCryptoCondition() != 0 ) // if cc change present
|
||||
{
|
||||
if( ConstrainVout(tx.vout[2], 1, origTokensCCaddr, 0) == 0 ) // tokens to originator cc addr (tokens+nonfungible evals)
|
||||
return eval->Invalid("vout2 doesnt go to origpubkey fillbuy");
|
||||
else if ( inputs != tx.vout[2].nValue + tx.vout[4].nValue )
|
||||
return eval->Invalid("asset inputs doesnt match vout2+3 fillbuy");
|
||||
preventCCvouts ++;
|
||||
}
|
||||
else if( ConstrainVout(tx.vout[2], 1, origTokensCCaddr, inputs) == 0 ) // tokens to originator cc addr (tokens+nonfungible evals)
|
||||
return eval->Invalid("vout2 doesnt match inputs fillbuy");
|
||||
else if( ConstrainVout(tx.vout[1], 0, NULL, 0) == 0 )
|
||||
return eval->Invalid("vout1 is CC for fillbuy");
|
||||
else if( ConstrainVout(tx.vout[3], 1, origAssetsCCaddr, 10000) == 0 ) // marker to asset cc addr
|
||||
return eval->Invalid("invalid marker for original pubkey");
|
||||
else if( ValidateBidRemainder(remaining_price, tx.vout[0].nValue, nValue, tx.vout[1].nValue, tx.vout[2].nValue, totalunits) == false )
|
||||
return eval->Invalid("mismatched remainder for fillbuy");
|
||||
else if( remaining_price != 0 )
|
||||
{
|
||||
if( ConstrainVout(tx.vout[0], 1, cpAssets->unspendableCCaddr, 0) == 0 ) // coins to asset unspendable cc addr
|
||||
return eval->Invalid("mismatched vout0 AssetsCCaddr for fillbuy");
|
||||
}
|
||||
}
|
||||
//fprintf(stderr,"fillbuy validated\n");
|
||||
break;
|
||||
//case 'e': // selloffer
|
||||
// break; // disable swaps
|
||||
case 's': // selloffer
|
||||
//vin.0: normal input
|
||||
//vin.1+: valid CC output for sale
|
||||
//vout.0: vin.1 assetoshis output to CC to unspendable
|
||||
//vout.1: CC output for marker
|
||||
//vout.2: CC output for change (if any)
|
||||
//vout.3: normal output for change (if any)
|
||||
//'s'.vout.n-1: opreturn [EVAL_ASSETS] ['s'] [assetid] [amount of native coin required] [origpubkey]
|
||||
//'e'.vout.n-1: opreturn [EVAL_ASSETS] ['e'] [assetid] [assetid2] [amount of asset2 required] [origpubkey]
|
||||
|
||||
// as we don't use tokenconvert we should not be here:
|
||||
return eval->Invalid("invalid asset funcid (s)");
|
||||
|
||||
preventCCvouts = 2;
|
||||
if( remaining_price == 0 )
|
||||
return eval->Invalid("illegal null remaining_price for selloffer");
|
||||
if ( tx.vout[1].scriptPubKey.IsPayToCryptoCondition() == 0 )
|
||||
return eval->Invalid("invalid normal vout1 for sellvin");
|
||||
if( tx.vout[2].scriptPubKey.IsPayToCryptoCondition() != 0 ) // if cc change presents
|
||||
{
|
||||
preventCCvouts++;
|
||||
if( ConstrainVout(tx.vout[0], 1, (char *)cpTokens->unspendableCCaddr, 0) == 0 ) // tokens to tokens unspendable cc addr. TODO: this in incorrect, should be assets if we got here!
|
||||
return eval->Invalid("mismatched vout0 TokensCCaddr for selloffer");
|
||||
else if( tx.vout[0].nValue + tx.vout[2].nValue != inputs )
|
||||
return eval->Invalid("mismatched vout0+vout2 total for selloffer");
|
||||
}
|
||||
// no cc change:
|
||||
else if( ConstrainVout(tx.vout[0], 1, (char *)cpTokens->unspendableCCaddr, inputs) == 0 ) // tokens to tokens unspendable cc addr TODO: this in incorrect, should be assets if got here!
|
||||
return eval->Invalid("mismatched vout0 TokensCCaddr for selloffer");
|
||||
//fprintf(stderr,"remaining.%d for sell\n",(int32_t)remaining_price);
|
||||
break;
|
||||
|
||||
case 'x': // cancel sell
|
||||
//vin.0: normal input
|
||||
//vin.1: unspendable.(vout.0 from exchange or selloffer) sellTx/exchangeTx.vout[0] inputTx
|
||||
//vin.2: CC marker from selloffer for txfee
|
||||
//vout.0: vin.1 assetoshis to original pubkey CC sellTx/exchangeTx.vout[0].nValue -> [origpubkey]
|
||||
//vout.1: vin.2 back to users pubkey
|
||||
//vout.2: normal output for change (if any)
|
||||
//vout.n-1: opreturn [EVAL_ASSETS] ['x'] [assetid]
|
||||
|
||||
if( (assetoshis = AssetValidateSellvin(cpAssets, eval, tmpprice, tmporigpubkey, origTokensCCaddr, origNormalAddr, tx, assetid)) == 0 ) // NOTE:
|
||||
return(false);
|
||||
else if( ConstrainVout(tx.vout[0], 1, origTokensCCaddr, assetoshis) == 0 ) // tokens returning to originator cc addr
|
||||
return eval->Invalid("invalid vout for cancel");
|
||||
preventCCvins = 3;
|
||||
preventCCvouts = 1;
|
||||
break;
|
||||
|
||||
case 'S': // fillsell
|
||||
//vin.0: normal input
|
||||
//vin.1: unspendable.(vout.0 assetoshis from selloffer) sellTx.vout[0]
|
||||
//'S'.vin.2+: normal output that satisfies selloffer (*tx.vin[2])->nValue
|
||||
//vout.0: remaining assetoshis -> unspendable
|
||||
//vout.1: vin.1 assetoshis to signer of vin.2 sellTx.vout[0].nValue -> any
|
||||
//'S'.vout.2: vin.2 value to original pubkey [origpubkey]
|
||||
//vout.3: normal output for change (if any)
|
||||
//'S'.vout.n-1: opreturn [EVAL_ASSETS] ['S'] [assetid] [amount of coin still required] [origpubkey]
|
||||
|
||||
if( (assetoshis = AssetValidateSellvin(cpAssets, eval, totalunits, tmporigpubkey, origTokensCCaddr, origNormalAddr, tx, assetid)) == 0 )
|
||||
return(false);
|
||||
else if( numvouts < 4 )
|
||||
return eval->Invalid("not enough vouts for fillask");
|
||||
else if( tmporigpubkey != origpubkey )
|
||||
return eval->Invalid("mismatched origpubkeys for fillask");
|
||||
else
|
||||
{
|
||||
if( assetoshis != tx.vout[0].nValue + tx.vout[1].nValue )
|
||||
return eval->Invalid("locked value doesnt match vout0+1 fillask");
|
||||
if( ValidateAskRemainder(remaining_price, tx.vout[0].nValue, assetoshis, tx.vout[1].nValue, tx.vout[2].nValue, totalunits) == false )
|
||||
return eval->Invalid("mismatched remainder for fillask");
|
||||
else if( ConstrainVout(tx.vout[1], 1, NULL, 0) == 0 ) // do not check token buyer's cc addr
|
||||
return eval->Invalid("normal vout1 for fillask");
|
||||
else if( ConstrainVout(tx.vout[2], 0, origNormalAddr, 0) == 0 ) // coins to originator normal addr
|
||||
return eval->Invalid("normal vout1 for fillask");
|
||||
else if( ConstrainVout(tx.vout[3], 1, origAssetsCCaddr, 10000) == 0 ) // marker to originator asset cc addr
|
||||
return eval->Invalid("invalid marker for original pubkey");
|
||||
else if( remaining_price != 0 )
|
||||
{
|
||||
if ( ConstrainVout(tx.vout[0], 1, tokensDualEvalUnspendableCCaddr, 0) == 0 )
|
||||
return eval->Invalid("mismatched vout0 assets dual unspendable CCaddr for fill sell");
|
||||
}
|
||||
}
|
||||
//fprintf(stderr,"fill validated\n");
|
||||
break;
|
||||
case 'E': // fillexchange
|
||||
////////// not implemented yet ////////////
|
||||
return eval->Invalid("unexpected assets fillexchange funcid");
|
||||
break; // disable asset swaps
|
||||
//vin.0: normal input
|
||||
//vin.1: unspendable.(vout.0 assetoshis from selloffer) sellTx.vout[0]
|
||||
//vin.2+: valid CC assetid2 output that satisfies exchange (*tx.vin[2])->nValue
|
||||
//vout.0: remaining assetoshis -> unspendable
|
||||
//vout.1: vin.1 assetoshis to signer of vin.2 sellTx.vout[0].nValue -> any
|
||||
//vout.2: vin.2+ assetoshis2 to original pubkey [origpubkey]
|
||||
//vout.3: CC output for asset2 change (if any)
|
||||
//vout.3/4: normal output for change (if any)
|
||||
//vout.n-1: opreturn [EVAL_ASSETS] ['E'] [assetid vin0+1] [assetid vin2] [remaining asset2 required] [origpubkey]
|
||||
|
||||
//if ( AssetExactAmounts(false, cp,inputs,outputs,eval,tx,assetid2) == false )
|
||||
// eval->Invalid("asset2 inputs != outputs");
|
||||
|
||||
////////// not implemented yet ////////////
|
||||
if( (assetoshis= AssetValidateSellvin(cpTokens, eval, totalunits, tmporigpubkey, origTokensCCaddr, origNormalAddr, tx, assetid)) == 0 )
|
||||
return(false);
|
||||
else if( numvouts < 3 )
|
||||
return eval->Invalid("not enough vouts for fillex");
|
||||
else if( tmporigpubkey != origpubkey )
|
||||
return eval->Invalid("mismatched origpubkeys for fillex");
|
||||
else
|
||||
{
|
||||
if( assetoshis != tx.vout[0].nValue + tx.vout[1].nValue )
|
||||
return eval->Invalid("locked value doesnt match vout0+1 fillex");
|
||||
else if( tx.vout[3].scriptPubKey.IsPayToCryptoCondition() != 0 )
|
||||
////////// not implemented yet ////////////
|
||||
{
|
||||
if( ConstrainVout(tx.vout[2], 1, origTokensCCaddr, 0) == 0 )
|
||||
return eval->Invalid("vout2 doesnt go to origpubkey fillex");
|
||||
else if( inputs != tx.vout[2].nValue + tx.vout[3].nValue )
|
||||
{
|
||||
fprintf(stderr,"inputs %.8f != %.8f + %.8f\n",(double)inputs/COIN,(double)tx.vout[2].nValue/COIN,(double)tx.vout[3].nValue/COIN);
|
||||
return eval->Invalid("asset inputs doesnt match vout2+3 fillex");
|
||||
}
|
||||
}
|
||||
////////// not implemented yet ////////////
|
||||
else if( ConstrainVout(tx.vout[2], 1, origTokensCCaddr, inputs) == 0 )
|
||||
return eval->Invalid("vout2 doesnt match inputs fillex");
|
||||
else if( ConstrainVout(tx.vout[1], 0, 0, 0) == 0 )
|
||||
return eval->Invalid("vout1 is CC for fillex");
|
||||
fprintf(stderr,"assets vout0 %llu, vin1 %llu, vout2 %llu -> orig, vout1 %llu, total %llu\n",(long long)tx.vout[0].nValue,(long long)assetoshis,(long long)tx.vout[2].nValue,(long long)tx.vout[1].nValue,(long long)totalunits);
|
||||
if( ValidateSwapRemainder(remaining_price, tx.vout[0].nValue, assetoshis,tx.vout[1].nValue, tx.vout[2].nValue, totalunits) == false )
|
||||
return eval->Invalid("mismatched remainder for fillex");
|
||||
else if( ConstrainVout(tx.vout[1], 1, 0, 0) == 0 )
|
||||
////////// not implemented yet ////////////
|
||||
return eval->Invalid("normal vout1 for fillex");
|
||||
else if( remaining_price != 0 )
|
||||
{
|
||||
if( ConstrainVout(tx.vout[0], 1, (char *)cpAssets->unspendableCCaddr, 0) == 0 ) // TODO: unsure about this, but this is not impl yet anyway
|
||||
return eval->Invalid("mismatched vout0 AssetsCCaddr for fillex");
|
||||
}
|
||||
}
|
||||
////////// not implemented yet ////////////
|
||||
//fprintf(stderr,"fill validated\n");
|
||||
break;
|
||||
|
||||
default:
|
||||
fprintf(stderr,"illegal assets funcid.(%c)\n",funcid);
|
||||
return eval->Invalid("unexpected assets funcid");
|
||||
//break;
|
||||
}
|
||||
|
||||
// what does this do?
|
||||
bool bPrevent = PreventCC(eval, tx, preventCCvins, numvins, preventCCvouts, numvouts); // seems we do not need this call as we already checked vouts well
|
||||
//std::cerr << "AssetsValidate() PreventCC returned=" << bPrevent << std::endl;
|
||||
return (bPrevent);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -26,7 +26,6 @@
|
||||
#include "main.h"
|
||||
#include "chain.h"
|
||||
#include "core_io.h"
|
||||
#include "crosschain.h"
|
||||
#define FAUCET2SIZE COIN
|
||||
#define EVAL_FAUCET2 EVAL_FIRSTUSER
|
||||
#ifdef BUILD_ROGUE
|
||||
@@ -83,10 +82,6 @@ CClib_methods[] =
|
||||
#elif BUILD_GAMESCC
|
||||
RPC_FUNCS
|
||||
#else
|
||||
{ (char *)"sudoku", (char *)"gen", (char *)"<no args>", 0, 0, 'G', EVAL_SUDOKU },
|
||||
{ (char *)"sudoku", (char *)"txidinfo", (char *)"txid", 1, 1, 'T', EVAL_SUDOKU },
|
||||
{ (char *)"sudoku", (char *)"pending", (char *)"<no args>", 0, 0, 'U', EVAL_SUDOKU },
|
||||
{ (char *)"sudoku", (char *)"solution", (char *)"txid solution timestamps[81]", 83, 83, 'S', EVAL_SUDOKU },
|
||||
{ (char *)"musig", (char *)"calcmsg", (char *)"sendtxid scriptPubKey", 2, 2, 'C', EVAL_MUSIG },
|
||||
{ (char *)"musig", (char *)"combine", (char *)"pubkeys ...", 2, 999999999, 'P', EVAL_MUSIG },
|
||||
{ (char *)"musig", (char *)"session", (char *)"myindex,numsigners,combined_pk,pkhash,msg32", 5, 5, 'R', EVAL_MUSIG },
|
||||
@@ -646,52 +641,11 @@ int32_t cclib_parsehash(uint8_t *hash32,cJSON *item,int32_t len)
|
||||
} else return(-1);
|
||||
}
|
||||
|
||||
#ifdef BUILD_ROGUE
|
||||
#include "rogue_rpc.cpp"
|
||||
#include "rogue/cursesd.c"
|
||||
#include "rogue/vers.c"
|
||||
#include "rogue/extern.c"
|
||||
#include "rogue/armor.c"
|
||||
#include "rogue/chase.c"
|
||||
#include "rogue/command.c"
|
||||
#include "rogue/daemon.c"
|
||||
#include "rogue/daemons.c"
|
||||
#include "rogue/fight.c"
|
||||
#include "rogue/init.c"
|
||||
#include "rogue/io.c"
|
||||
#include "rogue/list.c"
|
||||
#include "rogue/mach_dep.c"
|
||||
#include "rogue/rogue.c"
|
||||
#include "rogue/xcrypt.c"
|
||||
#include "rogue/mdport.c"
|
||||
#include "rogue/misc.c"
|
||||
#include "rogue/monsters.c"
|
||||
#include "rogue/move.c"
|
||||
#include "rogue/new_level.c"
|
||||
#include "rogue/options.c"
|
||||
#include "rogue/pack.c"
|
||||
#include "rogue/passages.c"
|
||||
#include "rogue/potions.c"
|
||||
#include "rogue/rings.c"
|
||||
#include "rogue/rip.c"
|
||||
#include "rogue/rooms.c"
|
||||
#include "rogue/save.c"
|
||||
#include "rogue/scrolls.c"
|
||||
#include "rogue/state.c"
|
||||
#include "rogue/sticks.c"
|
||||
#include "rogue/things.c"
|
||||
#include "rogue/weapons.c"
|
||||
#include "rogue/wizard.c"
|
||||
|
||||
#elif BUILD_CUSTOMCC
|
||||
#if BUILD_CUSTOMCC
|
||||
#include "customcc.cpp"
|
||||
|
||||
#elif BUILD_GAMESCC
|
||||
#include "rogue/cursesd.c"
|
||||
#include "gamescc.cpp"
|
||||
|
||||
#else
|
||||
#include "sudoku.cpp"
|
||||
#include "musig.cpp"
|
||||
#include "dilithium.c"
|
||||
//#include "../secp256k1/src/modules/musig/example.c"
|
||||
|
||||
@@ -1,807 +0,0 @@
|
||||
// Copyright (c) 2016-2023 The Hush developers
|
||||
// Distributed under the GPLv3 software license, see the accompanying
|
||||
// file COPYING or https://www.gnu.org/licenses/gpl-3.0.en.html
|
||||
/******************************************************************************
|
||||
* Copyright © 2014-2019 The SuperNET Developers. *
|
||||
* *
|
||||
* See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at *
|
||||
* the top-level directory of this distribution for the individual copyright *
|
||||
* holder information and the developer policies on copyright and licensing. *
|
||||
* *
|
||||
* Unless otherwise agreed in a custom licensing agreement, no part of the *
|
||||
* SuperNET software, including this file may be copied, modified, propagated *
|
||||
* or distributed except according to the terms contained in the LICENSE file *
|
||||
* *
|
||||
* Removal or modification of this copyright notice is prohibited. *
|
||||
* *
|
||||
******************************************************************************/
|
||||
|
||||
#include "CCchannels.h"
|
||||
|
||||
/*
|
||||
The idea here is to allow instant (mempool) payments that are secured by dPoW. In order to simplify things, channels CC will require creating reserves for each payee locked in the destination user's CC address. This will look like the payment is already made, but it is locked until further released. The dPoW protection comes from the cancel channel having a delayed effect until the next notarization. This way, if a payment release is made and the chain reorged, the same payment release will still be valid when it is re-broadcast into the mempool.
|
||||
|
||||
In order to achieve this effect, the payment release needs to be in a special form where its input cannot be spent only by the sender.
|
||||
|
||||
Given sender's payment to dest CC address, only the destination is able to spend, so we need to constrain that spending with a release mechanism. One idea is a 2of2 multisig, but that has the issue of needing confirmation and since a sender utxo is involved, subject to doublespend and we lose the speed. Another idea is release on secrets! since once revealed, the secret remains valid, this method is immune from double spend. Also, there is no worry about an MITM attack as the funds are only spendable by the destination pubkey and only with the secret. The secrets can be sent via any means, including OP_RETURN of normal transaction in the mempool.
|
||||
|
||||
Now the only remaining issue for sending is how to allocate funds to the secrets. This needs to be sent as hashes of secrets when the channel is created. A bruteforce method would be one secret per COIN, but for large amount channels this is cumbersome. A more practical approach is to have a set of secrets for each order of magnitude:
|
||||
|
||||
123.45 channel funds -> 1x secret100, 2x secret10, 3x secret1, 4x secret.1, 5x secret.01
|
||||
15 secrets achieves the 123.45 channel funding.
|
||||
|
||||
In order to avoid networking issues, the convention can be to send tx to normal address of destination with just an OP_RETURN, for the cost of txfee. For micropayments, a separate method of secret release needs to be established, but that is beyond the scope of this CC.
|
||||
|
||||
There is now the dPoW security that needs to be ensured. In order to close the channel, a tx needs to be confirmed that cancels the channel. As soon as this tx is seen, the destination will know that the channel will be closing soon, if the node is online. If not, the payments cant be credited anyway, so it seems no harm. Even after the channel is closed, it is possible for secrets to be releasing funds, but depending on when the notarization happens, it could invalidate the spends, so it is safest that as soon as the channel cancel tx is confirmed to invalidate any further payments released.
|
||||
|
||||
Given a channelclose and notarization confirmation (or enough blocks), the remaining funds needs to be able to come back to the sender. this means the funds need to be in a 1of2 CC multisig to allow either party to spend. Cheating is prevented by the additional rules of spending, ie. denomination secrets, or channelclose.
|
||||
|
||||
For efficiency we want to allow batch spend with multiple secrets to claim a single total
|
||||
|
||||
Second iteration:
|
||||
As implementing it, some efficieny gains to be made with a slightly different approach.
|
||||
Instead of separate secrets for each amount, a hashchain will be used, each releasing the same amount
|
||||
|
||||
To spend, the prior value in the hash chain is published, or can publish N deep. validation takes N hashes.
|
||||
|
||||
Also, in order to be able to track open channels, a tag is needed to be sent and better to send to a normal CC address for a pubkey to isolate the transactions for channel opens.
|
||||
|
||||
Possible third iteration:
|
||||
Let us try to setup a single "hot wallet" address to have all the channel funds and use it for payments to any destination. If there are no problems with reorgs and double spends, this would allow everyone to be "connected" to everyone else via the single special address.
|
||||
|
||||
So funds -> user's CC address along with hashchain, but likely best to have several utxo to span order of magnitudes.
|
||||
|
||||
a micropayment would then spend a utxo and attach a shared secret encoded unhashed link from the hashchain. That makes the receiver the only one that can decode the actual hashchain's prior value.
|
||||
|
||||
however, since this spend is only spendable by the sender, it is subject to a double spend attack. It seems it is a dead end. Alternative is to use the global CC address, but that commingles all funds from all users and any accounting error puts all funds at risk.
|
||||
|
||||
So, back to the second iteration, which is the only one so far that is immune from doublespend attack as the funds are already in the destination's CC address. One complication is that due to CC sorting of pubkeys, the address for sending and receiving is the same, so the destination pubkey needs to be attached to each opreturn.
|
||||
|
||||
Now when the prior hashchain value is sent via payment, it allows the receiver to spend the utxo, so the only protection needed is to prevent channel close from invalidating already made payments.
|
||||
|
||||
In order to allow multiple payments included in a single transaction, presentation of the N prior hashchain value can be used to get N payments and all the spends create a spending chain in sequential order of the hashchain.
|
||||
|
||||
*/
|
||||
|
||||
// start of consensus code
|
||||
|
||||
#define CC_MARKER_VALUE 10000
|
||||
|
||||
int64_t IsChannelsvout(struct CCcontract_info *cp,const CTransaction& tx,CPubKey srcpub, CPubKey destpub,int32_t v)
|
||||
{
|
||||
char destaddr[65],channeladdr[65],tokenschanneladdr[65];
|
||||
|
||||
GetCCaddress1of2(cp,channeladdr,srcpub,destpub);
|
||||
GetTokensCCaddress1of2(cp,tokenschanneladdr,srcpub,destpub);
|
||||
if ( tx.vout[v].scriptPubKey.IsPayToCryptoCondition() != 0 )
|
||||
{
|
||||
if ( Getscriptaddress(destaddr,tx.vout[v].scriptPubKey) > 0 && (strcmp(destaddr,channeladdr) == 0 || strcmp(destaddr,tokenschanneladdr) == 0))
|
||||
return(tx.vout[v].nValue);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
int64_t IsChannelsMarkervout(struct CCcontract_info *cp,const CTransaction& tx,CPubKey pubkey,int32_t v)
|
||||
{
|
||||
char destaddr[65],ccaddr[65];
|
||||
|
||||
GetCCaddress(cp,ccaddr,pubkey);
|
||||
if ( tx.vout[v].scriptPubKey.IsPayToCryptoCondition() != 0 )
|
||||
{
|
||||
if ( Getscriptaddress(destaddr,tx.vout[v].scriptPubKey) > 0 && strcmp(destaddr,ccaddr) == 0 )
|
||||
return(tx.vout[v].nValue);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
CScript EncodeChannelsOpRet(uint8_t funcid,uint256 tokenid,uint256 opentxid,CPubKey srcpub,CPubKey destpub,int32_t numpayments,int64_t payment,uint256 hashchain)
|
||||
{
|
||||
CScript opret; uint8_t evalcode = EVAL_CHANNELS;
|
||||
vscript_t vopret;
|
||||
|
||||
vopret = E_MARSHAL(ss << evalcode << funcid << opentxid << srcpub << destpub << numpayments << payment << hashchain);
|
||||
if (tokenid!=zeroid)
|
||||
{
|
||||
std::vector<CPubKey> pks;
|
||||
pks.push_back(srcpub);
|
||||
pks.push_back(destpub);
|
||||
return(EncodeTokenOpRet(tokenid,pks, std::make_pair(OPRETID_CHANNELSDATA, vopret)));
|
||||
}
|
||||
opret << OP_RETURN << vopret;
|
||||
return(opret);
|
||||
}
|
||||
|
||||
uint8_t DecodeChannelsOpRet(const CScript &scriptPubKey, uint256 &tokenid, uint256 &opentxid, CPubKey &srcpub,CPubKey &destpub,int32_t &numpayments,int64_t &payment,uint256 &hashchain)
|
||||
{
|
||||
std::vector<std::pair<uint8_t, vscript_t>> oprets;
|
||||
std::vector<uint8_t> vopret,vOpretExtra; uint8_t *script,e,f,tokenevalcode;
|
||||
std::vector<CPubKey> pubkeys;
|
||||
|
||||
if (DecodeTokenOpRet(scriptPubKey,tokenevalcode,tokenid,pubkeys,oprets)!=0 && GetOpretBlob(oprets, OPRETID_CHANNELSDATA, vOpretExtra) && tokenevalcode==EVAL_TOKENS && vOpretExtra.size()>0)
|
||||
{
|
||||
vopret=vOpretExtra;
|
||||
}
|
||||
else GetOpReturnData(scriptPubKey, vopret);
|
||||
if ( vopret.size() > 2 )
|
||||
{
|
||||
script = (uint8_t *)vopret.data();
|
||||
if ( script[0] == EVAL_CHANNELS )
|
||||
{
|
||||
if ( E_UNMARSHAL(vopret,ss >> e; ss >> f; ss >> opentxid; ss >> srcpub; ss >> destpub; ss >> numpayments; ss >> payment; ss >> hashchain) != 0 )
|
||||
{
|
||||
return(f);
|
||||
}
|
||||
} else LOGSTREAM("channelscc",CCLOG_DEBUG1, stream << "script[0] " << script[0] << " != EVAL_CHANNELS" << std::endl);
|
||||
} else LOGSTREAM("channelscc",CCLOG_DEBUG1, stream << "not enough opret.[" << vopret.size() << "]" << std::endl);
|
||||
return(0);
|
||||
}
|
||||
|
||||
bool ChannelsExactAmounts(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx,int32_t minage,uint64_t txfee)
|
||||
{
|
||||
uint256 txid,param3,tokenid;
|
||||
CPubKey srcpub,destpub;
|
||||
int32_t param1,numvouts; int64_t param2; uint8_t funcid;
|
||||
CTransaction vinTx; uint256 hashBlock; int64_t inputs=0,outputs=0;
|
||||
|
||||
if ((numvouts=tx.vout.size()) > 0 && (funcid=DecodeChannelsOpRet(tx.vout[numvouts-1].scriptPubKey, tokenid, txid, srcpub, destpub, param1, param2, param3))!=0)
|
||||
{
|
||||
switch (funcid)
|
||||
{
|
||||
case 'O':
|
||||
return (true);
|
||||
case 'P':
|
||||
if ( eval->GetTxUnconfirmed(tx.vin[1].prevout.hash,vinTx,hashBlock) == 0 )
|
||||
return eval->Invalid("cant find vinTx");
|
||||
inputs = vinTx.vout[tx.vin[1].prevout.n].nValue;
|
||||
outputs = tx.vout[0].nValue + tx.vout[3].nValue;
|
||||
break;
|
||||
case 'C':
|
||||
if ( eval->GetTxUnconfirmed(tx.vin[1].prevout.hash,vinTx,hashBlock) == 0 )
|
||||
return eval->Invalid("cant find vinTx");
|
||||
inputs = vinTx.vout[tx.vin[1].prevout.n].nValue;
|
||||
outputs = tx.vout[0].nValue;
|
||||
break;
|
||||
case 'R':
|
||||
if ( eval->GetTxUnconfirmed(tx.vin[1].prevout.hash,vinTx,hashBlock) == 0 )
|
||||
return eval->Invalid("cant find vinTx");
|
||||
inputs = vinTx.vout[tx.vin[1].prevout.n].nValue;
|
||||
outputs = tx.vout[2].nValue;
|
||||
break;
|
||||
default:
|
||||
return (false);
|
||||
}
|
||||
if ( inputs != outputs )
|
||||
{
|
||||
LOGSTREAM("channelscc",CCLOG_INFO, stream << "inputs " << inputs << " vs outputs " << outputs << std::endl);
|
||||
return eval->Invalid("mismatched inputs != outputs");
|
||||
}
|
||||
else return (true);
|
||||
}
|
||||
else
|
||||
{
|
||||
return eval->Invalid("invalid op_return data");
|
||||
}
|
||||
return(false);
|
||||
}
|
||||
|
||||
bool ChannelsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn)
|
||||
{
|
||||
int32_t numvins,numvouts,preventCCvins,preventCCvouts,i,numpayments,p1,param1; bool retval;
|
||||
uint256 txid,hashblock,p3,param3,opentxid,tmp_txid,genhashchain,hashchain,tokenid;
|
||||
uint8_t funcid,hash[32],hashdest[32]; char channeladdress[65],srcmarker[65],destmarker[65],destaddr[65],srcaddr[65],desttokensaddr[65],srctokensaddr[65];
|
||||
int64_t p2,param2,payment;
|
||||
CPubKey srcpub, destpub;
|
||||
CTransaction channelOpenTx,channelCloseTx,prevTx;
|
||||
|
||||
numvins = tx.vin.size();
|
||||
numvouts = tx.vout.size();
|
||||
preventCCvins = preventCCvouts = -1;
|
||||
if ( numvouts < 1 )
|
||||
return eval->Invalid("no vouts");
|
||||
else
|
||||
{
|
||||
if (ChannelsExactAmounts(cp,eval,tx,1,10000) == false )
|
||||
{
|
||||
return eval->Invalid("invalid channel inputs vs. outputs!");
|
||||
}
|
||||
else
|
||||
{
|
||||
txid = tx.GetHash();
|
||||
memcpy(hash,&txid,sizeof(hash));
|
||||
if ( (funcid = DecodeChannelsOpRet(tx.vout[numvouts-1].scriptPubKey, tokenid, opentxid, srcpub, destpub, param1, param2, param3)) != 0)
|
||||
{
|
||||
if (myGetTransaction(opentxid,channelOpenTx,hashblock)== 0)
|
||||
return eval->Invalid("invalid channelopen tx!");
|
||||
else if ((numvouts=channelOpenTx.vout.size()) > 0 && (DecodeChannelsOpRet(channelOpenTx.vout[numvouts-1].scriptPubKey, tokenid, tmp_txid, srcpub, destpub, numpayments, payment, hashchain)) != 'O')
|
||||
return eval->Invalid("invalid channelopen OP_RETURN data!");
|
||||
GetCCaddress1of2(cp,channeladdress,srcpub,destpub);
|
||||
GetCCaddress(cp,srcmarker,srcpub);
|
||||
GetCCaddress(cp,destmarker,destpub);
|
||||
Getscriptaddress(srcaddr,CScript() << ParseHex(HexStr(srcpub)) << OP_CHECKSIG);
|
||||
Getscriptaddress(destaddr,CScript() << ParseHex(HexStr(destpub)) << OP_CHECKSIG);
|
||||
_GetCCaddress(srctokensaddr,EVAL_TOKENS,srcpub);
|
||||
_GetCCaddress(desttokensaddr,EVAL_TOKENS,destpub);
|
||||
switch ( funcid )
|
||||
{
|
||||
case 'O':
|
||||
//vin.0: normal input
|
||||
//vout.0: CC vout for channel funding on CC1of2 pubkey
|
||||
//vout.1: CC vout marker to senders pubKey
|
||||
//vout.2: CC vout marker to receiver pubkey
|
||||
//vout.n-2: normal change
|
||||
//vout.n-1: opreturn - 'O' zerotxid senderspubkey receiverspubkey totalnumberofpayments paymentamount hashchain
|
||||
return eval->Invalid("unexpected ChannelsValidate for channelsopen!");
|
||||
case 'P':
|
||||
//vin.0: normal input
|
||||
//vin.1: CC input from channel funding
|
||||
//vin.2: CC input from src marker
|
||||
//vout.0: CC vout change to CC1of2 pubkey
|
||||
//vout.1: CC vout marker to senders pubKey
|
||||
//vout.2: CC vout marker to receiver pubkey
|
||||
//vout.3: normal output of payment amount to receiver pubkey
|
||||
//vout.n-2: normal change
|
||||
//vout.n-1: opreturn - 'P' opentxid senderspubkey receiverspubkey depth numpayments secret
|
||||
if ( IsCCInput(channelOpenTx.vin[0].scriptSig) != 0 )
|
||||
return eval->Invalid("vin.0 is normal for channelopen!");
|
||||
else if ( ConstrainVout(channelOpenTx.vout[0],1,channeladdress,numpayments*payment)==0 )
|
||||
return eval->Invalid("vout.0 is CC or invalid amount for channelopen!");
|
||||
else if ( ConstrainVout(channelOpenTx.vout[1],1,srcmarker,CC_MARKER_VALUE)==0 )
|
||||
return eval->Invalid("vout.1 is CC marker to srcpub or invalid amount for channelopen!");
|
||||
else if ( ConstrainVout(channelOpenTx.vout[2],1,destmarker,CC_MARKER_VALUE)==0 )
|
||||
return eval->Invalid("vout.2 is CC marker to destpub or invalid amount for channelopen!");
|
||||
else if (hush_txnotarizedconfirmed(opentxid) == 0)
|
||||
return eval->Invalid("channelopen is not yet confirmed(notarized)!");
|
||||
else if ( IsCCInput(tx.vin[0].scriptSig) != 0 )
|
||||
return eval->Invalid("vin.0 is normal for channelpayment!");
|
||||
else if ( IsCCInput(tx.vin[tx.vin.size()-2].scriptSig) == 0 )
|
||||
return eval->Invalid("vin."+std::to_string(tx.vin.size()-2)+" is CC for channelpayment!");
|
||||
else if ( ConstrainVout(tx.vout[1],1,srcmarker,CC_MARKER_VALUE)==0 )
|
||||
return eval->Invalid("vout.1 is CC marker to srcpub or invalid amount for channelpayment!");
|
||||
else if ( ConstrainVout(tx.vout[2],1,destmarker,CC_MARKER_VALUE)==0 )
|
||||
return eval->Invalid("vout.2 is CC marker to destpub or invalid amount for channelpayment!");
|
||||
else if ( tokenid!=zeroid && ConstrainVout(tx.vout[3],1,desttokensaddr,param2*payment)==0 )
|
||||
return eval->Invalid("vout.3 is CC or invalid amount or invalid receiver for channelpayment!");
|
||||
else if ( tokenid==zeroid && ConstrainVout(tx.vout[3],0,destaddr,param2*payment)==0 )
|
||||
return eval->Invalid("vout.3 is normal or invalid amount or invalid receiver for channelpayment!");
|
||||
else if ( param1 > CHANNELS_MAXPAYMENTS)
|
||||
return eval->Invalid("too many payment increments!");
|
||||
else
|
||||
{
|
||||
endiancpy(hash, (uint8_t * ) & param3, 32);
|
||||
for (i = 0; i < numpayments-param1; i++)
|
||||
{
|
||||
vcalc_sha256(0, hashdest, hash, 32);
|
||||
memcpy(hash, hashdest, 32);
|
||||
}
|
||||
endiancpy((uint8_t*)&genhashchain,hashdest,32);
|
||||
if (hashchain!=genhashchain)
|
||||
return eval->Invalid("invalid secret for payment, does not reach final hashchain!");
|
||||
else if (tx.vout[3].nValue != param2*payment)
|
||||
return eval->Invalid("vout amount does not match number_of_payments*payment!");
|
||||
if (myGetTransaction(tx.vin[1].prevout.hash,prevTx,hashblock) != 0)
|
||||
{
|
||||
if ((numvouts=prevTx.vout.size()) > 0 && DecodeChannelsOpRet(prevTx.vout[numvouts-1].scriptPubKey, tokenid, tmp_txid, srcpub, destpub, p1, p2, p3) == 0)
|
||||
return eval->Invalid("invalid previous tx OP_RETURN data!");
|
||||
else if ( ConstrainVout(tx.vout[0],1,channeladdress,(p1-param2)*payment)==0 )
|
||||
return eval->Invalid("vout.0 is CC or invalid CC change amount for channelpayment!");
|
||||
else if ((*cp->ismyvin)(tx.vin[tx.vin.size()-1].scriptSig) == 0 || prevTx.vout[tx.vin[tx.vin.size()-1].prevout.n].nValue!=CC_MARKER_VALUE)
|
||||
return eval->Invalid("vin."+std::to_string(tx.vin.size()-1)+" is CC marker or invalid marker amount for channelpayment!");
|
||||
else if (param1+param2!=p1)
|
||||
return eval->Invalid("invalid payment depth!");
|
||||
else if (tx.vout[3].nValue > prevTx.vout[0].nValue)
|
||||
return eval->Invalid("not enough funds in channel for that amount!");
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'C':
|
||||
//vin.0: normal input
|
||||
//vin.1: CC input from channel funding
|
||||
//vin.2: CC input from src marker
|
||||
//vout.0: CC vout for channel funding
|
||||
//vout.1: CC vout marker to senders pubKey
|
||||
//vout.2: CC vout marker to receiver pubkey
|
||||
//vout.n-2: normal change
|
||||
//vout.n-1: opreturn - 'C' opentxid senderspubkey receiverspubkey numpayments payment 0
|
||||
if ( IsCCInput(channelOpenTx.vin[0].scriptSig) != 0 )
|
||||
return eval->Invalid("vin.0 is normal for channelopen!");
|
||||
else if ( ConstrainVout(channelOpenTx.vout[0],1,channeladdress,numpayments*payment)==0 )
|
||||
return eval->Invalid("vout.0 is CC or invalid amount for channelopen!");
|
||||
else if ( ConstrainVout(channelOpenTx.vout[1],1,srcmarker,CC_MARKER_VALUE)==0 )
|
||||
return eval->Invalid("vout.1 is CC marker to srcpub or invalid amount for channelopen!");
|
||||
else if ( ConstrainVout(channelOpenTx.vout[2],1,destmarker,CC_MARKER_VALUE)==0 )
|
||||
return eval->Invalid("vout.2 is CC marker to destpub or invalid amount for channelopen!");
|
||||
else if (hush_txnotarizedconfirmed(opentxid) == 0)
|
||||
return eval->Invalid("channelopen is not yet confirmed(notarized)!");
|
||||
else if ( IsCCInput(tx.vin[0].scriptSig) != 0 )
|
||||
return eval->Invalid("vin.0 is normal for channelclose!");
|
||||
else if ( IsCCInput(tx.vin[tx.vin.size()-2].scriptSig) == 0 )
|
||||
return eval->Invalid("vin."+std::to_string(tx.vin.size()-2)+" is CC for channelclose!");
|
||||
else if ( ConstrainVout(tx.vout[0],1,channeladdress,0)==0 )
|
||||
return eval->Invalid("vout.0 is CC for channelclose!");
|
||||
else if ( ConstrainVout(tx.vout[1],1,srcmarker,CC_MARKER_VALUE)==0 )
|
||||
return eval->Invalid("vout.1 is CC marker to srcpub or invalid amount for channelclose!");
|
||||
else if ( ConstrainVout(tx.vout[2],1,destmarker,CC_MARKER_VALUE)==0 )
|
||||
return eval->Invalid("vout.2 is CC marker to destpub or invalid amount for channelclose!");
|
||||
else if ( param1 > CHANNELS_MAXPAYMENTS)
|
||||
return eval->Invalid("too many payment increments!");
|
||||
else if (myGetTransaction(tx.vin[1].prevout.hash,prevTx,hashblock) != 0)
|
||||
{
|
||||
if ((numvouts=prevTx.vout.size()) > 0 && DecodeChannelsOpRet(prevTx.vout[numvouts-1].scriptPubKey, tokenid, tmp_txid, srcpub, destpub, p1, p2, p3) == 0)
|
||||
return eval->Invalid("invalid previous tx OP_RETURN data!");
|
||||
else if ((*cp->ismyvin)(tx.vin[tx.vin.size()-1].scriptSig) == 0 || prevTx.vout[tx.vin[tx.vin.size()-1].prevout.n].nValue!=CC_MARKER_VALUE)
|
||||
return eval->Invalid("vin."+std::to_string(tx.vin.size()-1)+" is CC marker or invalid marker amount for channelclose!");
|
||||
else if (tx.vout[0].nValue != prevTx.vout[0].nValue)
|
||||
return eval->Invalid("invalid CC amount, amount must match funds in channel");
|
||||
}
|
||||
break;
|
||||
case 'R':
|
||||
//vin.0: normal input
|
||||
//vin.1: CC input from channel funding
|
||||
//vin.2: CC input from src marker
|
||||
//vout.0: CC vout marker to senders pubKey
|
||||
//vout.1: CC vout marker to receiver pubKey
|
||||
//vout.2: normal output of CC input to senders pubkey
|
||||
//vout.n-2: normal change
|
||||
//vout.n-1: opreturn - 'R' opentxid senderspubkey receiverspubkey numpayments payment closetxid
|
||||
if ( IsCCInput(channelOpenTx.vin[0].scriptSig) != 0 )
|
||||
return eval->Invalid("vin.0 is normal for channelopen!");
|
||||
else if ( ConstrainVout(channelOpenTx.vout[0],1,channeladdress,numpayments*payment)==0 )
|
||||
return eval->Invalid("vout.0 is CC or invalid amount for channelopen!");
|
||||
else if ( ConstrainVout(channelOpenTx.vout[1],1,srcmarker,CC_MARKER_VALUE)==0 )
|
||||
return eval->Invalid("vout.1 is CC marker to srcpub or invalid amount for channelopen!");
|
||||
else if ( ConstrainVout(channelOpenTx.vout[2],1,destmarker,CC_MARKER_VALUE)==0 )
|
||||
return eval->Invalid("vout.2 is CC marker to destpub or invalid amount for channelopen!");
|
||||
else if (hush_txnotarizedconfirmed(opentxid) == 0)
|
||||
return eval->Invalid("channelopen is not yet confirmed(notarized)!");
|
||||
else if (hush_txnotarizedconfirmed(param3) == 0)
|
||||
return eval->Invalid("channelClose is not yet confirmed(notarized)!");
|
||||
else if ( IsCCInput(tx.vin[0].scriptSig) != 0 )
|
||||
return eval->Invalid("vin.0 is normal for channelrefund!");
|
||||
else if ( IsCCInput(tx.vin[tx.vin.size()-2].scriptSig) == 0 )
|
||||
return eval->Invalid("vin."+std::to_string(tx.vin.size()-2)+" CC for channelrefund!");
|
||||
else if ( ConstrainVout(tx.vout[0],1,srcmarker,CC_MARKER_VALUE)==0 )
|
||||
return eval->Invalid("vout.0 is CC marker to srcpub or invalid amount for channelrefund!");
|
||||
else if ( ConstrainVout(tx.vout[1],1,destmarker,CC_MARKER_VALUE)==0 )
|
||||
return eval->Invalid("vout.1 is CC marker to destpub or invalid amount for channelrefund!");
|
||||
else if ( tokenid!=zeroid && ConstrainVout(tx.vout[2],1,srctokensaddr,param1*payment)==0 )
|
||||
return eval->Invalid("vout.2 is CC or invalid amount or invalid receiver for channelrefund!");
|
||||
else if ( tokenid==zeroid && ConstrainVout(tx.vout[2],0,srcaddr,param1*payment)==0 )
|
||||
return eval->Invalid("vout.2 is normal or invalid amount or invalid receiver for channelrefund!");
|
||||
else if ( param1 > CHANNELS_MAXPAYMENTS)
|
||||
return eval->Invalid("too many payment increments!");
|
||||
else if (myGetTransaction(tx.vin[1].prevout.hash,prevTx,hashblock) != 0)
|
||||
{
|
||||
if ((numvouts=prevTx.vout.size()) > 0 && DecodeChannelsOpRet(prevTx.vout[numvouts-1].scriptPubKey, tokenid, tmp_txid, srcpub, destpub, p1, p2, p3) == 0)
|
||||
return eval->Invalid("invalid previous tx OP_RETURN data!");
|
||||
else if ((*cp->ismyvin)(tx.vin[tx.vin.size()-1].scriptSig) == 0 || prevTx.vout[tx.vin[tx.vin.size()-1].prevout.n].nValue!=CC_MARKER_VALUE)
|
||||
return eval->Invalid("vin."+std::to_string(tx.vin.size()-1)+" is CC marker or invalid marker amount for channelrefund!");
|
||||
else if (tx.vout[2].nValue != prevTx.vout[0].nValue)
|
||||
return eval->Invalid("invalid amount, refund amount and funds in channel must match!");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr,"illegal channels funcid.(%c)\n",funcid);
|
||||
return eval->Invalid("unexpected channels funcid");
|
||||
}
|
||||
}
|
||||
else return eval->Invalid("unexpected channels missing funcid");
|
||||
retval = PreventCC(eval,tx,preventCCvins,numvins,preventCCvouts,numvouts);
|
||||
if ( retval != 0 )
|
||||
LOGSTREAM("channels",CCLOG_INFO, stream << "Channels tx validated" << std::endl);
|
||||
else fprintf(stderr,"Channels tx invalid\n");
|
||||
return(retval);
|
||||
}
|
||||
}
|
||||
}
|
||||
// end of consensus code
|
||||
|
||||
// helper functions for rpc calls in rpcwallet.cpp
|
||||
|
||||
int64_t AddChannelsInputs(struct CCcontract_info *cp,CMutableTransaction &mtx, CTransaction openTx, uint256 &prevtxid, CPubKey mypk)
|
||||
{
|
||||
char coinaddr[65]; int64_t param2,totalinputs = 0,numvouts; uint256 txid=zeroid,tmp_txid,hashBlock,param3,tokenid; CTransaction tx; int32_t marker,param1;
|
||||
std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > unspentOutputs;
|
||||
CPubKey srcpub,destpub;
|
||||
uint8_t myprivkey[32];
|
||||
|
||||
if ((numvouts=openTx.vout.size()) > 0 && DecodeChannelsOpRet(openTx.vout[numvouts-1].scriptPubKey,tokenid,tmp_txid,srcpub,destpub,param1,param2,param3)=='O')
|
||||
{
|
||||
if (tokenid!=zeroid) GetTokensCCaddress1of2(cp,coinaddr,srcpub,destpub);
|
||||
else GetCCaddress1of2(cp,coinaddr,srcpub,destpub);
|
||||
SetCCunspents(unspentOutputs,coinaddr,true);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOGSTREAM("channelscc",CCLOG_INFO, stream << "invalid channel open txid" << std::endl);
|
||||
return 0;
|
||||
}
|
||||
if (srcpub==mypk) marker=1;
|
||||
else marker=2;
|
||||
for (std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++)
|
||||
{
|
||||
if ( (int32_t)it->first.index==0 && myGetTransaction(it->first.txhash,tx,hashBlock) != 0 && (numvouts=tx.vout.size()) > 0)
|
||||
{
|
||||
if (DecodeChannelsOpRet(tx.vout[numvouts-1].scriptPubKey,tokenid,tmp_txid,srcpub,destpub,param1,param2,param3)!=0 &&
|
||||
(tmp_txid==openTx.GetHash() || tx.GetHash()==openTx.GetHash()) && IsChannelsMarkervout(cp,tx,marker==1?srcpub:destpub,marker)>0 &&
|
||||
(totalinputs=IsChannelsvout(cp,tx,srcpub,destpub,0))>0)
|
||||
{
|
||||
txid = it->first.txhash;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (txid!=zeroid && myIsutxo_spentinmempool(ignoretxid,ignorevin,txid,0) != 0)
|
||||
{
|
||||
txid=zeroid;
|
||||
int32_t mindepth=CHANNELS_MAXPAYMENTS;
|
||||
std::vector<CTransaction> tmp_txs;
|
||||
myGet_mempool_txs(tmp_txs,EVAL_CHANNELS,'P');
|
||||
for (std::vector<CTransaction>::const_iterator it=tmp_txs.begin(); it!=tmp_txs.end(); it++)
|
||||
{
|
||||
const CTransaction &txmempool = *it;
|
||||
const uint256 &hash = txmempool.GetHash();
|
||||
|
||||
if ((numvouts=txmempool.vout.size()) > 0 && DecodeChannelsOpRet(txmempool.vout[numvouts-1].scriptPubKey,tokenid,tmp_txid,srcpub,destpub,param1,param2,param3)=='P' &&
|
||||
tmp_txid==openTx.GetHash() && param1 < mindepth)
|
||||
{
|
||||
txid=hash;
|
||||
totalinputs=txmempool.vout[0].nValue;
|
||||
mindepth=param1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (txid != zeroid)
|
||||
{
|
||||
prevtxid=txid;
|
||||
mtx.vin.push_back(CTxIn(txid,0,CScript()));
|
||||
mtx.vin.push_back(CTxIn(txid,marker,CScript()));
|
||||
Myprivkey(myprivkey);
|
||||
if (tokenid!=zeroid) CCaddrTokens1of2set(cp,srcpub,destpub,myprivkey,coinaddr);
|
||||
else CCaddr1of2set(cp,srcpub,destpub,myprivkey,coinaddr);
|
||||
memset(myprivkey,0,32);
|
||||
return totalinputs;
|
||||
}
|
||||
else return 0;
|
||||
}
|
||||
|
||||
UniValue ChannelOpen(const CPubKey& pk, uint64_t txfee,CPubKey destpub,int32_t numpayments,int64_t payment, uint256 tokenid)
|
||||
{
|
||||
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), hush_nextheight());
|
||||
uint8_t hash[32],hashdest[32]; uint64_t amount,tokens=0,funds; int32_t i; uint256 hashchain,entropy,hentropy;
|
||||
CPubKey mypk; struct CCcontract_info *cp,*cpTokens,C,CTokens;
|
||||
|
||||
if ( numpayments <= 0 || payment <= 0 || numpayments > CHANNELS_MAXPAYMENTS )
|
||||
CCERR_RESULT("channelscc",CCLOG_INFO, stream << "invalid ChannelOpen param numpayments." << numpayments << " payment." << payment << " - max_numpayments." << CHANNELS_MAXPAYMENTS);
|
||||
if (!destpub.IsFullyValid())
|
||||
CCERR_RESULT("channelscc",CCLOG_INFO, stream << "invalid destination pubkey");
|
||||
if (numpayments <1)
|
||||
CCERR_RESULT("channelscc",CCLOG_INFO, stream << "invalid number of payments, must be greater than 0");
|
||||
if (payment <1)
|
||||
CCERR_RESULT("channelscc",CCLOG_INFO, stream << "invalid payment amount, must be greater than 0");
|
||||
cp = CCinit(&C,EVAL_CHANNELS);
|
||||
cpTokens = CCinit(&CTokens,EVAL_TOKENS);
|
||||
if ( txfee == 0 )
|
||||
txfee = 10000;
|
||||
mypk = pk.IsValid()?pk:pubkey2pk(Mypubkey());
|
||||
funds = numpayments * payment;
|
||||
if (tokenid!=zeroid)
|
||||
{
|
||||
amount=AddNormalinputs(mtx,mypk,txfee+2*CC_MARKER_VALUE,5,pk.IsValid());
|
||||
tokens=AddTokenCCInputs(cpTokens, mtx, mypk, tokenid, funds, 64);
|
||||
}
|
||||
else amount=AddNormalinputs(mtx,mypk,funds+txfee+2*CC_MARKER_VALUE,64,pk.IsValid());
|
||||
if (amount+tokens >= funds+txfee+2*CC_MARKER_VALUE)
|
||||
{
|
||||
hentropy = DiceHashEntropy(entropy,mtx.vin[0].prevout.hash,mtx.vin[0].prevout.n,1);
|
||||
endiancpy(hash,(uint8_t *)&hentropy,32);
|
||||
for (i=0; i<numpayments; i++)
|
||||
{
|
||||
vcalc_sha256(0,hashdest,hash,32);
|
||||
memcpy(hash,hashdest,32);
|
||||
}
|
||||
endiancpy((uint8_t *)&hashchain,hashdest,32);
|
||||
if (tokenid!=zeroid) mtx.vout.push_back(MakeTokensCC1of2vout(EVAL_CHANNELS,funds,mypk,destpub));
|
||||
else mtx.vout.push_back(MakeCC1of2vout(EVAL_CHANNELS,funds,mypk,destpub));
|
||||
mtx.vout.push_back(MakeCC1vout(EVAL_CHANNELS,CC_MARKER_VALUE,mypk));
|
||||
mtx.vout.push_back(MakeCC1vout(EVAL_CHANNELS,CC_MARKER_VALUE,destpub));
|
||||
if (tokenid!=zeroid && tokens>funds) mtx.vout.push_back(MakeCC1vout(EVAL_TOKENS,tokens-funds,mypk));
|
||||
return(FinalizeCCTxExt(pk.IsValid(),0,cp,mtx,mypk,txfee,EncodeChannelsOpRet('O',tokenid,zeroid,mypk,destpub,numpayments,payment,hashchain)));
|
||||
}
|
||||
CCERR_RESULT("channelscc",CCLOG_INFO, stream << "error adding funds");
|
||||
}
|
||||
|
||||
UniValue ChannelPayment(const CPubKey& pk, uint64_t txfee,uint256 opentxid,int64_t amount, uint256 secret)
|
||||
{
|
||||
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), hush_nextheight());
|
||||
CPubKey mypk,srcpub,destpub; uint256 txid,hashchain,gensecret,hashblock,entropy,hentropy,prevtxid,param3,tokenid;
|
||||
struct CCcontract_info *cp,C; int32_t i,funcid,prevdepth,numvouts,numpayments,totalnumpayments;
|
||||
int64_t payment,change,funds,param2;
|
||||
uint8_t hash[32],hashdest[32];
|
||||
CTransaction channelOpenTx,prevTx;
|
||||
|
||||
cp = CCinit(&C,EVAL_CHANNELS);
|
||||
if ( txfee == 0 )
|
||||
txfee = 10000;
|
||||
mypk = pk.IsValid()?pk:pubkey2pk(Mypubkey());
|
||||
if (amount <1)
|
||||
CCERR_RESULT("channelscc",CCLOG_INFO, stream << "invalid payment amount, must be greater than 0");
|
||||
if (myGetTransaction(opentxid,channelOpenTx,hashblock) == 0)
|
||||
CCERR_RESULT("channelscc",CCLOG_INFO, stream << "invalid channel open txid");
|
||||
if ((numvouts=channelOpenTx.vout.size()) > 0 && DecodeChannelsOpRet(channelOpenTx.vout[numvouts-1].scriptPubKey, tokenid, txid, srcpub, destpub, totalnumpayments, payment, hashchain)=='O')
|
||||
{
|
||||
if (mypk != srcpub && mypk != destpub)
|
||||
CCERR_RESULT("channelscc",CCLOG_INFO, stream << "this is not our channel");
|
||||
else if (amount % payment != 0 || amount<payment)
|
||||
CCERR_RESULT("channelscc",CCLOG_INFO, stream << "invalid amount, not a magnitude of payment size");
|
||||
else if (mypk == destpub && secret==zeroid) CCERR_RESULT("channelscc",CCLOG_INFO, stream << "invalid secret, secret is necessary when making payment from destination");
|
||||
}
|
||||
else
|
||||
CCERR_RESULT("channelscc",CCLOG_INFO, stream << "invalid channel open tx");
|
||||
if (hush_txnotarizedconfirmed(opentxid)==false) CCERR_RESULT("channelscc",CCLOG_INFO, stream << "channelsopen tx not yet confirmed/notarized");
|
||||
if (AddNormalinputs(mtx,mypk,txfee+CC_MARKER_VALUE,3,pk.IsValid()) > 0)
|
||||
{
|
||||
if ((funds=AddChannelsInputs(cp,mtx,channelOpenTx,prevtxid,mypk)) !=0 && (change=funds-amount)>=0)
|
||||
{
|
||||
numpayments=amount/payment;
|
||||
if (myGetTransaction(prevtxid,prevTx,hashblock) != 0 && (numvouts=prevTx.vout.size()) > 0 &&
|
||||
((funcid = DecodeChannelsOpRet(prevTx.vout[numvouts-1].scriptPubKey, tokenid, txid, srcpub, destpub, prevdepth, param2, param3)) != 0) &&
|
||||
(funcid == 'P' || funcid=='O'))
|
||||
{
|
||||
if (numpayments > prevdepth)
|
||||
CCERR_RESULT("channelscc",CCLOG_INFO, stream << "not enough funds in channel for that amount");
|
||||
else if (numpayments == 0)
|
||||
CCERR_RESULT("channelscc",CCLOG_INFO, stream << "invalid amount");
|
||||
if (secret!=zeroid)
|
||||
{
|
||||
endiancpy(hash, (uint8_t * ) & secret, 32);
|
||||
for (i = 0; i < totalnumpayments-(prevdepth-numpayments); i++)
|
||||
{
|
||||
vcalc_sha256(0, hashdest, hash, 32);
|
||||
memcpy(hash, hashdest, 32);
|
||||
}
|
||||
endiancpy((uint8_t * ) & gensecret, hashdest, 32);
|
||||
if (gensecret!=hashchain) CCERR_RESULT("channelscc",CCLOG_INFO, stream << "invalid secret supplied");
|
||||
}
|
||||
else
|
||||
{
|
||||
hentropy = DiceHashEntropy(entropy,channelOpenTx.vin[0].prevout.hash,channelOpenTx.vin[0].prevout.n,1);
|
||||
if (prevdepth-numpayments)
|
||||
{
|
||||
endiancpy(hash, (uint8_t * ) & hentropy, 32);
|
||||
for (i = 0; i < prevdepth-numpayments; i++)
|
||||
{
|
||||
vcalc_sha256(0, hashdest, hash, 32);
|
||||
memcpy(hash, hashdest, 32);
|
||||
}
|
||||
endiancpy((uint8_t * ) & secret, hashdest, 32);
|
||||
}
|
||||
else endiancpy((uint8_t * ) & secret, (uint8_t * ) & hentropy, 32);
|
||||
}
|
||||
}
|
||||
else
|
||||
CCERR_RESULT("channelscc",CCLOG_INFO, stream << "invalid previous tx");
|
||||
if (tokenid!=zeroid) mtx.vout.push_back(MakeTokensCC1of2vout(EVAL_CHANNELS, change, srcpub, destpub));
|
||||
else mtx.vout.push_back(MakeCC1of2vout(EVAL_CHANNELS, change, srcpub, destpub));
|
||||
mtx.vout.push_back(MakeCC1vout(EVAL_CHANNELS,CC_MARKER_VALUE,srcpub));
|
||||
mtx.vout.push_back(MakeCC1vout(EVAL_CHANNELS,CC_MARKER_VALUE,destpub));
|
||||
if (tokenid!=zeroid) mtx.vout.push_back(MakeCC1vout(EVAL_TOKENS, amount, destpub));
|
||||
else mtx.vout.push_back(CTxOut(amount, CScript() << ParseHex(HexStr(destpub)) << OP_CHECKSIG));
|
||||
return (FinalizeCCTxExt(pk.IsValid(), 0, cp, mtx, mypk, txfee, EncodeChannelsOpRet('P', tokenid, opentxid, srcpub, destpub, prevdepth-numpayments, numpayments, secret)));
|
||||
}
|
||||
else
|
||||
CCERR_RESULT("channelscc",CCLOG_INFO, stream << "error adding CC inputs");
|
||||
}
|
||||
CCERR_RESULT("channelscc",CCLOG_INFO, stream << "error adding normal inputs");
|
||||
}
|
||||
|
||||
UniValue ChannelClose(const CPubKey& pk, uint64_t txfee,uint256 opentxid)
|
||||
{
|
||||
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), hush_nextheight());
|
||||
CPubKey mypk,srcpub,destpub; struct CCcontract_info *cp,C;
|
||||
CTransaction channelOpenTx;
|
||||
uint256 hashblock,tmp_txid,prevtxid,hashchain,tokenid;
|
||||
int32_t numvouts,numpayments;
|
||||
int64_t payment,funds;
|
||||
|
||||
// verify this is one of our outbound channels
|
||||
cp = CCinit(&C,EVAL_CHANNELS);
|
||||
if ( txfee == 0 )
|
||||
txfee = 10000;
|
||||
mypk = pk.IsValid()?pk:pubkey2pk(Mypubkey());
|
||||
if (myGetTransaction(opentxid,channelOpenTx,hashblock) == 0)
|
||||
CCERR_RESULT("channelscc",CCLOG_INFO, stream << "invalid channel open txid");
|
||||
if ((numvouts=channelOpenTx.vout.size()) < 1 || DecodeChannelsOpRet(channelOpenTx.vout[numvouts-1].scriptPubKey,tokenid,tmp_txid,srcpub,destpub,numpayments,payment,hashchain)!='O')
|
||||
CCERR_RESULT("channelscc",CCLOG_INFO, stream << "invalid channel open tx");
|
||||
if (hush_txnotarizedconfirmed(opentxid)==false)
|
||||
CCERR_RESULT("channelscc",CCLOG_INFO, stream <<"channelsopen tx not yet confirmed/notarized");
|
||||
if (mypk != srcpub)
|
||||
CCERR_RESULT("channelscc",CCLOG_INFO, stream << "cannot close, you are not channel owner");
|
||||
if ( AddNormalinputs(mtx,mypk,txfee+CC_MARKER_VALUE,3,pk.IsValid()) > 0 )
|
||||
{
|
||||
if ((funds=AddChannelsInputs(cp,mtx,channelOpenTx,prevtxid,mypk)) !=0 && funds>0)
|
||||
{
|
||||
if (tokenid!=zeroid) mtx.vout.push_back(MakeTokensCC1of2vout(EVAL_CHANNELS, funds, mypk, destpub));
|
||||
else mtx.vout.push_back(MakeCC1of2vout(EVAL_CHANNELS, funds, mypk, destpub));
|
||||
mtx.vout.push_back(MakeCC1vout(EVAL_CHANNELS,CC_MARKER_VALUE,mypk));
|
||||
mtx.vout.push_back(MakeCC1vout(EVAL_CHANNELS,CC_MARKER_VALUE,destpub));
|
||||
return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeChannelsOpRet('C',tokenid,opentxid,mypk,destpub,funds/payment,payment,zeroid)));
|
||||
}
|
||||
else
|
||||
CCERR_RESULT("channelscc",CCLOG_INFO, stream << "error adding CC inputs");
|
||||
}
|
||||
CCERR_RESULT("channelscc",CCLOG_INFO, stream << "error adding normal inputs");
|
||||
}
|
||||
|
||||
UniValue ChannelRefund(const CPubKey& pk, uint64_t txfee,uint256 opentxid,uint256 closetxid)
|
||||
{
|
||||
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), hush_nextheight());
|
||||
CPubKey mypk; struct CCcontract_info *cp,C; int64_t funds,payment,param2;
|
||||
int32_t i,numpayments,numvouts,param1;
|
||||
uint256 hashchain,hashblock,txid,prevtxid,param3,tokenid;
|
||||
CTransaction channelOpenTx,channelCloseTx,prevTx;
|
||||
CPubKey srcpub,destpub;
|
||||
|
||||
// verify stoptxid and origtxid match and are mine
|
||||
cp = CCinit(&C,EVAL_CHANNELS);
|
||||
if ( txfee == 0 )
|
||||
txfee = 10000;
|
||||
mypk = pk.IsValid()?pk:pubkey2pk(Mypubkey());
|
||||
if (myGetTransaction(closetxid,channelCloseTx,hashblock) == 0)
|
||||
CCERR_RESULT("channelscc",CCLOG_INFO, stream << "invalid channel close txid");
|
||||
if ((numvouts=channelCloseTx.vout.size()) < 1 || DecodeChannelsOpRet(channelCloseTx.vout[numvouts-1].scriptPubKey,tokenid,txid,srcpub,destpub,param1,param2,param3)!='C')
|
||||
CCERR_RESULT("channelscc",CCLOG_INFO, stream << "invalid channel close tx");
|
||||
if (hush_txnotarizedconfirmed(closetxid)==false)
|
||||
CCERR_RESULT("channelscc",CCLOG_INFO, stream << "channelsclose tx not yet confirmed/notarized");
|
||||
if (txid!=opentxid)
|
||||
CCERR_RESULT("channelscc",CCLOG_INFO, stream << "open and close txid are not from same channel");
|
||||
if (myGetTransaction(opentxid,channelOpenTx,hashblock) == 0)
|
||||
CCERR_RESULT("channelscc",CCLOG_INFO, stream << "invalid channel open txid");
|
||||
if (hush_txnotarizedconfirmed(opentxid)==false)
|
||||
CCERR_RESULT("channelscc",CCLOG_INFO, stream << "channelsopen tx not yet confirmed/notarized");
|
||||
if ((numvouts=channelOpenTx.vout.size()) < 1 || DecodeChannelsOpRet(channelOpenTx.vout[numvouts-1].scriptPubKey,tokenid,txid,srcpub,destpub,numpayments,payment,hashchain)!='O')
|
||||
CCERR_RESULT("channelscc",CCLOG_INFO, stream << "invalid channel open tx");
|
||||
if (mypk != srcpub)
|
||||
CCERR_RESULT("channelscc",CCLOG_INFO, stream << "cannot refund, you are not the channel owner");
|
||||
if ( AddNormalinputs(mtx,mypk,txfee+CC_MARKER_VALUE,3,pk.IsValid()) > 0 )
|
||||
{
|
||||
if ((funds=AddChannelsInputs(cp,mtx,channelOpenTx,prevtxid,mypk)) !=0 && funds>0)
|
||||
{
|
||||
if ((myGetTransaction(prevtxid,prevTx,hashblock) != 0) && (numvouts=prevTx.vout.size()) > 0 &&
|
||||
DecodeChannelsOpRet(prevTx.vout[numvouts-1].scriptPubKey, tokenid, txid, srcpub, destpub, param1, param2, param3) != 0)
|
||||
{
|
||||
mtx.vout.push_back(MakeCC1vout(EVAL_CHANNELS,CC_MARKER_VALUE,mypk));
|
||||
mtx.vout.push_back(MakeCC1vout(EVAL_CHANNELS,CC_MARKER_VALUE,destpub));
|
||||
if (tokenid!=zeroid) mtx.vout.push_back(MakeCC1vout(EVAL_TOKENS,funds,mypk));
|
||||
else mtx.vout.push_back(CTxOut(funds,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG));
|
||||
return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeChannelsOpRet('R',tokenid,opentxid,mypk,destpub,funds/payment,payment,closetxid)));
|
||||
}
|
||||
else
|
||||
CCERR_RESULT("channelscc",CCLOG_INFO, stream << "previous tx is invalid");
|
||||
}
|
||||
else
|
||||
CCERR_RESULT("channelscc",CCLOG_INFO, stream << "error adding CC inputs");
|
||||
}
|
||||
CCERR_RESULT("channelscc",CCLOG_INFO, stream << "error adding normal inputs");
|
||||
}
|
||||
|
||||
UniValue ChannelsList(const CPubKey& pk)
|
||||
{
|
||||
UniValue result(UniValue::VOBJ); std::vector<uint256> txids; struct CCcontract_info *cp,C; uint256 txid,hashBlock,tmp_txid,param3,tokenid;
|
||||
CTransaction tx; char myCCaddr[65],str[512],pub[34]; CPubKey mypk,srcpub,destpub; int32_t vout,numvouts,param1;
|
||||
int64_t nValue,param2;
|
||||
|
||||
cp = CCinit(&C,EVAL_CHANNELS);
|
||||
mypk = pk.IsValid()?pk:pubkey2pk(Mypubkey());
|
||||
GetCCaddress(cp,myCCaddr,mypk);
|
||||
SetCCtxids(txids,myCCaddr,true,EVAL_CHANNELS,zeroid,'O');
|
||||
result.push_back(Pair("result","success"));
|
||||
result.push_back(Pair("name","Channels List"));
|
||||
for (std::vector<uint256>::const_iterator it=txids.begin(); it!=txids.end(); it++)
|
||||
{
|
||||
txid = *it;
|
||||
if ( myGetTransaction(txid,tx,hashBlock) != 0 && (numvouts= tx.vout.size()) > 0 )
|
||||
{
|
||||
if (DecodeChannelsOpRet(tx.vout[numvouts-1].scriptPubKey,tokenid,tmp_txid,srcpub,destpub,param1,param2,param3) == 'O')
|
||||
{
|
||||
sprintf(str,"%lld payments of %lld satoshi to %s",(long long)param1,(long long)param2,pubkey33_str(pub,(uint8_t *)&destpub));
|
||||
result.push_back(Pair(txid.GetHex().data(),str));
|
||||
}
|
||||
}
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
UniValue ChannelsInfo(const CPubKey& pk,uint256 channeltxid)
|
||||
{
|
||||
UniValue result(UniValue::VOBJ),array(UniValue::VARR); CTransaction tx,opentx; uint256 txid,tmp_txid,hashBlock,param3,opentxid,hashchain,tokenid;
|
||||
struct CCcontract_info *cp,C; char CCaddr[65],addr[65],str[512]; int32_t vout,numvouts,param1,numpayments;
|
||||
int64_t param2,payment; CPubKey srcpub,destpub,mypk;
|
||||
std::vector<uint256> txids; std::vector<CTransaction> txs;
|
||||
|
||||
cp = CCinit(&C,EVAL_CHANNELS);
|
||||
mypk = pk.IsValid()?pk:pubkey2pk(Mypubkey());
|
||||
|
||||
if (myGetTransaction(channeltxid,tx,hashBlock) != 0 && (numvouts= tx.vout.size()) > 0 &&
|
||||
(DecodeChannelsOpRet(tx.vout[numvouts-1].scriptPubKey,tokenid,opentxid,srcpub,destpub,param1,param2,param3) == 'O'))
|
||||
{
|
||||
GetCCaddress1of2(cp,CCaddr,srcpub,destpub);
|
||||
Getscriptaddress(addr,CScript() << ParseHex(HexStr(destpub)) << OP_CHECKSIG);
|
||||
result.push_back(Pair("result","success"));
|
||||
result.push_back(Pair("Channel CC address",CCaddr));
|
||||
result.push_back(Pair("Destination address",addr));
|
||||
result.push_back(Pair("Number of payments",param1));
|
||||
if(tokenid!=zeroid)
|
||||
{
|
||||
result.push_back(Pair("Token id",tokenid.GetHex().data()));
|
||||
result.push_back(Pair("Denomination (token satoshi)",i64tostr(param2)));
|
||||
result.push_back(Pair("Amount (token satoshi)",i64tostr(param1*param2)));
|
||||
}
|
||||
else
|
||||
{
|
||||
result.push_back(Pair("Denomination (satoshi)",i64tostr(param2)));
|
||||
result.push_back(Pair("Amount (satoshi)",i64tostr(param1*param2)));
|
||||
}
|
||||
GetCCaddress(cp,CCaddr,mypk);
|
||||
SetCCtxids(txids,CCaddr,true,EVAL_CHANNELS,channeltxid,0);
|
||||
for (std::vector<uint256>::const_iterator it=txids.begin(); it!=txids.end(); it++)
|
||||
{
|
||||
if (myGetTransaction(*it,tx,hashBlock) != 0 && (numvouts= tx.vout.size()) > 0 &&
|
||||
DecodeChannelsOpRet(tx.vout[numvouts-1].scriptPubKey,tokenid,tmp_txid,srcpub,destpub,param1,param2,param3)!=0 && (tmp_txid==channeltxid || tx.GetHash()==channeltxid))
|
||||
txs.push_back(tx);
|
||||
}
|
||||
std::vector<CTransaction> tmp_txs;
|
||||
myGet_mempool_txs(tmp_txs,EVAL_CHANNELS,'P');
|
||||
for (std::vector<CTransaction>::const_iterator it=tmp_txs.begin(); it!=tmp_txs.end(); it++)
|
||||
{
|
||||
const CTransaction &txmempool = *it;
|
||||
|
||||
if ((numvouts=txmempool.vout.size()) > 0 && DecodeChannelsOpRet(txmempool.vout[numvouts-1].scriptPubKey,tokenid,tmp_txid,srcpub,destpub,param1,param2,param3) == 'P' && tmp_txid==channeltxid)
|
||||
txs.push_back(txmempool);
|
||||
}
|
||||
for (std::vector<CTransaction>::const_iterator it=txs.begin(); it!=txs.end(); it++)
|
||||
{
|
||||
tx=*it;
|
||||
if ((numvouts= tx.vout.size()) > 0 )
|
||||
{
|
||||
UniValue obj(UniValue::VOBJ);
|
||||
if (DecodeChannelsOpRet(tx.vout[numvouts-1].scriptPubKey,tokenid,tmp_txid,srcpub,destpub,param1,param2,param3) == 'O' && tx.GetHash()==channeltxid)
|
||||
{
|
||||
obj.push_back(Pair("Open",tx.GetHash().GetHex().data()));
|
||||
}
|
||||
else if (DecodeChannelsOpRet(tx.vout[numvouts-1].scriptPubKey,tokenid,opentxid,srcpub,destpub,param1,param2,param3) == 'P' && opentxid==channeltxid)
|
||||
{
|
||||
if (myGetTransaction(opentxid,opentx,hashBlock) != 0 && (numvouts=opentx.vout.size()) > 0 &&
|
||||
DecodeChannelsOpRet(opentx.vout[numvouts-1].scriptPubKey,tokenid,tmp_txid,srcpub,destpub,numpayments,payment,hashchain) == 'O')
|
||||
{
|
||||
Getscriptaddress(str,tx.vout[3].scriptPubKey);
|
||||
obj.push_back(Pair("Payment",tx.GetHash().GetHex().data()));
|
||||
obj.push_back(Pair("Number of payments",param2));
|
||||
obj.push_back(Pair("Amount",param2*payment));
|
||||
obj.push_back(Pair("Destination",str));
|
||||
obj.push_back(Pair("Secret",param3.ToString().c_str()));
|
||||
obj.push_back(Pair("Payments left",param1));
|
||||
}
|
||||
}
|
||||
else if (DecodeChannelsOpRet(tx.vout[numvouts-1].scriptPubKey,tokenid,opentxid,srcpub,destpub,param1,param2,param3) == 'C' && opentxid==channeltxid)
|
||||
{
|
||||
obj.push_back(Pair("Close",tx.GetHash().GetHex().data()));
|
||||
}
|
||||
else if (DecodeChannelsOpRet(tx.vout[numvouts-1].scriptPubKey,tokenid,opentxid,srcpub,destpub,param1,param2,param3) == 'R' && opentxid==channeltxid)
|
||||
{
|
||||
Getscriptaddress(str,tx.vout[2].scriptPubKey);
|
||||
obj.push_back(Pair("Refund",tx.GetHash().GetHex().data()));
|
||||
obj.push_back(Pair("Amount",param1*param2));
|
||||
obj.push_back(Pair("Destination",str));
|
||||
}
|
||||
array.push_back(obj);
|
||||
}
|
||||
}
|
||||
result.push_back(Pair("Transactions",array));
|
||||
}
|
||||
else
|
||||
{
|
||||
result.push_back(Pair("result","error"));
|
||||
result.push_back(Pair("Error","Channel not found!"));
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
1871
src/cc/dice.cpp
1871
src/cc/dice.cpp
File diff suppressed because it is too large
Load Diff
@@ -103,6 +103,7 @@ bool Eval::Dispatch(const CC *cond, const CTransaction &txTo, unsigned int nIn)
|
||||
|
||||
switch ( ecode )
|
||||
{
|
||||
/*
|
||||
case EVAL_IMPORTPAYOUT:
|
||||
return ImportPayout(vparams, txTo, nIn);
|
||||
break;
|
||||
@@ -110,7 +111,7 @@ bool Eval::Dispatch(const CC *cond, const CTransaction &txTo, unsigned int nIn)
|
||||
case EVAL_IMPORTCOIN:
|
||||
return ImportCoin(vparams, txTo, nIn);
|
||||
break;
|
||||
|
||||
*/
|
||||
default:
|
||||
return(ProcessCC(cp,this, vparams, txTo, nIn));
|
||||
break;
|
||||
|
||||
1813
src/cc/gamescc.cpp
1813
src/cc/gamescc.cpp
File diff suppressed because it is too large
Load Diff
1552
src/cc/gateways.cpp
1552
src/cc/gateways.cpp
File diff suppressed because it is too large
Load Diff
@@ -545,7 +545,7 @@ template <class Helper> int64_t Add1of2AddressInputs(struct CCcontract_info* cp,
|
||||
if ((txid == fundingtxid || fundingTxidInOpret == fundingtxid) &&
|
||||
funcId != 0 &&
|
||||
isMyFuncId(funcId) &&
|
||||
(typeid(Helper) != typeid(TokenHelper) || IsTokensvout(true, true, cp, nullptr, heirtx, voutIndex, tokenid) > 0) && // token validation logic
|
||||
(typeid(Helper) != typeid(TokenHelper) ) && // token validation logic
|
||||
//(voutValue = IsHeirFundingVout<Helper>(cp, heirtx, voutIndex, ownerPubkey, heirPubkey)) > 0 && // heir contract vout validation logic - not used since we moved to 2-eval vouts
|
||||
!myIsutxo_spentinmempool(ignoretxid,ignorevin,txid, voutIndex))
|
||||
{
|
||||
@@ -596,7 +596,7 @@ template <class Helper> int64_t LifetimeHeirContractFunds(struct CCcontract_info
|
||||
if (funcId != 0 &&
|
||||
(txid == fundingtxid || fundingTxidInOpret == fundingtxid) &&
|
||||
isMyFuncId(funcId) && !isSpendingTx(funcId) &&
|
||||
(typeid(Helper) != typeid(TokenHelper) || IsTokensvout(true, true, cp, nullptr, heirtx, ivout, tokenid) > 0) &&
|
||||
(typeid(Helper) != typeid(TokenHelper) ) &&
|
||||
!myIsutxo_spentinmempool(ignoretxid,ignorevin,txid, ivout)) // exclude tx in mempool
|
||||
{
|
||||
total += it->second; // dont do this: tx.vout[ivout].nValue; // in vin[0] always is the pay to 1of2 addr (funding or change)
|
||||
|
||||
@@ -68,9 +68,12 @@ class TokenHelper {
|
||||
public:
|
||||
static uint8_t getMyEval() { return EVAL_TOKENS; }
|
||||
static int64_t addOwnerInputs(uint256 tokenid, CMutableTransaction& mtx, CPubKey ownerPubkey, int64_t total, int32_t maxinputs) {
|
||||
/*
|
||||
struct CCcontract_info *cpHeir, heirC;
|
||||
cpHeir = CCinit(&heirC, EVAL_TOKENS);
|
||||
return AddTokenCCInputs(cpHeir, mtx, ownerPubkey, tokenid, total, maxinputs);
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
static CScript makeCreateOpRet(uint256 tokenid, std::vector<CPubKey> voutTokenPubkeys, CPubKey ownerPubkey, CPubKey heirPubkey, int64_t inactivityTimeSec, std::string heirName, std::string memo) {
|
||||
|
||||
@@ -1,764 +0,0 @@
|
||||
// Copyright (c) 2016-2023 The Hush developers
|
||||
// Distributed under the GPLv3 software license, see the accompanying
|
||||
// file COPYING or https://www.gnu.org/licenses/gpl-3.0.en.html
|
||||
/******************************************************************************
|
||||
* Copyright © 2014-2019 The SuperNET Developers. *
|
||||
* *
|
||||
* See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at *
|
||||
* the top-level directory of this distribution for the individual copyright *
|
||||
* holder information and the developer policies on copyright and licensing. *
|
||||
* *
|
||||
* Unless otherwise agreed in a custom licensing agreement, no part of the *
|
||||
* SuperNET software, including this file may be copied, modified, propagated *
|
||||
* or distributed except according to the terms contained in the LICENSE file *
|
||||
* *
|
||||
* Removal or modification of this copyright notice is prohibited. *
|
||||
* *
|
||||
******************************************************************************/
|
||||
|
||||
#include "cc/eval.h"
|
||||
#include "cc/utils.h"
|
||||
#include "importcoin.h"
|
||||
#include "crosschain.h"
|
||||
#include "primitives/transaction.h"
|
||||
#include "cc/CCinclude.h"
|
||||
#include <wolfssl/wolfcrypt/sha.h>
|
||||
#include "cc/CCtokens.h"
|
||||
|
||||
#include "key_io.h"
|
||||
#define CODA_BURN_ADDRESS "KPrrRoPfHOnNpZZQ6laHXdQDkSQDkVHaN0V+LizLlHxz7NaA59sBAAAA"
|
||||
/*
|
||||
* CC Eval method for import coin.
|
||||
*
|
||||
* This method should control every parameter of the ImportCoin transaction, since it has no signature
|
||||
* to protect it from malleability.
|
||||
|
||||
##### 0xffffffff is a special CCid for single chain/dual daemon imports
|
||||
*/
|
||||
|
||||
extern std::string ASSETCHAINS_SELFIMPORT;
|
||||
extern uint16_t ASSETCHAINS_CODAPORT,ASSETCHAINS_BEAMPORT;
|
||||
extern uint8_t ASSETCHAINS_OVERRIDE_PUBKEY33[33];
|
||||
extern uint256 HUSH_EARLYTXID;
|
||||
|
||||
// utilities from gateways.cpp
|
||||
uint256 BitcoinGetProofMerkleRoot(const std::vector<uint8_t> &proofData, std::vector<uint256> &txids);
|
||||
uint256 GatewaysReverseScan(uint256 &txid, int32_t height, uint256 reforacletxid, uint256 batontxid);
|
||||
int32_t GatewaysCointxidExists(struct CCcontract_info *cp, uint256 cointxid);
|
||||
uint8_t DecodeImportGatewayBindOpRet(char *burnaddr,const CScript &scriptPubKey,std::string &coin,uint256 &oracletxid,uint8_t &M,uint8_t &N,std::vector<CPubKey> &importgatewaypubkeys,uint8_t &taddr,uint8_t &prefix,uint8_t &prefix2,uint8_t &wiftype);
|
||||
int64_t ImportGatewayVerify(char *refburnaddr,uint256 oracletxid,int32_t claimvout,std::string refcoin,uint256 burntxid,const std::string deposithex,std::vector<uint8_t>proof,uint256 merkleroot,CPubKey destpub,uint8_t taddr,uint8_t prefix,uint8_t prefix2);
|
||||
char *nonportable_path(char *str);
|
||||
char *portable_path(char *str);
|
||||
void *loadfile(char *fname,uint8_t **bufp,long *lenp,long *allocsizep);
|
||||
void *filestr(long *allocsizep,char *_fname);
|
||||
|
||||
cJSON* CodaRPC(char **retstr,char const *arg0,char const *arg1,char const *arg2,char const *arg3,char const *arg4,char const *arg5)
|
||||
{
|
||||
char cmdstr[5000],fname[256],*jsonstr;
|
||||
long fsize;
|
||||
cJSON *retjson=NULL;
|
||||
|
||||
sprintf(fname,"/tmp/coda.%s",arg0);
|
||||
sprintf(cmdstr,"coda.exe client %s %s %s %s %s %s > %s 2>&1",arg0,arg1,arg2,arg3,arg4,arg5,fname);
|
||||
*retstr = 0;
|
||||
if (system(cmdstr)<0) return (retjson);
|
||||
if ( (jsonstr=(char *)filestr(&fsize,fname)) != 0 )
|
||||
{
|
||||
jsonstr[strlen(jsonstr)-1]='\0';
|
||||
if ( (strncmp(jsonstr,"Merkle List of transactions:",28)!=0) || (retjson= cJSON_Parse(jsonstr+29)) == 0)
|
||||
*retstr=jsonstr;
|
||||
else free(jsonstr);
|
||||
}
|
||||
return(retjson);
|
||||
}
|
||||
|
||||
// makes source tx for self import tx
|
||||
CMutableTransaction MakeSelfImportSourceTx(CTxDestination &dest, int64_t amount)
|
||||
{
|
||||
const int64_t txfee = 10000;
|
||||
int64_t inputs, change;
|
||||
CPubKey myPubKey = Mypubkey();
|
||||
struct CCcontract_info *cpDummy, C;
|
||||
|
||||
cpDummy = CCinit(&C, EVAL_TOKENS); // this is just for FinalizeCCTx to work
|
||||
|
||||
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), hush_nextheight());
|
||||
|
||||
if (AddNormalinputs(mtx, myPubKey, 2 * txfee, 4) == 0) {
|
||||
LOGSTREAM("importcoin", CCLOG_INFO, stream << "MakeSelfImportSourceTx() warning: cannot find normal inputs for txfee" << std::endl);
|
||||
}
|
||||
|
||||
CScript scriptPubKey = GetScriptForDestination(dest);
|
||||
mtx.vout.push_back(CTxOut(txfee, scriptPubKey));
|
||||
|
||||
//make opret with 'burned' amount:
|
||||
FinalizeCCTx(0, cpDummy, mtx, myPubKey, txfee, CScript() << OP_RETURN << E_MARSHAL(ss << (uint8_t)EVAL_IMPORTCOIN << (uint8_t)'A' << amount));
|
||||
return mtx;
|
||||
}
|
||||
|
||||
// make sure vin is signed by pubkey33
|
||||
bool CheckVinPubKey(const CTransaction &sourcetx, int32_t i, uint8_t pubkey33[33])
|
||||
{
|
||||
CTransaction vintx;
|
||||
uint256 blockHash;
|
||||
char destaddr[64], pkaddr[64];
|
||||
|
||||
if (i < 0 || i >= sourcetx.vin.size())
|
||||
return false;
|
||||
|
||||
if( !myGetTransaction(sourcetx.vin[i].prevout.hash, vintx, blockHash) ) {
|
||||
LOGSTREAM("importcoin", CCLOG_INFO, stream << "CheckVinPubKey() could not load vintx" << sourcetx.vin[i].prevout.hash.GetHex() << std::endl);
|
||||
return false;
|
||||
}
|
||||
if( sourcetx.vin[i].prevout.n < vintx.vout.size() && Getscriptaddress(destaddr, vintx.vout[sourcetx.vin[i].prevout.n].scriptPubKey) != 0 )
|
||||
{
|
||||
pubkey2addr(pkaddr, pubkey33);
|
||||
if (strcmp(pkaddr, destaddr) == 0) {
|
||||
return true;
|
||||
}
|
||||
LOGSTREAM("importcoin", CCLOG_INFO, stream << "CheckVinPubKey() mismatched vin[" << i << "].prevout.n=" << sourcetx.vin[i].prevout.n << " -> destaddr=" << destaddr << " vs pkaddr=" << pkaddr << std::endl);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// ac_import=PUBKEY support:
|
||||
// prepare a tx for creating import tx and quasi-burn tx
|
||||
int32_t GetSelfimportProof(const CMutableTransaction sourceMtx, CMutableTransaction &templateMtx, ImportProof &proofNull) // find burnTx with hash from "other" daemon
|
||||
{
|
||||
MerkleBranch newBranch;
|
||||
CMutableTransaction tmpmtx;
|
||||
//CTransaction sourcetx;
|
||||
|
||||
tmpmtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), hush_nextheight());
|
||||
|
||||
/*
|
||||
if (!E_UNMARSHAL(ParseHex(rawsourcetx), ss >> sourcetx)) {
|
||||
LOGSTREAM("importcoin", CCLOG_INFO, stream << "GetSelfimportProof: could not unmarshal source tx" << std::endl);
|
||||
return(-1);
|
||||
}
|
||||
|
||||
if (sourcetx.vout.size() == 0) {
|
||||
LOGSTREAM("importcoin", CCLOG_INFO, stream << "GetSelfimportProof: vout size is 0" << std::endl);
|
||||
return -1;
|
||||
} */
|
||||
|
||||
/*if (ivout < 0) { // "ivout < 0" means "find"
|
||||
// try to find vout
|
||||
CPubKey myPubkey = Mypubkey();
|
||||
ivout = 0;
|
||||
// skip change:
|
||||
if (sourcetx.vout[ivout].scriptPubKey == (CScript() << ParseHex(HexStr(myPubkey)) << OP_CHECKSIG))
|
||||
ivout++;
|
||||
}
|
||||
|
||||
if (ivout >= sourcetx.vout.size()) {
|
||||
LOGSTREAM("importcoin", CCLOG_INFO, stream << "GetSelfimportProof: needed vout not found" << std::endl);
|
||||
return -1;
|
||||
} */
|
||||
|
||||
int32_t ivout = 0;
|
||||
|
||||
// LOGSTREAM("importcoin", CCLOG_DEBUG1, stream << "GetSelfimportProof: using vout[" << ivout << "] of the passed rawtx" << std::endl);
|
||||
|
||||
CScript scriptPubKey = sourceMtx.vout[ivout].scriptPubKey;
|
||||
|
||||
//mtx is template for import tx
|
||||
templateMtx = sourceMtx;
|
||||
templateMtx.fOverwintered = tmpmtx.fOverwintered;
|
||||
|
||||
//malleability fix for burn tx:
|
||||
//mtx.nExpiryHeight = tmpmtx.nExpiryHeight;
|
||||
templateMtx.nExpiryHeight = sourceMtx.nExpiryHeight;
|
||||
|
||||
templateMtx.nVersionGroupId = tmpmtx.nVersionGroupId;
|
||||
templateMtx.nVersion = tmpmtx.nVersion;
|
||||
templateMtx.vout.clear();
|
||||
templateMtx.vout.resize(1);
|
||||
|
||||
uint8_t evalCode, funcId;
|
||||
int64_t burnAmount;
|
||||
vscript_t vopret;
|
||||
if( !GetOpReturnData(sourceMtx.vout.back().scriptPubKey, vopret) ||
|
||||
!E_UNMARSHAL(vopret, ss >> evalCode; ss >> funcId; ss >> burnAmount)) {
|
||||
LOGSTREAM("importcoin", CCLOG_INFO, stream << "GetSelfimportProof() could not unmarshal source tx opret" << std::endl);
|
||||
return -1;
|
||||
}
|
||||
templateMtx.vout[0].nValue = burnAmount;
|
||||
templateMtx.vout[0].scriptPubKey = scriptPubKey;
|
||||
|
||||
// not sure we need this now as we create sourcetx ourselves:
|
||||
/*if (sourcetx.GetHash() != sourcetxid) {
|
||||
LOGSTREAM("importcoin", CCLOG_INFO, stream << "GetSelfimportProof: passed source txid incorrect" << std::endl);
|
||||
return(-1);
|
||||
}*/
|
||||
|
||||
// check ac_pubkey:
|
||||
if (!CheckVinPubKey(sourceMtx, 0, ASSETCHAINS_OVERRIDE_PUBKEY33)) {
|
||||
return -1;
|
||||
}
|
||||
proofNull = ImportProof(std::make_pair(sourceMtx.GetHash(), newBranch));
|
||||
return 0;
|
||||
}
|
||||
|
||||
// make import tx with burntx and dual daemon
|
||||
std::string MakeCodaImportTx(uint64_t txfee, std::string receipt, std::string srcaddr, std::vector<CTxOut> vouts)
|
||||
{
|
||||
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), hush_nextheight()),burntx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), hush_nextheight());
|
||||
CPubKey mypk; uint256 codaburntxid; std::vector<unsigned char> dummyproof;
|
||||
int32_t i,numvouts,n,m; std::string coin,error; struct CCcontract_info *cp, C;
|
||||
cJSON *result,*tmp,*tmp1; unsigned char hash[SHA256_DIGEST_LENGTH+1];
|
||||
char out[SHA256_DIGEST_LENGTH*2+1],*retstr,*destaddr,*receiver; TxProof txProof; uint64_t amount;
|
||||
|
||||
cp = CCinit(&C, EVAL_GATEWAYS);
|
||||
if (txfee == 0)
|
||||
txfee = 10000;
|
||||
mypk = pubkey2pk(Mypubkey());
|
||||
SHA256_CTX sha256;
|
||||
SHA256_Init(&sha256);
|
||||
SHA256_Update(&sha256, receipt.c_str(), receipt.size());
|
||||
SHA256_Final(hash, &sha256);
|
||||
for(i = 0; i < SHA256_DIGEST_LENGTH; i++)
|
||||
{
|
||||
sprintf(out + (i * 2), "%02x", hash[i]);
|
||||
}
|
||||
out[65]='\0';
|
||||
LOGSTREAM("importcoin", CCLOG_DEBUG1, stream << "MakeCodaImportTx: hash=" << out << std::endl);
|
||||
codaburntxid.SetHex(out);
|
||||
LOGSTREAM("importcoin", CCLOG_DEBUG1, stream << "MakeCodaImportTx: receipt=" << receipt << " codaburntxid=" << codaburntxid.GetHex().data() << " amount=" << (double)amount / COIN << std::endl);
|
||||
result=CodaRPC(&retstr,"prove-payment","-address",srcaddr.c_str(),"-receipt-chain-hash",receipt.c_str(),"");
|
||||
if (result==0)
|
||||
{
|
||||
if (retstr!=0)
|
||||
{
|
||||
CCerror=std::string("CodaRPC: ")+retstr;
|
||||
free(retstr);
|
||||
}
|
||||
return("");
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((tmp=jobj(jitem(jarray(&n,result,(char *)"payments"),0),(char *)"payload"))!=0 && (destaddr=jstr(jobj(tmp,(char *)"common"),(char *)"memo"))!=0 &&
|
||||
(receiver=jstr(jitem(jarray(&m,tmp,(char *)"body"),1),(char *)"receiver"))!=0 && (amount=j64bits(jitem(jarray(&m,tmp,(char *)"body"),1),(char *)"amount"))!=0)
|
||||
{
|
||||
LOGSTREAM("importcoin", CCLOG_DEBUG1, stream << "MakeCodaImportTx: receiver=" << receiver << " destaddr=" << destaddr << " amount=" << amount << std::endl);
|
||||
if (strcmp(receiver,CODA_BURN_ADDRESS)!=0)
|
||||
{
|
||||
CCerror="MakeCodaImportTx: invalid burn address, coins do not go to predefined burn address - ";
|
||||
CCerror+=CODA_BURN_ADDRESS;
|
||||
LOGSTREAM("importcoin", CCLOG_INFO, stream << CCerror << std::endl);
|
||||
free(result);
|
||||
return("");
|
||||
}
|
||||
CTxDestination dest = DecodeDestination(destaddr);
|
||||
CScript scriptPubKey = GetScriptForDestination(dest);
|
||||
if (vouts[0]!=CTxOut(amount*COIN,scriptPubKey))
|
||||
{
|
||||
CCerror="MakeCodaImportTx: invalid destination address, burnTx memo!=importTx destination";
|
||||
LOGSTREAM("importcoin", CCLOG_INFO, stream << CCerror << std::endl);
|
||||
free(result);
|
||||
return("");
|
||||
}
|
||||
if (amount*COIN!=vouts[0].nValue)
|
||||
{
|
||||
CCerror="MakeCodaImportTx: invalid amount, burnTx amount!=importTx amount";
|
||||
LOGSTREAM("importcoin", CCLOG_INFO, stream << CCerror << std::endl);
|
||||
free(result);
|
||||
return("");
|
||||
}
|
||||
burntx.vin.push_back(CTxIn(codaburntxid,0,CScript()));
|
||||
burntx.vout.push_back(MakeBurnOutput(amount*COIN,0xffffffff,"CODA",vouts,dummyproof,srcaddr,receipt));
|
||||
return HexStr(E_MARSHAL(ss << MakeImportCoinTransaction(txProof,burntx,vouts)));
|
||||
}
|
||||
else
|
||||
{
|
||||
CCerror="MakeCodaImportTx: invalid Coda burn tx";
|
||||
LOGSTREAM("importcoin", CCLOG_INFO, stream << CCerror << std::endl);
|
||||
free(result);
|
||||
return("");
|
||||
}
|
||||
|
||||
}
|
||||
CCerror="MakeCodaImportTx: error fetching Coda tx";
|
||||
LOGSTREAM("importcoin", CCLOG_INFO, stream << CCerror << std::endl);
|
||||
free(result);
|
||||
return("");
|
||||
}
|
||||
|
||||
// use proof from the above functions to validate the import
|
||||
|
||||
int32_t CheckBEAMimport(TxProof proof,std::vector<uint8_t> rawproof,CTransaction burnTx,std::vector<CTxOut> payouts)
|
||||
{
|
||||
// check with dual-BEAM daemon via ASSETCHAINS_BEAMPORT for validity of burnTx
|
||||
return(-1);
|
||||
}
|
||||
|
||||
int32_t CheckCODAimport(CTransaction importTx,CTransaction burnTx,std::vector<CTxOut> payouts,std::string srcaddr,std::string receipt)
|
||||
{
|
||||
cJSON *result,*tmp,*tmp1; char *retstr,out[SHA256_DIGEST_LENGTH*2+1]; unsigned char hash[SHA256_DIGEST_LENGTH+1]; int i,n,m;
|
||||
SHA256_CTX sha256; uint256 codaburntxid; char *destaddr,*receiver; uint64_t amount;
|
||||
|
||||
// check with dual-CODA daemon via ASSETCHAINS_CODAPORT for validity of burnTx
|
||||
SHA256_Init(&sha256);
|
||||
SHA256_Update(&sha256, receipt.c_str(), receipt.size());
|
||||
SHA256_Final(hash, &sha256);
|
||||
for(i = 0; i < SHA256_DIGEST_LENGTH; i++)
|
||||
{
|
||||
sprintf(out + (i * 2), "%02x", hash[i]);
|
||||
}
|
||||
out[65]='\0';
|
||||
codaburntxid.SetHex(out);
|
||||
result=CodaRPC(&retstr,"prove-payment","-address",srcaddr.c_str(),"-receipt-chain-hash",receipt.c_str(),"");
|
||||
if (result==0)
|
||||
{
|
||||
LOGSTREAM("importcoin", CCLOG_INFO, stream << "CodaRPC error: " << retstr << std::endl);
|
||||
free(retstr);
|
||||
return (-1);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((tmp=jobj(jitem(jarray(&n,result,(char *)"payments"),0),(char *)"payload"))==0 || (destaddr=jstr(jobj(tmp,(char *)"common"),(char *)"memo"))==0 ||
|
||||
(receiver=jstr(jitem(jarray(&m,tmp,(char *)"body"),1),(char *)"receiver"))==0 || (amount=j64bits(jitem(jarray(&m,tmp,(char *)"body"),1),(char *)"amount"))==0)
|
||||
{
|
||||
LOGSTREAM("importcoin", CCLOG_INFO, stream << "Invalid Coda burn tx" << jprint(result,1) << std::endl);
|
||||
free(result);
|
||||
return (-1);
|
||||
}
|
||||
CTxDestination dest = DecodeDestination(destaddr);
|
||||
CScript scriptPubKey = GetScriptForDestination(dest);
|
||||
if (payouts[0]!=CTxOut(amount*COIN,scriptPubKey));
|
||||
{
|
||||
LOGSTREAM("importcoin", CCLOG_INFO, stream << "Destination address in burn tx does not match destination in import tx" << std::endl);
|
||||
free(result);
|
||||
return (-1);
|
||||
}
|
||||
if (strcmp(receiver,CODA_BURN_ADDRESS)!=0)
|
||||
{
|
||||
LOGSTREAM("importcoin", CCLOG_INFO, stream << "Invalid burn address " << jstr(tmp1,(char *)"receiver") << std::endl);
|
||||
free(result);
|
||||
return (-1);
|
||||
}
|
||||
if (amount*COIN!=payouts[0].nValue)
|
||||
{
|
||||
LOGSTREAM("importcoin", CCLOG_INFO, stream << "Burn amount and import amount not matching, " << j64bits(tmp,(char *)"amount") << " - " << payouts[0].nValue/COIN << std::endl);
|
||||
free(result);
|
||||
return (-1);
|
||||
}
|
||||
if (burnTx.vin[0].prevout.hash!=codaburntxid || importTx.vin[0].prevout.hash!=burnTx.GetHash())
|
||||
{
|
||||
LOGSTREAM("importcoin", CCLOG_INFO, stream << "Invalid import/burn tx vin" << std::endl);
|
||||
free(result);
|
||||
return (-1);
|
||||
}
|
||||
free(result);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
int32_t CheckGATEWAYimport(CTransaction importTx,CTransaction burnTx,std::string refcoin,std::vector<uint8_t> proof,
|
||||
uint256 bindtxid,std::vector<CPubKey> publishers,std::vector<uint256> txids,uint256 burntxid,int32_t height,int32_t burnvout,std::string rawburntx,CPubKey destpub, int64_t amount)
|
||||
{
|
||||
CTransaction oracletx,bindtx,regtx; int32_t i,m,n=0,numvouts; uint8_t M,N,taddr,prefix,prefix2,wiftype;
|
||||
uint256 txid,oracletxid,tmporacletxid,merkleroot,mhash,hashBlock;
|
||||
std::string name,desc,format,coin; std::vector<CTxOut> vouts; CPubKey regpk;
|
||||
std::vector<CPubKey> pubkeys,tmppubkeys,tmppublishers; char markeraddr[64],deposit[64],destaddr[64],tmpdest[64]; int64_t datafee;
|
||||
std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > unspentOutputs;
|
||||
|
||||
// ASSETCHAINS_SELFIMPORT is coin
|
||||
if (HUSH_EARLYTXID!=zeroid && bindtxid!=HUSH_EARLYTXID)
|
||||
{
|
||||
LOGSTREAM("importgateway", CCLOG_INFO, stream << "CheckGATEWAYimport invalid import gateway. On this chain only valid import gateway is " << HUSH_EARLYTXID.GetHex() << std::endl);
|
||||
return(-1);
|
||||
}
|
||||
// check for valid burn from external coin blockchain and if valid return(0);
|
||||
if (myGetTransaction(bindtxid, bindtx, hashBlock) == 0 || (numvouts = bindtx.vout.size()) <= 0)
|
||||
{
|
||||
LOGSTREAM("importgateway", CCLOG_INFO, stream << "CheckGATEWAYimport cant find bindtxid=" << bindtxid.GetHex() << std::endl);
|
||||
return(-1);
|
||||
}
|
||||
else if (DecodeImportGatewayBindOpRet(deposit,bindtx.vout[numvouts - 1].scriptPubKey,coin,oracletxid,M,N,tmppubkeys,taddr,prefix,prefix2,wiftype) != 'B')
|
||||
{
|
||||
LOGSTREAM("importcoin", CCLOG_INFO, stream << "CheckGATEWAYimport invalid bind tx. bindtxid=" << bindtxid.GetHex() << std::endl);
|
||||
return(-1);
|
||||
}
|
||||
else if (refcoin!=coin)
|
||||
{
|
||||
LOGSTREAM("importgateway", CCLOG_INFO, stream << "CheckGATEWAYimport invalid coin " << refcoin << "!=" << coin << std::endl);
|
||||
return(-1);
|
||||
}
|
||||
else if ( N == 0 || N > 15 || M > N )
|
||||
{
|
||||
LOGSTREAM("importgateway", CCLOG_INFO, stream << "CheckGATEWAYimport invalid N or M " << std::endl);
|
||||
return(-1);
|
||||
}
|
||||
else if (tmppubkeys.size()!=N)
|
||||
{
|
||||
LOGSTREAM("importgateway", CCLOG_INFO, stream << "CheckGATEWAYimport not enough pubkeys for given N " << std::endl);
|
||||
return(-1);
|
||||
}
|
||||
else if (hush_txnotarizedconfirmed(bindtxid) == false)
|
||||
{
|
||||
LOGSTREAM("importgateway", CCLOG_INFO, stream << "CheckGATEWAYimport bindtx not yet confirmed/notarized" << std::endl);
|
||||
return(-1);
|
||||
}
|
||||
else if (myGetTransaction(oracletxid, oracletx, hashBlock) == 0 || (numvouts = oracletx.vout.size()) <= 0)
|
||||
{
|
||||
LOGSTREAM("importgateway", CCLOG_INFO, stream << "CheckGATEWAYimport cant find oracletxid=" << oracletxid.GetHex() << std::endl);
|
||||
return(-1);
|
||||
}
|
||||
else if (DecodeOraclesCreateOpRet(oracletx.vout[numvouts - 1].scriptPubKey,name,desc,format) != 'C')
|
||||
{
|
||||
LOGSTREAM("importgateway", CCLOG_INFO, stream << "CheckGATEWAYimport invalid oracle tx. oracletxid=" << oracletxid.GetHex() << std::endl);
|
||||
return(-1);
|
||||
}
|
||||
else if (name!=refcoin || format!="Ihh")
|
||||
{
|
||||
LOGSTREAM("importgateway", CCLOG_INFO, stream << "CheckGATEWAYimport invalid oracle name or format tx. oracletxid=" << oracletxid.GetHex() << " name=" << name << " format=" << format << std::endl);
|
||||
return(-1);
|
||||
}
|
||||
CCtxidaddr(markeraddr,oracletxid);
|
||||
SetCCunspents(unspentOutputs,markeraddr,false);
|
||||
for (std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++)
|
||||
{
|
||||
txid = it->first.txhash;
|
||||
if ( myGetTransaction(txid,regtx,hashBlock) != 0 && regtx.vout.size() > 0
|
||||
&& DecodeOraclesOpRet(regtx.vout[regtx.vout.size()-1].scriptPubKey,tmporacletxid,regpk,datafee) == 'R' && oracletxid == tmporacletxid )
|
||||
{
|
||||
pubkeys.push_back(regpk);
|
||||
n++;
|
||||
}
|
||||
}
|
||||
if (pubkeys.size()!=tmppubkeys.size())
|
||||
{
|
||||
LOGSTREAM("importgateway", CCLOG_INFO, stream << "CheckGATEWAYimport different number of bind and oracle pubkeys " << tmppubkeys.size() << "!=" << pubkeys.size() << std::endl);
|
||||
return(-1);
|
||||
}
|
||||
merkleroot = zeroid;
|
||||
for (i = m = 0; i < n; i++)
|
||||
{
|
||||
if ((mhash = CCOraclesReverseScan("importgateway-1",txid, height, oracletxid, OraclesBatontxid(oracletxid, pubkeys[i]))) != zeroid)
|
||||
{
|
||||
if (merkleroot == zeroid)
|
||||
merkleroot = mhash, m = 1;
|
||||
else if (mhash == merkleroot)
|
||||
m ++;
|
||||
tmppublishers.push_back(pubkeys[i]);
|
||||
}
|
||||
}
|
||||
if (publishers.size()!=tmppublishers.size())
|
||||
{
|
||||
LOGSTREAM("importgateway", CCLOG_INFO, stream << "CheckGATEWAYimport different number of publishers for burtx in oracle" << std::endl);
|
||||
return(-1);
|
||||
}
|
||||
else if (merkleroot == zeroid || m < n / 2) // none or less than half oracle nodes sent merkleroot
|
||||
{
|
||||
LOGSTREAM("importgateway", CCLOG_INFO, stream << "CheckGATEWAYimport couldnt find merkleroot for block height=" << height << "coin=" << refcoin.c_str() << " oracleid=" << oracletxid.GetHex() << " m=" << m << " vs n=" << n << std::endl );
|
||||
return(-1);
|
||||
}
|
||||
else if ( ImportGatewayVerify(deposit,oracletxid,burnvout,refcoin,burntxid,rawburntx,proof,merkleroot,destpub,taddr,prefix,prefix2) != amount )
|
||||
{
|
||||
CCerror = strprintf("burntxid didnt validate !");
|
||||
LOGSTREAM("importgateway",CCLOG_INFO, stream << CCerror << std::endl);
|
||||
return(-1);
|
||||
}
|
||||
else if (importTx.vout[0].nValue!=amount)
|
||||
{
|
||||
LOGSTREAM("importgateway", CCLOG_INFO, stream << "CheckGATEWAYimport import amount different than in burntx" << std::endl);
|
||||
return(-1);
|
||||
}
|
||||
Getscriptaddress(destaddr,importTx.vout[0].scriptPubKey);
|
||||
Getscriptaddress(tmpdest,CScript() << ParseHex(HexStr(destpub)) << OP_CHECKSIG);
|
||||
if (strcmp(destaddr,tmpdest)!=0)
|
||||
{
|
||||
LOGSTREAM("importgateway", CCLOG_INFO, stream << "CheckGATEWAYimport import coins destination different than in burntx" << std::endl);
|
||||
return(-1);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
int32_t CheckPUBKEYimport(TxProof proof,std::vector<uint8_t> rawproof,CTransaction burnTx,std::vector<CTxOut> payouts)
|
||||
{
|
||||
// if burnTx has ASSETCHAINS_PUBKEY vin, it is valid return(0);
|
||||
LOGSTREAM("importcoin", CCLOG_DEBUG1, stream << "proof txid=" << proof.first.GetHex() << std::endl);
|
||||
|
||||
uint256 sourcetxid = proof.first, hashBlock;
|
||||
CTransaction sourcetx;
|
||||
|
||||
if (!myGetTransaction(sourcetxid, sourcetx, hashBlock)) {
|
||||
LOGSTREAM("importcoin", CCLOG_INFO, stream << "could not load source txid=" << sourcetxid.GetHex() << std::endl);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (sourcetx.vout.size() == 0) {
|
||||
LOGSTREAM("importcoin", CCLOG_INFO, stream << "no vouts in source txid=" << sourcetxid.GetHex() << std::endl);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// might be malleable:
|
||||
if (burnTx.nExpiryHeight != sourcetx.nExpiryHeight) {
|
||||
LOGSTREAM("importcoin", CCLOG_INFO, stream << "burntx nExpiryHeight incorrect for source txid=" << sourcetxid.GetHex() << std::endl);
|
||||
return -1;
|
||||
}
|
||||
|
||||
//ac_pubkey check:
|
||||
if (!CheckVinPubKey(sourcetx, 0, ASSETCHAINS_OVERRIDE_PUBKEY33)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// get source tx opret:
|
||||
std::vector<uint8_t> vopret;
|
||||
uint8_t evalCode, funcId;
|
||||
int64_t amount;
|
||||
|
||||
if (!GetOpReturnData(sourcetx.vout.back().scriptPubKey, vopret) ||
|
||||
vopret.size() == 0 ||
|
||||
!E_UNMARSHAL(vopret, ss >> evalCode; ss >> funcId; ss >> amount) ||
|
||||
evalCode != EVAL_IMPORTCOIN || funcId != 'A') {
|
||||
LOGSTREAM("importcoin", CCLOG_INFO, stream << "none or incorrect opret to validate in source txid=" << sourcetxid.GetHex() << std::endl);
|
||||
return -1;
|
||||
}
|
||||
|
||||
LOGSTREAM("importcoin", CCLOG_DEBUG1, stream << "importTx amount=" << payouts[0].nValue << " burnTx amount=" << burnTx.vout[0].nValue << " opret amount=" << amount << " source txid=" << sourcetxid.GetHex() << std::endl);
|
||||
|
||||
// amount malleability check with the opret from the source tx:
|
||||
if (payouts[0].nValue != amount) { // assume that burntx amount is checked in the common code in Eval::ImportCoin()
|
||||
LOGSTREAM("importcoin", CCLOG_INFO, stream << "importTx amount != amount in the opret of source txid=" << sourcetxid.GetHex() << std::endl);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
bool CheckMigration(Eval *eval, const CTransaction &importTx, const CTransaction &burnTx, std::vector<CTxOut> & payouts, const ImportProof &proof, const std::vector<uint8_t> &rawproof)
|
||||
{
|
||||
vscript_t vimportOpret;
|
||||
if (!GetOpReturnData(importTx.vout.back().scriptPubKey, vimportOpret) ||
|
||||
vimportOpret.empty())
|
||||
return eval->Invalid("invalid-import-tx-no-opret");
|
||||
|
||||
|
||||
uint256 tokenid = zeroid;
|
||||
if (vimportOpret.begin()[0] == EVAL_TOKENS) { // for tokens (new opret with tokens)
|
||||
struct CCcontract_info *cpTokens, CCtokens_info;
|
||||
std::vector<std::pair<uint8_t, vscript_t>> oprets;
|
||||
uint8_t evalCodeInOpret;
|
||||
std::vector<CPubKey> voutTokenPubkeys;
|
||||
vscript_t vnonfungibleOpret;
|
||||
|
||||
cpTokens = CCinit(&CCtokens_info, EVAL_TOKENS);
|
||||
|
||||
if (DecodeTokenOpRet(importTx.vout.back().scriptPubKey, evalCodeInOpret, tokenid, voutTokenPubkeys, oprets) == 0)
|
||||
return eval->Invalid("cannot-decode-import-tx-token-opret");
|
||||
|
||||
uint8_t nonfungibleEvalCode = EVAL_TOKENS; // init to no non-fungibles
|
||||
GetOpretBlob(oprets, OPRETID_NONFUNGIBLEDATA, vnonfungibleOpret);
|
||||
if (!vnonfungibleOpret.empty())
|
||||
nonfungibleEvalCode = vnonfungibleOpret.begin()[0];
|
||||
|
||||
// check if burn tx at least has cc evaltoken vins (we cannot get cc input)
|
||||
bool hasTokenVin = false;
|
||||
for (auto vin : burnTx.vin)
|
||||
if (cpTokens->ismyvin(vin.scriptSig))
|
||||
hasTokenVin = true;
|
||||
if (!hasTokenVin)
|
||||
return eval->Invalid("burn-tx-has-no-token-vins");
|
||||
|
||||
// calc outputs for burn tx
|
||||
CAmount ccBurnOutputs = 0;
|
||||
for (auto v : burnTx.vout)
|
||||
if (v.scriptPubKey.IsPayToCryptoCondition() &&
|
||||
CTxOut(v.nValue, v.scriptPubKey) == MakeTokensCC1vout(nonfungibleEvalCode, v.nValue, pubkey2pk(ParseHex(CC_BURNPUBKEY)))) // burned to dead pubkey
|
||||
ccBurnOutputs += v.nValue;
|
||||
|
||||
// calc outputs for import tx
|
||||
CAmount ccImportOutputs = 0;
|
||||
for (auto v : importTx.vout)
|
||||
if (v.scriptPubKey.IsPayToCryptoCondition() &&
|
||||
!IsTokenMarkerVout(v)) // should not be marker here
|
||||
ccImportOutputs += v.nValue;
|
||||
|
||||
if (ccBurnOutputs != ccImportOutputs)
|
||||
return eval->Invalid("token-cc-burned-output-not-equal-cc-imported-output");
|
||||
|
||||
}
|
||||
else if (vimportOpret.begin()[0] != EVAL_IMPORTCOIN) {
|
||||
return eval->Invalid("import-tx-incorrect-opret-eval");
|
||||
}
|
||||
|
||||
// for tokens check burn, import, tokenbase tx
|
||||
if (!tokenid.IsNull()) {
|
||||
|
||||
std::string sourceSymbol;
|
||||
CTransaction tokenbaseTx;
|
||||
if (!E_UNMARSHAL(rawproof, ss >> sourceSymbol; ss >> tokenbaseTx))
|
||||
return eval->Invalid("cannot-unmarshal-rawproof-for-tokens");
|
||||
|
||||
uint256 sourceTokenId;
|
||||
std::vector<std::pair<uint8_t, vscript_t>> oprets;
|
||||
uint8_t evalCodeInOpret;
|
||||
std::vector<CPubKey> voutTokenPubkeys;
|
||||
if (burnTx.vout.size() > 0 && DecodeTokenOpRet(burnTx.vout.back().scriptPubKey, evalCodeInOpret, sourceTokenId, voutTokenPubkeys, oprets) == 0)
|
||||
return eval->Invalid("cannot-decode-burn-tx-token-opret");
|
||||
|
||||
if (sourceTokenId != tokenbaseTx.GetHash()) // check tokenid in burn tx opret maches the passed tokenbase tx (to prevent cheating by importing user)
|
||||
return eval->Invalid("incorrect-token-creation-tx-passed");
|
||||
|
||||
std::vector<std::pair<uint8_t, vscript_t>> opretsSrc;
|
||||
vscript_t vorigpubkeySrc;
|
||||
std::string nameSrc, descSrc;
|
||||
if (DecodeTokenCreateOpRet(tokenbaseTx.vout.back().scriptPubKey, vorigpubkeySrc, nameSrc, descSrc, opretsSrc) == 0)
|
||||
return eval->Invalid("cannot-decode-token-creation-tx");
|
||||
|
||||
std::vector<std::pair<uint8_t, vscript_t>> opretsImport;
|
||||
vscript_t vorigpubkeyImport;
|
||||
std::string nameImport, descImport;
|
||||
if (importTx.vout.size() == 0 || DecodeTokenCreateOpRet(importTx.vout.back().scriptPubKey, vorigpubkeySrc, nameSrc, descSrc, opretsImport) == 0)
|
||||
return eval->Invalid("cannot-decode-token-import-tx");
|
||||
|
||||
// check that name,pubkey,description in import tx correspond ones in token creation tx in the source chain:
|
||||
if (vorigpubkeySrc != vorigpubkeyImport ||
|
||||
nameSrc != nameImport ||
|
||||
descSrc != descImport)
|
||||
return eval->Invalid("import-tx-token-params-incorrect");
|
||||
}
|
||||
|
||||
|
||||
// Check burntx shows correct outputs hash
|
||||
// if (payoutsHash != SerializeHash(payouts)) // done in ImportCoin
|
||||
// return eval->Invalid("wrong-payouts");
|
||||
|
||||
|
||||
TxProof merkleBranchProof;
|
||||
std::vector<uint256> notaryTxids;
|
||||
|
||||
// Check proof confirms existance of burnTx
|
||||
if (proof.IsMerkleBranch(merkleBranchProof)) {
|
||||
uint256 target = merkleBranchProof.second.Exec(burnTx.GetHash());
|
||||
LOGSTREAM("importcoin", CCLOG_DEBUG2, stream << "Eval::ImportCoin() momom target=" << target.GetHex() << " merkleBranchProof.first=" << merkleBranchProof.first.GetHex() << std::endl);
|
||||
if (!CheckMoMoM(merkleBranchProof.first, target)) {
|
||||
LOGSTREAM("importcoin", CCLOG_INFO, stream << "MoMoM check failed for importtx=" << importTx.GetHash().GetHex() << std::endl);
|
||||
return eval->Invalid("momom-check-fail");
|
||||
}
|
||||
}
|
||||
else if (proof.IsNotaryTxids(notaryTxids)) {
|
||||
if (!CheckNotariesApproval(burnTx.GetHash(), notaryTxids)) {
|
||||
return eval->Invalid("notaries-approval-check-fail");
|
||||
}
|
||||
}
|
||||
else {
|
||||
return eval->Invalid("invalid-import-proof");
|
||||
}
|
||||
|
||||
/* if (vimportOpret.begin()[0] == EVAL_TOKENS)
|
||||
return eval->Invalid("test-invalid-tokens-are-good!!");
|
||||
else
|
||||
return eval->Invalid("test-invalid-coins-are-good!!"); */
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Eval::ImportCoin(const std::vector<uint8_t> params, const CTransaction &importTx, unsigned int nIn)
|
||||
{
|
||||
ImportProof proof;
|
||||
CTransaction burnTx;
|
||||
std::vector<CTxOut> payouts;
|
||||
CAmount txfee = 10000, amount;
|
||||
int32_t height, burnvout;
|
||||
std::vector<CPubKey> publishers;
|
||||
uint32_t targetCcid;
|
||||
std::string targetSymbol, srcaddr, destaddr, receipt, rawburntx;
|
||||
uint256 payoutsHash, bindtxid, burntxid;
|
||||
std::vector<uint8_t> rawproof;
|
||||
std::vector<uint256> txids;
|
||||
CPubKey destpub;
|
||||
|
||||
LOGSTREAM("importcoin", CCLOG_DEBUG1, stream << "Validating import tx..., txid=" << importTx.GetHash().GetHex() << std::endl);
|
||||
|
||||
if (importTx.vout.size() < 2)
|
||||
return Invalid("too-few-vouts");
|
||||
// params
|
||||
if (!UnmarshalImportTx(importTx, proof, burnTx, payouts))
|
||||
return Invalid("invalid-params");
|
||||
// Control all aspects of this transaction
|
||||
// It should not be at all malleable
|
||||
if (ASSETCHAINS_SELFIMPORT!="PEGSCC" && MakeImportCoinTransaction(proof, burnTx, payouts, importTx.nExpiryHeight).GetHash() != importTx.GetHash()) // ExistsImportTombstone prevents from duplication
|
||||
return Invalid("non-canonical");
|
||||
// burn params
|
||||
if (!UnmarshalBurnTx(burnTx, targetSymbol, &targetCcid, payoutsHash, rawproof))
|
||||
return Invalid("invalid-burn-tx");
|
||||
|
||||
if (burnTx.vout.size() == 0)
|
||||
return Invalid("invalid-burn-tx-no-vouts");
|
||||
|
||||
// check burned normal amount >= import amount && burned amount <= import amount + txfee (extra txfee is for miners and relaying, see GetImportCoinValue() func)
|
||||
CAmount burnAmount = burnTx.vout.back().nValue;
|
||||
if (burnAmount == 0)
|
||||
return Invalid("invalid-burn-amount");
|
||||
CAmount totalOut = 0;
|
||||
for (auto v : importTx.vout)
|
||||
if (!v.scriptPubKey.IsPayToCryptoCondition())
|
||||
totalOut += v.nValue;
|
||||
if (totalOut > burnAmount || totalOut < burnAmount - txfee)
|
||||
return Invalid("payout-too-high-or-too-low");
|
||||
|
||||
// Check burntx shows correct outputs hash
|
||||
if (payoutsHash != SerializeHash(payouts))
|
||||
return Invalid("wrong-payouts");
|
||||
if (targetCcid < HUSH_FIRSTFUNGIBLEID)
|
||||
return Invalid("chain-not-fungible");
|
||||
|
||||
if ( targetCcid != 0xffffffff )
|
||||
{
|
||||
|
||||
if (targetCcid != GetAssetchainsCC() || targetSymbol != GetAssetchainsSymbol())
|
||||
return Invalid("importcoin-wrong-chain");
|
||||
|
||||
if (!CheckMigration(this, importTx, burnTx, payouts, proof, rawproof))
|
||||
return false; // eval->Invalid() is called in the func
|
||||
}
|
||||
else
|
||||
{
|
||||
TxProof merkleBranchProof;
|
||||
if (!proof.IsMerkleBranch(merkleBranchProof))
|
||||
return Invalid("invalid-import-proof-for-0xFFFFFFFF");
|
||||
|
||||
if ( targetSymbol == "BEAM" )
|
||||
{
|
||||
if ( ASSETCHAINS_BEAMPORT == 0 )
|
||||
return Invalid("BEAM-import-without-port");
|
||||
else if ( CheckBEAMimport(merkleBranchProof,rawproof,burnTx,payouts) < 0 )
|
||||
return Invalid("BEAM-import-failure");
|
||||
}
|
||||
else if ( targetSymbol == "CODA" )
|
||||
{
|
||||
if ( ASSETCHAINS_CODAPORT == 0 )
|
||||
return Invalid("CODA-import-without-port");
|
||||
else if ( UnmarshalBurnTx(burnTx,srcaddr,receipt)==0 || CheckCODAimport(importTx,burnTx,payouts,srcaddr,receipt) < 0 )
|
||||
return Invalid("CODA-import-failure");
|
||||
}
|
||||
else if ( targetSymbol == "PEGSCC" )
|
||||
{
|
||||
if ( ASSETCHAINS_SELFIMPORT != "PEGSCC" )
|
||||
return Invalid("PEGSCC-import-when-not PEGSCC");
|
||||
// else if ( CheckPUBKEYimport(merkleBranchProof,rawproof,burnTx,payouts) < 0 )
|
||||
// return Invalid("PEGSCC-import-failure");
|
||||
}
|
||||
else if ( targetSymbol == "PUBKEY" )
|
||||
{
|
||||
if ( ASSETCHAINS_SELFIMPORT != "PUBKEY" )
|
||||
return Invalid("PUBKEY-import-when-not PUBKEY");
|
||||
else if ( CheckPUBKEYimport(merkleBranchProof,rawproof,burnTx,payouts) < 0 )
|
||||
return Invalid("PUBKEY-import-failure");
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( targetSymbol != ASSETCHAINS_SELFIMPORT )
|
||||
return Invalid("invalid-gateway-import-coin");
|
||||
else if ( UnmarshalBurnTx(burnTx,bindtxid,publishers,txids,burntxid,height,burnvout,rawburntx,destpub,amount)==0 || CheckGATEWAYimport(importTx,burnTx,targetSymbol,rawproof,bindtxid,publishers,txids,burntxid,height,burnvout,rawburntx,destpub,amount) < 0 )
|
||||
return Invalid("GATEWAY-import-failure");
|
||||
}
|
||||
}
|
||||
|
||||
// return Invalid("test-invalid");
|
||||
LOGSTREAM("importcoin", CCLOG_DEBUG2, stream << "Valid import tx! txid=" << importTx.GetHash().GetHex() << std::endl);
|
||||
|
||||
return Valid();
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
344
src/cc/lotto.cpp
344
src/cc/lotto.cpp
@@ -1,344 +0,0 @@
|
||||
// Copyright (c) 2016-2023 The Hush developers
|
||||
// Distributed under the GPLv3 software license, see the accompanying
|
||||
// file COPYING or https://www.gnu.org/licenses/gpl-3.0.en.html
|
||||
/******************************************************************************
|
||||
* Copyright © 2014-2019 The SuperNET Developers. *
|
||||
* *
|
||||
* See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at *
|
||||
* the top-level directory of this distribution for the individual copyright *
|
||||
* holder information and the developer policies on copyright and licensing. *
|
||||
* *
|
||||
* Unless otherwise agreed in a custom licensing agreement, no part of the *
|
||||
* SuperNET software, including this file may be copied, modified, propagated *
|
||||
* or distributed except according to the terms contained in the LICENSE file *
|
||||
* *
|
||||
* Removal or modification of this copyright notice is prohibited. *
|
||||
* *
|
||||
******************************************************************************/
|
||||
|
||||
#include "CClotto.h"
|
||||
#include "../txmempool.h"
|
||||
|
||||
/*
|
||||
A blockchain lotto has the problem of generating the deterministic random numbers needed to get a winner in a way that doesnt allow cheating. If we save the entropy for later publishing and display the hash of the entropy, it is true that the players wont know what the entropy value is, however the creator of the lotto funds will be able to know and simply create a winning ticket when the jackpot is large enough.
|
||||
|
||||
We also need to avoid chain reorgs from disclosing the entropy and then allowing people to submit a winning ticket calculated based on the disclosed entropy (see attack vector in dice.cpp)
|
||||
|
||||
As usual it needs to be provably fair and random
|
||||
|
||||
The solution is for everybody to post the hash of their entropy when purchasing tickets. Then at the time of the drawing, nodes would post their entropy over an N block period to avoid censorship attack. After the N block period, then we have valid entropy that we know was locked in prior to the start of the N blocks and that nobody would have been able to know ahead of time the final entropy value.
|
||||
|
||||
As long as one node submits a high entropy value, then just by combining all the submissions together, we get the drawing's entropy value. Given that, the usual process can determine if there was a winner at the specified odds. In fact, all the nodes are able to determine exactly how many winners there were and whether to validate 1/w payouts to the w winners or rollover the jackpot to the next drawing.
|
||||
|
||||
To remove the need for an autopayout, the winning node(s) would need to submit a 1/w payout tx, this would be able to be done at any time and the winner does not have to have submitted proof of hentropy. In order to prevent a player from opportunistically withholding their entropy, the lotto creator will post the original proof of hentropy after the N block player submission period. This masks to all the players the final value of entropy.
|
||||
|
||||
Attack vector: the lotto creator can have many player tickets in reserve all with their entropy ready to submit, but based on the actual submissions, find the one which gives him the best outcome. since all the player submissions will be known via mempool, along with the original hentropy. However the lotto creator would have to mine the final block in order to know the order of the player tickets.
|
||||
|
||||
Thinking about this evil miner attack, it seems pretty bad, so a totally new approach is needed. Preferably with a simple enough protocol. Let us remove any special knowledge by the lotto creator, so like the faucet, it seems just that there is a single lotto for a chain.
|
||||
|
||||
>>>>>>>>>>>> second iteration
|
||||
|
||||
What we need is something that gives each ticket an equal chance at the jackpot, without allowing miner or relayer to gain an advantage. ultimately the jackpot payout tx needs to be confirmed, so there needs to be some number of blocks to make a claim to avoid censorship attack. If onchain entropy is needed, then it should be reduced to 1 bit per block to reduce the grinding that is possible. This does mean a block miner for the last bit of entropy can double their chances at winning, but the alternative is to have an external source of entropy, which creates its own set of issues like what prevents the nodes getting the external entropy from cheating?
|
||||
|
||||
Conveniently the lotto mechanics are similar to a PoS staking, so it can be based on everybody trying to stake a single lotto jackpot.
|
||||
|
||||
The calculation would need to be based on the payout address and utxosize, so relayers cant intercept it to steal the jackpot.
|
||||
|
||||
each jackpot would effectively restart the lotto
|
||||
|
||||
the funds from new lotto tickets can be spent by the jackpot, but those tickets can still win the new jackpot
|
||||
|
||||
each set of tickets (utxo) would become eligible to claim the jackpot after some time is elapsed so the entropy for that utxo can be obtained. [6 bits * 32 + 1 bit * 16] 48 blocks
|
||||
|
||||
It is possible to have a jackpot but miss out on it due to not claiming it. To minimize the effect from this, each ticket would have one chance to win, which can be calculated and a jackpot claim submitted just once.
|
||||
|
||||
in order to randomize the timing of claim, a txid PoW similar to faucetget will maximize the chance of only a single jackpot txid that can propagate throughout the mempools, which will prevent the second one broadcast. Granted the mining node can override this if they also have a winning ticket, but assuming the PoS lottery makes it unlikely for two winners in a single block, this is not a big issue.
|
||||
|
||||
In order to adapt the difficulty of winning the lotto, but not requiring recalculating all past tickets, as new lotto tickets are sold without a jackpot, it needs to become easier to win. Basically as the lotto jackpot gets bigger and bigger, it keeps getting easier to win! This convergence will avoid having unwinnable jackpots.
|
||||
|
||||
rpc calls
|
||||
lottoinfo
|
||||
lottotickets <numtickets>
|
||||
lottostatus
|
||||
lottowinner tickethash ticketid
|
||||
|
||||
*/
|
||||
|
||||
// start of consensus code
|
||||
|
||||
int64_t IsLottovout(struct CCcontract_info *cp,const CTransaction& tx,int32_t v)
|
||||
{
|
||||
char destaddr[64];
|
||||
if ( tx.vout[v].scriptPubKey.IsPayToCryptoCondition() != 0 )
|
||||
{
|
||||
if ( Getscriptaddress(destaddr,tx.vout[v].scriptPubKey) > 0 && strcmp(destaddr,cp->unspendableCCaddr) == 0 )
|
||||
return(tx.vout[v].nValue);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
bool LottoExactAmounts(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx,int32_t minage,uint64_t txfee)
|
||||
{
|
||||
static uint256 zerohash;
|
||||
CTransaction vinTx; uint256 hashBlock,activehash; int32_t i,numvins,numvouts; int64_t inputs=0,outputs=0,assetoshis;
|
||||
numvins = tx.vin.size();
|
||||
numvouts = tx.vout.size();
|
||||
for (i=0; i<numvins; i++)
|
||||
{
|
||||
//fprintf(stderr,"vini.%d\n",i);
|
||||
if ( (*cp->ismyvin)(tx.vin[i].scriptSig) != 0 )
|
||||
{
|
||||
//fprintf(stderr,"vini.%d check mempool\n",i);
|
||||
if ( eval->GetTxUnconfirmed(tx.vin[i].prevout.hash,vinTx,hashBlock) == 0 )
|
||||
return eval->Invalid("cant find vinTx");
|
||||
else
|
||||
{
|
||||
//fprintf(stderr,"vini.%d check hash and vout\n",i);
|
||||
if ( hashBlock == zerohash )
|
||||
return eval->Invalid("cant Lotto from mempool");
|
||||
if ( (assetoshis= IsLottovout(cp,vinTx,tx.vin[i].prevout.n)) != 0 )
|
||||
inputs += assetoshis;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (i=0; i<numvouts; i++)
|
||||
{
|
||||
//fprintf(stderr,"i.%d of numvouts.%d\n",i,numvouts);
|
||||
if ( (assetoshis= IsLottovout(cp,tx,i)) != 0 )
|
||||
outputs += assetoshis;
|
||||
}
|
||||
if ( inputs != outputs+txfee )
|
||||
{
|
||||
fprintf(stderr,"inputs %llu vs outputs %llu\n",(long long)inputs,(long long)outputs);
|
||||
return eval->Invalid("mismatched inputs != outputs + txfee");
|
||||
}
|
||||
else return(true);
|
||||
}
|
||||
|
||||
bool LottoValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn)
|
||||
{
|
||||
int32_t numvins,numvouts,preventCCvins,preventCCvouts,i; bool retval;
|
||||
return eval->Invalid("no validation yet");
|
||||
numvins = tx.vin.size();
|
||||
numvouts = tx.vout.size();
|
||||
preventCCvins = preventCCvouts = -1;
|
||||
if ( numvouts < 1 )
|
||||
return eval->Invalid("no vouts");
|
||||
else
|
||||
{
|
||||
//fprintf(stderr,"check vins\n");
|
||||
for (i=0; i<numvins; i++)
|
||||
{
|
||||
if ( IsCCInput(tx.vin[0].scriptSig) == 0 )
|
||||
{
|
||||
fprintf(stderr,"Lottoget invalid vini\n");
|
||||
return eval->Invalid("illegal normal vini");
|
||||
}
|
||||
}
|
||||
//fprintf(stderr,"check amounts\n");
|
||||
if ( LottoExactAmounts(cp,eval,tx,1,10000) == false )
|
||||
{
|
||||
fprintf(stderr,"Lottoget invalid amount\n");
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
preventCCvouts = 1;
|
||||
if ( IsLottovout(cp,tx,0) != 0 )
|
||||
{
|
||||
preventCCvouts++;
|
||||
i = 1;
|
||||
} else i = 0;
|
||||
if ( tx.vout[i].nValue != COIN )
|
||||
return eval->Invalid("invalid Lotto output");
|
||||
retval = PreventCC(eval,tx,preventCCvins,numvins,preventCCvouts,numvouts);
|
||||
if ( retval != 0 )
|
||||
fprintf(stderr,"Lottoget validated\n");
|
||||
else fprintf(stderr,"Lottoget invalid\n");
|
||||
return(retval);
|
||||
}
|
||||
}
|
||||
}
|
||||
// end of consensus code
|
||||
|
||||
// helper functions for rpc calls in rpcwallet.cpp
|
||||
|
||||
int64_t AddLottoInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,CPubKey pk,int64_t total,int32_t maxinputs)
|
||||
{
|
||||
// add threshold check
|
||||
char coinaddr[64]; int64_t nValue,price,totalinputs = 0; uint256 txid,hashBlock; std::vector<uint8_t> origpubkey; CTransaction vintx; int32_t n = 0;
|
||||
std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > unspentOutputs;
|
||||
GetCCaddress(cp,coinaddr,pk);
|
||||
SetCCunspents(unspentOutputs,coinaddr,true);
|
||||
for (std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++)
|
||||
{
|
||||
txid = it->first.txhash;
|
||||
// prevent dup
|
||||
if ( it->second.satoshis < COIN )
|
||||
continue;
|
||||
if ( myGetTransaction(txid,vintx,hashBlock) != 0 )
|
||||
{
|
||||
if ( (nValue= IsLottovout(cp,vintx,(int32_t)it->first.index)) > 0 )
|
||||
{
|
||||
if ( total != 0 && maxinputs != 0 )
|
||||
mtx.vin.push_back(CTxIn(txid,(int32_t)it->first.index,CScript()));
|
||||
nValue = it->second.satoshis;
|
||||
totalinputs += nValue;
|
||||
n++;
|
||||
if ( (total > 0 && totalinputs >= total) || (maxinputs > 0 && n >= maxinputs) )
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return(totalinputs);
|
||||
}
|
||||
|
||||
uint8_t DecodeLottoFundingOpRet(const CScript &scriptPubKey,uint64_t &sbits,int32_t ticketsize,int32_t odds,int32_t firstheight,int32_t period,uint256 hentropy)
|
||||
{
|
||||
std::vector<uint8_t> vopret; uint8_t *script,e,f;
|
||||
GetOpReturnData(scriptPubKey, vopret);
|
||||
script = (uint8_t *)vopret.data();
|
||||
if ( vopret.size() > 2 && E_UNMARSHAL(vopret,ss >> e; ss >> f; ss >> sbits; ss >> ticketsize; ss >> odds; ss >> firstheight; ss >> period; ss >> hentropy) != 0 )
|
||||
{
|
||||
if ( e == EVAL_LOTTO && f == 'F' )
|
||||
return(f);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
int64_t LottoPlanFunds(uint64_t refsbits,struct CCcontract_info *cp,CPubKey pk,uint256 reffundingtxid)
|
||||
{
|
||||
char coinaddr[64]; uint64_t sbits; int64_t nValue,lockedfunds; uint256 txid,hashBlock,fundingtxid; CTransaction tx; int32_t vout; uint8_t funcid;
|
||||
std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > unspentOutputs;
|
||||
lockedfunds = 0;
|
||||
GetCCaddress(cp,coinaddr,pk);
|
||||
SetCCunspents(unspentOutputs,coinaddr,true);
|
||||
for (std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++)
|
||||
{
|
||||
txid = it->first.txhash;
|
||||
vout = (int32_t)it->first.index;
|
||||
if ( myGetTransaction(txid,tx,hashBlock) != 0 && tx.vout[vout].scriptPubKey.IsPayToCryptoCondition() != 0 )
|
||||
{
|
||||
// need to implement this! if ( (funcid= DecodeLottoOpRet(txid,tx.vout[tx.vout.size()-1].scriptPubKey,sbits,fundingtxid)) == 'F' || funcid == 'T' )
|
||||
{
|
||||
if ( refsbits == sbits && (funcid == 'F' && reffundingtxid == txid) || reffundingtxid == fundingtxid )
|
||||
{
|
||||
if ( (nValue= IsLottovout(cp,tx,vout)) > 0 )
|
||||
lockedfunds += nValue;
|
||||
else fprintf(stderr,"refsbits.%llx sbits.%llx nValue %.8f\n",(long long)refsbits,(long long)sbits,(double)nValue/COIN);
|
||||
} //else fprintf(stderr,"else case\n");
|
||||
} //else fprintf(stderr,"funcid.%d %c skipped %.8f\n",funcid,funcid,(double)tx.vout[vout].nValue/COIN);
|
||||
}
|
||||
}
|
||||
return(lockedfunds);
|
||||
}
|
||||
|
||||
UniValue LottoInfo(uint256 lottoid)
|
||||
{
|
||||
UniValue result(UniValue::VOBJ); uint256 hashBlock,hentropy; CTransaction vintx; uint64_t lockedfunds,sbits; int32_t ticketsize,odds,firstheight,period; CPubKey lottopk; struct CCcontract_info *cp,C; char str[67],numstr[65];
|
||||
if ( myGetTransaction(lottoid,vintx,hashBlock) == 0 )
|
||||
{
|
||||
fprintf(stderr,"cant find lottoid\n");
|
||||
result.push_back(Pair("result","error"));
|
||||
result.push_back(Pair("error","cant find lottoid"));
|
||||
return(result);
|
||||
}
|
||||
if ( vintx.vout.size() > 0 && DecodeLottoFundingOpRet(vintx.vout[vintx.vout.size()-1].scriptPubKey,sbits,ticketsize,odds,firstheight,period,hentropy) == 0 )
|
||||
{
|
||||
fprintf(stderr,"lottoid isnt lotto creation txid\n");
|
||||
result.push_back(Pair("result","error"));
|
||||
result.push_back(Pair("error","lottoid isnt lotto creation txid"));
|
||||
return(result);
|
||||
}
|
||||
result.push_back(Pair("result","success"));
|
||||
result.push_back(Pair("lottoid",uint256_str(str,lottoid)));
|
||||
unstringbits(str,sbits);
|
||||
result.push_back(Pair("name",str));
|
||||
result.push_back(Pair("sbits",sbits));
|
||||
result.push_back(Pair("ticketsize",ticketsize));
|
||||
result.push_back(Pair("odds",odds));
|
||||
cp = CCinit(&C,EVAL_LOTTO);
|
||||
lottopk = GetUnspendable(cp,0);
|
||||
lockedfunds = LottoPlanFunds(sbits,cp,lottopk,lottoid);
|
||||
sprintf(numstr,"%.8f",(double)lockedfunds/COIN);
|
||||
result.push_back(Pair("jackpot",numstr));
|
||||
return(result);
|
||||
}
|
||||
|
||||
UniValue LottoList()
|
||||
{
|
||||
UniValue result(UniValue::VARR); std::vector<uint256> txids; struct CCcontract_info *cp,C; uint256 txid,hashBlock,hentropy; CTransaction vintx; uint64_t sbits; int32_t ticketsize,odds,firstheight,period; char str[65];
|
||||
cp = CCinit(&C,EVAL_LOTTO);
|
||||
SetCCtxids(txids,cp->normaladdr,true,cp->evalcode,zeroid,'F');
|
||||
for (std::vector<uint256>::const_iterator it=txids.begin(); it!=txids.end(); it++)
|
||||
{
|
||||
txid = *it;
|
||||
if ( myGetTransaction(txid,vintx,hashBlock) != 0 )
|
||||
{
|
||||
if ( vintx.vout.size() > 0 && DecodeLottoFundingOpRet(vintx.vout[vintx.vout.size()-1].scriptPubKey,sbits,ticketsize,odds,firstheight,period,hentropy) == 'F' )
|
||||
{
|
||||
result.push_back(uint256_str(str,txid));
|
||||
}
|
||||
}
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
std::string LottoCreate(uint64_t txfee,char *planstr,int64_t funding,int32_t ticketsize,int32_t odds,int32_t firstheight,int32_t period)
|
||||
{
|
||||
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), hush_nextheight());
|
||||
uint256 entropy,hentropy; CPubKey mypk,lottopk; uint64_t sbits; int64_t inputs,CCchange=0,nValue=COIN; struct CCcontract_info *cp,C;
|
||||
cp = CCinit(&C,EVAL_LOTTO);
|
||||
if ( txfee == 0 )
|
||||
txfee = 10000;
|
||||
lottopk = GetUnspendable(cp,0);
|
||||
mypk = pubkey2pk(Mypubkey());
|
||||
sbits = stringbits(planstr);
|
||||
if ( AddNormalinputs(mtx,mypk,funding+txfee,60) > 0 )
|
||||
{
|
||||
hentropy = DiceHashEntropy(entropy,mtx.vin[0].prevout.hash,mtx.vin[0].prevout.n,1);
|
||||
mtx.vout.push_back(MakeCC1vout(EVAL_LOTTO,funding,lottopk));
|
||||
return(FinalizeCCTx(0,cp,mtx,mypk,txfee,CScript() << OP_RETURN << E_MARSHAL(ss << (uint8_t)EVAL_LOTTO << (uint8_t)'F' << sbits << ticketsize << odds << firstheight << period << hentropy)));
|
||||
}
|
||||
return("");
|
||||
}
|
||||
|
||||
std::string LottoTicket(uint64_t txfee,uint256 lottoid,int64_t numtickets)
|
||||
{
|
||||
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), hush_nextheight());
|
||||
CPubKey mypk,lottopk; CScript opret; int64_t inputs,CCchange=0,nValue=COIN; struct CCcontract_info *cp,C;
|
||||
cp = CCinit(&C,EVAL_LOTTO);
|
||||
if ( txfee == 0 )
|
||||
txfee = 10000;
|
||||
lottopk = GetUnspendable(cp,0);
|
||||
mypk = pubkey2pk(Mypubkey());
|
||||
if ( (inputs= AddLottoInputs(cp,mtx,lottopk,nValue+txfee,60)) > 0 )
|
||||
{
|
||||
if ( inputs > nValue )
|
||||
CCchange = (inputs - nValue - txfee);
|
||||
if ( CCchange != 0 )
|
||||
mtx.vout.push_back(MakeCC1vout(EVAL_LOTTO,CCchange,lottopk));
|
||||
mtx.vout.push_back(CTxOut(nValue,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG));
|
||||
return(FinalizeCCTx(-1LL,cp,mtx,mypk,txfee,opret));
|
||||
} else fprintf(stderr,"cant find Lotto inputs\n");
|
||||
return("");
|
||||
}
|
||||
|
||||
std::string LottoWinner(uint64_t txfee)
|
||||
{
|
||||
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), hush_nextheight());
|
||||
CPubKey mypk,lottopk; int64_t winnings = 0; CScript opret; struct CCcontract_info *cp,C;
|
||||
cp = CCinit(&C,EVAL_LOTTO);
|
||||
if ( txfee == 0 )
|
||||
txfee = 10000;
|
||||
mypk = pubkey2pk(Mypubkey());
|
||||
lottopk = GetUnspendable(cp,0);
|
||||
if ( AddNormalinputs(mtx,mypk,txfee,64) > 0 )
|
||||
{
|
||||
mtx.vout.push_back(MakeCC1vout(EVAL_LOTTO,winnings,lottopk));
|
||||
return(FinalizeCCTx(0,cp,mtx,mypk,txfee,opret));
|
||||
}
|
||||
return("");
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
echo pricescc.so
|
||||
gcc -O3 -DBUILD_GAMESCC -DBUILD_PRICES -std=c++11 -I../secp256k1/include -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I.. -I. -fPIC -shared -c -o pricescc.so cclib.cpp
|
||||
echo prices
|
||||
cd games
|
||||
gcc -O3 -std=c++11 -I../secp256k1/include -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I.. -I. -DSTANDALONE -DBUILD_PRICES ../gamescc.cpp -lncurses -lcurl -o prices
|
||||
cd ..
|
||||
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
echo gamescc.so with tetris
|
||||
gcc -O3 -DBUILD_GAMESCC -std=c++11 -I../secp256k1/include -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I.. -I. -fPIC -shared -c -o gamescc.so cclib.cpp
|
||||
echo tetris dapp
|
||||
cd games
|
||||
gcc -O3 -std=c++11 -I../secp256k1/include -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I.. -I. -DSTANDALONE ../gamescc.cpp -lncurses -lcurl -o tetris
|
||||
cd ..
|
||||
|
||||
1572
src/cc/payments.cpp
1572
src/cc/payments.cpp
File diff suppressed because it is too large
Load Diff
1287
src/cc/pegs.cpp
1287
src/cc/pegs.cpp
File diff suppressed because it is too large
Load Diff
@@ -1,378 +0,0 @@
|
||||
// Copyright (c) 2016-2023 The Hush developers
|
||||
// Distributed under the GPLv3 software license, see the accompanying
|
||||
// file COPYING or https://www.gnu.org/licenses/gpl-3.0.en.html
|
||||
/******************************************************************************
|
||||
* Copyright © 2014-2019 The SuperNET Developers. *
|
||||
* *
|
||||
* See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at *
|
||||
* the top-level directory of this distribution for the individual copyright *
|
||||
* holder information and the developer policies on copyright and licensing. *
|
||||
* *
|
||||
* Unless otherwise agreed in a custom licensing agreement, no part of the *
|
||||
* SuperNET software, including this file may be copied, modified, propagated *
|
||||
* or distributed except according to the terms contained in the LICENSE file *
|
||||
* *
|
||||
* Removal or modification of this copyright notice is prohibited. *
|
||||
* *
|
||||
*****************************************************************************/
|
||||
//TODO: Finish deleting all this jl777 garbage. This CC will never function
|
||||
|
||||
#include "CCassets.h"
|
||||
#include "CCPrices.h"
|
||||
#include <cstdlib>
|
||||
#include <gmp.h>
|
||||
|
||||
#define IS_CHARINSTR(c, str) (std::string(str).find((char)(c)) != std::string::npos)
|
||||
#define NVOUT_CCMARKER 1
|
||||
#define NVOUT_NORMALMARKER 3
|
||||
|
||||
typedef struct OneBetData {
|
||||
int64_t positionsize;
|
||||
int32_t firstheight;
|
||||
int64_t costbasis;
|
||||
int64_t profits;
|
||||
|
||||
OneBetData() { positionsize = 0; firstheight = 0; costbasis = 0; profits = 0; }
|
||||
} onebetdata;
|
||||
|
||||
typedef struct BetInfo {
|
||||
uint256 txid;
|
||||
int64_t averageCostbasis, firstprice, lastprice, liquidationprice, equity;
|
||||
int64_t exitfee;
|
||||
int32_t lastheight;
|
||||
int16_t leverage;
|
||||
bool isOpen, isRekt;
|
||||
uint256 tokenid;
|
||||
|
||||
std::vector<uint16_t> vecparsed;
|
||||
std::vector<onebetdata> bets;
|
||||
CPubKey pk;
|
||||
|
||||
bool isUp;
|
||||
|
||||
BetInfo() {
|
||||
averageCostbasis = firstprice = lastprice = liquidationprice = equity = 0;
|
||||
lastheight = 0;
|
||||
leverage = 0;
|
||||
exitfee = 0;
|
||||
isOpen = isRekt = isUp = false;
|
||||
}
|
||||
} BetInfo;
|
||||
|
||||
typedef struct MatchedBookTotal {
|
||||
|
||||
int64_t diffLeveragedPosition;
|
||||
|
||||
} MatchedBookTotal;
|
||||
|
||||
typedef struct TotalFund {
|
||||
int64_t totalFund;
|
||||
int64_t totalActiveBets;
|
||||
int64_t totalCashout;
|
||||
int64_t totalRekt;
|
||||
int64_t totalEquity;
|
||||
|
||||
TotalFund() {
|
||||
totalFund = totalActiveBets = totalCashout = totalRekt = totalEquity = 0;
|
||||
}
|
||||
|
||||
} TotalFund;
|
||||
|
||||
int32_t prices_syntheticprofits(int64_t &costbasis, int32_t firstheight, int32_t height, int16_t leverage, std::vector<uint16_t> vec, int64_t positionsize, int64_t &profits, int64_t &outprice);
|
||||
static bool prices_isacceptableamount(const std::vector<uint16_t> &vecparsed, int64_t amount, int16_t leverage);
|
||||
|
||||
// helpers:
|
||||
|
||||
// returns true if there are only digits and no alphas or slashes in 's'
|
||||
inline bool is_weight_str(std::string s) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// start of consensus code
|
||||
|
||||
CScript prices_betopret(CPubKey mypk,int32_t height,int64_t amount,int16_t leverage,int64_t firstprice,std::vector<uint16_t> vec,uint256 tokenid)
|
||||
{
|
||||
CScript opret;
|
||||
opret << OP_RETURN << E_MARSHAL(ss << EVAL_PRICES << 'B' << mypk << height << amount << leverage << firstprice << vec << tokenid);
|
||||
return(opret);
|
||||
}
|
||||
|
||||
uint8_t prices_betopretdecode(CScript scriptPubKey,CPubKey &pk,int32_t &height,int64_t &amount,int16_t &leverage,int64_t &firstprice,std::vector<uint16_t> &vec,uint256 &tokenid)
|
||||
{
|
||||
return(0);
|
||||
}
|
||||
|
||||
CScript prices_addopret(uint256 bettxid,CPubKey mypk,int64_t amount)
|
||||
{
|
||||
CScript opret;
|
||||
return(opret);
|
||||
}
|
||||
|
||||
uint8_t prices_addopretdecode(CScript scriptPubKey,uint256 &bettxid,CPubKey &pk,int64_t &amount)
|
||||
{
|
||||
return(0);
|
||||
}
|
||||
|
||||
CScript prices_costbasisopret(uint256 bettxid,CPubKey mypk,int32_t height,int64_t costbasis)
|
||||
{
|
||||
CScript opret;
|
||||
return(opret);
|
||||
}
|
||||
|
||||
uint8_t prices_costbasisopretdecode(CScript scriptPubKey,uint256 &bettxid,CPubKey &pk,int32_t &height,int64_t &costbasis)
|
||||
{
|
||||
return(0);
|
||||
}
|
||||
|
||||
CScript prices_finalopret(bool isRekt, uint256 bettxid, CPubKey pk, int32_t lastheight, int64_t costbasis, int64_t lastprice, int64_t liquidationprice, int64_t equity, int64_t exitfee, uint32_t nonce)
|
||||
{
|
||||
CScript opret;
|
||||
return(opret);
|
||||
}
|
||||
|
||||
uint8_t prices_finalopretdecode(CScript scriptPubKey, uint256 &bettxid, CPubKey &pk, int32_t &lastheight, int64_t &costbasis, int64_t &lastprice, int64_t &liquidationprice, int64_t &equity, int64_t &exitfee)
|
||||
{
|
||||
return(0);
|
||||
}
|
||||
|
||||
// price opret basic validation and retrieval
|
||||
static uint8_t PricesCheckOpret(const CTransaction & tx, vscript_t &opret)
|
||||
{
|
||||
return (uint8_t)0;
|
||||
}
|
||||
|
||||
// validate bet tx helper
|
||||
static bool ValidateBetTx(struct CCcontract_info *cp, Eval *eval, const CTransaction & bettx)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// validate add funding tx helper
|
||||
static bool ValidateAddFundingTx(struct CCcontract_info *cp, Eval *eval, const CTransaction & addfundingtx, const CTransaction & vintx)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// validate final tx helper
|
||||
static bool ValidateFinalTx(struct CCcontract_info *cp, Eval *eval, const CTransaction & finaltx, const CTransaction & bettx)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PricesValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
// helper functions for rpc calls in rpcwallet.cpp
|
||||
|
||||
int64_t AddPricesInputs(struct CCcontract_info *cp, CMutableTransaction &mtx, char *destaddr, int64_t total, int32_t maxinputs)
|
||||
{
|
||||
int64_t totalinputs = 0;
|
||||
return(totalinputs);
|
||||
}
|
||||
|
||||
double prices_minmarginpercent(int16_t leverage)
|
||||
{
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
|
||||
UniValue prices_rawtxresult(UniValue &result, std::string rawtx, int32_t broadcastflag)
|
||||
{
|
||||
return(result);
|
||||
}
|
||||
|
||||
static std::string prices_getsourceexpression(const std::vector<uint16_t> &vec) {
|
||||
std::string expr;
|
||||
return expr;
|
||||
}
|
||||
|
||||
// helper functions to get synthetic expression reduced:
|
||||
|
||||
// return s true and needed operand count if string is opcode
|
||||
static bool prices_isopcode(const std::string &s, int &need)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// split pair onto two quotes divided by "_"
|
||||
static void prices_splitpair(const std::string &pair, std::string &upperquote, std::string &bottomquote)
|
||||
{
|
||||
}
|
||||
|
||||
// invert pair like BTS_USD -> USD_BTC
|
||||
static std::string prices_invertpair(const std::string &pair)
|
||||
{
|
||||
std::string s;
|
||||
return s;
|
||||
}
|
||||
|
||||
// invert pairs in operation accordingly to "/" operator, convert operator to * or ***
|
||||
static void prices_invertoperation(const std::vector<std::string> &vexpr, int p, std::vector<std::string> &voperation)
|
||||
{
|
||||
}
|
||||
|
||||
// reduce pairs in the operation, change or remove opcode if reduced
|
||||
static int prices_reduceoperands(std::vector<std::string> &voperation)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// substitute reduced operation in vectored expr
|
||||
static void prices_substitutereduced(std::vector<std::string> &vexpr, int p, std::vector<std::string> voperation)
|
||||
{
|
||||
}
|
||||
|
||||
// try to reduce synthetic expression by substituting "BTC_USD, BTC_EUR, 30, /" with "EUR_USD, 30" etc
|
||||
static std::string prices_getreducedexpr(const std::string &expr)
|
||||
{
|
||||
std::string reduced;
|
||||
return reduced;
|
||||
}
|
||||
|
||||
// parse synthetic expression into vector of codes
|
||||
int32_t prices_syntheticvec(std::vector<uint16_t> &vec, std::vector<std::string> synthetic)
|
||||
{
|
||||
return(0);
|
||||
}
|
||||
|
||||
// calculates price for synthetic expression
|
||||
int64_t prices_syntheticprice(std::vector<uint16_t> vec, int32_t height, int32_t minmax, int16_t leverage)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// calculates costbasis and profit/loss for the bet
|
||||
int32_t prices_syntheticprofits(int64_t &costbasis, int32_t firstheight, int32_t height, int16_t leverage, std::vector<uint16_t> vec, int64_t positionsize, int64_t &profits, int64_t &outprice)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// makes result json object
|
||||
void prices_betjson(UniValue &result, std::vector<OneBetData> bets, int16_t leverage, int32_t endheight, int64_t lastprice)
|
||||
{
|
||||
}
|
||||
|
||||
// retrieves costbasis from a tx spending bettx vout1 (deprecated)
|
||||
int64_t prices_costbasis(CTransaction bettx, uint256 &txidCostbasis)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// enumerates and retrieves added bets, returns the last baton txid
|
||||
int64_t prices_enumaddedbets(uint256 &batontxid, std::vector<OneBetData> &bets, uint256 bettxid)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// pricesbet rpc impl: make betting tx
|
||||
UniValue PricesBet(int64_t txfee, int64_t amount, int16_t leverage, std::vector<std::string> synthetic)
|
||||
{
|
||||
UniValue result(UniValue::VOBJ);
|
||||
return(result);
|
||||
}
|
||||
|
||||
// pricesaddfunding rpc impl: add yet another bet
|
||||
UniValue PricesAddFunding(int64_t txfee, uint256 bettxid, int64_t amount)
|
||||
{
|
||||
UniValue result(UniValue::VOBJ);
|
||||
return(result);
|
||||
}
|
||||
|
||||
// scan chain from the initial bet's first position upto the chain tip and calculate bet's costbasises and profits, breaks if rekt detected
|
||||
int32_t prices_scanchain(std::vector<OneBetData> &bets, int16_t leverage, std::vector<uint16_t> vec, int64_t &lastprice, int32_t &endheight) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// pricescostbasis rpc impl: set cost basis (open price) for the bet (deprecated)
|
||||
UniValue PricesSetcostbasis(int64_t txfee, uint256 bettxid)
|
||||
{
|
||||
UniValue result(UniValue::VOBJ);
|
||||
return(result);
|
||||
}
|
||||
|
||||
|
||||
// pricesaddfunding rpc impl: add yet another bet
|
||||
UniValue PricesRefillFund(int64_t amount)
|
||||
{
|
||||
UniValue result(UniValue::VOBJ);
|
||||
return(result);
|
||||
}
|
||||
|
||||
|
||||
int32_t prices_getbetinfo(uint256 bettxid, BetInfo &betinfo)
|
||||
{
|
||||
return (-420);
|
||||
}
|
||||
|
||||
// pricesrekt rpc: anyone can rekt a bet at some block where losses reached limit, collecting fee
|
||||
UniValue PricesRekt(int64_t txfee, uint256 bettxid, int32_t rektheight)
|
||||
{
|
||||
UniValue result(UniValue::VOBJ);
|
||||
return(result);
|
||||
}
|
||||
|
||||
// pricescashout rpc impl: bettor can cashout hit bet if it is not rekt
|
||||
UniValue PricesCashout(int64_t txfee, uint256 bettxid)
|
||||
{
|
||||
UniValue result(UniValue::VOBJ);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
// pricesinfo rpc impl
|
||||
UniValue PricesInfo(uint256 bettxid, int32_t refheight)
|
||||
{
|
||||
UniValue result(UniValue::VOBJ);
|
||||
return(result);
|
||||
}
|
||||
|
||||
// priceslist rpc impl
|
||||
UniValue PricesList(uint32_t filter, CPubKey mypk)
|
||||
{
|
||||
UniValue result(UniValue::VARR);
|
||||
return(result);
|
||||
}
|
||||
|
||||
|
||||
static bool prices_addbookentry(uint256 txid, std::vector<BetInfo> &book)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
static bool prices_ispositionup(const std::vector<uint16_t> &vecparsed, int16_t leverage) {
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool prices_isopposite(BetInfo p1, BetInfo p2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static std::string findMatchedBook(const std::vector<uint16_t> &vecparsed, const std::map<std::string, std::vector<BetInfo> > & bookmatched) {
|
||||
return std::string("");
|
||||
}
|
||||
|
||||
|
||||
void prices_getorderbook(std::map<std::string, std::vector<BetInfo> > & bookmatched, std::map<std::string, MatchedBookTotal> &matchedTotals, TotalFund &fundTotals) {
|
||||
}
|
||||
|
||||
static bool prices_isacceptableamount(const std::vector<uint16_t> &vecparsed, int64_t amount, int16_t leverage) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// walk through uxtos on the global address
|
||||
// calculate the balance:
|
||||
// + rekt positions
|
||||
// = opposite positions
|
||||
// - unbalanced positions
|
||||
UniValue PricesGetOrderbook()
|
||||
{
|
||||
UniValue result(UniValue::VOBJ);
|
||||
return result;
|
||||
}
|
||||
@@ -1,756 +0,0 @@
|
||||
// Copyright (c) 2016-2023 The Hush developers
|
||||
// Distributed under the GPLv3 software license, see the accompanying
|
||||
// file COPYING or https://www.gnu.org/licenses/gpl-3.0.en.html
|
||||
/******************************************************************************
|
||||
* Copyright © 2014-2019 The SuperNET Developers. *
|
||||
* *
|
||||
* See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at *
|
||||
* the top-level directory of this distribution for the individual copyright *
|
||||
* holder information and the developer policies on copyright and licensing. *
|
||||
* *
|
||||
* Unless otherwise agreed in a custom licensing agreement, no part of the *
|
||||
* SuperNET software, including this file may be copied, modified, propagated *
|
||||
* or distributed except according to the terms contained in the LICENSE file *
|
||||
* *
|
||||
* Removal or modification of this copyright notice is prohibited. *
|
||||
* *
|
||||
******************************************************************************/
|
||||
|
||||
#include "CCrewards.h"
|
||||
|
||||
/*
|
||||
The rewards CC contract is initially for OOT, which needs this functionality. However, many of the attributes can be parameterized to allow different rewards programs to run. Multiple rewards plans could even run on the same blockchain, though the user would need to choose which one to lock funds into.
|
||||
|
||||
At the high level, the user would lock funds for some amount of time and at the end of it, would get all the locked funds back with an additional reward. So there needs to be a lock funds and unlock funds ability. Additionally, the rewards need to come from somewhere, so similar to the faucet, there would be a way to fund the reward.
|
||||
|
||||
Additional requirements are for the user to be able to lock funds via SPV. This requirement in turns forces the creation of a way for anybody to be able to unlock the funds as that operation requires a native daemon running and cant be done over SPV. The idea is to allow anybody to run a script that would unlock all funds that are matured. As far as the user is concerned, he locks his funds via SPV and after some time it comes back with an extra reward.
|
||||
|
||||
In reality, the funds are locked into a CC address that is unspendable, except for some special conditions and it needs to come back to the address that funded the lock. In order to implement this, several things are clear.
|
||||
|
||||
1) each locked CC utxo needs to be linked to a specific rewards plan
|
||||
2) each locked CC utxo needs to know the only address that it can be unlocked into
|
||||
3) SPV requirement means the lock transaction needs to be able to be created without any CC signing
|
||||
|
||||
The opreturn will be used to store the name of the rewards plan and all funding and locked funds with the same plan will use the same pool of rewards. plan names will be limited to 8 chars and encoded into a uint64_t.
|
||||
|
||||
The initial funding transaction will have all the parameters for the rewards plan encoded in the vouts. Additional fundings will just increase the available CC utxo for the rewards.
|
||||
|
||||
Locks wont have any CC vins, but will send to the RewardsCCaddress, with the plan stringbits in the opreturn. vout1 will have the unlock address and no other destination is valid.
|
||||
|
||||
Unlock does a CC spend to the vout1 address
|
||||
|
||||
|
||||
createfunding
|
||||
vins.*: normal inputs
|
||||
vout.0: CC vout for funding
|
||||
vout.1: normal marker vout for easy searching
|
||||
vout.2: normal change
|
||||
vout.n-1: opreturn 'F' sbits APR minseconds maxseconds mindeposit
|
||||
|
||||
addfunding
|
||||
vins.*: normal inputs
|
||||
vout.0: CC vout for funding
|
||||
vout.1: normal change
|
||||
vout.n-1: opreturn 'A' sbits fundingtxid
|
||||
|
||||
lock
|
||||
vins.*: normal inputs
|
||||
vout.0: CC vout for locked funds
|
||||
vout.1: normal output to unlock address
|
||||
vout.2: change
|
||||
vout.n-1: opreturn 'L' sbits fundingtxid
|
||||
|
||||
unlock
|
||||
vin.0: locked funds CC vout.0 from lock
|
||||
vin.1+: funding CC vout.0 from 'F' and 'A' and 'U'
|
||||
vout.0: funding CC change
|
||||
vout.1: normal output to unlock address
|
||||
vout.n-1: opreturn 'U' sbits fundingtxid
|
||||
|
||||
*/
|
||||
|
||||
/// the following are compatible with windows
|
||||
/// mpz_set_lli sets a long long singed int to a big num mpz_t for very large integer math
|
||||
extern void mpz_set_lli( mpz_t rop, long long op );
|
||||
// mpz_get_si2 gets a mpz_t and returns a signed long long int
|
||||
extern int64_t mpz_get_si2( mpz_t op );
|
||||
// mpz_get_ui2 gets a mpz_t and returns a unsigned long long int
|
||||
extern uint64_t mpz_get_ui2( mpz_t op );
|
||||
|
||||
uint64_t RewardsCalc(int64_t amount, uint256 txid, int64_t APR, int64_t minseconds, int64_t maxseconds, uint32_t timestamp)
|
||||
{
|
||||
int32_t numblocks; int64_t duration; uint64_t reward = 0;
|
||||
//fprintf(stderr,"minseconds %llu maxseconds %llu\n",(long long)minseconds,(long long)maxseconds);
|
||||
if ( (duration= CCduration(numblocks,txid)) < minseconds )
|
||||
{
|
||||
fprintf(stderr,"duration %lli < minseconds %lli\n",(long long)duration,(long long)minseconds);
|
||||
return(0);
|
||||
//duration = (uint32_t)time(NULL) - (1532713903 - 3600 * 24);
|
||||
} else if ( duration > maxseconds )
|
||||
duration = maxseconds;
|
||||
/* if ( 0 ) // amount * APR * duration / COIN * 100 * 365*24*3600
|
||||
reward = (((amount * APR) / COIN) * duration) / (365*24*3600LL * 100);
|
||||
else reward = (((amount * duration) / (365 * 24 * 3600LL)) * (APR / 1000000)) / 10000;
|
||||
*/
|
||||
if ( !hush_hardfork_active(timestamp) )
|
||||
reward = (((amount * duration) / (365 * 24 * 3600LL)) * (APR / 1000000)) / 10000;
|
||||
else
|
||||
{
|
||||
// declare and init the mpz_t big num variables
|
||||
mpz_t mpzAmount, mpzDuration, mpzReward, mpzAPR, mpzModifier;
|
||||
mpz_init(mpzAmount);
|
||||
mpz_init(mpzDuration);
|
||||
mpz_init(mpzAPR);
|
||||
mpz_init(mpzReward);
|
||||
mpz_init(mpzModifier);
|
||||
|
||||
// set the inputs to big num variables
|
||||
mpz_set_lli(mpzAmount, amount);
|
||||
mpz_set_lli(mpzDuration, duration);
|
||||
mpz_set_lli(mpzAPR, APR);
|
||||
mpz_set_lli(mpzModifier, COIN*100*365*24*3600LL);
|
||||
|
||||
// (amount * APR * duration)
|
||||
mpz_mul(mpzReward, mpzAmount, mpzDuration);
|
||||
mpz_mul(mpzReward, mpzReward, mpzAPR);
|
||||
|
||||
// total_of_above / (COIN * 100 * 365*24*3600LL)
|
||||
mpz_tdiv_q(mpzReward, mpzReward, mpzModifier);
|
||||
|
||||
// set result to variable we can use and return it.
|
||||
reward = mpz_get_ui2(mpzReward);
|
||||
}
|
||||
if ( reward > amount )
|
||||
reward = amount;
|
||||
fprintf(stderr, "amount.%lli duration.%lli APR.%lli reward.%llu\n", (long long)amount, (long long)duration, (long long)APR, (long long)reward);
|
||||
//fprintf(stderr,"amount %.8f %.8f %llu -> duration.%llu reward %.8f vals %.8f %.8f\n",(double)amount/COIN,((double)amount * APR)/COIN,(long long)((amount * APR) / (COIN * 365*24*3600)),(long long)duration,(double)reward/COIN,(double)((amount * duration) / (365 * 24 * 3600LL))/COIN,(double)(((amount * duration) / (365 * 24 * 3600LL)) * (APR / 1000000))/COIN);
|
||||
return(reward);
|
||||
}
|
||||
|
||||
CScript EncodeRewardsFundingOpRet(uint8_t funcid,uint64_t sbits,uint64_t APR,uint64_t minseconds,uint64_t maxseconds,uint64_t mindeposit)
|
||||
{
|
||||
CScript opret; uint8_t evalcode = EVAL_REWARDS;
|
||||
opret << OP_RETURN << E_MARSHAL(ss << evalcode << 'F' << sbits << APR << minseconds << maxseconds << mindeposit);
|
||||
return(opret);
|
||||
}
|
||||
|
||||
uint8_t DecodeRewardsFundingOpRet(const CScript &scriptPubKey,uint64_t &sbits,uint64_t &APR,uint64_t &minseconds,uint64_t &maxseconds,uint64_t &mindeposit)
|
||||
{
|
||||
std::vector<uint8_t> vopret; uint8_t *script,e,f;
|
||||
GetOpReturnData(scriptPubKey, vopret);
|
||||
script = (uint8_t *)vopret.data();
|
||||
if ( vopret.size() > 2 && E_UNMARSHAL(vopret,ss >> e; ss >> f; ss >> sbits; ss >> APR; ss >> minseconds; ss >> maxseconds; ss >> mindeposit) != 0 )
|
||||
{
|
||||
if ( e == EVAL_REWARDS && f == 'F' )
|
||||
return(f);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
CScript EncodeRewardsOpRet(uint8_t funcid,uint64_t sbits,uint256 fundingtxid)
|
||||
{
|
||||
CScript opret; uint8_t evalcode = EVAL_REWARDS;
|
||||
opret << OP_RETURN << E_MARSHAL(ss << evalcode << funcid << sbits << fundingtxid);
|
||||
return(opret);
|
||||
}
|
||||
|
||||
uint8_t DecodeRewardsOpRet(uint256 txid,const CScript &scriptPubKey,uint64_t &sbits,uint256 &fundingtxid)
|
||||
{
|
||||
std::vector<uint8_t> vopret; uint8_t *script,e,f,funcid; uint64_t APR,minseconds,maxseconds,mindeposit;
|
||||
GetOpReturnData(scriptPubKey, vopret);
|
||||
if ( vopret.size() > 2 )
|
||||
{
|
||||
script = (uint8_t *)vopret.data();
|
||||
if ( script[0] == EVAL_REWARDS )
|
||||
{
|
||||
if ( script[1] == 'F' )
|
||||
{
|
||||
if ( E_UNMARSHAL(vopret,ss >> e; ss >> f; ss >> sbits; ss >> APR; ss >> minseconds; ss >> maxseconds; ss >> mindeposit) != 0 )
|
||||
{
|
||||
fundingtxid = txid;
|
||||
return('F');
|
||||
} else fprintf(stderr,"unmarshal error for F\n");
|
||||
}
|
||||
else if ( E_UNMARSHAL(vopret,ss >> e; ss >> f; ss >> sbits; ss >> fundingtxid) != 0 )
|
||||
{
|
||||
if ( e == EVAL_REWARDS && (f == 'L' || f == 'U' || f == 'A') )
|
||||
return(f);
|
||||
else fprintf(stderr,"mismatched e.%02x f.(%c)\n",e,f);
|
||||
}
|
||||
} else fprintf(stderr,"script[0] %02x != EVAL_REWARDS\n",script[0]);
|
||||
} else fprintf(stderr,"not enough opret.[%d]\n",(int32_t)vopret.size());
|
||||
return(0);
|
||||
}
|
||||
|
||||
int64_t IsRewardsvout(struct CCcontract_info *cp,const CTransaction& tx,int32_t v,uint64_t refsbits,uint256 reffundingtxid)
|
||||
{
|
||||
char destaddr[64]; uint64_t sbits; uint256 fundingtxid,txid; uint8_t funcid; int32_t numvouts;
|
||||
if ( tx.vout[v].scriptPubKey.IsPayToCryptoCondition() != 0 && (numvouts= (int32_t)tx.vout.size()) > 0 )
|
||||
{
|
||||
txid = tx.GetHash();
|
||||
if ( (funcid= DecodeRewardsOpRet(txid,tx.vout[numvouts-1].scriptPubKey,sbits,fundingtxid)) != 0 && sbits == refsbits && (fundingtxid == reffundingtxid || txid == reffundingtxid) )
|
||||
{
|
||||
|
||||
if ( Getscriptaddress(destaddr,tx.vout[v].scriptPubKey) > 0 && strcmp(destaddr,cp->unspendableCCaddr) == 0 )
|
||||
return(tx.vout[v].nValue);
|
||||
}
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
bool RewardsExactAmounts(struct CCcontract_info *cp,Eval *eval,const CTransaction &tx,uint64_t txfee,uint64_t refsbits,uint256 reffundingtxid)
|
||||
{
|
||||
static uint256 zerohash;
|
||||
CTransaction vinTx; uint256 hashBlock; int32_t i,numvins,numvouts; int64_t inputs=0,outputs=0,assetoshis;
|
||||
numvins = tx.vin.size();
|
||||
numvouts = tx.vout.size();
|
||||
for (i=0; i<numvins; i++)
|
||||
{
|
||||
if ( (*cp->ismyvin)(tx.vin[i].scriptSig) != 0 )
|
||||
{
|
||||
if ( eval->GetTxUnconfirmed(tx.vin[i].prevout.hash,vinTx,hashBlock) == 0 )
|
||||
return eval->Invalid("always should find vin, but didnt");
|
||||
else
|
||||
{
|
||||
if ( hashBlock == zerohash )
|
||||
return eval->Invalid("cant rewards from mempool");
|
||||
if ( (assetoshis= IsRewardsvout(cp,vinTx,tx.vin[i].prevout.n,refsbits,reffundingtxid)) != 0 )
|
||||
inputs += assetoshis;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (i=0; i<numvouts; i++)
|
||||
{
|
||||
//fprintf(stderr,"i.%d of numvouts.%d\n",i,numvouts);
|
||||
if ( (assetoshis= IsRewardsvout(cp,tx,i,refsbits,reffundingtxid)) != 0 )
|
||||
outputs += assetoshis;
|
||||
}
|
||||
if ( inputs != outputs+txfee )
|
||||
{
|
||||
fprintf(stderr,"inputs %llu vs outputs %llu txfee %llu\n",(long long)inputs,(long long)outputs,(long long)txfee);
|
||||
return eval->Invalid("mismatched inputs != outputs + txfee");
|
||||
}
|
||||
else return(true);
|
||||
}
|
||||
|
||||
bool RewardsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn)
|
||||
{
|
||||
uint256 txid,fundingtxid,hashBlock,vinfundingtxid; uint64_t vinsbits,sbits,APR,minseconds,maxseconds,mindeposit,amount,reward,txfee=10000; int32_t numvins,numvouts,preventCCvins,preventCCvouts,i; uint8_t funcid; CScript scriptPubKey; CTransaction fundingTx,vinTx;
|
||||
int64_t dummy;
|
||||
numvins = tx.vin.size();
|
||||
numvouts = tx.vout.size();
|
||||
preventCCvins = preventCCvouts = -1;
|
||||
if ( numvouts < 1 )
|
||||
return eval->Invalid("no vouts");
|
||||
else
|
||||
{
|
||||
txid = tx.GetHash();
|
||||
if ( (funcid= DecodeRewardsOpRet(txid,tx.vout[numvouts-1].scriptPubKey,sbits,fundingtxid)) != 0 )
|
||||
{
|
||||
if ( eval->GetTxUnconfirmed(fundingtxid,fundingTx,hashBlock) == 0 )
|
||||
return eval->Invalid("cant find fundingtxid");
|
||||
else if ( fundingTx.vout.size() > 0 && DecodeRewardsFundingOpRet(fundingTx.vout[fundingTx.vout.size()-1].scriptPubKey,sbits,APR,minseconds,maxseconds,mindeposit) != 'F' )
|
||||
return eval->Invalid("fundingTx not valid");
|
||||
if ( APR > REWARDSCC_MAXAPR )
|
||||
return eval->Invalid("excessive APR");
|
||||
switch ( funcid )
|
||||
{
|
||||
case 'F':
|
||||
//vins.*: normal inputs
|
||||
//vout.0: CC vout for funding
|
||||
//vout.1: normal marker vout for easy searching
|
||||
//vout.2: normal change
|
||||
//vout.n-1: opreturn 'F' sbits APR minseconds maxseconds mindeposit
|
||||
return eval->Invalid("unexpected RewardsValidate for createfunding");
|
||||
break;
|
||||
case 'A':
|
||||
//vins.*: normal inputs
|
||||
//vout.0: CC vout for funding
|
||||
//vout.1: normal change
|
||||
//vout.n-1: opreturn 'A' sbits fundingtxid
|
||||
return eval->Invalid("unexpected RewardsValidate for addfunding");
|
||||
break;
|
||||
case 'L':
|
||||
//vins.*: normal inputs
|
||||
//vout.0: CC vout for locked funds
|
||||
//vout.1: normal output to unlock address
|
||||
//vout.2: change
|
||||
//vout.n-1: opreturn 'L' sbits fundingtxid
|
||||
return eval->Invalid("unexpected RewardsValidate for lock");
|
||||
break;
|
||||
case 'U':
|
||||
//vin.0: locked funds CC vout.0 from lock
|
||||
//vin.1+: funding CC vout.0 from 'F' and 'A' and 'U'
|
||||
//vout.0: funding CC change or recover normal payout
|
||||
//vout.1: normal output to unlock address
|
||||
//vout.n-1: opreturn 'U' sbits fundingtxid
|
||||
if ( fundingtxid == tx.vin[0].prevout.hash )
|
||||
return eval->Invalid("cant unlock fundingtxid");
|
||||
else if ( eval->GetTxUnconfirmed(tx.vin[0].prevout.hash,vinTx,hashBlock) == 0 )
|
||||
return eval->Invalid("always should find vin.0, but didnt");
|
||||
else if ( DecodeRewardsOpRet(tx.vin[0].prevout.hash,vinTx.vout[vinTx.vout.size()-1].scriptPubKey,vinsbits,vinfundingtxid) != 'L' )
|
||||
return eval->Invalid("can only unlock locktxid");
|
||||
else if ( fundingtxid != vinfundingtxid )
|
||||
return eval->Invalid("mismatched vinfundingtxid");
|
||||
for (i=0; i<numvins; i++)
|
||||
{
|
||||
if ( (*cp->ismyvin)(tx.vin[i].scriptSig) == 0 )
|
||||
return eval->Invalid("unexpected normal vin for unlock");
|
||||
}
|
||||
if ( !CheckTxFee(tx, txfee, chainActive.LastTip()->GetHeight(), chainActive.LastTip()->nTime, dummy) )
|
||||
return eval->Invalid("txfee is too high");
|
||||
amount = vinTx.vout[0].nValue;
|
||||
reward = RewardsCalc((int64_t)amount,tx.vin[0].prevout.hash,(int64_t)APR,(int64_t)minseconds,(int64_t)maxseconds,GetLatestTimestamp(eval->GetCurrentHeight()));
|
||||
if ( reward == 0 )
|
||||
return eval->Invalid("no eligible rewards");
|
||||
if ( numvins == 1 && tx.vout[0].scriptPubKey.IsPayToCryptoCondition() == 0 )
|
||||
{
|
||||
if ( tx.vout[1].nValue != 10000 )
|
||||
return eval->Invalid("wrong marker vout value");
|
||||
else if ( tx.vout[1].scriptPubKey != tx.vout[0].scriptPubKey )
|
||||
return eval->Invalid("unlock recover tx vout.1 mismatched scriptPubKey");
|
||||
else if ( tx.vout[0].scriptPubKey != vinTx.vout[1].scriptPubKey )
|
||||
return eval->Invalid("unlock recover tx vout.0 mismatched scriptPubKey");
|
||||
else if ( tx.vout[0].nValue > vinTx.vout[0].nValue )
|
||||
return eval->Invalid("unlock recover tx vout.0 mismatched amounts");
|
||||
else if ( tx.vout[2].nValue > 0 )
|
||||
return eval->Invalid("unlock recover tx vout.1 nonz amount");
|
||||
else return(true);
|
||||
}
|
||||
if ( vinTx.vout[0].scriptPubKey.IsPayToCryptoCondition() == 0 )
|
||||
return eval->Invalid("unlock tx vout.0 is normal output");
|
||||
else if ( numvouts != 3 )
|
||||
return eval->Invalid("unlock tx wrong number of vouts");
|
||||
else if ( tx.vout[0].scriptPubKey.IsPayToCryptoCondition() == 0 )
|
||||
return eval->Invalid("unlock tx vout.0 is normal output");
|
||||
else if ( tx.vout[1].scriptPubKey.IsPayToCryptoCondition() != 0 )
|
||||
return eval->Invalid("unlock tx vout.1 is CC output");
|
||||
else if ( tx.vout[1].scriptPubKey != vinTx.vout[1].scriptPubKey )
|
||||
return eval->Invalid("unlock tx vout.1 mismatched scriptPubKey");
|
||||
if ( RewardsExactAmounts(cp,eval,tx,txfee+tx.vout[1].nValue,sbits,fundingtxid) == 0 )
|
||||
return false;
|
||||
else if ( tx.vout[1].nValue > amount+reward )
|
||||
return eval->Invalid("unlock tx vout.1 isnt amount+reward");
|
||||
else if ( tx.vout[2].nValue > 0 )
|
||||
return eval->Invalid("unlock tx vout.2 isnt 0");
|
||||
preventCCvouts = 1;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr,"illegal rewards funcid.(%c)\n",funcid);
|
||||
return eval->Invalid("unexpected rewards funcid");
|
||||
break;
|
||||
}
|
||||
} else return eval->Invalid("unexpected rewards missing funcid");
|
||||
return(PreventCC(eval,tx,preventCCvins,numvins,preventCCvouts,numvouts));
|
||||
}
|
||||
return(true);
|
||||
}
|
||||
|
||||
static uint64_t myIs_unlockedtx_inmempool(uint256 &txid,int32_t &vout,uint64_t refsbits,uint256 reffundingtxid,uint64_t needed)
|
||||
{
|
||||
uint8_t funcid; uint64_t sbits,nValue; uint256 fundingtxid; char str[65];
|
||||
memset(&txid,0,sizeof(txid));
|
||||
vout = -1;
|
||||
nValue = 0;
|
||||
BOOST_FOREACH(const CTxMemPoolEntry &e,mempool.mapTx)
|
||||
{
|
||||
const CTransaction &tx = e.GetTx();
|
||||
if ( tx.vout.size() > 0 && tx.vout[0].nValue >= needed )
|
||||
{
|
||||
const uint256 &hash = tx.GetHash();
|
||||
if ( tx.vout[0].scriptPubKey.IsPayToCryptoCondition() != 0 && myIsutxo_spentinmempool(ignoretxid,ignorevin,hash,0) == 0 )
|
||||
{
|
||||
if ( (funcid= DecodeRewardsOpRet(hash,tx.vout[tx.vout.size()-1].scriptPubKey,sbits,fundingtxid)) == 'U' && sbits == refsbits && fundingtxid == reffundingtxid )
|
||||
{
|
||||
txid = hash;
|
||||
vout = 0;
|
||||
nValue = tx.vout[0].nValue;
|
||||
fprintf(stderr,"found 'U' %s %.8f in unspent in mempool\n",uint256_str(str,txid),(double)nValue/COIN);
|
||||
return(nValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return(nValue);
|
||||
}
|
||||
|
||||
// 'L' vs 'F' and 'A'
|
||||
int64_t AddRewardsInputs(CScript &scriptPubKey,uint64_t maxseconds,struct CCcontract_info *cp,CMutableTransaction &mtx,CPubKey pk,int64_t total,int32_t maxinputs,uint64_t refsbits,uint256 reffundingtxid)
|
||||
{
|
||||
char coinaddr[64],str[65]; uint64_t threshold,sbits,nValue,totalinputs = 0; uint256 txid,hashBlock,fundingtxid; CTransaction tx; int32_t numblocks,j,vout,n = 0; uint8_t funcid;
|
||||
std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > unspentOutputs;
|
||||
GetCCaddress(cp,coinaddr,pk);
|
||||
SetCCunspents(unspentOutputs,coinaddr,true);
|
||||
if ( maxinputs > CC_MAXVINS )
|
||||
maxinputs = CC_MAXVINS;
|
||||
if ( maxinputs > 0 )
|
||||
threshold = total/maxinputs;
|
||||
else threshold = total;
|
||||
for (std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++)
|
||||
{
|
||||
txid = it->first.txhash;
|
||||
vout = (int32_t)it->first.index;
|
||||
if ( it->second.satoshis < threshold )
|
||||
continue;
|
||||
//fprintf(stderr,"(%s) %s/v%d %.8f\n",coinaddr,uint256_str(str,txid),vout,(double)it->second.satoshis/COIN);
|
||||
for (j=0; j<mtx.vin.size(); j++)
|
||||
if ( txid == mtx.vin[j].prevout.hash && vout == mtx.vin[j].prevout.n )
|
||||
break;
|
||||
if ( j != mtx.vin.size() )
|
||||
continue;
|
||||
if ( myGetTransaction(txid,tx,hashBlock) != 0 && tx.vout.size() > 0 && tx.vout[vout].scriptPubKey.IsPayToCryptoCondition() != 0 && myIsutxo_spentinmempool(ignoretxid,ignorevin,txid,vout) == 0 )
|
||||
{
|
||||
if ( (funcid= DecodeRewardsOpRet(txid,tx.vout[tx.vout.size()-1].scriptPubKey,sbits,fundingtxid)) != 0 )
|
||||
{
|
||||
if ( sbits != refsbits || fundingtxid != reffundingtxid )
|
||||
continue;
|
||||
if ( maxseconds == 0 && funcid != 'F' && funcid != 'A' && funcid != 'U' )
|
||||
continue;
|
||||
else if ( maxseconds != 0 && funcid != 'L' )
|
||||
{
|
||||
if ( CCduration(numblocks,txid) < maxseconds )
|
||||
continue;
|
||||
}
|
||||
fprintf(stderr,"maxseconds.%d (%c) %.8f %.8f\n",(int32_t)maxseconds,funcid,(double)tx.vout[vout].nValue/COIN,(double)it->second.satoshis/COIN);
|
||||
if ( total != 0 && maxinputs != 0 )
|
||||
{
|
||||
if ( maxseconds != 0 )
|
||||
scriptPubKey = tx.vout[1].scriptPubKey;
|
||||
mtx.vin.push_back(CTxIn(txid,vout,CScript()));
|
||||
}
|
||||
totalinputs += it->second.satoshis;
|
||||
n++;
|
||||
if ( (total > 0 && totalinputs >= total) || (maxinputs > 0 && n >= maxinputs) )
|
||||
break;
|
||||
} else fprintf(stderr,"null funcid\n");
|
||||
}
|
||||
}
|
||||
if ( maxseconds == 0 && totalinputs < total && (maxinputs == 0 || n < maxinputs-1) )
|
||||
{
|
||||
fprintf(stderr,"search mempool for unlocked and unspent CC rewards output for %.8f\n",(double)(total-totalinputs)/COIN);
|
||||
if ( (nValue= myIs_unlockedtx_inmempool(txid,vout,refsbits,reffundingtxid,total-totalinputs)) > 0 )
|
||||
{
|
||||
mtx.vin.push_back(CTxIn(txid,vout,CScript()));
|
||||
fprintf(stderr,"added mempool vout for %.8f\n",(double)nValue/COIN);
|
||||
totalinputs += nValue;
|
||||
n++;
|
||||
}
|
||||
}
|
||||
return(totalinputs);
|
||||
}
|
||||
|
||||
int64_t RewardsPlanFunds(uint64_t &lockedfunds,uint64_t refsbits,struct CCcontract_info *cp,CPubKey pk,uint256 reffundingtxid)
|
||||
{
|
||||
char coinaddr[64]; uint64_t sbits; int64_t nValue,totalinputs = 0; uint256 txid,hashBlock,fundingtxid; CTransaction tx; int32_t vout; uint8_t funcid;
|
||||
std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > unspentOutputs;
|
||||
lockedfunds = 0;
|
||||
GetCCaddress(cp,coinaddr,pk);
|
||||
SetCCunspents(unspentOutputs,coinaddr,true);
|
||||
for (std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++)
|
||||
{
|
||||
txid = it->first.txhash;
|
||||
vout = (int32_t)it->first.index;
|
||||
if ( myGetTransaction(txid,tx,hashBlock) != 0 && tx.vout[vout].scriptPubKey.IsPayToCryptoCondition() != 0 )
|
||||
{
|
||||
if ( (funcid= DecodeRewardsOpRet(txid,tx.vout[tx.vout.size()-1].scriptPubKey,sbits,fundingtxid)) == 'F' || funcid == 'A' || funcid == 'U' || funcid == 'L' )
|
||||
{
|
||||
if ( refsbits == sbits && (funcid == 'F' && reffundingtxid == txid) || reffundingtxid == fundingtxid )
|
||||
{
|
||||
if ( (nValue= IsRewardsvout(cp,tx,vout,sbits,fundingtxid)) > 0 )
|
||||
{
|
||||
if ( funcid == 'L' )
|
||||
lockedfunds += nValue;
|
||||
else totalinputs += nValue;
|
||||
}
|
||||
else fprintf(stderr,"refsbits.%llx sbits.%llx nValue %.8f\n",(long long)refsbits,(long long)sbits,(double)nValue/COIN);
|
||||
} //else fprintf(stderr,"else case\n");
|
||||
} else fprintf(stderr,"funcid.%d %c skipped %.8f\n",funcid,funcid,(double)tx.vout[vout].nValue/COIN);
|
||||
}
|
||||
}
|
||||
return(totalinputs);
|
||||
}
|
||||
|
||||
bool RewardsPlanExists(struct CCcontract_info *cp,uint64_t refsbits,CPubKey rewardspk,uint64_t &APR,uint64_t &minseconds,uint64_t &maxseconds,uint64_t &mindeposit)
|
||||
{
|
||||
char CCaddr[64]; uint64_t sbits; uint256 txid,hashBlock; CTransaction tx;
|
||||
std::vector<uint256> txids;
|
||||
GetCCaddress(cp,CCaddr,rewardspk);
|
||||
SetCCtxids(txids,CCaddr,true,cp->evalcode,zeroid,'F');
|
||||
for (std::vector<uint256>::const_iterator it=txids.begin(); it!=txids.end(); it++)
|
||||
{
|
||||
//int height = it->first.blockHeight;
|
||||
txid = *it;
|
||||
if ( myGetTransaction(txid,tx,hashBlock) != 0 && tx.vout.size() > 0 && ConstrainVout(tx.vout[0],1,CCaddr,0) != 0 )
|
||||
{
|
||||
//char str[65]; fprintf(stderr,"rewards plan %s\n",uint256_str(str,txid));
|
||||
if ( DecodeRewardsFundingOpRet(tx.vout[tx.vout.size()-1].scriptPubKey,sbits,APR,minseconds,maxseconds,mindeposit) == 'F' )
|
||||
{
|
||||
if ( sbits == refsbits )
|
||||
return(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
return(false);
|
||||
}
|
||||
|
||||
UniValue RewardsInfo(uint256 rewardsid)
|
||||
{
|
||||
UniValue result(UniValue::VOBJ); uint256 hashBlock; CTransaction vintx; uint64_t lockedfunds,APR,minseconds,maxseconds,mindeposit,sbits,funding; CPubKey rewardspk; struct CCcontract_info *cp,C; char str[67],numstr[65];
|
||||
if ( myGetTransaction(rewardsid,vintx,hashBlock) == 0 )
|
||||
{
|
||||
fprintf(stderr,"cant find fundingtxid\n");
|
||||
result.push_back(Pair("result","error"));
|
||||
result.push_back(Pair("error","cant find fundingtxid"));
|
||||
return(result);
|
||||
}
|
||||
if ( vintx.vout.size() > 0 && DecodeRewardsFundingOpRet(vintx.vout[vintx.vout.size()-1].scriptPubKey,sbits,APR,minseconds,maxseconds,mindeposit) == 0 )
|
||||
{
|
||||
fprintf(stderr,"fundingtxid isnt rewards creation txid\n");
|
||||
result.push_back(Pair("result","error"));
|
||||
result.push_back(Pair("error","fundingtxid isnt rewards creation txid"));
|
||||
return(result);
|
||||
}
|
||||
result.push_back(Pair("result","success"));
|
||||
result.push_back(Pair("fundingtxid",uint256_str(str,rewardsid)));
|
||||
unstringbits(str,sbits);
|
||||
result.push_back(Pair("name",str));
|
||||
result.push_back(Pair("sbits",sbits));
|
||||
sprintf(numstr,"%.8f",(double)APR/COIN);
|
||||
result.push_back(Pair("APR",numstr));
|
||||
result.push_back(Pair("minseconds",minseconds));
|
||||
result.push_back(Pair("maxseconds",maxseconds));
|
||||
sprintf(numstr,"%.8f",(double)mindeposit/COIN);
|
||||
result.push_back(Pair("mindeposit",numstr));
|
||||
cp = CCinit(&C,EVAL_REWARDS);
|
||||
rewardspk = GetUnspendable(cp,0);
|
||||
funding = RewardsPlanFunds(lockedfunds,sbits,cp,rewardspk,rewardsid);
|
||||
sprintf(numstr,"%.8f",(double)funding/COIN);
|
||||
result.push_back(Pair("funding",numstr));
|
||||
sprintf(numstr,"%.8f",(double)lockedfunds/COIN);
|
||||
result.push_back(Pair("locked",numstr));
|
||||
return(result);
|
||||
}
|
||||
|
||||
UniValue RewardsList()
|
||||
{
|
||||
UniValue result(UniValue::VARR); std::vector<uint256> txids; struct CCcontract_info *cp,C; uint256 txid,hashBlock; CTransaction vintx; uint64_t sbits,APR,minseconds,maxseconds,mindeposit; char str[65];
|
||||
cp = CCinit(&C,EVAL_REWARDS);
|
||||
SetCCtxids(txids,cp->normaladdr,false,cp->evalcode,zeroid,'F');
|
||||
for (std::vector<uint256>::const_iterator it=txids.begin(); it!=txids.end(); it++)
|
||||
{
|
||||
txid = *it;
|
||||
if ( myGetTransaction(txid,vintx,hashBlock) != 0 )
|
||||
{
|
||||
if ( vintx.vout.size() > 0 && DecodeRewardsFundingOpRet(vintx.vout[vintx.vout.size()-1].scriptPubKey,sbits,APR,minseconds,maxseconds,mindeposit) != 0 )
|
||||
{
|
||||
result.push_back(uint256_str(str,txid));
|
||||
}
|
||||
}
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
std::string RewardsCreateFunding(uint64_t txfee,char *planstr,int64_t funds,int64_t APR,int64_t minseconds,int64_t maxseconds,int64_t mindeposit)
|
||||
{
|
||||
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), hush_nextheight());
|
||||
CPubKey mypk,rewardspk; CScript opret; uint64_t sbits,a,b,c,d; struct CCcontract_info *cp,C;
|
||||
if ( funds < COIN || mindeposit < 0 || minseconds < 0 || maxseconds < 0 )
|
||||
{
|
||||
fprintf(stderr,"negative parameter error\n");
|
||||
return("");
|
||||
}
|
||||
if ( APR > REWARDSCC_MAXAPR )
|
||||
{
|
||||
fprintf(stderr,"25%% APR is maximum\n");
|
||||
return("");
|
||||
}
|
||||
cp = CCinit(&C,EVAL_REWARDS);
|
||||
if ( txfee == 0 )
|
||||
txfee = 10000;
|
||||
mypk = pubkey2pk(Mypubkey());
|
||||
rewardspk = GetUnspendable(cp,0);
|
||||
sbits = stringbits(planstr);
|
||||
if ( RewardsPlanExists(cp,sbits,rewardspk,a,b,c,d) != 0 )
|
||||
{
|
||||
fprintf(stderr,"Rewards plan (%s) already exists\n",planstr);
|
||||
return("");
|
||||
}
|
||||
if ( AddNormalinputs(mtx,mypk,funds+2*txfee,64) > 0 )
|
||||
{
|
||||
mtx.vout.push_back(MakeCC1vout(cp->evalcode,funds,rewardspk));
|
||||
mtx.vout.push_back(CTxOut(txfee,CScript() << ParseHex(HexStr(rewardspk)) << OP_CHECKSIG));
|
||||
return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeRewardsFundingOpRet('F',sbits,APR,minseconds,maxseconds,mindeposit)));
|
||||
}
|
||||
fprintf(stderr,"cant find enough inputs\n");
|
||||
return("");
|
||||
}
|
||||
|
||||
std::string RewardsAddfunding(uint64_t txfee,char *planstr,uint256 fundingtxid,int64_t amount)
|
||||
{
|
||||
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), hush_nextheight());
|
||||
CPubKey mypk,rewardspk; CScript opret; uint64_t sbits,a,b,c,d; struct CCcontract_info *cp,C;
|
||||
if ( amount < 0 )
|
||||
{
|
||||
fprintf(stderr,"negative parameter error\n");
|
||||
return("");
|
||||
}
|
||||
cp = CCinit(&C,EVAL_REWARDS);
|
||||
if ( txfee == 0 )
|
||||
txfee = 10000;
|
||||
mypk = pubkey2pk(Mypubkey());
|
||||
rewardspk = GetUnspendable(cp,0);
|
||||
sbits = stringbits(planstr);
|
||||
if ( RewardsPlanExists(cp,sbits,rewardspk,a,b,c,d) == 0 )
|
||||
{
|
||||
CCerror = strprintf("Rewards plan %s doesnt exist\n",planstr);
|
||||
fprintf(stderr,"%s\n",CCerror.c_str());
|
||||
return("");
|
||||
}
|
||||
sbits = stringbits(planstr);
|
||||
if ( AddNormalinputs(mtx,mypk,amount+txfee,64) > 0 )
|
||||
{
|
||||
mtx.vout.push_back(MakeCC1vout(cp->evalcode,amount,rewardspk));
|
||||
return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeRewardsOpRet('A',sbits,fundingtxid)));
|
||||
} else {
|
||||
CCerror = "cant find enough inputs";
|
||||
fprintf(stderr,"%s\n", CCerror.c_str());
|
||||
}
|
||||
CCerror = "cant find fundingtxid";
|
||||
fprintf(stderr,"%s\n", CCerror.c_str());
|
||||
return("");
|
||||
}
|
||||
|
||||
std::string RewardsLock(uint64_t txfee,char *planstr,uint256 fundingtxid,int64_t deposit)
|
||||
{
|
||||
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), hush_nextheight());
|
||||
CPubKey mypk,rewardspk; CScript opret; uint64_t lockedfunds,sbits,funding,APR,minseconds,maxseconds,mindeposit; struct CCcontract_info *cp,C;
|
||||
if ( deposit < txfee )
|
||||
{
|
||||
CCerror = "deposit amount less than txfee";
|
||||
fprintf(stderr,"%s\n",CCerror.c_str());
|
||||
return("");
|
||||
}
|
||||
cp = CCinit(&C,EVAL_REWARDS);
|
||||
if ( txfee == 0 )
|
||||
txfee = 10000;
|
||||
mypk = pubkey2pk(Mypubkey());
|
||||
rewardspk = GetUnspendable(cp,0);
|
||||
sbits = stringbits(planstr);
|
||||
if ( RewardsPlanExists(cp,sbits,rewardspk,APR,minseconds,maxseconds,mindeposit) == 0 )
|
||||
{
|
||||
CCerror = strprintf("Rewards plan %s doesnt exist\n",planstr);
|
||||
fprintf(stderr,"%s\n",CCerror.c_str());
|
||||
return("");
|
||||
}
|
||||
if ( deposit < mindeposit )
|
||||
{
|
||||
CCerror = strprintf("Rewards plan %s deposit %.8f < mindeposit %.8f\n",planstr,(double)deposit/COIN,(double)mindeposit/COIN);
|
||||
fprintf(stderr,"%s\n",CCerror.c_str());
|
||||
return("");
|
||||
}
|
||||
if ( (funding= RewardsPlanFunds(lockedfunds,sbits,cp,rewardspk,fundingtxid)) >= deposit ) // arbitrary cmpval
|
||||
{
|
||||
if ( AddNormalinputs(mtx,mypk,deposit+2*txfee,64) > 0 )
|
||||
{
|
||||
mtx.vout.push_back(MakeCC1vout(cp->evalcode,deposit,rewardspk));
|
||||
mtx.vout.push_back(CTxOut(txfee,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG));
|
||||
return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeRewardsOpRet('L',sbits,fundingtxid)));
|
||||
} else {
|
||||
CCerror = strprintf("cant find enough inputs %.8f not enough for %.8f, make sure you imported privkey for the -pubkey address\n",(double)funding/COIN,(double)deposit/COIN);
|
||||
fprintf(stderr,"%s\n",CCerror.c_str());
|
||||
}
|
||||
}
|
||||
fprintf(stderr,"cant find rewards inputs funding %.8f locked %.8f vs deposit %.8f\n",(double)funding/COIN,(double)lockedfunds/COIN,(double)deposit/COIN);
|
||||
return("");
|
||||
}
|
||||
|
||||
std::string RewardsUnlock(uint64_t txfee,char *planstr,uint256 fundingtxid,uint256 locktxid)
|
||||
{
|
||||
CMutableTransaction firstmtx,mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), hush_nextheight());
|
||||
CTransaction tx; char coinaddr[64]; CPubKey mypk,rewardspk; CScript scriptPubKey,ignore; uint256 hashBlock; uint64_t sbits,APR,minseconds,maxseconds,mindeposit; int64_t funding,reward=0,amount=0,inputs,CCchange=0; struct CCcontract_info *cp,C;
|
||||
cp = CCinit(&C,EVAL_REWARDS);
|
||||
if ( txfee == 0 )
|
||||
txfee = 10000;
|
||||
rewardspk = GetUnspendable(cp,0);
|
||||
mypk = pubkey2pk(Mypubkey());
|
||||
sbits = stringbits(planstr);
|
||||
if ( locktxid == fundingtxid )
|
||||
{
|
||||
fprintf(stderr,"Rewards plan cant unlock fundingtxid\n");
|
||||
CCerror = "Rewards plan cant unlock fundingtxid";
|
||||
return("");
|
||||
}
|
||||
if ( RewardsPlanExists(cp,sbits,rewardspk,APR,minseconds,maxseconds,mindeposit) == 0 )
|
||||
{
|
||||
fprintf(stderr,"Rewards plan %s doesnt exist\n",planstr);
|
||||
CCerror = "Rewards plan does not exist";
|
||||
return("");
|
||||
}
|
||||
fprintf(stderr,"APR %.8f minseconds.%llu maxseconds.%llu mindeposit %.8f\n",(double)APR/COIN,(long long)minseconds,(long long)maxseconds,(double)mindeposit/COIN);
|
||||
if ( locktxid == zeroid )
|
||||
amount = AddRewardsInputs(scriptPubKey,maxseconds,cp,mtx,rewardspk,(1LL << 30),1,sbits,fundingtxid);
|
||||
else
|
||||
{
|
||||
GetCCaddress(cp,coinaddr,rewardspk);
|
||||
if ( (amount= CCutxovalue(coinaddr,locktxid,0,1)) == 0 )
|
||||
{
|
||||
fprintf(stderr,"%s locktxid/v0 is spent\n",coinaddr);
|
||||
CCerror = "locktxid/v0 is spent";
|
||||
return("");
|
||||
}
|
||||
if ( myGetTransaction(locktxid,tx,hashBlock) != 0 && tx.vout.size() > 0 && tx.vout[1].scriptPubKey.IsPayToCryptoCondition() == 0 )
|
||||
{
|
||||
scriptPubKey = tx.vout[1].scriptPubKey;
|
||||
mtx.vin.push_back(CTxIn(locktxid,0,CScript()));
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr,"%s no normal vout.1 in locktxid\n",coinaddr);
|
||||
CCerror = "no normal vout.1 in locktxid";
|
||||
return("");
|
||||
}
|
||||
}
|
||||
if ( amount > txfee )
|
||||
{
|
||||
reward = RewardsCalc((int64_t)amount,mtx.vin[0].prevout.hash,(int64_t)APR,(int64_t)minseconds,(int64_t)maxseconds,hush_chainactive_timestamp());
|
||||
if ( scriptPubKey.size() > 0 )
|
||||
{
|
||||
if ( reward > txfee )
|
||||
{
|
||||
firstmtx = mtx;
|
||||
if ( (inputs= AddRewardsInputs(ignore,0,cp,mtx,rewardspk,reward+txfee,30,sbits,fundingtxid)) >= reward+txfee )
|
||||
{
|
||||
if ( inputs >= (reward + 2*txfee) )
|
||||
CCchange = (inputs - (reward + txfee));
|
||||
fprintf(stderr,"inputs %.8f CCchange %.8f amount %.8f reward %.8f\n",(double)inputs/COIN,(double)CCchange/COIN,(double)amount/COIN,(double)reward/COIN);
|
||||
mtx.vout.push_back(MakeCC1vout(cp->evalcode,CCchange,rewardspk));
|
||||
mtx.vout.push_back(CTxOut(amount+reward,scriptPubKey));
|
||||
return(FinalizeCCTx(-1LL,cp,mtx,mypk,txfee,EncodeRewardsOpRet('U',sbits,fundingtxid)));
|
||||
}
|
||||
else
|
||||
{
|
||||
firstmtx.vout.push_back(CTxOut(amount-txfee*2,scriptPubKey));
|
||||
fprintf(stderr,"not enough rewards funds to payout %.8f, recover mode tx\n",(double)(reward+txfee)/COIN);
|
||||
return(FinalizeCCTx(-1LL,cp,firstmtx,mypk,txfee,EncodeRewardsOpRet('U',sbits,fundingtxid)));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CCerror = strprintf("reward %.8f is <= the transaction fee", reward);
|
||||
fprintf(stderr,"%s\n", CCerror.c_str());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CCerror = "invalid scriptPubKey";
|
||||
fprintf(stderr,"%s\n", CCerror.c_str());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CCerror = "amount must be more than txfee";
|
||||
fprintf(stderr,"%s\n", CCerror.c_str());
|
||||
}
|
||||
fprintf(stderr,"amount %.8f -> reward %.8f\n",(double)amount/COIN,(double)reward/COIN);
|
||||
return("");
|
||||
}
|
||||
@@ -1,93 +0,0 @@
|
||||
Rogue: Exploring the Dungeons of Doom
|
||||
Copyright (C) 1980-1983, 1985, 1999 Michael Toy, Ken Arnold and Glenn Wichman
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. Neither the name(s) of the author(s) nor the names of other contributors
|
||||
may be used to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AND CONTRIBUTORS ``AS IS'' AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGE.
|
||||
|
||||
===========================================================================
|
||||
|
||||
Portions of this software (state.c, mdport.c) are based on the work
|
||||
of Nicholas J. Kisseberth. Used under license:
|
||||
|
||||
Copyright (C) 1999, 2000, 2005 Nicholas J. Kisseberth
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. Neither the name(s) of the author(s) nor the names of other contributors
|
||||
may be used to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AND CONTRIBUTORS ``AS IS'' AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGE.
|
||||
|
||||
===========================================================================
|
||||
|
||||
Portions of this software (xcrypt.c) are based on the work
|
||||
of David Burren. Used under license:
|
||||
|
||||
FreeSec: libcrypt
|
||||
|
||||
Copyright (C) 1994 David Burren
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. Neither the name(s) of the author(s) nor the names of other contributors
|
||||
may be used to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AND CONTRIBUTORS ``AS IS'' AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTORS BE LIABLE
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGE.
|
||||
@@ -1,225 +0,0 @@
|
||||
# Copyright (c) 2016-2023 The Hush developers
|
||||
# Distributed under the GPLv3 software license, see the accompanying
|
||||
# file COPYING or https://www.gnu.org/licenses/gpl-3.0.en.html
|
||||
###############################################################################
|
||||
#
|
||||
# Makefile for rogue
|
||||
#
|
||||
# Rogue: Exploring the Dungeons of Doom
|
||||
# Copyright (C) 1980-1983, 1985, 1999 Michael Toy, Ken Arnold and Glenn Wichman
|
||||
# All rights reserved.
|
||||
#
|
||||
# See the file LICENSE.TXT for full copyright and licensing information.
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
###############################################################################
|
||||
# Site configuration occurs beneath this comment
|
||||
# Typically ./configure (autoconf tools) configures this section
|
||||
# This section could be manually configured if autoconf/configure fails
|
||||
###############################################################################
|
||||
|
||||
DISTNAME=@PACKAGE_TARNAME@@PACKAGE_VERSION@
|
||||
PACKAGE_TARNAME = @PACKAGE_TARNAME@-@PACKAGE_VERSION@
|
||||
PROGRAM=@PROGRAM@
|
||||
|
||||
O=o
|
||||
|
||||
#CC=gcc
|
||||
CC = @CC@
|
||||
|
||||
#CFLAGS=-O2
|
||||
CFLAGS= @CFLAGS@ -fPIC
|
||||
|
||||
LIBS=-lcurses -lcurl
|
||||
#LIBS = @LIBS@
|
||||
|
||||
#RM=rm -f
|
||||
RM = rm -f
|
||||
|
||||
#GROFF=groff
|
||||
GROFF = @GROFF@
|
||||
|
||||
#NROFF=nroff
|
||||
NROFF = @NROFF@
|
||||
|
||||
#TBL=tbl
|
||||
TBL = @TBL@
|
||||
|
||||
#COLCRT=colcrt
|
||||
COLCRT = @COLCRT@
|
||||
|
||||
#SED=sed
|
||||
SED = @SED@
|
||||
|
||||
#SCOREFILE=rogue54.scr
|
||||
SCOREFILE = @SCOREFILE@
|
||||
|
||||
#LOCKFILE=rogue54.lck
|
||||
LOCKFILE = @LOCKFILE@
|
||||
|
||||
#GROUPOWNER=games
|
||||
GROUPOWNER = @GROUPOWNER@
|
||||
|
||||
#CPPFLAGS=-DHAVE_CONFIG_H
|
||||
CPPFLAGS =@DEFS@ @CPPFLAGS@
|
||||
|
||||
#DISTFILE = $(PROGRAM)
|
||||
DISTFILE = $(DISTNAME)-@TARGET@
|
||||
|
||||
INSTALL=./install-sh
|
||||
|
||||
#INSTGROUP=-g games
|
||||
INSTGROUP=
|
||||
#INSTOWNER=-u root
|
||||
INSTOWNER=
|
||||
|
||||
CHGRP=chgrp
|
||||
|
||||
MKDIR=mkdir
|
||||
|
||||
TOUCH=touch
|
||||
|
||||
RMDIR=rmdir
|
||||
|
||||
CHMOD=chmod
|
||||
|
||||
DESTDIR=
|
||||
|
||||
prefix=@prefix@
|
||||
exec_prefix=@exec_prefix@
|
||||
datarootdir=@datarootdir@
|
||||
datadir=@datadir@
|
||||
bindir=@bindir@
|
||||
mandir=@mandir@
|
||||
docdir=@docdir@
|
||||
man6dir = $(mandir)/man6
|
||||
|
||||
###############################################################################
|
||||
# Site configuration occurs above this comment
|
||||
# It should not be necessary to change anything below this comment
|
||||
###############################################################################
|
||||
|
||||
HDRS = rogue.h extern.h score.h
|
||||
OBJS1 = vers.$(O) extern.$(O) armor.$(O) chase.$(O) command.$(O) \
|
||||
daemon.$(O) daemons.$(O) fight.$(O) init.$(O) io.$(O) list.$(O) \
|
||||
mach_dep.$(O) rogue.$(O) mdport.$(O) misc.$(O) monsters.$(O) \
|
||||
move.$(O) new_level.$(O)
|
||||
OBJS2 = options.$(O) pack.$(O) passages.$(O) potions.$(O) rings.$(O) \
|
||||
rip.$(O) rooms.$(O) save.$(O) scrolls.$(O) state.$(O) sticks.$(O) \
|
||||
things.$(O) weapons.$(O) wizard.$(O) xcrypt.$(O)
|
||||
OBJS = main.$(O) $(OBJS1) $(OBJS2)
|
||||
CFILES = vers.c extern.c armor.c chase.c command.c daemon.c \
|
||||
daemons.c fight.c init.c io.c list.c mach_dep.c \
|
||||
main.c mdport.c misc.c monsters.c move.c new_level.c \
|
||||
options.c pack.c passages.c potions.c rings.c rip.c \
|
||||
rooms.c save.c scrolls.c state.c sticks.c things.c \
|
||||
weapons.c wizard.c xcrypt.c
|
||||
MISC_C = findpw.c scedit.c scmisc.c
|
||||
DOCSRC = rogue.me.in rogue.6.in rogue.doc.in rogue.html.in rogue.cat.in
|
||||
DOCS = $(PROGRAM).doc $(PROGRAM).html $(PROGRAM).cat $(PROGRAM).me \
|
||||
$(PROGRAM).6
|
||||
AFILES = configure Makefile.in configure.ac config.h.in config.sub config.guess \
|
||||
install-sh rogue.6.in rogue.me.in rogue.html.in rogue.doc.in rogue.cat.in
|
||||
MISC = Makefile.std LICENSE.TXT rogue54.sln rogue54.vcproj rogue.spec \
|
||||
rogue.png rogue.desktop
|
||||
|
||||
.SUFFIXES: .obj
|
||||
|
||||
.c.obj:
|
||||
$(CC) $(CFLAGS) $(CPPFLAGS) /c $*.c
|
||||
|
||||
.c.o:
|
||||
$(CC) $(CFLAGS) $(CPPFLAGS) -c $*.c
|
||||
|
||||
#$(RM) rogue.so ; $(CC) -shared -o rogue.so cursesd.c $(OBJS1) $(OBJS2); $(CC) $(CFLAGS) $(LDFLAGS) $(OBJS) $(LIBS) -o $@
|
||||
|
||||
$(PROGRAM): $(HDRS) $(OBJS)
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) $(OBJS) $(LIBS) -o $@
|
||||
|
||||
clean:
|
||||
$(RM) $(OBJS1); $(RM) main.$(O) ; $(RM) rogue.so
|
||||
$(RM) $(OBJS2)
|
||||
$(RM) core a.exe a.out a.exe.stackdump $(PROGRAM) $(PROGRAM).exe
|
||||
$(RM) $(PROGRAM).tar $(PROGRAM).tar.gz $(PROGRAM).zip
|
||||
$(RM) $(DISTNAME)/*
|
||||
-rmdir $(DISTNAME)
|
||||
|
||||
maintainer-clean:
|
||||
$(RM) config.h
|
||||
$(RM) Makefile
|
||||
$(RM) config.status
|
||||
$(RM) -r autom4te.cache
|
||||
$(RM) config.log
|
||||
$(RM) $(PROGRAM).scr $(PROGRAM).lck
|
||||
|
||||
stddocs:
|
||||
sed -e 's/@PROGRAM@/rogue/' -e 's/@SCOREFILE@/rogue.scr/' rogue.6.in > rogue.6
|
||||
sed -e 's/@PROGRAM@/rogue/' -e 's/@SCOREFILE@/rogue.scr/' rogue.me.in > rogue.me
|
||||
sed -e 's/@PROGRAM@/rogue/' -e 's/@SCOREFILE@/rogue.scr/' rogue.html.in > rogue,html
|
||||
sed -e 's/@PROGRAM@/rogue/' -e 's/@SCOREFILE@/rogue.scr/' rogue.doc.in > rogue.doc
|
||||
sed -e 's/@PROGRAM@/rogue/' -e 's/@SCOREFILE@/rogue.scr/' rogue.cat.in > rogue.cat
|
||||
|
||||
dist.src:
|
||||
$(MAKE) $(MAKEFILE) clean
|
||||
mkdir $(DISTNAME)
|
||||
cp $(CFILES) $(HDRS) $(MISC) $(AFILES) $(DISTNAME)
|
||||
tar cf $(DISTNAME)-src.tar $(DISTNAME)
|
||||
gzip -f $(DISTNAME)-src.tar
|
||||
rm -fr $(DISTNAME)
|
||||
|
||||
findpw: findpw.c xcrypt.o mdport.o xcrypt.o
|
||||
$(CC) -s -o findpw findpw.c xcrypt.o mdport.o -lcurses
|
||||
|
||||
scedit: scedit.o scmisc.o vers.o mdport.o xcrypt.o
|
||||
$(CC) -s -o scedit vers.o scedit.o scmisc.o mdport.o xcrypt.o -lcurses
|
||||
|
||||
scmisc.o scedit.o:
|
||||
$(CC) -O -c $(SF) $*.c
|
||||
|
||||
$(PROGRAM).doc: rogue.me
|
||||
if test "x$(GROFF)" != "x" -a "x$(SED)" != "x" ; then \
|
||||
$(GROFF) -P-c -t -me -Tascii rogue.me | $(SED) -e 's/.\x08//g' > $(PROGRAM).doc ;\
|
||||
elif test "x$(NROFF)" != "x" -a "x$(TBL)" != "x" -a "x$(COLCRT)" != "x" ; then \
|
||||
tbl rogue.me | $(NROFF) -me | colcrt - > $(PROGRAM).doc ;\
|
||||
fi
|
||||
|
||||
$(PROGRAM).cat: rogue.6
|
||||
if test "x$(GROFF)" != "x" -a "x$(SED)" != "x" ; then \
|
||||
$(GROFF) -Tascii -man rogue.6 | $(SED) -e 's/.\x08//g' > $(PROGRAM).cat ;\
|
||||
elif test "x$(NROFF)" != "x" -a "x$(TBL)" != "x" -a "x$(COLCRT)" != "x" ; then \
|
||||
$(NROFF) -man rogue.6 | $(COLCRT) - > $(PROGRAM).cat ;\
|
||||
fi
|
||||
|
||||
dist: clean $(PROGRAM)
|
||||
tar cf $(DISTFILE).tar $(PROGRAM) LICENSE.TXT $(DOCS)
|
||||
gzip -f $(DISTFILE).tar
|
||||
|
||||
install: $(PROGRAM)
|
||||
-$(TOUCH) test
|
||||
-if test ! -f $(DESTDIR)$(SCOREFILE) ; then $(INSTALL) -m 0664 test $(DESTDIR)$(SCOREFILE) ; fi
|
||||
-$(INSTALL) -m 0755 $(PROGRAM) $(DESTDIR)$(bindir)/$(PROGRAM)
|
||||
-if test "x$(GROUPOWNER)" != "x" ; then \
|
||||
$(CHGRP) $(GROUPOWNER) $(DESTDIR)$(SCOREFILE) ; \
|
||||
$(CHGRP) $(GROUPOWNER) $(DESTDIR)$(bindir)/$(PROGRAM) ; \
|
||||
$(CHMOD) 02755 $(DESTDIR)$(bindir)/$(PROGRAM) ; \
|
||||
$(CHMOD) 0464 $(DESTDIR)$(SCOREFILE) ; \
|
||||
fi
|
||||
-if test -d $(man6dir) ; then $(INSTALL) -m 0644 rogue.6 $(DESTDIR)$(man6dir)/$(PROGRAM).6 ; fi
|
||||
-if test ! -d $(man6dir) ; then $(INSTALL) -m 0644 rogue.6 $(DESTDIR)$(mandir)/$(PROGRAM).6 ; fi
|
||||
-$(INSTALL) -m 0644 rogue.doc $(DESTDIR)$(docdir)/$(PROGRAM).doc
|
||||
-$(INSTALL) -m 0644 rogue.html $(DESTDIR)$(docdir)/$(PROGRAM).html
|
||||
-$(INSTALL) -m 0644 rogue.cat $(DESTDIR)$(docdir)/$(PROGRAM).cat
|
||||
-$(INSTALL) -m 0644 LICENSE.TXT $(DESTDIR)$(docdir)/LICENSE.TXT
|
||||
-$(INSTALL) -m 0644 rogue.me $(DESTDIR)$(docdir)/$(PROGRAM).me
|
||||
-if test ! -f $(DESTDIR)$(LOCKFILE) ; then $(INSTALL) -m 0666 test $(DESTDIR)$(LOCKFILE) ; $(RM) $(DESTDIR)$(LOCKFILE) ; fi
|
||||
-$(RM) test
|
||||
|
||||
uninstall:
|
||||
-$(RM) $(DESTDIR)$(bindir)/$(PROGRAM)
|
||||
-$(RM) $(DESTDIR)$(man6dir)/$(PROGRAM).6
|
||||
-$(RM) $(DESTDIR)$(docdir)$(PROGRAM)/$(PROGRAM).doc
|
||||
-$(RM) $(DESTDIR)$(LOCKFILE)
|
||||
-$(RMDIR) $(DESTDIR)$(docdir)$(PROGRAM)
|
||||
|
||||
reinstall: uninstall install
|
||||
@@ -1,158 +0,0 @@
|
||||
#
|
||||
# Makefile for rogue
|
||||
# @(#)Makefile 4.21 (Berkeley) 02/04/99
|
||||
#
|
||||
# Rogue: Exploring the Dungeons of Doom
|
||||
# Copyright (C) 1980-1983, 1985, 1999 Michael Toy, Ken Arnold and Glenn Wichman
|
||||
# All rights reserved.
|
||||
#
|
||||
# See the file LICENSE.TXT for full copyright and licensing information.
|
||||
#
|
||||
|
||||
DISTNAME = rogue5.4.4
|
||||
PROGRAM = rogue54
|
||||
O = o
|
||||
HDRS = rogue.h extern.h score.h
|
||||
OBJS1 = vers.$(O) extern.$(O) armor.$(O) chase.$(O) command.$(O) \
|
||||
daemon.$(O) daemons.$(O) fight.$(O) init.$(O) io.$(O) list.$(O) \
|
||||
mach_dep.$(O) main.$(O) mdport.$(O) misc.$(O) monsters.$(O) \
|
||||
move.$(O) new_level.$(O)
|
||||
OBJS2 = options.$(O) pack.$(O) passages.$(O) potions.$(O) rings.$(O) \
|
||||
rip.$(O) rooms.$(O) save.$(O) scrolls.$(O) state.$(O) sticks.$(O) \
|
||||
things.$(O) weapons.$(O) wizard.$(O) xcrypt.$(O)
|
||||
OBJS = $(OBJS1) $(OBJS2)
|
||||
CFILES = vers.c extern.c armor.c chase.c command.c daemon.c \
|
||||
daemons.c fight.c init.c io.c list.c mach_dep.c \
|
||||
main.c mdport.c misc.c monsters.c move.c new_level.c \
|
||||
options.c pack.c passages.c potions.c rings.c rip.c \
|
||||
rooms.c save.c scrolls.c state.c sticks.c things.c \
|
||||
weapons.c wizard.c xcrypt.c
|
||||
MISC_C = findpw.c scedit.c scmisc.c
|
||||
DOCSRC = rogue.me.in rogue.6.in rogue.doc.in rogue.html.in rogue.cat.in
|
||||
DOCS = $(PROGRAM).doc $(PROGRAM).html $(PROGRAM).cat $(PROGRAM).me \
|
||||
$(PROGRAM).6
|
||||
AFILES = configure Makefile.in configure.ac config.h.in config.sub config.guess \
|
||||
install-sh rogue.6.in rogue.me.in rogue.html.in rogue.doc.in rogue.cat.in
|
||||
MISC = Makefile.std LICENSE.TXT rogue54.sln rogue54.vcproj rogue.spec \
|
||||
rogue.png rogue.desktop
|
||||
CC = gcc
|
||||
FEATURES = -DALLSCORES -DSCOREFILE=\"$(SCOREFILE)\" -DLOCKFILE=\"$(LOCKFILE)\"
|
||||
CPPFLAGS =
|
||||
CFLAGS = -O3
|
||||
LDFLAGS =
|
||||
LIBS = -lcurses
|
||||
RM = rm -f
|
||||
MAKEFILE = -f Makefile.std
|
||||
SCOREFILE= $(PROGRAM).scr
|
||||
LOCKFILE = $(PROGRAM).lck
|
||||
OUTFLAG = -o
|
||||
EXE =
|
||||
|
||||
.SUFFIXES: .obj
|
||||
|
||||
.c.obj:
|
||||
$(CC) $(CFLAGS) $(CPPFLAGS) $(FEATURES) /c $*.c
|
||||
|
||||
.c.o:
|
||||
$(CC) $(CFLAGS) $(CPPFLAGS) $(FEATURES) -c $*.c
|
||||
|
||||
$(PROGRAM): $(HDRS) $(OBJS) fixdocs
|
||||
$(CC) $(LDFLAGS) $(OBJS) $(LIBS) $(OUTFLAG)$@$(EXE)
|
||||
|
||||
clean:
|
||||
$(RM) $(OBJS1)
|
||||
$(RM) $(OBJS2)
|
||||
$(RM) core a.exe a.out a.exe.stackdump $(PROGRAM) $(PROGRAM).exe $(PROGRAM).lck
|
||||
$(RM) $(PROGRAM).tar $(PROGRAM).tar.gz $(PROGRAM).zip
|
||||
$(RM) $(DISTNAME)/*
|
||||
|
||||
dist.src:
|
||||
$(MAKE) $(MAKEFILE) clean
|
||||
mkdir $(DISTNAME)
|
||||
cp $(CFILES) $(HDRS) $(MISC) $(AFILES) $(DISTNAME)
|
||||
tar cf $(DISTNAME)-src.tar $(DISTNAME)
|
||||
gzip -f $(DISTNAME)-src.tar
|
||||
rm -fr $(DISTNAME)
|
||||
|
||||
findpw: findpw.c xcrypt.o mdport.o xcrypt.o
|
||||
$(CC) -s -o findpw findpw.c xcrypt.o mdport.o -lcurses
|
||||
|
||||
scedit: scedit.o scmisc.o vers.o mdport.o xcrypt.o
|
||||
$(CC) -s -o scedit vers.o scedit.o scmisc.o mdport.o xcrypt.o -lcurses
|
||||
|
||||
scmisc.o scedit.o:
|
||||
$(CC) -O -c $(SF) $*.c
|
||||
|
||||
doc.nroff:
|
||||
tbl rogue.me | nroff -me | colcrt - > rogue.doc
|
||||
nroff -man rogue.6 | colcrt - > rogue.cat
|
||||
|
||||
doc.groff:
|
||||
groff -P-c -t -me -Tascii rogue.me | sed -e 's/.\x08//g' > rogue.doc
|
||||
groff -man rogue.6 | sed -e 's/.\x08//g' > rogue.cat
|
||||
|
||||
fixdocs:
|
||||
sed -e 's/@PROGRAM@/$(PROGRAM)/' -e 's/@SCOREFILE@/$(SCOREFILE)/' rogue.6.in > $(PROGRAM).6
|
||||
sed -e 's/@PROGRAM@/$(PROGRAM)/' -e 's/@SCOREFILE@/$(SCOREFILE)/' rogue.me.in > $(PROGRAM).me
|
||||
sed -e 's/@PROGRAM@/$(PROGRAM)/' -e 's/@SCOREFILE@/$(SCOREFILE)/' rogue.html.in > $(PROGRAM).html
|
||||
sed -e 's/@PROGRAM@/$(PROGRAM)/' -e 's/@SCOREFILE@/$(SCOREFILE)/' rogue.doc.in > $(PROGRAM).doc
|
||||
sed -e 's/@PROGRAM@/$(PROGRAM)/' -e 's/@SCOREFILE@/$(SCOREFILE)/' rogue.cat.in > $(PROGRAM).cat
|
||||
|
||||
dist.irix:
|
||||
$(MAKE) $(MAKEFILE) clean
|
||||
$(MAKE) $(MAKEFILE) CC=cc $(PROGRAM)
|
||||
tar cf $(DISTNAME)-irix.tar $(PROGRAM) LICENSE.TXT $(DOCS)
|
||||
gzip -f $(DISTNAME)-irix.tar
|
||||
|
||||
dist.aix:
|
||||
$(MAKE) $(MAKEFILE) clean
|
||||
$(MAKE) $(MAKEFILE) CC=xlc CFLAGS="-qmaxmem=16768 -O3 -qstrict" $(PROGRAM)
|
||||
tar cf $(DISTNAME)-aix.tar $(PROGRAM) LICENSE.TXT $(DOCS)
|
||||
gzip -f $(DISTNAME)-aix.tar
|
||||
|
||||
dist.linux:
|
||||
$(MAKE) $(MAKEFILE) clean
|
||||
$(MAKE) $(MAKEFILE) $(PROGRAM)
|
||||
tar cf $(DISTNAME)-linux.tar $(PROGRAM) LICENSE.TXT $(DOCS)
|
||||
gzip -f $(DISTNAME)-linux.tar
|
||||
|
||||
dist.interix:
|
||||
@$(MAKE) $(MAKEFILE) clean
|
||||
@$(MAKE) $(MAKEFILE) CFLAGS="-ansi" $(PROGRAM)
|
||||
tar cf $(DISTNAME)-interix.tar $(PROGRAM) LICENSE.TXT $(DOCS)
|
||||
gzip -f $(DISTNAME)-interix.tar
|
||||
|
||||
dist.cygwin:
|
||||
@$(MAKE) $(MAKEFILE) --no-print-directory clean
|
||||
@$(MAKE) $(MAKEFILE) CPPFLAGS="-I/usr/include/ncurses" --no-print-directory $(PROGRAM)
|
||||
tar cf $(DISTNAME)-cygwin.tar $(PROGRAM).exe LICENSE.TXT $(DOCS)
|
||||
gzip -f $(DISTNAME)-cygwin.tar
|
||||
|
||||
#
|
||||
# Use MINGW32-MAKE to build this target
|
||||
#
|
||||
dist.mingw32:
|
||||
@$(MAKE) $(MAKEFILE) --no-print-directory RM="cmd /c del" clean
|
||||
@$(MAKE) $(MAKEFILE) --no-print-directory CPPFLAGS="-I../pdcurses" LIBS="../pdcurses/pdcurses.a" $(PROGRAM)
|
||||
cmd /c del $(DISTNAME)-mingw32.zip
|
||||
zip $(DISTNAME)-mingw32.zip $(PROGRAM).exe LICENSE.TXT $(DOCS)
|
||||
|
||||
dist.djgpp:
|
||||
@$(MAKE) $(MAKEFILE) --no-print-directory clean
|
||||
@$(MAKE) $(MAKEFILE) --no-print-directory LDFLAGS="-L$(DJDIR)/LIB" \
|
||||
LIBS="-lpdcurses" $(PROGRAM)
|
||||
rm -f $(DISTNAME)-djgpp.zip
|
||||
zip $(DISTNAME)-djgpp.zip $(PROGRAM) LICENSE.TXT $(DOCS)
|
||||
|
||||
#
|
||||
# Use NMAKE to build this targer
|
||||
#
|
||||
|
||||
dist.win32:
|
||||
@$(MAKE) $(MAKEFILE) /NOLOGO O="obj" RM="-del" clean
|
||||
@$(MAKE) $(MAKEFILE) /NOLOGO O="obj" CC="CL" \
|
||||
LIBS="..\pdcurses\pdcurses.lib shell32.lib user32.lib Advapi32.lib" \
|
||||
EXE=".exe" OUTFLAG="/Fe" CPPFLAGS="-I..\pdcurses" \
|
||||
CFLAGS="-nologo -Ox -wd4033 -wd4716" $(PROGRAM)
|
||||
-del $(DISTNAME)-win32.zip
|
||||
zip $(DISTNAME)-win32.zip $(PROGRAM).exe LICENSE.TXT $(DOCS)
|
||||
@@ -1,222 +0,0 @@
|
||||
###############################################################################
|
||||
#
|
||||
# Makefile for rogue
|
||||
#
|
||||
# Rogue: Exploring the Dungeons of Doom
|
||||
# Copyright (C) 1980-1983, 1985, 1999 Michael Toy, Ken Arnold and Glenn Wichman
|
||||
# All rights reserved.
|
||||
#
|
||||
# See the file LICENSE.TXT for full copyright and licensing information.
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
###############################################################################
|
||||
# Site configuration occurs beneath this comment
|
||||
# Typically ./configure (autoconf tools) configures this section
|
||||
# This section could be manually configured if autoconf/configure fails
|
||||
###############################################################################
|
||||
|
||||
DISTNAME=rogue5.4.4
|
||||
PACKAGE_TARNAME = rogue-5.4.4
|
||||
PROGRAM=rogue
|
||||
|
||||
O=o
|
||||
|
||||
#CC=gcc
|
||||
CC = x86_64-w64-mingw32-gcc
|
||||
|
||||
#CFLAGS=-O2
|
||||
CFLAGS= -g -O2 -I./x86_64-w64-mingw32/include -I./x86_64-w64-mingw32/include/ncursesw
|
||||
|
||||
#LIBS=-lcurses
|
||||
LIBS = -L./x86_64-w64-mingw32/lib -lncursesw -lcurl
|
||||
|
||||
#RM=rm -f
|
||||
RM = rm -f
|
||||
|
||||
#GROFF=groff
|
||||
GROFF = groff
|
||||
|
||||
#NROFF=nroff
|
||||
NROFF = nroff
|
||||
|
||||
#TBL=tbl
|
||||
TBL = tbl
|
||||
|
||||
#COLCRT=colcrt
|
||||
COLCRT = colcrt
|
||||
|
||||
#SED=sed
|
||||
SED = sed
|
||||
|
||||
#SCOREFILE=rogue54.scr
|
||||
SCOREFILE = rogue.scr
|
||||
|
||||
#LOCKFILE=rogue54.lck
|
||||
LOCKFILE = rogue.lck
|
||||
|
||||
#GROUPOWNER=games
|
||||
GROUPOWNER =
|
||||
|
||||
#CPPFLAGS=-DHAVE_CONFIG_H
|
||||
CPPFLAGS =-DHAVE_CONFIG_H
|
||||
|
||||
#DISTFILE = $(PROGRAM)
|
||||
DISTFILE = $(DISTNAME)-x86_64-w64-mingw32
|
||||
|
||||
INSTALL=./install-sh
|
||||
|
||||
#INSTGROUP=-g games
|
||||
INSTGROUP=
|
||||
#INSTOWNER=-u root
|
||||
INSTOWNER=
|
||||
|
||||
CHGRP=chgrp
|
||||
|
||||
MKDIR=mkdir
|
||||
|
||||
TOUCH=touch
|
||||
|
||||
RMDIR=rmdir
|
||||
|
||||
CHMOD=chmod
|
||||
|
||||
DESTDIR=
|
||||
|
||||
prefix=/usr/local
|
||||
exec_prefix=${prefix}
|
||||
datarootdir=${prefix}/share
|
||||
datadir=${datarootdir}
|
||||
bindir=${exec_prefix}/bin
|
||||
mandir=${datarootdir}/man
|
||||
docdir=${datarootdir}/doc/${PACKAGE_TARNAME}
|
||||
man6dir = $(mandir)/man6
|
||||
|
||||
###############################################################################
|
||||
# Site configuration occurs above this comment
|
||||
# It should not be necessary to change anything below this comment
|
||||
###############################################################################
|
||||
|
||||
HDRS = rogue.h extern.h score.h
|
||||
OBJS1 = vers.$(O) extern.$(O) armor.$(O) chase.$(O) command.$(O) \
|
||||
daemon.$(O) daemons.$(O) fight.$(O) init.$(O) io.$(O) list.$(O) \
|
||||
mach_dep.$(O) rogue.$(O) mdport.$(O) misc.$(O) monsters.$(O) \
|
||||
move.$(O) new_level.$(O)
|
||||
OBJS2 = options.$(O) pack.$(O) passages.$(O) potions.$(O) rings.$(O) \
|
||||
rip.$(O) rooms.$(O) save.$(O) scrolls.$(O) state.$(O) sticks.$(O) \
|
||||
things.$(O) weapons.$(O) wizard.$(O) xcrypt.$(O)
|
||||
OBJS = main.$(O) $(OBJS1) $(OBJS2)
|
||||
CFILES = vers.c extern.c armor.c chase.c command.c daemon.c \
|
||||
daemons.c fight.c init.c io.c list.c mach_dep.c \
|
||||
main.c mdport.c misc.c monsters.c move.c new_level.c \
|
||||
options.c pack.c passages.c potions.c rings.c rip.c \
|
||||
rooms.c save.c scrolls.c state.c sticks.c things.c \
|
||||
weapons.c wizard.c xcrypt.c
|
||||
MISC_C = findpw.c scedit.c scmisc.c
|
||||
DOCSRC = rogue.me.in rogue.6.in rogue.doc.in rogue.html.in rogue.cat.in
|
||||
DOCS = $(PROGRAM).doc $(PROGRAM).html $(PROGRAM).cat $(PROGRAM).me \
|
||||
$(PROGRAM).6
|
||||
AFILES = configure Makefile.in configure.ac config.h.in config.sub config.guess \
|
||||
install-sh rogue.6.in rogue.me.in rogue.html.in rogue.doc.in rogue.cat.in
|
||||
MISC = Makefile.std LICENSE.TXT rogue54.sln rogue54.vcproj rogue.spec \
|
||||
rogue.png rogue.desktop
|
||||
|
||||
.SUFFIXES: .obj
|
||||
|
||||
.c.obj:
|
||||
$(CC) $(CFLAGS) $(CPPFLAGS) /c $*.c
|
||||
|
||||
.c.o:
|
||||
$(CC) $(CFLAGS) $(CPPFLAGS) -c $*.c
|
||||
|
||||
#$(RM) rogue.so ; $(CC) -shared -o rogue.so cursesd.c $(OBJS1) $(OBJS2); $(CC) $(CFLAGS) $(LDFLAGS) $(OBJS) $(LIBS) -o $@
|
||||
|
||||
$(PROGRAM): $(HDRS) $(OBJS)
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) $(OBJS) $(LIBS) -o $@.exe
|
||||
|
||||
clean:
|
||||
$(RM) $(OBJS1); $(RM) main.$(O) ; $(RM) rogue.so
|
||||
$(RM) $(OBJS2)
|
||||
$(RM) core a.exe a.out a.exe.stackdump $(PROGRAM) $(PROGRAM).exe
|
||||
$(RM) $(PROGRAM).tar $(PROGRAM).tar.gz $(PROGRAM).zip
|
||||
$(RM) $(DISTNAME)/*
|
||||
-rmdir $(DISTNAME)
|
||||
|
||||
maintainer-clean:
|
||||
$(RM) config.h
|
||||
$(RM) Makefile
|
||||
$(RM) config.status
|
||||
$(RM) -r autom4te.cache
|
||||
$(RM) config.log
|
||||
$(RM) $(PROGRAM).scr $(PROGRAM).lck
|
||||
|
||||
stddocs:
|
||||
sed -e 's/rogue/rogue/' -e 's/rogue.scr/rogue.scr/' rogue.6.in > rogue.6
|
||||
sed -e 's/rogue/rogue/' -e 's/rogue.scr/rogue.scr/' rogue.me.in > rogue.me
|
||||
sed -e 's/rogue/rogue/' -e 's/rogue.scr/rogue.scr/' rogue.html.in > rogue,html
|
||||
sed -e 's/rogue/rogue/' -e 's/rogue.scr/rogue.scr/' rogue.doc.in > rogue.doc
|
||||
sed -e 's/rogue/rogue/' -e 's/rogue.scr/rogue.scr/' rogue.cat.in > rogue.cat
|
||||
|
||||
dist.src:
|
||||
$(MAKE) $(MAKEFILE) clean
|
||||
mkdir $(DISTNAME)
|
||||
cp $(CFILES) $(HDRS) $(MISC) $(AFILES) $(DISTNAME)
|
||||
tar cf $(DISTNAME)-src.tar $(DISTNAME)
|
||||
gzip -f $(DISTNAME)-src.tar
|
||||
rm -fr $(DISTNAME)
|
||||
|
||||
findpw: findpw.c xcrypt.o mdport.o xcrypt.o
|
||||
$(CC) -s -o findpw findpw.c xcrypt.o mdport.o -lcurses
|
||||
|
||||
scedit: scedit.o scmisc.o vers.o mdport.o xcrypt.o
|
||||
$(CC) -s -o scedit vers.o scedit.o scmisc.o mdport.o xcrypt.o -lcurses
|
||||
|
||||
scmisc.o scedit.o:
|
||||
$(CC) -O -c $(SF) $*.c
|
||||
|
||||
$(PROGRAM).doc: rogue.me
|
||||
if test "x$(GROFF)" != "x" -a "x$(SED)" != "x" ; then \
|
||||
$(GROFF) -P-c -t -me -Tascii rogue.me | $(SED) -e 's/.\x08//g' > $(PROGRAM).doc ;\
|
||||
elif test "x$(NROFF)" != "x" -a "x$(TBL)" != "x" -a "x$(COLCRT)" != "x" ; then \
|
||||
tbl rogue.me | $(NROFF) -me | colcrt - > $(PROGRAM).doc ;\
|
||||
fi
|
||||
|
||||
$(PROGRAM).cat: rogue.6
|
||||
if test "x$(GROFF)" != "x" -a "x$(SED)" != "x" ; then \
|
||||
$(GROFF) -Tascii -man rogue.6 | $(SED) -e 's/.\x08//g' > $(PROGRAM).cat ;\
|
||||
elif test "x$(NROFF)" != "x" -a "x$(TBL)" != "x" -a "x$(COLCRT)" != "x" ; then \
|
||||
$(NROFF) -man rogue.6 | $(COLCRT) - > $(PROGRAM).cat ;\
|
||||
fi
|
||||
|
||||
dist: clean $(PROGRAM)
|
||||
tar cf $(DISTFILE).tar $(PROGRAM) LICENSE.TXT $(DOCS)
|
||||
gzip -f $(DISTFILE).tar
|
||||
|
||||
install: $(PROGRAM)
|
||||
-$(TOUCH) test
|
||||
-if test ! -f $(DESTDIR)$(SCOREFILE) ; then $(INSTALL) -m 0664 test $(DESTDIR)$(SCOREFILE) ; fi
|
||||
-$(INSTALL) -m 0755 $(PROGRAM) $(DESTDIR)$(bindir)/$(PROGRAM)
|
||||
-if test "x$(GROUPOWNER)" != "x" ; then \
|
||||
$(CHGRP) $(GROUPOWNER) $(DESTDIR)$(SCOREFILE) ; \
|
||||
$(CHGRP) $(GROUPOWNER) $(DESTDIR)$(bindir)/$(PROGRAM) ; \
|
||||
$(CHMOD) 02755 $(DESTDIR)$(bindir)/$(PROGRAM) ; \
|
||||
$(CHMOD) 0464 $(DESTDIR)$(SCOREFILE) ; \
|
||||
fi
|
||||
-if test -d $(man6dir) ; then $(INSTALL) -m 0644 rogue.6 $(DESTDIR)$(man6dir)/$(PROGRAM).6 ; fi
|
||||
-if test ! -d $(man6dir) ; then $(INSTALL) -m 0644 rogue.6 $(DESTDIR)$(mandir)/$(PROGRAM).6 ; fi
|
||||
-$(INSTALL) -m 0644 rogue.doc $(DESTDIR)$(docdir)/$(PROGRAM).doc
|
||||
-$(INSTALL) -m 0644 rogue.html $(DESTDIR)$(docdir)/$(PROGRAM).html
|
||||
-$(INSTALL) -m 0644 rogue.cat $(DESTDIR)$(docdir)/$(PROGRAM).cat
|
||||
-$(INSTALL) -m 0644 LICENSE.TXT $(DESTDIR)$(docdir)/LICENSE.TXT
|
||||
-$(INSTALL) -m 0644 rogue.me $(DESTDIR)$(docdir)/$(PROGRAM).me
|
||||
-if test ! -f $(DESTDIR)$(LOCKFILE) ; then $(INSTALL) -m 0666 test $(DESTDIR)$(LOCKFILE) ; $(RM) $(DESTDIR)$(LOCKFILE) ; fi
|
||||
-$(RM) test
|
||||
|
||||
uninstall:
|
||||
-$(RM) $(DESTDIR)$(bindir)/$(PROGRAM)
|
||||
-$(RM) $(DESTDIR)$(man6dir)/$(PROGRAM).6
|
||||
-$(RM) $(DESTDIR)$(docdir)$(PROGRAM)/$(PROGRAM).doc
|
||||
-$(RM) $(DESTDIR)$(LOCKFILE)
|
||||
-$(RMDIR) $(DESTDIR)$(docdir)$(PROGRAM)
|
||||
|
||||
reinstall: uninstall install
|
||||
@@ -1,92 +0,0 @@
|
||||
// Copyright (c) 2016-2023 The Hush developers
|
||||
// Distributed under the GPLv3 software license, see the accompanying
|
||||
// file COPYING or https://www.gnu.org/licenses/gpl-3.0.en.html
|
||||
/*
|
||||
* This file contains misc functions for dealing with armor
|
||||
* @(#)armor.c 4.14 (Berkeley) 02/05/99
|
||||
*
|
||||
* Rogue: Exploring the Dungeons of Doom
|
||||
* Copyright (C) 1980-1983, 1985, 1999 Michael Toy, Ken Arnold and Glenn Wichman
|
||||
* All rights reserved.
|
||||
*
|
||||
* See the file LICENSE.TXT for full copyright and licensing information.
|
||||
*/
|
||||
|
||||
//#include <curses.h>
|
||||
#include "rogue.h"
|
||||
|
||||
/*
|
||||
* wear:
|
||||
* The player wants to wear something, so let him/her put it on.
|
||||
*/
|
||||
void
|
||||
wear(struct rogue_state *rs)
|
||||
{
|
||||
register THING *obj;
|
||||
register char *sp;
|
||||
|
||||
if ((obj = get_item(rs,"wear", ARMOR)) == NULL)
|
||||
return;
|
||||
if (cur_armor != NULL)
|
||||
{
|
||||
addmsg(rs,"you are already wearing some");
|
||||
if (!terse)
|
||||
addmsg(rs,". You'll have to take it off first");
|
||||
endmsg(rs);
|
||||
after = FALSE;
|
||||
return;
|
||||
}
|
||||
if (obj->o_type != ARMOR)
|
||||
{
|
||||
msg(rs,"you can't wear that");
|
||||
return;
|
||||
}
|
||||
waste_time(rs);
|
||||
obj->o_flags |= ISKNOW;
|
||||
sp = inv_name(obj, TRUE);
|
||||
cur_armor = obj;
|
||||
if (!terse)
|
||||
addmsg(rs,"you are now ");
|
||||
msg(rs,"wearing %s", sp);
|
||||
}
|
||||
|
||||
/*
|
||||
* take_off:
|
||||
* Get the armor off of the players back
|
||||
*/
|
||||
void
|
||||
take_off(struct rogue_state *rs)
|
||||
{
|
||||
register THING *obj;
|
||||
|
||||
if ((obj = cur_armor) == NULL)
|
||||
{
|
||||
after = FALSE;
|
||||
if (terse)
|
||||
msg(rs,"not wearing armor");
|
||||
else
|
||||
msg(rs,"you aren't wearing any armor");
|
||||
return;
|
||||
}
|
||||
if (!dropcheck(rs,cur_armor))
|
||||
return;
|
||||
cur_armor = NULL;
|
||||
if (terse)
|
||||
addmsg(rs,"was");
|
||||
else
|
||||
addmsg(rs,"you used to be");
|
||||
msg(rs," wearing %c) %s", obj->o_packch, inv_name(obj, TRUE));
|
||||
}
|
||||
|
||||
/*
|
||||
* waste_time:
|
||||
* Do nothing but let other things happen
|
||||
*/
|
||||
void
|
||||
waste_time(struct rogue_state *rs)
|
||||
{
|
||||
do_daemons(rs,BEFORE);
|
||||
do_fuses(rs,BEFORE);
|
||||
do_daemons(rs,AFTER);
|
||||
do_fuses(rs,AFTER);
|
||||
}
|
||||
@@ -1,544 +0,0 @@
|
||||
// Copyright (c) 2016-2023 The Hush developers
|
||||
// Distributed under the GPLv3 software license, see the accompanying
|
||||
// file COPYING or https://www.gnu.org/licenses/gpl-3.0.en.html
|
||||
/*
|
||||
* Code for one creature to chase another
|
||||
*
|
||||
* @(#)chase.c 4.57 (Berkeley) 02/05/99
|
||||
*
|
||||
* Rogue: Exploring the Dungeons of Doom
|
||||
* Copyright (C) 1980-1983, 1985, 1999 Michael Toy, Ken Arnold and Glenn Wichman
|
||||
* All rights reserved.
|
||||
*
|
||||
* See the file LICENSE.TXT for full copyright and licensing information.
|
||||
*/
|
||||
|
||||
//#include <stdlib.h>
|
||||
//#include <curses.h>
|
||||
#include "rogue.h"
|
||||
|
||||
#define DRAGONSHOT 5 /* one chance in DRAGONSHOT that a dragon will flame */
|
||||
|
||||
static coord ch_ret; /* Where chasing takes you */
|
||||
|
||||
/*
|
||||
* runners:
|
||||
* Make all the running monsters move.
|
||||
*/
|
||||
void
|
||||
runners(struct rogue_state *rs,int arg)
|
||||
{
|
||||
register THING *tp;
|
||||
THING *next;
|
||||
bool wastarget;
|
||||
static coord orig_pos;
|
||||
|
||||
for (tp = mlist; tp != NULL; tp = next)
|
||||
{
|
||||
/* remember this in case the monster's "next" is changed */
|
||||
next = next(tp);
|
||||
if (!on(*tp, ISHELD) && on(*tp, ISRUN))
|
||||
{
|
||||
orig_pos = tp->t_pos;
|
||||
wastarget = on(*tp, ISTARGET);
|
||||
if (move_monst(rs,tp) == -1)
|
||||
continue;
|
||||
if (on(*tp, ISFLY) && dist_cp(&hero, &tp->t_pos) >= 3)
|
||||
move_monst(rs,tp);
|
||||
if (wastarget && !ce(orig_pos, tp->t_pos))
|
||||
{
|
||||
tp->t_flags &= ~ISTARGET;
|
||||
to_death = FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (has_hit)
|
||||
{
|
||||
endmsg(rs);
|
||||
has_hit = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* move_monst:
|
||||
* Execute a single turn of running for a monster
|
||||
*/
|
||||
int
|
||||
move_monst(struct rogue_state *rs,THING *tp)
|
||||
{
|
||||
if (!on(*tp, ISSLOW) || tp->t_turn)
|
||||
if (do_chase(rs,tp) == -1)
|
||||
return(-1);
|
||||
if (on(*tp, ISHASTE))
|
||||
if (do_chase(rs,tp) == -1)
|
||||
return(-1);
|
||||
tp->t_turn ^= TRUE;
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* relocate:
|
||||
* Make the monster's new location be the specified one, updating
|
||||
* all the relevant state.
|
||||
*/
|
||||
void
|
||||
relocate(struct rogue_state *rs,THING *th, coord *new_loc)
|
||||
{
|
||||
struct room *oroom;
|
||||
|
||||
if (!ce(*new_loc, th->t_pos))
|
||||
{
|
||||
mvaddch(th->t_pos.y, th->t_pos.x, th->t_oldch);
|
||||
th->t_room = roomin(rs,new_loc);
|
||||
set_oldch(th, new_loc);
|
||||
oroom = th->t_room;
|
||||
moat(th->t_pos.y, th->t_pos.x) = NULL;
|
||||
|
||||
if (oroom != th->t_room)
|
||||
th->t_dest = find_dest(rs,th);
|
||||
th->t_pos = *new_loc;
|
||||
moat(new_loc->y, new_loc->x) = th;
|
||||
}
|
||||
move(new_loc->y, new_loc->x);
|
||||
if (see_monst(th))
|
||||
addch(th->t_disguise);
|
||||
else if (on(player, SEEMONST))
|
||||
{
|
||||
standout();
|
||||
addch(th->t_type);
|
||||
standend();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* do_chase:
|
||||
* Make one thing chase another.
|
||||
*/
|
||||
int
|
||||
do_chase(struct rogue_state *rs,THING *th)
|
||||
{
|
||||
register coord *cp;
|
||||
register struct room *rer, *ree; /* room of chaser, room of chasee */
|
||||
register int mindist = 32767, curdist;
|
||||
register bool stoprun = FALSE; /* TRUE means we are there */
|
||||
register bool door;
|
||||
register THING *obj;
|
||||
static coord DEST; /* Temporary destination for chaser */
|
||||
|
||||
rer = th->t_room; /* Find room of chaser */
|
||||
if (on(*th, ISGREED) && rer->r_goldval == 0)
|
||||
th->t_dest = &hero; /* If gold has been taken, run after hero */
|
||||
if (th->t_dest == &hero) /* Find room of chasee */
|
||||
ree = proom;
|
||||
else
|
||||
ree = roomin(rs,th->t_dest);
|
||||
/*
|
||||
* We don't count doors as inside rooms for this routine
|
||||
*/
|
||||
door = (chat(th->t_pos.y, th->t_pos.x) == DOOR);
|
||||
/*
|
||||
* If the object of our desire is in a different room,
|
||||
* and we are not in a corridor, run to the door nearest to
|
||||
* our goal.
|
||||
*/
|
||||
over:
|
||||
if (rer != ree)
|
||||
{
|
||||
for (cp = rer->r_exit; cp < &rer->r_exit[rer->r_nexits]; cp++)
|
||||
{
|
||||
curdist = dist_cp(th->t_dest, cp);
|
||||
if (curdist < mindist)
|
||||
{
|
||||
DEST = *cp;
|
||||
mindist = curdist;
|
||||
}
|
||||
}
|
||||
if (door)
|
||||
{
|
||||
rer = &passages[flat(th->t_pos.y, th->t_pos.x) & F_PNUM];
|
||||
door = FALSE;
|
||||
goto over;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DEST = *th->t_dest;
|
||||
/*
|
||||
* For dragons check and see if (a) the hero is on a straight
|
||||
* line from it, and (b) that it is within shooting distance,
|
||||
* but outside of striking range.
|
||||
*/
|
||||
if (th->t_type == 'D' && (th->t_pos.y == hero.y || th->t_pos.x == hero.x
|
||||
|| abs(th->t_pos.y - hero.y) == abs(th->t_pos.x - hero.x))
|
||||
&& dist_cp(&th->t_pos, &hero) <= BOLT_LENGTH * BOLT_LENGTH
|
||||
&& !on(*th, ISCANC) && rnd(DRAGONSHOT) == 0)
|
||||
{
|
||||
delta.y = sign(hero.y - th->t_pos.y);
|
||||
delta.x = sign(hero.x - th->t_pos.x);
|
||||
if (has_hit)
|
||||
endmsg(rs);
|
||||
fire_bolt(rs,&th->t_pos, &delta, "flame");
|
||||
running = FALSE;
|
||||
count = 0;
|
||||
quiet = 0;
|
||||
if (to_death && !on(*th, ISTARGET))
|
||||
{
|
||||
to_death = FALSE;
|
||||
kamikaze = FALSE;
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* This now contains what we want to run to this time
|
||||
* so we run to it. If we hit it we either want to fight it
|
||||
* or stop running
|
||||
*/
|
||||
if (!chase(th, &DEST))
|
||||
{
|
||||
if (ce(DEST, hero))
|
||||
{
|
||||
return( attack(rs,th) );
|
||||
}
|
||||
else if (ce(DEST, *th->t_dest))
|
||||
{
|
||||
for (obj = lvl_obj; obj != NULL; obj = next(obj))
|
||||
if (th->t_dest == &obj->o_pos)
|
||||
{
|
||||
detach(lvl_obj, obj);
|
||||
attach(th->t_pack, obj);
|
||||
chat(obj->o_pos.y, obj->o_pos.x) =
|
||||
(th->t_room->r_flags & ISGONE) ? PASSAGE : FLOOR;
|
||||
th->t_dest = find_dest(rs,th);
|
||||
break;
|
||||
}
|
||||
if (th->t_type != 'F')
|
||||
stoprun = TRUE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (th->t_type == 'F')
|
||||
return(0);
|
||||
}
|
||||
relocate(rs,th, &ch_ret);
|
||||
/*
|
||||
* And stop running if need be
|
||||
*/
|
||||
if (stoprun && ce(th->t_pos, *(th->t_dest)))
|
||||
th->t_flags &= ~ISRUN;
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* set_oldch:
|
||||
* Set the oldch character for the monster
|
||||
*/
|
||||
void
|
||||
set_oldch(THING *tp, coord *cp)
|
||||
{
|
||||
char sch;
|
||||
|
||||
if (ce(tp->t_pos, *cp))
|
||||
return;
|
||||
|
||||
sch = tp->t_oldch;
|
||||
tp->t_oldch = CCHAR( mvinch(cp->y,cp->x) );
|
||||
if (!on(player, ISBLIND))
|
||||
{
|
||||
if ((sch == FLOOR || tp->t_oldch == FLOOR) &&
|
||||
(tp->t_room->r_flags & ISDARK))
|
||||
tp->t_oldch = ' ';
|
||||
else if (dist_cp(cp, &hero) <= LAMPDIST && see_floor)
|
||||
tp->t_oldch = chat(cp->y, cp->x);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* see_monst:
|
||||
* Return TRUE if the hero can see the monster
|
||||
*/
|
||||
bool
|
||||
see_monst(THING *mp)
|
||||
{
|
||||
int y, x;
|
||||
|
||||
if (on(player, ISBLIND))
|
||||
return FALSE;
|
||||
if (on(*mp, ISINVIS) && !on(player, CANSEE))
|
||||
return FALSE;
|
||||
y = mp->t_pos.y;
|
||||
x = mp->t_pos.x;
|
||||
if (dist(y, x, hero.y, hero.x) < LAMPDIST)
|
||||
{
|
||||
if (y != hero.y && x != hero.x &&
|
||||
!step_ok(chat(y, hero.x)) && !step_ok(chat(hero.y, x)))
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
if (mp->t_room != proom)
|
||||
return FALSE;
|
||||
return ((bool)!(mp->t_room->r_flags & ISDARK));
|
||||
}
|
||||
|
||||
/*
|
||||
* runto:
|
||||
* Set a monster running after the hero.
|
||||
*/
|
||||
void
|
||||
runto(struct rogue_state *rs,coord *runner)
|
||||
{
|
||||
register THING *tp;
|
||||
|
||||
/*
|
||||
* If we couldn't find him, something is funny
|
||||
*/
|
||||
#ifdef MASTER
|
||||
if ((tp = moat(runner->y, runner->x)) == NULL)
|
||||
msg(rs,"couldn't find monster in runto at (%d,%d)", runner->y, runner->x);
|
||||
#else
|
||||
tp = moat(runner->y, runner->x);
|
||||
#endif
|
||||
/*
|
||||
* Start the beastie running
|
||||
*/
|
||||
tp->t_flags |= ISRUN;
|
||||
tp->t_flags &= ~ISHELD;
|
||||
tp->t_dest = find_dest(rs,tp);
|
||||
}
|
||||
|
||||
/*
|
||||
* chase:
|
||||
* Find the spot for the chaser(er) to move closer to the
|
||||
* chasee(ee). Returns TRUE if we want to keep on chasing later
|
||||
* FALSE if we reach the goal.
|
||||
*/
|
||||
bool
|
||||
chase(THING *tp, coord *ee)
|
||||
{
|
||||
register THING *obj;
|
||||
register int x, y;
|
||||
register int curdist, thisdist;
|
||||
register coord *er = &tp->t_pos;
|
||||
register char ch;
|
||||
register int plcnt = 1;
|
||||
static coord tryp;
|
||||
|
||||
/*
|
||||
* If the thing is confused, let it move randomly. Invisible
|
||||
* Stalkers are slightly confused all of the time, and bats are
|
||||
* quite confused all the time
|
||||
*/
|
||||
if ((on(*tp, ISHUH) && rnd(5) != 0) || (tp->t_type == 'P' && rnd(5) == 0)
|
||||
|| (tp->t_type == 'B' && rnd(2) == 0))
|
||||
{
|
||||
/*
|
||||
* get a valid random move
|
||||
*/
|
||||
ch_ret = *rndmove(tp);
|
||||
curdist = dist_cp(&ch_ret, ee);
|
||||
/*
|
||||
* Small chance that it will become un-confused
|
||||
*/
|
||||
if (rnd(20) == 0)
|
||||
tp->t_flags &= ~ISHUH;
|
||||
}
|
||||
/*
|
||||
* Otherwise, find the empty spot next to the chaser that is
|
||||
* closest to the chasee.
|
||||
*/
|
||||
else
|
||||
{
|
||||
register int ey, ex;
|
||||
/*
|
||||
* This will eventually hold where we move to get closer
|
||||
* If we can't find an empty spot, we stay where we are.
|
||||
*/
|
||||
curdist = dist_cp(er, ee);
|
||||
ch_ret = *er;
|
||||
|
||||
ey = er->y + 1;
|
||||
if (ey >= NUMLINES - 1)
|
||||
ey = NUMLINES - 2;
|
||||
ex = er->x + 1;
|
||||
if (ex >= NUMCOLS)
|
||||
ex = NUMCOLS - 1;
|
||||
|
||||
for (x = er->x - 1; x <= ex; x++)
|
||||
{
|
||||
if (x < 0)
|
||||
continue;
|
||||
tryp.x = x;
|
||||
for (y = er->y - 1; y <= ey; y++)
|
||||
{
|
||||
tryp.y = y;
|
||||
if (!diag_ok(er, &tryp))
|
||||
continue;
|
||||
ch = winat(y, x);
|
||||
if (step_ok(ch))
|
||||
{
|
||||
/*
|
||||
* If it is a scroll, it might be a scare monster scroll
|
||||
* so we need to look it up to see what type it is.
|
||||
*/
|
||||
if (ch == SCROLL)
|
||||
{
|
||||
for (obj = lvl_obj; obj != NULL; obj = next(obj))
|
||||
{
|
||||
if (y == obj->o_pos.y && x == obj->o_pos.x)
|
||||
break;
|
||||
}
|
||||
if (obj != NULL && obj->o_which == S_SCARE)
|
||||
continue;
|
||||
}
|
||||
/*
|
||||
* It can also be a Xeroc, which we shouldn't step on
|
||||
*/
|
||||
if ((obj = moat(y, x)) != NULL && obj->t_type == 'X')
|
||||
continue;
|
||||
/*
|
||||
* If we didn't find any scrolls at this place or it
|
||||
* wasn't a scare scroll, then this place counts
|
||||
*/
|
||||
thisdist = dist(y, x, ee->y, ee->x);
|
||||
if (thisdist < curdist)
|
||||
{
|
||||
plcnt = 1;
|
||||
ch_ret = tryp;
|
||||
curdist = thisdist;
|
||||
}
|
||||
else if (thisdist == curdist && rnd(++plcnt) == 0)
|
||||
{
|
||||
ch_ret = tryp;
|
||||
curdist = thisdist;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return (bool)(curdist != 0 && !ce(ch_ret, hero));
|
||||
}
|
||||
|
||||
/*
|
||||
* roomin:
|
||||
* Find what room some coordinates are in. NULL means they aren't
|
||||
* in any room.
|
||||
*/
|
||||
struct room *
|
||||
roomin(struct rogue_state *rs,coord *cp)
|
||||
{
|
||||
register struct room *rp;
|
||||
register char *fp;
|
||||
|
||||
|
||||
fp = &flat(cp->y, cp->x);
|
||||
if (*fp & F_PASS)
|
||||
return &passages[*fp & F_PNUM];
|
||||
|
||||
for (rp = rooms; rp < &rooms[MAXROOMS]; rp++)
|
||||
if (cp->x <= rp->r_pos.x + rp->r_max.x && rp->r_pos.x <= cp->x
|
||||
&& cp->y <= rp->r_pos.y + rp->r_max.y && rp->r_pos.y <= cp->y)
|
||||
return rp;
|
||||
|
||||
msg(rs,"in some bizarre place (%d, %d)", unc(*cp));
|
||||
#ifdef MASTER
|
||||
abort();
|
||||
return NULL;
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* diag_ok:
|
||||
* Check to see if the move is legal if it is diagonal
|
||||
*/
|
||||
bool
|
||||
diag_ok(coord *sp, coord *ep)
|
||||
{
|
||||
if (ep->x < 0 || ep->x >= NUMCOLS || ep->y <= 0 || ep->y >= NUMLINES - 1)
|
||||
return FALSE;
|
||||
if (ep->x == sp->x || ep->y == sp->y)
|
||||
return TRUE;
|
||||
return (bool)(step_ok(chat(ep->y, sp->x)) && step_ok(chat(sp->y, ep->x)));
|
||||
}
|
||||
|
||||
/*
|
||||
* cansee:
|
||||
* Returns true if the hero can see a certain coordinate.
|
||||
*/
|
||||
bool
|
||||
cansee(struct rogue_state *rs,int y, int x)
|
||||
{
|
||||
register struct room *rer;
|
||||
static coord tp;
|
||||
|
||||
if (on(player, ISBLIND))
|
||||
return FALSE;
|
||||
if (dist(y, x, hero.y, hero.x) < LAMPDIST)
|
||||
{
|
||||
if (flat(y, x) & F_PASS)
|
||||
if (y != hero.y && x != hero.x &&
|
||||
!step_ok(chat(y, hero.x)) && !step_ok(chat(hero.y, x)))
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
/*
|
||||
* We can only see if the hero in the same room as
|
||||
* the coordinate and the room is lit or if it is close.
|
||||
*/
|
||||
tp.y = y;
|
||||
tp.x = x;
|
||||
return (bool)((rer = roomin(rs,&tp)) == proom && !(rer->r_flags & ISDARK));
|
||||
}
|
||||
|
||||
/*
|
||||
* find_dest:
|
||||
* find the proper destination for the monster
|
||||
*/
|
||||
coord *
|
||||
find_dest(struct rogue_state *rs,THING *tp)
|
||||
{
|
||||
register THING *obj;
|
||||
register int prob;
|
||||
|
||||
if ((prob = monsters[tp->t_type - 'A'].m_carry) <= 0 || tp->t_room == proom
|
||||
|| see_monst(tp))
|
||||
return &hero;
|
||||
for (obj = lvl_obj; obj != NULL; obj = next(obj))
|
||||
{
|
||||
if (obj->o_type == SCROLL && obj->o_which == S_SCARE)
|
||||
continue;
|
||||
if (roomin(rs,&obj->o_pos) == tp->t_room && rnd(100) < prob)
|
||||
{
|
||||
for (tp = mlist; tp != NULL; tp = next(tp))
|
||||
if (tp->t_dest == &obj->o_pos)
|
||||
break;
|
||||
if (tp == NULL)
|
||||
return &obj->o_pos;
|
||||
}
|
||||
}
|
||||
return &hero;
|
||||
}
|
||||
|
||||
/*
|
||||
* dist:
|
||||
* Calculate the "distance" between to points. Actually,
|
||||
* this calculates d^2, not d, but that's good enough for
|
||||
* our purposes, since it's only used comparitively.
|
||||
*/
|
||||
int
|
||||
dist(int y1, int x1, int y2, int x2)
|
||||
{
|
||||
return ((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));
|
||||
}
|
||||
|
||||
/*
|
||||
* dist_cp:
|
||||
* Call dist() with appropriate arguments for coord pointers
|
||||
*/
|
||||
int
|
||||
dist_cp(coord *c1, coord *c2)
|
||||
{
|
||||
return dist(c1->y, c1->x, c2->y, c2->x);
|
||||
}
|
||||
@@ -1,847 +0,0 @@
|
||||
// Copyright (c) 2016-2023 The Hush developers
|
||||
// Distributed under the GPLv3 software license, see the accompanying
|
||||
// file COPYING or https://www.gnu.org/licenses/gpl-3.0.en.html
|
||||
/*
|
||||
* Read and execute the user commands
|
||||
*
|
||||
* @(#)command.c 4.73 (Berkeley) 08/06/83
|
||||
*
|
||||
* Rogue: Exploring the Dungeons of Doom
|
||||
* Copyright (C) 1980-1983, 1985, 1999 Michael Toy, Ken Arnold and Glenn Wichman
|
||||
* All rights reserved.
|
||||
*
|
||||
* See the file LICENSE.TXT for full copyright and licensing information.
|
||||
*/
|
||||
|
||||
//#include <curses.h>
|
||||
#include "rogue.h"
|
||||
|
||||
/*
|
||||
* command:
|
||||
* Process the user commands
|
||||
*/
|
||||
void
|
||||
command(struct rogue_state *rs)
|
||||
{
|
||||
register char ch;
|
||||
register int ntimes = 1; /* Number of player moves */
|
||||
char *fp;
|
||||
THING *mp;
|
||||
static char countch, direction, newcount = FALSE;
|
||||
if (on(player, ISHASTE))
|
||||
ntimes++;
|
||||
/*
|
||||
* Let the daemons start up
|
||||
*/
|
||||
do_daemons(rs,BEFORE);
|
||||
do_fuses(rs,BEFORE);
|
||||
while (ntimes--)
|
||||
{
|
||||
if ( rs->replaydone != 0 )
|
||||
return;
|
||||
again = FALSE;
|
||||
if (has_hit)
|
||||
{
|
||||
endmsg(rs);
|
||||
has_hit = FALSE;
|
||||
}
|
||||
/*
|
||||
* these are illegal things for the player to be, so if any are
|
||||
* set, someone's been poking in memeory
|
||||
*/
|
||||
if (on(player, ISSLOW|ISGREED|ISINVIS|ISREGEN|ISTARGET))
|
||||
exit(1);
|
||||
|
||||
look(rs,TRUE);
|
||||
if (!running)
|
||||
door_stop = FALSE;
|
||||
status(rs);
|
||||
lastscore = purse;
|
||||
move(hero.y, hero.x);
|
||||
if ( rs->sleeptime != 0 )
|
||||
{
|
||||
if (!((running || count) && jump))
|
||||
refresh(); /* Draw screen */
|
||||
}
|
||||
take = 0;
|
||||
after = TRUE;
|
||||
/*
|
||||
* Read command or continue run
|
||||
*/
|
||||
#ifdef MASTER
|
||||
if (wizard)
|
||||
noscore = TRUE;
|
||||
#endif
|
||||
if (!no_command)
|
||||
{
|
||||
if (running || to_death)
|
||||
ch = runch;
|
||||
else if (count)
|
||||
ch = countch;
|
||||
else
|
||||
{
|
||||
ch = readchar(rs);
|
||||
move_on = FALSE;
|
||||
if (mpos != 0) /* Erase message if its there */
|
||||
msg(rs,"");
|
||||
}
|
||||
}
|
||||
else
|
||||
ch = '.';
|
||||
if (no_command)
|
||||
{
|
||||
if (--no_command == 0)
|
||||
{
|
||||
player.t_flags |= ISRUN;
|
||||
msg(rs,"you can move again");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* check for prefixes
|
||||
*/
|
||||
newcount = FALSE;
|
||||
if (isdigit(ch))
|
||||
{
|
||||
count = 0;
|
||||
newcount = TRUE;
|
||||
while (isdigit(ch))
|
||||
{
|
||||
count = count * 10 + (ch - '0');
|
||||
if (count > 255)
|
||||
count = 255;
|
||||
ch = readchar(rs);
|
||||
}
|
||||
countch = ch;
|
||||
/*
|
||||
* turn off count for commands which don't make sense
|
||||
* to repeat
|
||||
*/
|
||||
if ( rs->guiflag == 0 && rs->replaydone != 0 )
|
||||
ch = 'Q';
|
||||
switch (ch)
|
||||
{
|
||||
case CTRL('B'): case CTRL('H'): case CTRL('J'):
|
||||
case CTRL('K'): case CTRL('L'): case CTRL('N'):
|
||||
case CTRL('U'): case CTRL('Y'):
|
||||
case '.': case 'a': case 'b': case 'h': case 'j':
|
||||
case 'k': case 'l': case 'm': case 'n': case 'q':
|
||||
case 'r': case 's': case 't': case 'u': case 'y':
|
||||
case 'z': case 'B': case 'C': case 'H': case 'I':
|
||||
case 'J': case 'K': case 'L': case 'N': case 'U':
|
||||
case 'Y':
|
||||
#ifdef MASTER
|
||||
case CTRL('D'): case CTRL('A'):
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
count = 0;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* execute a command
|
||||
*/
|
||||
if (count && !running)
|
||||
count--;
|
||||
if (ch != 'a' && ch != ESCAPE && !(running || count || to_death))
|
||||
{
|
||||
l_last_comm = last_comm;
|
||||
l_last_dir = last_dir;
|
||||
l_last_pick = last_pick;
|
||||
last_comm = ch;
|
||||
last_dir = '\0';
|
||||
last_pick = NULL;
|
||||
}
|
||||
over:
|
||||
switch (ch)
|
||||
{
|
||||
case ',': {
|
||||
THING *obj = NULL;
|
||||
int found = 0;
|
||||
for (obj = lvl_obj; obj != NULL; obj = next(obj))
|
||||
{
|
||||
if (obj->o_pos.y == hero.y && obj->o_pos.x == hero.x)
|
||||
{
|
||||
found=1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (found) {
|
||||
if (levit_check(rs))
|
||||
;
|
||||
else
|
||||
pick_up(rs,(char)obj->o_type);
|
||||
}
|
||||
else {
|
||||
if (!terse)
|
||||
addmsg(rs,"there is ");
|
||||
addmsg(rs,"nothing here");
|
||||
if (!terse)
|
||||
addmsg(rs," to pick up");
|
||||
endmsg(rs);
|
||||
}
|
||||
}
|
||||
when '!': shell(rs);
|
||||
when 'h': do_move(rs,0, -1);
|
||||
when 'j': do_move(rs,1, 0);
|
||||
when 'k': do_move(rs,-1, 0);
|
||||
when 'l': do_move(rs,0, 1);
|
||||
when 'y': do_move(rs,-1, -1);
|
||||
when 'u': do_move(rs,-1, 1);
|
||||
when 'b': do_move(rs,1, -1);
|
||||
when 'n': do_move(rs,1, 1);
|
||||
when 'H': do_run('h');
|
||||
when 'J': do_run('j');
|
||||
when 'K': do_run('k');
|
||||
when 'L': do_run('l');
|
||||
when 'Y': do_run('y');
|
||||
when 'U': do_run('u');
|
||||
when 'B': do_run('b');
|
||||
when 'N': do_run('n');
|
||||
when CTRL('H'): case CTRL('J'): case CTRL('K'): case CTRL('L'):
|
||||
case CTRL('Y'): case CTRL('U'): case CTRL('B'): case CTRL('N'):
|
||||
{
|
||||
if (!on(player, ISBLIND))
|
||||
{
|
||||
door_stop = TRUE;
|
||||
firstmove = TRUE;
|
||||
}
|
||||
if (count && !newcount)
|
||||
ch = direction;
|
||||
else
|
||||
{
|
||||
ch += ('A' - CTRL('A'));
|
||||
direction = ch;
|
||||
}
|
||||
goto over;
|
||||
}
|
||||
when 'F':
|
||||
kamikaze = TRUE;
|
||||
/* FALLTHROUGH */
|
||||
case 'f':
|
||||
if (!get_dir(rs))
|
||||
{
|
||||
after = FALSE;
|
||||
break;
|
||||
}
|
||||
delta.y += hero.y;
|
||||
delta.x += hero.x;
|
||||
if ( ((mp = moat(delta.y, delta.x)) == NULL)
|
||||
|| ((!see_monst(mp)) && !on(player, SEEMONST)))
|
||||
{
|
||||
if (!terse)
|
||||
addmsg(rs,"I see ");
|
||||
msg(rs,"no monster there");
|
||||
after = FALSE;
|
||||
}
|
||||
else if (diag_ok(&hero, &delta))
|
||||
{
|
||||
to_death = TRUE;
|
||||
max_hit = 0;
|
||||
mp->t_flags |= ISTARGET;
|
||||
runch = ch = dir_ch;
|
||||
goto over;
|
||||
}
|
||||
when 't':
|
||||
if (!get_dir(rs))
|
||||
after = FALSE;
|
||||
else
|
||||
missile(rs,delta.y, delta.x);
|
||||
when 'a':
|
||||
if (last_comm == '\0')
|
||||
{
|
||||
msg(rs,"you haven't typed a command yet");
|
||||
after = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
ch = last_comm;
|
||||
again = TRUE;
|
||||
goto over;
|
||||
}
|
||||
case 'q': quaff(rs);
|
||||
break;
|
||||
when 'Q':
|
||||
after = FALSE;
|
||||
q_comm = TRUE;
|
||||
if ( _quit() > 0 )
|
||||
{
|
||||
if ( rs->guiflag != 0 )
|
||||
{
|
||||
if (rs->needflush == 0 )
|
||||
rs->needflush = (uint32_t)time(NULL);
|
||||
rogue_bailout(rs);
|
||||
} else rs->replaydone = (uint32_t)time(NULL);
|
||||
}
|
||||
q_comm = FALSE;
|
||||
return;
|
||||
when 'i': after = FALSE; inventory(rs,pack, 0);
|
||||
when 'I': after = FALSE; picky_inven(rs);
|
||||
when 'd': drop(rs);
|
||||
when 'r': read_scroll(rs);
|
||||
when 'e': eat(rs);
|
||||
when 'w': wield(rs);
|
||||
when 'W': wear(rs);
|
||||
when 'T': take_off(rs);
|
||||
when 'P': ring_on(rs);
|
||||
when 'R': ring_off(rs);
|
||||
when 'o': option(rs); after = FALSE;
|
||||
when 'c': call(rs); after = FALSE;
|
||||
|
||||
when '>': after = FALSE; d_level(rs);
|
||||
if ( rs->guiflag != 0 && rs->needflush == 0 )
|
||||
rs->needflush = (uint32_t)time(NULL);
|
||||
|
||||
when '<': after = FALSE; u_level(rs);
|
||||
if ( rs->guiflag != 0 && rs->needflush == 0 )
|
||||
rs->needflush = (uint32_t)time(NULL);
|
||||
|
||||
when '?': after = FALSE; help(rs);
|
||||
when '/': after = FALSE; identify(rs);
|
||||
when 's': search(rs);
|
||||
when 'z':
|
||||
if (get_dir(rs))
|
||||
do_zap(rs);
|
||||
else
|
||||
after = FALSE;
|
||||
when 'D': after = FALSE; discovered(rs);
|
||||
when CTRL('P'): after = FALSE; msg(rs,huh);
|
||||
when CTRL('R'):
|
||||
after = FALSE;
|
||||
clearok(curscr,TRUE);
|
||||
wrefresh(curscr);
|
||||
when 'v':
|
||||
after = FALSE;
|
||||
msg(rs,"version %s. (mctesq was here)", release);
|
||||
when 'S':
|
||||
after = FALSE;
|
||||
#ifdef STANDALONE
|
||||
save_game(rs);
|
||||
#else
|
||||
msg(rs,"Saving is disabled, use bailout rpc");
|
||||
#endif
|
||||
when '.': ; /* Rest command */
|
||||
when ' ': after = FALSE; /* "Legal" illegal command */
|
||||
when '^':
|
||||
after = FALSE;
|
||||
if (get_dir(rs)) {
|
||||
delta.y += hero.y;
|
||||
delta.x += hero.x;
|
||||
fp = &flat(delta.y, delta.x);
|
||||
if (!terse)
|
||||
addmsg(rs,"You have found ");
|
||||
if (chat(delta.y, delta.x) != TRAP)
|
||||
msg(rs,"no trap there");
|
||||
else if (on(player, ISHALU))
|
||||
msg(rs,(char *)tr_name[rnd(NTRAPS)]);
|
||||
else {
|
||||
msg(rs,(char *)tr_name[*fp & F_TMASK]);
|
||||
*fp |= F_SEEN;
|
||||
}
|
||||
}
|
||||
#ifdef MASTER
|
||||
when '+':
|
||||
after = FALSE;
|
||||
if (wizard)
|
||||
{
|
||||
wizard = FALSE;
|
||||
turn_see(rs,TRUE);
|
||||
msg(rs,"not wizard any more");
|
||||
}
|
||||
else
|
||||
{
|
||||
wizard = passwd();
|
||||
if (wizard)
|
||||
{
|
||||
noscore = TRUE;
|
||||
turn_see(rs,FALSE);
|
||||
msg(rs,"you are suddenly as smart as Ken Arnold in dungeon #%d", dnum);
|
||||
}
|
||||
else
|
||||
msg(rs,"sorry");
|
||||
}
|
||||
#endif
|
||||
when ESCAPE: /* Escape */
|
||||
door_stop = FALSE;
|
||||
count = 0;
|
||||
after = FALSE;
|
||||
again = FALSE;
|
||||
when 'm':
|
||||
move_on = TRUE;
|
||||
if (!get_dir(rs))
|
||||
after = FALSE;
|
||||
else
|
||||
{
|
||||
ch = dir_ch;
|
||||
countch = dir_ch;
|
||||
goto over;
|
||||
}
|
||||
when ')': current(rs,cur_weapon, "wielding", NULL);
|
||||
when ']': current(rs,cur_armor, "wearing", NULL);
|
||||
when '=':
|
||||
current(rs,cur_ring[LEFT], "wearing",
|
||||
terse ? (char *)"(L)" : (char *)"on left hand");
|
||||
current(rs,cur_ring[RIGHT], "wearing",
|
||||
terse ? (char *)"(R)" : (char *)"on right hand");
|
||||
when '@':
|
||||
stat_msg = TRUE;
|
||||
status(rs);
|
||||
stat_msg = FALSE;
|
||||
after = FALSE;
|
||||
otherwise:
|
||||
after = FALSE;
|
||||
#ifdef MASTER
|
||||
if (wizard) switch (ch)
|
||||
{
|
||||
case '|': msg(rs,"@ %d,%d", hero.y, hero.x);
|
||||
when 'C': create_obj();
|
||||
when '$': msg(rs,"inpack = %d", inpack);
|
||||
when CTRL('G'): inventory(rs,lvl_obj, 0);
|
||||
when CTRL('W'): whatis(rs,FALSE, 0);
|
||||
when CTRL('D'): level++; new_level();
|
||||
when CTRL('A'): level--; new_level();
|
||||
when CTRL('F'): show_map();
|
||||
when CTRL('T'): teleport();
|
||||
when CTRL('E'): msg(rs,"food left: %d", food_left);
|
||||
when CTRL('C'): add_pass();
|
||||
when CTRL('X'): turn_see(rs,on(player, SEEMONST));
|
||||
when CTRL('~'):
|
||||
{
|
||||
THING *item;
|
||||
|
||||
if ((item = get_item(rs,"charge", STICK)) != NULL)
|
||||
item->o_charges = 10000;
|
||||
}
|
||||
when CTRL('I'):
|
||||
{
|
||||
int i;
|
||||
THING *obj;
|
||||
|
||||
for (i = 0; i < 9; i++)
|
||||
raise_level(rs);
|
||||
/*
|
||||
* Give him a sword (+1,+1)
|
||||
*/
|
||||
obj = new_item();
|
||||
init_weapon(obj, TWOSWORD);
|
||||
obj->o_hplus = 1;
|
||||
obj->o_dplus = 1;
|
||||
add_pack(rs,obj, TRUE);
|
||||
cur_weapon = obj;
|
||||
/*
|
||||
* And his suit of armor
|
||||
*/
|
||||
obj = new_item();
|
||||
obj->o_type = ARMOR;
|
||||
obj->o_which = PLATE_MAIL;
|
||||
obj->o_arm = -5;
|
||||
obj->o_flags |= ISKNOW;
|
||||
obj->o_count = 1;
|
||||
obj->o_group = 0;
|
||||
cur_armor = obj;
|
||||
add_pack(rs,obj, TRUE);
|
||||
}
|
||||
when '*' :
|
||||
pr_list();
|
||||
otherwise:
|
||||
illcom(rs,ch);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
illcom(rs,ch);
|
||||
}
|
||||
/*
|
||||
* turn off flags if no longer needed
|
||||
*/
|
||||
if (!running)
|
||||
door_stop = FALSE;
|
||||
}
|
||||
/*
|
||||
* If he ran into something to take, let him pick it up.
|
||||
*/
|
||||
if (take != 0)
|
||||
pick_up(rs,take);
|
||||
if (!running)
|
||||
door_stop = FALSE;
|
||||
if (!after)
|
||||
ntimes++;
|
||||
}
|
||||
do_daemons(rs,AFTER);
|
||||
do_fuses(rs,AFTER);
|
||||
if (ISRING(LEFT, R_SEARCH))
|
||||
search(rs);
|
||||
else if (ISRING(LEFT, R_TELEPORT) && rnd(50) == 0)
|
||||
teleport(rs);
|
||||
if (ISRING(RIGHT, R_SEARCH))
|
||||
search(rs);
|
||||
else if (ISRING(RIGHT, R_TELEPORT) && rnd(50) == 0)
|
||||
teleport(rs);
|
||||
}
|
||||
|
||||
/*
|
||||
* illcom:
|
||||
* What to do with an illegal command
|
||||
*/
|
||||
void
|
||||
illcom(struct rogue_state *rs,int ch)
|
||||
{
|
||||
save_msg = FALSE;
|
||||
count = 0;
|
||||
msg(rs,"illegal command '%s'", unctrl(ch));
|
||||
save_msg = TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* search:
|
||||
* player gropes about him to find hidden things.
|
||||
*/
|
||||
void
|
||||
search(struct rogue_state *rs)
|
||||
{
|
||||
register int y, x;
|
||||
register char *fp;
|
||||
register int ey, ex;
|
||||
int probinc;
|
||||
bool found;
|
||||
|
||||
ey = hero.y + 1;
|
||||
ex = hero.x + 1;
|
||||
probinc = (on(player, ISHALU) ? 3 : 0);
|
||||
probinc += (on(player, ISBLIND) ? 2 : 0);
|
||||
found = FALSE;
|
||||
for (y = hero.y - 1; y <= ey; y++)
|
||||
for (x = hero.x - 1; x <= ex; x++)
|
||||
{
|
||||
if (y == hero.y && x == hero.x)
|
||||
continue;
|
||||
fp = &flat(y, x);
|
||||
if (!(*fp & F_REAL))
|
||||
switch (chat(y, x))
|
||||
{
|
||||
case '|':
|
||||
case '-':
|
||||
if (rnd(5 + probinc) != 0)
|
||||
break;
|
||||
chat(y, x) = DOOR;
|
||||
msg(rs,"a secret door");
|
||||
foundone:
|
||||
found = TRUE;
|
||||
*fp |= F_REAL;
|
||||
count = FALSE;
|
||||
running = FALSE;
|
||||
break;
|
||||
case FLOOR:
|
||||
if (rnd(2 + probinc) != 0)
|
||||
break;
|
||||
chat(y, x) = TRAP;
|
||||
if (!terse)
|
||||
addmsg(rs,"you found ");
|
||||
if (on(player, ISHALU))
|
||||
msg(rs,(char *)tr_name[rnd(NTRAPS)]);
|
||||
else {
|
||||
msg(rs,(char *)tr_name[*fp & F_TMASK]);
|
||||
*fp |= F_SEEN;
|
||||
}
|
||||
goto foundone;
|
||||
break;
|
||||
case ' ':
|
||||
if (rnd(3 + probinc) != 0)
|
||||
break;
|
||||
chat(y, x) = PASSAGE;
|
||||
goto foundone;
|
||||
}
|
||||
}
|
||||
if (found)
|
||||
look(rs,FALSE);
|
||||
}
|
||||
|
||||
/*
|
||||
* help:
|
||||
* Give single character help, or the whole mess if he wants it
|
||||
*/
|
||||
void
|
||||
help(struct rogue_state *rs)
|
||||
{
|
||||
register const struct h_list *strp;
|
||||
register char helpch;
|
||||
register int numprint, cnt;
|
||||
msg(rs,"character you want help for (* for all): ");
|
||||
helpch = readchar(rs);
|
||||
mpos = 0;
|
||||
/*
|
||||
* If its not a *, print the right help string
|
||||
* or an error if he typed a funny character.
|
||||
*/
|
||||
if (helpch != '*')
|
||||
{
|
||||
move(0, 0);
|
||||
for (strp = helpstr; strp->h_desc != NULL; strp++)
|
||||
if (strp->h_ch == helpch)
|
||||
{
|
||||
lower_msg = TRUE;
|
||||
msg(rs,"%s%s", unctrl(strp->h_ch), strp->h_desc);
|
||||
lower_msg = FALSE;
|
||||
return;
|
||||
}
|
||||
msg(rs,"unknown character '%s'", unctrl(helpch));
|
||||
return;
|
||||
}
|
||||
/*
|
||||
* Here we print help for everything.
|
||||
* Then wait before we return to command mode
|
||||
*/
|
||||
numprint = 0;
|
||||
for (strp = helpstr; strp->h_desc != NULL; strp++)
|
||||
if (strp->h_print)
|
||||
numprint++;
|
||||
if (numprint & 01) /* round odd numbers up */
|
||||
numprint++;
|
||||
numprint /= 2;
|
||||
if (numprint > LINES - 1)
|
||||
numprint = LINES - 1;
|
||||
|
||||
wclear(hw);
|
||||
cnt = 0;
|
||||
for (strp = helpstr; strp->h_desc != NULL; strp++)
|
||||
if (strp->h_print)
|
||||
{
|
||||
wmove(hw, cnt % numprint, cnt >= numprint ? COLS / 2 : 0);
|
||||
if (strp->h_ch)
|
||||
waddstr(hw, unctrl(strp->h_ch));
|
||||
waddstr(hw, strp->h_desc);
|
||||
if (++cnt >= numprint * 2)
|
||||
break;
|
||||
}
|
||||
wmove(hw, LINES - 1, 0);
|
||||
waddstr(hw, "--Press space to continue--");
|
||||
wrefresh(hw);
|
||||
wait_for(rs,' ');
|
||||
clearok(stdscr, TRUE);
|
||||
/*
|
||||
refresh();
|
||||
*/
|
||||
msg(rs,"");
|
||||
touchwin(stdscr);
|
||||
wrefresh(stdscr);
|
||||
}
|
||||
|
||||
/*
|
||||
* identify:
|
||||
* Tell the player what a certain thing is.
|
||||
*/
|
||||
void
|
||||
identify(struct rogue_state *rs)
|
||||
{
|
||||
register int ch;
|
||||
register const struct h_list *hp;
|
||||
register char *str;
|
||||
static const struct h_list ident_list[] = {
|
||||
{'|', "wall of a room", FALSE},
|
||||
{'-', "wall of a room", FALSE},
|
||||
{GOLD, "gold", FALSE},
|
||||
{STAIRS, "a staircase", FALSE},
|
||||
{DOOR, "door", FALSE},
|
||||
{FLOOR, "room floor", FALSE},
|
||||
{PLAYER, "you", FALSE},
|
||||
{PASSAGE, "passage", FALSE},
|
||||
{TRAP, "trap", FALSE},
|
||||
{POTION, "potion", FALSE},
|
||||
{SCROLL, "scroll", FALSE},
|
||||
{FOOD, "food", FALSE},
|
||||
{WEAPON, "weapon", FALSE},
|
||||
{' ', "solid rock", FALSE},
|
||||
{ARMOR, "armor", FALSE},
|
||||
{AMULET, "the Amulet of Yendor", FALSE},
|
||||
{RING, "ring", FALSE},
|
||||
{STICK, "wand or staff", FALSE},
|
||||
{'\0'}
|
||||
};
|
||||
|
||||
msg(rs,"what do you want identified? ");
|
||||
ch = readchar(rs);
|
||||
mpos = 0;
|
||||
if (ch == ESCAPE)
|
||||
{
|
||||
msg(rs,"");
|
||||
return;
|
||||
}
|
||||
if (isupper(ch))
|
||||
str = monsters[ch-'A'].m_name;
|
||||
else
|
||||
{
|
||||
str = "unknown character";
|
||||
for (hp = ident_list; hp->h_ch != '\0'; hp++)
|
||||
if (hp->h_ch == ch)
|
||||
{
|
||||
str = hp->h_desc;
|
||||
break;
|
||||
}
|
||||
}
|
||||
msg(rs,"'%s': %s", unctrl(ch), str);
|
||||
}
|
||||
|
||||
/*
|
||||
* d_level:
|
||||
* He wants to go down a level
|
||||
*/
|
||||
void
|
||||
d_level(struct rogue_state *rs)
|
||||
{
|
||||
if (levit_check(rs))
|
||||
return;
|
||||
if (chat(hero.y, hero.x) != STAIRS)
|
||||
msg(rs,"I see no way down");
|
||||
else
|
||||
{
|
||||
level++;
|
||||
seenstairs = FALSE;
|
||||
new_level(rs);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* u_level:
|
||||
* He wants to go up a level
|
||||
*/
|
||||
void
|
||||
u_level(struct rogue_state *rs)
|
||||
{
|
||||
if (levit_check(rs))
|
||||
return;
|
||||
if (chat(hero.y, hero.x) == STAIRS)
|
||||
if (amulet)
|
||||
{
|
||||
level--;
|
||||
if (level == 0)
|
||||
total_winner(rs);
|
||||
new_level(rs);
|
||||
msg(rs,"you feel a wrenching sensation in your gut");
|
||||
}
|
||||
else
|
||||
msg(rs,"your way is magically blocked");
|
||||
else
|
||||
msg(rs,"I see no way up");
|
||||
}
|
||||
|
||||
/*
|
||||
* levit_check:
|
||||
* Check to see if she's levitating, and if she is, print an
|
||||
* appropriate message.
|
||||
*/
|
||||
bool
|
||||
levit_check(struct rogue_state *rs)
|
||||
{
|
||||
if (!on(player, ISLEVIT))
|
||||
return FALSE;
|
||||
msg(rs,"You can't. You're floating off the ground!");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* call:
|
||||
* Allow a user to call a potion, scroll, or ring something
|
||||
*/
|
||||
void
|
||||
call(struct rogue_state *rs)
|
||||
{
|
||||
register THING *obj;
|
||||
register const struct obj_info *op = NULL;
|
||||
register char **guess; const char *elsewise = NULL;
|
||||
register const bool *know;
|
||||
|
||||
obj = get_item(rs,"call", CALLABLE);
|
||||
/*
|
||||
* Make certain that it is somethings that we want to wear
|
||||
*/
|
||||
if (obj == NULL)
|
||||
return;
|
||||
switch (obj->o_type)
|
||||
{
|
||||
case RING:
|
||||
op = &ring_info[obj->o_which];
|
||||
elsewise = r_stones[obj->o_which];
|
||||
goto norm;
|
||||
when POTION:
|
||||
op = &pot_info[obj->o_which];
|
||||
elsewise = p_colors[obj->o_which];
|
||||
goto norm;
|
||||
when SCROLL:
|
||||
op = &scr_info[obj->o_which];
|
||||
elsewise = s_names[obj->o_which];
|
||||
goto norm;
|
||||
when STICK:
|
||||
op = &ws_info[obj->o_which];
|
||||
elsewise = ws_made[obj->o_which];
|
||||
norm:
|
||||
know = &op->oi_know;
|
||||
guess = (char **)&op->oi_guess;
|
||||
if (*guess != NULL)
|
||||
elsewise = *guess;
|
||||
when FOOD:
|
||||
msg(rs,"you can't call that anything");
|
||||
return;
|
||||
otherwise:
|
||||
guess = &obj->o_label;
|
||||
know = NULL;
|
||||
elsewise = obj->o_label;
|
||||
}
|
||||
if (know != NULL && *know)
|
||||
{
|
||||
msg(rs,"that has already been identified");
|
||||
return;
|
||||
}
|
||||
if (elsewise != NULL && elsewise == *guess)
|
||||
{
|
||||
if (!terse)
|
||||
addmsg(rs,"Was ");
|
||||
msg(rs,"called \"%s\"", elsewise);
|
||||
}
|
||||
if (terse)
|
||||
msg(rs,"call it: ");
|
||||
else
|
||||
msg(rs,"what do you want to call it? ");
|
||||
|
||||
if (elsewise == NULL)
|
||||
strcpy(prbuf, "");
|
||||
else
|
||||
strcpy(prbuf, elsewise);
|
||||
if (get_str(rs,prbuf, stdscr) == NORM)
|
||||
{
|
||||
if (*guess != NULL)
|
||||
free(*guess);
|
||||
*guess = (char *)malloc((unsigned int) strlen(prbuf) + 1);
|
||||
strcpy(*guess, prbuf);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* current:
|
||||
* Print the current weapon/armor
|
||||
*/
|
||||
void
|
||||
current(struct rogue_state *rs,THING *cur, char *how, char *where)
|
||||
{
|
||||
after = FALSE;
|
||||
if (cur != NULL)
|
||||
{
|
||||
if (!terse)
|
||||
addmsg(rs,"you are %s (", how);
|
||||
inv_describe = FALSE;
|
||||
addmsg(rs,"%c) %s", cur->o_packch, inv_name(cur, TRUE));
|
||||
inv_describe = TRUE;
|
||||
if (where)
|
||||
addmsg(rs," %s", where);
|
||||
endmsg(rs);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!terse)
|
||||
addmsg(rs,"you are ");
|
||||
addmsg(rs,"%s nothing", how);
|
||||
if (where)
|
||||
addmsg(rs," %s", where);
|
||||
endmsg(rs);
|
||||
}
|
||||
}
|
||||
1500
src/cc/rogue/config.guess
vendored
1500
src/cc/rogue/config.guess
vendored
File diff suppressed because it is too large
Load Diff
@@ -1,269 +0,0 @@
|
||||
/* config.h.in. Generated from configure.ac by autoheader. */
|
||||
|
||||
/* Define if scorefile is top scores, not top players */
|
||||
#undef ALLSCORES
|
||||
|
||||
/* Define if checktime feature should be enabled */
|
||||
#undef CHECKTIME
|
||||
|
||||
/* Define to group owner of setgid executable */
|
||||
#undef GROUPOWNER
|
||||
|
||||
/* Define to 1 if you have the `alarm' function. */
|
||||
#undef HAVE_ALARM
|
||||
|
||||
/* Define to 1 if you have the <arpa/inet.h> header file. */
|
||||
#undef HAVE_ARPA_INET_H
|
||||
|
||||
/* Define to 1 if libcurses is requested */
|
||||
#undef HAVE_CURSES_H
|
||||
|
||||
/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */
|
||||
#undef HAVE_DOPRNT
|
||||
|
||||
/* Define to 1 if you have the `erasechar' function. */
|
||||
#undef HAVE_ERASECHAR
|
||||
|
||||
/* Define if ncurses has ESCDELAY variable */
|
||||
#undef HAVE_ESCDELAY
|
||||
|
||||
/* Define to 1 if you have the <fcntl.h> header file. */
|
||||
#undef HAVE_FCNTL_H
|
||||
|
||||
/* Define to 1 if you have the `fork' function. */
|
||||
#undef HAVE_FORK
|
||||
|
||||
/* Define to 1 if you have the `getgid' function. */
|
||||
#undef HAVE_GETGID
|
||||
|
||||
/* Define to 1 if you have the `getloadavg' function. */
|
||||
#undef HAVE_GETLOADAVG
|
||||
|
||||
/* Define to 1 if you have the `getpass' function. */
|
||||
#undef HAVE_GETPASS
|
||||
|
||||
/* Define to 1 if you have the `getpwuid' function. */
|
||||
#undef HAVE_GETPWUID
|
||||
|
||||
/* Define to 1 if you have the `getuid' function. */
|
||||
#undef HAVE_GETUID
|
||||
|
||||
/* Define to 1 if you have the <inttypes.h> header file. */
|
||||
#undef HAVE_INTTYPES_H
|
||||
|
||||
/* Define to 1 if you have the `killchar' function. */
|
||||
#undef HAVE_KILLCHAR
|
||||
|
||||
/* Define to 1 if you have the <limits.h> header file. */
|
||||
#undef HAVE_LIMITS_H
|
||||
|
||||
/* Define to 1 if you have the `loadav' function. */
|
||||
#undef HAVE_LOADAV
|
||||
|
||||
/* Define to 1 if `lstat' has the bug that it succeeds when given the
|
||||
zero-length file name argument. */
|
||||
#undef HAVE_LSTAT_EMPTY_STRING_BUG
|
||||
|
||||
/* Define to 1 if you have the <memory.h> header file. */
|
||||
#undef HAVE_MEMORY_H
|
||||
|
||||
/* Define to 1 if you have the `memset' function. */
|
||||
#undef HAVE_MEMSET
|
||||
|
||||
/* Define to 1 if libncurses is requested */
|
||||
#undef HAVE_NCURSES_H
|
||||
|
||||
/* Define to 1 if you have the <ncurses/term.h> header file. */
|
||||
#undef HAVE_NCURSES_TERM_H
|
||||
|
||||
/* Define to 1 if you have the `nlist' function. */
|
||||
#undef HAVE_NLIST
|
||||
|
||||
/* Define to 1 if you have the <nlist.h> header file. */
|
||||
#undef HAVE_NLIST_H
|
||||
|
||||
/* Define to 1 if you have the <process.h> header file. */
|
||||
#undef HAVE_PROCESS_H
|
||||
|
||||
/* Define to 1 if you have the <pwd.h> header file. */
|
||||
#undef HAVE_PWD_H
|
||||
|
||||
/* Define to 1 if you have the `setenv' function. */
|
||||
#undef HAVE_SETENV
|
||||
|
||||
/* Define to 1 if you have the `setgid' function. */
|
||||
#undef HAVE_SETGID
|
||||
|
||||
/* Define to 1 if you have the `setregid' function. */
|
||||
#undef HAVE_SETREGID
|
||||
|
||||
/* Define to 1 if you have the `setresgid' function. */
|
||||
#undef HAVE_SETRESGID
|
||||
|
||||
/* Define to 1 if you have the `setresuid' function. */
|
||||
#undef HAVE_SETRESUID
|
||||
|
||||
/* Define to 1 if you have the `setreuid' function. */
|
||||
#undef HAVE_SETREUID
|
||||
|
||||
/* Define to 1 if you have the `setuid' function. */
|
||||
#undef HAVE_SETUID
|
||||
|
||||
/* Define to 1 if you have the `spawnl' function. */
|
||||
#undef HAVE_SPAWNL
|
||||
|
||||
/* Define to 1 if `stat' has the bug that it succeeds when given the
|
||||
zero-length file name argument. */
|
||||
#undef HAVE_STAT_EMPTY_STRING_BUG
|
||||
|
||||
/* Define to 1 if stdbool.h conforms to C99. */
|
||||
#undef HAVE_STDBOOL_H
|
||||
|
||||
/* Define to 1 if you have the <stdint.h> header file. */
|
||||
#undef HAVE_STDINT_H
|
||||
|
||||
/* Define to 1 if you have the <stdlib.h> header file. */
|
||||
#undef HAVE_STDLIB_H
|
||||
|
||||
/* Define to 1 if you have the `strchr' function. */
|
||||
#undef HAVE_STRCHR
|
||||
|
||||
/* Define to 1 if you have the `strerror' function. */
|
||||
#undef HAVE_STRERROR
|
||||
|
||||
/* Define to 1 if you have the <strings.h> header file. */
|
||||
#undef HAVE_STRINGS_H
|
||||
|
||||
/* Define to 1 if you have the <string.h> header file. */
|
||||
#undef HAVE_STRING_H
|
||||
|
||||
/* Define to 1 if you have the <sys/ioctl.h> header file. */
|
||||
#undef HAVE_SYS_IOCTL_H
|
||||
|
||||
/* Define to 1 if you have the <sys/stat.h> header file. */
|
||||
#undef HAVE_SYS_STAT_H
|
||||
|
||||
/* Define to 1 if you have the <sys/types.h> header file. */
|
||||
#undef HAVE_SYS_TYPES_H
|
||||
|
||||
/* Define to 1 if you have the <sys/utsname.h> header file. */
|
||||
#undef HAVE_SYS_UTSNAME_H
|
||||
|
||||
/* Define to 1 if you have the <termios.h> header file. */
|
||||
#undef HAVE_TERMIOS_H
|
||||
|
||||
/* Define to 1 if you have the <term.h> header file. */
|
||||
#undef HAVE_TERM_H
|
||||
|
||||
/* Define to 1 if you have the <unistd.h> header file. */
|
||||
#undef HAVE_UNISTD_H
|
||||
|
||||
/* Define to 1 if you have the <utmp.h> header file. */
|
||||
#undef HAVE_UTMP_H
|
||||
|
||||
/* Define to 1 if you have the `vfork' function. */
|
||||
#undef HAVE_VFORK
|
||||
|
||||
/* Define to 1 if you have the <vfork.h> header file. */
|
||||
#undef HAVE_VFORK_H
|
||||
|
||||
/* Define to 1 if you have the `vprintf' function. */
|
||||
#undef HAVE_VPRINTF
|
||||
|
||||
/* Define to 1 if `fork' works. */
|
||||
#undef HAVE_WORKING_FORK
|
||||
|
||||
/* Define to 1 if `vfork' works. */
|
||||
#undef HAVE_WORKING_VFORK
|
||||
|
||||
/* Define to 1 if the system has the type `_Bool'. */
|
||||
#undef HAVE__BOOL
|
||||
|
||||
/* Define to 1 if you have the `_spawnl' function. */
|
||||
#undef HAVE__SPAWNL
|
||||
|
||||
/* define if we should use program's load average function instead of system
|
||||
*/
|
||||
#undef LOADAV
|
||||
|
||||
/* Define to file to use for scoreboard lockfile */
|
||||
#undef LOCKFILE
|
||||
|
||||
/* Define to 1 if `lstat' dereferences a symlink specified with a trailing
|
||||
slash. */
|
||||
#undef LSTAT_FOLLOWS_SLASHED_SYMLINK
|
||||
|
||||
/* Define to include wizard mode */
|
||||
#undef MASTER
|
||||
|
||||
/* Define if maxusers feature should be enabled */
|
||||
#undef MAXLOAD
|
||||
|
||||
/* Define if maxusers feature should be enabled */
|
||||
#undef MAXUSERS
|
||||
|
||||
/* kernel file to pass to nlist() when reading load average (unlikely to work)
|
||||
*/
|
||||
#undef NAMELIST
|
||||
|
||||
/* word for the number of scores to store in scoreboard */
|
||||
#undef NUMNAME
|
||||
|
||||
/* number of scores to store in scoreboard */
|
||||
#undef NUMSCORES
|
||||
|
||||
/* Define to the address where bug reports for this package should be sent. */
|
||||
#undef PACKAGE_BUGREPORT
|
||||
|
||||
/* Define to the full name of this package. */
|
||||
#undef PACKAGE_NAME
|
||||
|
||||
/* Define to the full name and version of this package. */
|
||||
#undef PACKAGE_STRING
|
||||
|
||||
/* Define to the one symbol short name of this package. */
|
||||
#undef PACKAGE_TARNAME
|
||||
|
||||
/* Define to the version of this package. */
|
||||
#undef PACKAGE_VERSION
|
||||
|
||||
/* Define crypt(3) wizard mode password */
|
||||
#undef PASSWD
|
||||
|
||||
/* Define as the return type of signal handlers (`int' or `void'). */
|
||||
#undef RETSIGTYPE
|
||||
|
||||
/* Define to file to use for scoreboard */
|
||||
#undef SCOREFILE
|
||||
|
||||
/* Define to 1 if you have the ANSI C header files. */
|
||||
#undef STDC_HEADERS
|
||||
|
||||
/* Define to 1 if your <sys/time.h> declares `struct tm'. */
|
||||
#undef TM_IN_SYS_TIME
|
||||
|
||||
/* define if we should use program's user counting function instead of
|
||||
system's */
|
||||
#undef UCOUNT
|
||||
|
||||
/* utmp like file to pass to ucount() when counting online users (unlikely to
|
||||
work) */
|
||||
#undef UTMP
|
||||
|
||||
/* Define to empty if `const' does not conform to ANSI C. */
|
||||
#undef const
|
||||
|
||||
/* Define to `int' if <sys/types.h> doesn't define. */
|
||||
#undef gid_t
|
||||
|
||||
/* Define to `int' if <sys/types.h> does not define. */
|
||||
#undef pid_t
|
||||
|
||||
/* Define to `unsigned int' if <sys/types.h> does not define. */
|
||||
#undef size_t
|
||||
|
||||
/* Define to `int' if <sys/types.h> doesn't define. */
|
||||
#undef uid_t
|
||||
|
||||
/* Define as `fork' if `vfork' does not work. */
|
||||
#undef vfork
|
||||
1608
src/cc/rogue/config.sub
vendored
1608
src/cc/rogue/config.sub
vendored
File diff suppressed because it is too large
Load Diff
7511
src/cc/rogue/configure
vendored
7511
src/cc/rogue/configure
vendored
File diff suppressed because it is too large
Load Diff
@@ -1,246 +0,0 @@
|
||||
# -*- Autoconf -*-
|
||||
# Process this file with autoconf to produce a configure script.
|
||||
|
||||
AC_PREREQ(2.56)
|
||||
AC_INIT([Rogue],[5.4.4], [yendor@rogueforge.net])
|
||||
AC_CONFIG_SRCDIR([armor.c])
|
||||
AC_CONFIG_HEADER([config.h])
|
||||
AC_CONFIG_FILES([Makefile rogue.6 rogue.cat rogue.doc rogue.html rogue.me])
|
||||
AC_CANONICAL_SYSTEM([])
|
||||
|
||||
# Checks for programs.
|
||||
AC_PROG_CC
|
||||
|
||||
# Checks for libraries.
|
||||
|
||||
# Checks for header files.
|
||||
AC_HEADER_STDC
|
||||
AC_CHECK_HEADERS([arpa/inet.h sys/utsname.h pwd.h fcntl.h limits.h nlist.h stdlib.h string.h sys/ioctl.h termios.h unistd.h utmp.h term.h ncurses/term.h process.h])
|
||||
|
||||
# Checks for typedefs, structures, and compiler characteristics.
|
||||
AC_HEADER_STDBOOL
|
||||
AC_C_CONST
|
||||
AC_TYPE_UID_T
|
||||
AC_TYPE_SIZE_T
|
||||
AC_STRUCT_TM
|
||||
MP_WITH_CURSES
|
||||
# Checks for library functions.
|
||||
AC_FUNC_FORK
|
||||
AC_PROG_GCC_TRADITIONAL
|
||||
AC_FUNC_LSTAT
|
||||
AC_FUNC_LSTAT_FOLLOWS_SLASHED_SYMLINK
|
||||
AC_TYPE_SIGNAL
|
||||
AC_FUNC_STAT
|
||||
AC_FUNC_VPRINTF
|
||||
AC_CHECK_FUNCS([erasechar killchar alarm getpass memset setenv strchr nlist _spawnl spawnl getpwuid loadav getloadavg strerror setresgid setregid setgid setresuid setreuid setuid getuid getgid])
|
||||
|
||||
AC_CHECK_PROG([NROFF], [nroff], [nroff],)
|
||||
AC_CHECK_PROG([GROFF], [groff], [groff],)
|
||||
AC_CHECK_PROG([COLCRT], [colcrt], [colcrt],)
|
||||
AC_CHECK_PROG([TBL], [tbl], [tbl],)
|
||||
AC_CHECK_PROG([SED], [sed], [sed],)
|
||||
|
||||
AC_ARG_WITH(program-name, AC_HELP_STRING([--with-program-name=NAME],[alternate executable name]),[progname="$withval" ], [progname="rogue"] )
|
||||
PROGRAM=$progname
|
||||
AC_SUBST(PROGRAM)
|
||||
|
||||
AC_ARG_ENABLE(setgid, AC_HELP_STRING([--enable-setgid=NAME],[install executable as setgid with group ownership of NAME @<:@default=no@:>@])],[],[])
|
||||
AC_MSG_CHECKING([if using setgid execute bit])
|
||||
if test "x$enable_setgid" = "xno" ; then
|
||||
GROUPOWNER=
|
||||
elif test "x$enable_setgid" = "xyes" ; then
|
||||
GROUPOWNER=games
|
||||
elif test "x$enable_setgid" = "x" ; then
|
||||
GROUPOWNER=
|
||||
else
|
||||
GROUPOWNER=$enable_setgid
|
||||
fi
|
||||
|
||||
if test "x$GROUPOWNER" != "x" ; then
|
||||
AC_DEFINE_UNQUOTED([GROUPOWNER],[$GROUPOWNER], [Define to group owner of setgid executable])
|
||||
AC_MSG_RESULT([$GROUPOWNER])
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
fi
|
||||
|
||||
AC_SUBST(GROUPOWNER)
|
||||
|
||||
AC_ARG_ENABLE([scorefile],[AC_HELP_STRING([--enable-scorefile=SCOREFILE], [enable scoreboard with given filename])],[],[])
|
||||
AC_MSG_CHECKING([for scoreboard file])
|
||||
if test "x$enable_scorefile" = "xno" ; then
|
||||
SCOREFILE=
|
||||
elif test "x$enable_scorefile" = "xyes" ; then
|
||||
SCOREFILE=$progname.scr
|
||||
elif test "x$enable_scorefile" = "x" ; then
|
||||
SCOREFILE=$progname.scr
|
||||
else
|
||||
SCOREFILE=$enable_scorefile
|
||||
fi
|
||||
|
||||
if test "x$SCOREFILE" != "x" ; then
|
||||
AC_DEFINE_UNQUOTED([SCOREFILE], ["$SCOREFILE"], [Define to file to use for scoreboard])
|
||||
AC_MSG_RESULT([$SCOREFILE])
|
||||
else
|
||||
AC_MSG_RESULT([disabled])
|
||||
fi
|
||||
|
||||
AC_SUBST(SCOREFILE)
|
||||
|
||||
AC_ARG_ENABLE([lockfile],[AC_HELP_STRING([--enable-lockfile=LOCKFILE], [enable scoreboard lockfile with given filename])],[],[])
|
||||
AC_MSG_CHECKING([for scoreboard lockfile file])
|
||||
if test "x$enable_lockfile" = "xno" ; then
|
||||
LOCKFILE=
|
||||
elif test "x$enable_lockfile" = "xyes" ; then
|
||||
LOCKFILE=$progname.lck
|
||||
elif test "x$enable_lockfile" = "x" ; then
|
||||
LOCKFILE=$progname.lck
|
||||
else
|
||||
LOCKFILE=$enable_lockfile
|
||||
fi
|
||||
|
||||
if test "x$LOCKFILE" != "x" ; then
|
||||
AC_DEFINE_UNQUOTED([LOCKFILE], ["$LOCKFILE"], [Define to file to use for scoreboard lockfile])
|
||||
AC_MSG_RESULT([$LOCKFILE])
|
||||
else
|
||||
AC_MSG_RESULT([disabled])
|
||||
fi
|
||||
|
||||
AC_SUBST(LOCKFILE)
|
||||
|
||||
AC_ARG_ENABLE([wizardmode],[AC_HELP_STRING([--enable-wizardmode], [enable availability of wizard mode @<:@default=no@:>@])],[],[])
|
||||
AC_MSG_CHECKING([if wizard mode is enabled])
|
||||
if test "x$enable_wizardmode" = "xno" ; then
|
||||
AC_MSG_RESULT([no])
|
||||
elif test "x$enable_wizardmode" = "x" ; then
|
||||
AC_MSG_RESULT([no])
|
||||
else
|
||||
AC_DEFINE([MASTER], [], [Define to include wizard mode])
|
||||
if test "x$enable_wizardmode" != "xyes" ; then
|
||||
AC_DEFINE_UNQUOTED([PASSWD],[$enable_wizardmode], [Define crypt(3) wizard mode password])
|
||||
fi
|
||||
AC_MSG_RESULT([yes])
|
||||
fi
|
||||
|
||||
AC_ARG_ENABLE([allscores],[AC_HELP_STRING([--enable-allscores], [enable scoreboard to show top scores, not just top players @<:@default=yes@:>@])],[],[enable_allscores=yes])
|
||||
AC_MSG_CHECKING([if allscores is enabled])
|
||||
if test "x$enable_allscores" = "xyes" ; then
|
||||
AC_DEFINE([ALLSCORES], [1], [Define if scorefile is top scores, not top players])
|
||||
AC_MSG_RESULT([yes])
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
fi
|
||||
|
||||
AC_ARG_ENABLE([checktime],[AC_HELP_STRING([--enable-checktime], [enable checktime @<:@default=no@:>@])],[],[])
|
||||
AC_MSG_CHECKING([if checktime is enabled])
|
||||
if test "x$enable_checktime" = "xyes" ; then
|
||||
AC_DEFINE([CHECKTIME], [1], [Define if checktime feature should be enabled])
|
||||
AC_MSG_RESULT([yes])
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
fi
|
||||
|
||||
AC_ARG_ENABLE([maxload],[AC_HELP_STRING([--enable-maxload], [enable maxload @<:@default=no@:>@])],[],[])
|
||||
AC_MSG_CHECKING([runtime execution limit (maximum system load average)])
|
||||
if test "x$enable_maxload" = "xyes" ; then
|
||||
AC_DEFINE([MAXLOAD], [100], [Define if maxload feature should be enabled])
|
||||
AC_MSG_RESULT([100])
|
||||
elif test "x$enable_maxload" = "x" ; then
|
||||
AC_MSG_RESULT([unlimited])
|
||||
elif test "x$enable_maxload" = "xno" ; then
|
||||
AC_MSG_RESULT([unlimited])
|
||||
else
|
||||
AC_DEFINE_UNQUOTED([MAXLOAD], [$enable_maxload], [Define if maxload feature should be enabled])
|
||||
AC_MSG_RESULT([$enable_maxload])
|
||||
fi
|
||||
|
||||
AC_ARG_ENABLE([maxusers],[AC_HELP_STRING([--enable-maxusers], [enable maxuser @<:@default=no@:>@])],[],[])
|
||||
AC_MSG_CHECKING([runtime execution limit (maximum online system users)])
|
||||
if test "x$enable_maxusers" = "xyes" ; then
|
||||
AC_DEFINE([MAXUSERS], [100], [Define if maxusers feature should be enabled])
|
||||
AC_MSG_RESULT([100])
|
||||
elif test "x$enable_maxusers" = "x" ; then
|
||||
AC_MSG_RESULT([unlimited])
|
||||
elif test "x$enable_maxload" = "xno" ; then
|
||||
AC_MSG_RESULT([unlimited])
|
||||
else
|
||||
AC_DEFINE_UNQUOTED([MAXLOAD], [$enable_maxusers], [Define if maxusers feature should be enabled])
|
||||
AC_MSG_RESULT([$enable_maxusers])
|
||||
fi
|
||||
|
||||
AC_ARG_ENABLE([numscores],[AC_HELP_STRING([--enable-numscores], [number of scores to store in scoreboard @<:@default=10@:>@])],[],[])
|
||||
AC_MSG_CHECKING([what the number of scores to store in scoreboard is])
|
||||
if test "x$numscores" = "xyes" ; then
|
||||
AC_DEFINE([NUMSCORES], [10], [number of scores to store in scoreboard])
|
||||
AC_MSG_RESULT([10])
|
||||
elif test "x$enable_numscores" = "x" ; then
|
||||
AC_DEFINE([NUMSCORES], [10], [number of scores to store in scoreboard])
|
||||
AC_MSG_RESULT([10])
|
||||
elif test "x$enable_numscores" = "xno" ; then
|
||||
AC_DEFINE([NUMSCORES], [10], [number of scores to store in scoreboard])
|
||||
AC_MSG_RESULT([10])
|
||||
else
|
||||
AC_DEFINE_UNQUOTED([NUMSCORES], [$enable_numscores], [number of scores to store in scoreboard])
|
||||
AC_MSG_RESULT([$enable_numscores])
|
||||
fi
|
||||
|
||||
AC_ARG_ENABLE([numname],[AC_HELP_STRING([--enable-numname], [word for number of scores to store in scoreboard @<:@default=Ten@:>@])],[],[])
|
||||
AC_MSG_CHECKING([word for the number of scores to store in scoreboard is])
|
||||
if test "x$enable_numname" = "xyes" ; then
|
||||
AC_DEFINE([NUMNAME], ["Ten"], [word for the number of scores to store in scoreboard])
|
||||
AC_MSG_RESULT([Ten])
|
||||
elif test "x$enable_numname" = "x" ; then
|
||||
AC_DEFINE([NUMNAME], ["Ten"], [word for the number of scores to store in scoreboard])
|
||||
AC_MSG_RESULT([Ten])
|
||||
elif test "x$enable_numname" = "xno" ; then
|
||||
AC_DEFINE([NUMNAME], ["Ten"], [word for the number of scores to store in scoreboard])
|
||||
AC_MSG_RESULT([Ten])
|
||||
else
|
||||
AC_DEFINE_UNQUOTED([NUMNAME], ["$enable_numname"], [word for the number of scores to store in scoreboard])
|
||||
AC_MSG_RESULT([$enable_numname])
|
||||
fi
|
||||
|
||||
AC_ARG_ENABLE([loadav],[AC_HELP_STRING([--enable-loadav=NAMELIST], [use program's load average function (unlikely to work) @<:@default=no@:>@])],[],[])
|
||||
AC_MSG_CHECKING([whether to use program's built in load average function])
|
||||
if test "x$enable_loadav" = "xyes" ; then
|
||||
AC_DEFINE([LOADAV], [], [define if we should use program's load average function instead of system])
|
||||
AC_DEFINE([NAMELIST], [/vmunix], [kernel file to pass to nlist() when reading load average (unlikely to work)])
|
||||
AC_MSG_RESULT([/vmunix])
|
||||
elif test "x$enable_loadav" = "x" ; then
|
||||
AC_MSG_RESULT([no])
|
||||
elif test "x$enable_loadav" = "xno" ; then
|
||||
AC_MSG_RESULT([no])
|
||||
else
|
||||
AC_DEFINE([LOADAV], [], [define if we should use program's load average function instead of system])
|
||||
AC_DEFINE_UNQUOTED([NAMELIST], [$enable_loadav], [kernel file to pass to nlist() when reading load average (unlikely to work)])
|
||||
AC_MSG_RESULT([$enable_loadav])
|
||||
fi
|
||||
|
||||
AC_ARG_ENABLE([ucount],[AC_HELP_STRING([--enable-ucount=UTMPFILE], [use program's own function to count users (unlikely to work) @<:@default=no@:>@])],[],[])
|
||||
AC_MSG_CHECKING([whether to use program's built in user counting function])
|
||||
if test "x$enable_ucount" = "xyes" ; then
|
||||
AC_DEFINE([UCOUNT], [], [define if we should use program's user counting function instead of system's])
|
||||
AC_DEFINE([UTMP], [/etc/utmp], [utmp like file to pass to ucount() when counting online users (unlikely to work)])
|
||||
AC_MSG_RESULT([/etc/utmp])
|
||||
elif test "x$enable_ucount" = "x" ; then
|
||||
AC_MSG_RESULT([no])
|
||||
elif test "x$enable_count" = "xno" ; then
|
||||
AC_MSG_RESULT([no])
|
||||
else
|
||||
AC_DEFINE([UCOUNT], [], [define if we should use program's user counting function instead of system's])
|
||||
AC_DEFINE_UNQUOTED([UTMP], [$enable_ucount], [utmp like file to pass to ucount() when counting online users (unlikely to work)])
|
||||
AC_MSG_RESULT([$enable_ucount])
|
||||
fi
|
||||
|
||||
TARGET=$target
|
||||
AC_SUBST(TARGET)
|
||||
|
||||
AC_MSG_CHECKING([whether to docdir is defined])
|
||||
if test "x$docdir" = "x" ; then
|
||||
AC_MSG_RESULT([docdir undefined])
|
||||
docdir=\${datadir}/doc/\${PACKAGE_TARNAME}
|
||||
AC_SUBST(docdir)
|
||||
else
|
||||
AC_MSG_RESULT([docdir defined])
|
||||
fi
|
||||
|
||||
AC_OUTPUT
|
||||
@@ -1,435 +0,0 @@
|
||||
// Copyright (c) 2016-2023 The Hush developers
|
||||
// Distributed under the GPLv3 software license, see the accompanying
|
||||
// file COPYING or https://www.gnu.org/licenses/gpl-3.0.en.html
|
||||
/******************************************************************************
|
||||
* Copyright © 2014-2019 The SuperNET Developers. *
|
||||
* *
|
||||
* See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at *
|
||||
* the top-level directory of this distribution for the individual copyright *
|
||||
* holder information and the developer policies on copyright and licensing. *
|
||||
* *
|
||||
* Unless otherwise agreed in a custom licensing agreement, no part of the *
|
||||
* SuperNET software, including this file may be copied, modified, propagated *
|
||||
* or distributed except according to the terms contained in the LICENSE file *
|
||||
* *
|
||||
* Removal or modification of this copyright notice is prohibited. *
|
||||
* *
|
||||
******************************************************************************/
|
||||
|
||||
#include "cursesd.h"
|
||||
|
||||
static int32_t endwinflag;
|
||||
WINDOW *stdscr,*curscr;
|
||||
int32_t ESCDELAY;
|
||||
|
||||
WINDOW *newwin(int32_t nlines,int32_t ncols,int32_t begin_y,int32_t begin_x)
|
||||
{
|
||||
WINDOW *scr = 0;
|
||||
if ( nlines == LINES && ncols == COLS && begin_y == 0 && begin_x == 0 )
|
||||
scr = (WINDOW *)calloc(1,sizeof(*stdscr));
|
||||
curscr = scr;
|
||||
return(scr);
|
||||
}
|
||||
|
||||
WINDOW *initscr()
|
||||
{
|
||||
if ( stdscr == 0 )
|
||||
stdscr = newwin(LINES,COLS,0,0);
|
||||
return(stdscr);
|
||||
}
|
||||
|
||||
int32_t delwin(WINDOW *win)
|
||||
{
|
||||
free(win);
|
||||
return(0);
|
||||
}
|
||||
|
||||
int32_t wmove(WINDOW *win, int32_t y, int32_t x)
|
||||
{
|
||||
win->y = y;
|
||||
win->x = x;
|
||||
return(0);
|
||||
}
|
||||
|
||||
int32_t move(int32_t y, int32_t x)
|
||||
{
|
||||
return(wmove(stdscr,y,x));
|
||||
}
|
||||
|
||||
int32_t werase(WINDOW *win)
|
||||
{
|
||||
memset(win->screen,' ',sizeof(win->screen));
|
||||
return(0);
|
||||
}
|
||||
|
||||
int32_t wclear(WINDOW *win)
|
||||
{
|
||||
werase(win);
|
||||
clearok(win,TRUE);
|
||||
return(0);
|
||||
}
|
||||
|
||||
int32_t wclrtoeol(WINDOW *win)
|
||||
{
|
||||
if ( win->x < COLS-1 )
|
||||
memset(&win->screen[win->y][win->x],' ',COLS - win->x);
|
||||
return(0);
|
||||
}
|
||||
|
||||
int32_t wclrtobot(WINDOW *win)
|
||||
{
|
||||
wclrtoeol(win);
|
||||
if ( win->y < LINES-1 )
|
||||
memset(&win->screen[win->y+1][0],' ',COLS);
|
||||
return(0);
|
||||
}
|
||||
|
||||
int32_t erase(void)
|
||||
{
|
||||
return(werase(stdscr));
|
||||
}
|
||||
|
||||
int32_t clear(void)
|
||||
{
|
||||
return(wclear(stdscr));
|
||||
}
|
||||
|
||||
int32_t clrtobot(void)
|
||||
{
|
||||
return(wclrtobot(stdscr));
|
||||
}
|
||||
|
||||
int32_t clrtoeol(void)
|
||||
{
|
||||
return(wclrtoeol(stdscr));
|
||||
}
|
||||
|
||||
int32_t waddch(WINDOW *win, chtype ch)
|
||||
{
|
||||
int32_t i;
|
||||
if ( ch == '\t' )
|
||||
{
|
||||
for (i=0; i<8; i++)
|
||||
{
|
||||
if ( win->x >= COLS-1 )
|
||||
break;
|
||||
win->x++;
|
||||
if ( (win->x & 7) == 0 )
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if ( ch == '\n' )
|
||||
{
|
||||
wclrtoeol(win);
|
||||
win->x = 0;
|
||||
win->y++;
|
||||
if ( win->y >= LINES )
|
||||
win->y = 0;
|
||||
}
|
||||
else if ( ch == '\b' )
|
||||
{
|
||||
if ( win->x > 0 )
|
||||
win->x--;
|
||||
}
|
||||
else
|
||||
{
|
||||
win->screen[win->y][win->x++] = ch;
|
||||
if ( win->x >= COLS )
|
||||
{
|
||||
win->x = 0;
|
||||
win->y++;
|
||||
if ( win->y >= LINES )
|
||||
win->y = 0;
|
||||
}
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
int32_t mvwaddch(WINDOW *win, int32_t y, int32_t x, chtype ch)
|
||||
{
|
||||
win->y = y;
|
||||
win->x = x;
|
||||
return(waddch(win,ch));
|
||||
}
|
||||
|
||||
int32_t addch(chtype ch)
|
||||
{
|
||||
return(waddch(stdscr,ch));
|
||||
}
|
||||
|
||||
int32_t mvaddch(int32_t y, int32_t x, chtype ch)
|
||||
{
|
||||
return(mvwaddch(stdscr,y,x,ch));
|
||||
}
|
||||
|
||||
int32_t waddstr(WINDOW *win, const char *str)
|
||||
{
|
||||
int32_t i;
|
||||
//fprintf(stderr,"%s\n",str);
|
||||
for (i=0; str[i]!=0; i++)
|
||||
waddch(win,str[i]);
|
||||
return(0);
|
||||
}
|
||||
|
||||
int32_t waddnstr(WINDOW *win, const char *str, int32_t n)
|
||||
{
|
||||
int32_t i;
|
||||
for (i=0; str[i]!=0 && i<n; i++)
|
||||
waddch(win,str[i]);
|
||||
return(0);
|
||||
}
|
||||
|
||||
int32_t mvwaddstr(WINDOW *win, int32_t y, int32_t x, const char *str)
|
||||
{
|
||||
win->y = y;
|
||||
win->x = x;
|
||||
return(waddstr(win,str));
|
||||
}
|
||||
|
||||
int32_t mvwaddnstr(WINDOW *win, int32_t y, int32_t x, const char *str, int32_t n)
|
||||
{
|
||||
win->y = y;
|
||||
win->x = x;
|
||||
return(waddnstr(win,str,n));
|
||||
}
|
||||
|
||||
int32_t addstr(const char *str)
|
||||
{
|
||||
return(waddstr(stdscr,str));
|
||||
}
|
||||
|
||||
int32_t addnstr(const char *str, int32_t n)
|
||||
{
|
||||
return(waddnstr(stdscr,str,n));
|
||||
}
|
||||
|
||||
int32_t mvaddstr(int32_t y, int32_t x, const char *str)
|
||||
{
|
||||
stdscr->y = y;
|
||||
stdscr->x = x;
|
||||
return(waddstr(stdscr,str));
|
||||
}
|
||||
|
||||
int32_t mvaddnstr(int32_t y, int32_t x, const char *str, int32_t n)
|
||||
{
|
||||
stdscr->y = y;
|
||||
stdscr->x = x;
|
||||
return(waddnstr(stdscr,str,n));
|
||||
}
|
||||
|
||||
int32_t printw(char *fmt,...)
|
||||
{
|
||||
char str[512]; int32_t ret; va_list myargs; // Declare a va_list type variable
|
||||
va_start(myargs,fmt); // Initialise the va_list variable with the ... after fmt
|
||||
ret = vsprintf(str,fmt,myargs); // Forward the '...' to vsprintf
|
||||
va_end(myargs); // Clean up the va_list
|
||||
return(addstr(str));
|
||||
}
|
||||
|
||||
int32_t wprintw(WINDOW *win,char *fmt,...)
|
||||
{
|
||||
char str[512]; int32_t ret; va_list myargs; // Declare a va_list type variable
|
||||
va_start(myargs,fmt); // Initialise the va_list variable with the ... after fmt
|
||||
ret = vsprintf(str,fmt,myargs); // Forward the '...' to vsprintf
|
||||
va_end(myargs); // Clean up the va_list
|
||||
return(waddstr(win,str));
|
||||
}
|
||||
|
||||
int32_t mvprintw(int32_t y,int32_t x,char *fmt,...)
|
||||
{
|
||||
char str[512]; int32_t ret; va_list myargs; // Declare a va_list type variable
|
||||
va_start(myargs,fmt); // Initialise the va_list variable with the ... after fmt
|
||||
ret = vsprintf(str,fmt,myargs); // Forward the '...' to vsprintf
|
||||
va_end(myargs); // Clean up the va_list
|
||||
stdscr->y = y;
|
||||
stdscr->x = x;
|
||||
return(addstr(str));
|
||||
}
|
||||
|
||||
int32_t mvwprintw(WINDOW *win,int32_t y,int32_t x,char *fmt,...)
|
||||
{
|
||||
char str[512]; int32_t ret; va_list myargs; // Declare a va_list type variable
|
||||
va_start(myargs,fmt); // Initialise the va_list variable with the ... after fmt
|
||||
ret = vsprintf(str,fmt,myargs); // Forward the '...' to vsprintf
|
||||
va_end(myargs); // Clean up the va_list
|
||||
win->y = y;
|
||||
win->x = x;
|
||||
return(waddstr(win,str));
|
||||
}
|
||||
|
||||
chtype winch(WINDOW *win)
|
||||
{
|
||||
return(win->screen[win->y][win->x]);
|
||||
}
|
||||
|
||||
chtype inch(void)
|
||||
{
|
||||
return(winch(stdscr));
|
||||
}
|
||||
|
||||
chtype mvwinch(WINDOW *win, int32_t y, int32_t x)
|
||||
{
|
||||
win->y = y;
|
||||
win->x = x;
|
||||
return(win->screen[win->y][win->x]);
|
||||
}
|
||||
|
||||
chtype mvinch(int32_t y, int32_t x)
|
||||
{
|
||||
return(mvwinch(stdscr,y,x));
|
||||
}
|
||||
|
||||
int32_t mvcur(int32_t oldrow, int32_t oldcol, int32_t newrow, int32_t newcol)
|
||||
{
|
||||
stdscr->y = newrow;
|
||||
stdscr->x = newcol;
|
||||
return(0);
|
||||
}
|
||||
|
||||
int32_t endwin(void)
|
||||
{
|
||||
if ( stdscr != 0 )
|
||||
free(stdscr), stdscr = 0;
|
||||
endwinflag = 1;
|
||||
return(0);
|
||||
}
|
||||
|
||||
int32_t isendwin(void)
|
||||
{
|
||||
return(endwinflag);
|
||||
}
|
||||
|
||||
int32_t refresh(void)
|
||||
{
|
||||
endwinflag = 0;
|
||||
return(wrefresh(stdscr));
|
||||
}
|
||||
|
||||
int32_t redrawwin(WINDOW *win)
|
||||
{
|
||||
return(wrefresh(win));
|
||||
}
|
||||
|
||||
int32_t wredrawln(WINDOW *win, int32_t beg_line, int32_t num_lines)
|
||||
{
|
||||
return(wrefresh(win));
|
||||
}
|
||||
|
||||
// functions with no data side effect
|
||||
#ifdef they_are_macros
|
||||
int32_t wrefresh(WINDOW *win)
|
||||
{
|
||||
return(0);
|
||||
}
|
||||
|
||||
int32_t wnoutrefresh(WINDOW *win)
|
||||
{
|
||||
return(0);
|
||||
}
|
||||
|
||||
int32_t doupdate(void)
|
||||
{
|
||||
return(0);
|
||||
}
|
||||
|
||||
int32_t touchwin(WINDOW *win)
|
||||
{
|
||||
return(0);
|
||||
}
|
||||
|
||||
int32_t standout(void)
|
||||
{
|
||||
return(0);
|
||||
}
|
||||
|
||||
int32_t standend(void)
|
||||
{
|
||||
return(0);
|
||||
}
|
||||
|
||||
int32_t raw(void)
|
||||
{
|
||||
return(0);
|
||||
}
|
||||
|
||||
int32_t keypad(WINDOW *win, bool bf)
|
||||
{
|
||||
return(0);
|
||||
}
|
||||
|
||||
int32_t noecho(void)
|
||||
{
|
||||
return(0);
|
||||
}
|
||||
|
||||
int32_t flushinp(void)
|
||||
{
|
||||
return(0);
|
||||
}
|
||||
|
||||
int32_t clearok(WINDOW *win, bool bf)
|
||||
{
|
||||
return(0);
|
||||
}
|
||||
|
||||
int32_t idlok(WINDOW *win, bool bf)
|
||||
{
|
||||
return(0);
|
||||
}
|
||||
|
||||
int32_t leaveok(WINDOW *win, bool bf)
|
||||
{
|
||||
return(0);
|
||||
}
|
||||
#endif
|
||||
|
||||
int32_t mvwin(WINDOW *win, int32_t y, int32_t x) // stub
|
||||
{
|
||||
fprintf(stderr,"unexpected call to mvwin\n");
|
||||
return(0);
|
||||
}
|
||||
|
||||
WINDOW *subwin(WINDOW *orig, int32_t nlines, int32_t ncols, int32_t begin_y, int32_t begin_x)
|
||||
{
|
||||
fprintf(stderr,"unexpected and unsupported call to subwin\n");
|
||||
return(0);
|
||||
}
|
||||
|
||||
char erasechar(void)
|
||||
{
|
||||
fprintf(stderr,"unexpected and unsupported call to erasechar\n");
|
||||
return(8);
|
||||
}
|
||||
|
||||
char killchar(void)
|
||||
{
|
||||
fprintf(stderr,"unexpected and unsupported call to erasechar\n");
|
||||
return(3);
|
||||
}
|
||||
|
||||
int32_t wgetnstr(WINDOW *win, char *str, int32_t n) // stub
|
||||
{
|
||||
fprintf(stderr,"unexpected and unsupported call to mvgetnstr\n");
|
||||
return(0);
|
||||
}
|
||||
|
||||
#ifndef __MINGW32__
|
||||
int32_t getch(void)
|
||||
{
|
||||
fprintf(stderr,"unexpected and unsupported call to getch\n");
|
||||
return(0);
|
||||
}
|
||||
#endif
|
||||
|
||||
int32_t md_readchar(void)
|
||||
{
|
||||
fprintf(stderr,"unexpected and unsupported call to md_readchar\n");
|
||||
return(0);
|
||||
}
|
||||
|
||||
char *unctrl(char c)
|
||||
{
|
||||
static char ctrlstr[5];
|
||||
sprintf(ctrlstr,"^%%%02x",c);
|
||||
return(ctrlstr);
|
||||
}
|
||||
@@ -1,201 +0,0 @@
|
||||
// Copyright (c) 2016-2023 The Hush developers
|
||||
// Distributed under the GPLv3 software license, see the accompanying
|
||||
// file COPYING or https://www.gnu.org/licenses/gpl-3.0.en.html
|
||||
/******************************************************************************
|
||||
* Copyright © 2014-2019 The SuperNET Developers. *
|
||||
* *
|
||||
* See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at *
|
||||
* the top-level directory of this distribution for the individual copyright *
|
||||
* holder information and the developer policies on copyright and licensing. *
|
||||
* *
|
||||
* Unless otherwise agreed in a custom licensing agreement, no part of the *
|
||||
* SuperNET software, including this file may be copied, modified, propagated *
|
||||
* or distributed except according to the terms contained in the LICENSE file *
|
||||
* *
|
||||
* Removal or modification of this copyright notice is prohibited. *
|
||||
* *
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef H_CURSESD_H
|
||||
#define H_CURSESD_H
|
||||
|
||||
#define KEY_OFFSET 0x100
|
||||
#define KEY_DOWN (KEY_OFFSET + 0x02) /* Down arrow key */
|
||||
#define KEY_UP (KEY_OFFSET + 0x03) /* Up arrow key */
|
||||
#define KEY_LEFT (KEY_OFFSET + 0x04) /* Left arrow key */
|
||||
#define KEY_RIGHT (KEY_OFFSET + 0x05) /* Right arrow key */
|
||||
|
||||
|
||||
#define COLOR_BLACK 0
|
||||
|
||||
#ifdef PDC_RGB /* RGB */
|
||||
# define COLOR_RED 1
|
||||
# define COLOR_GREEN 2
|
||||
# define COLOR_BLUE 4
|
||||
#else /* BGR */
|
||||
# define COLOR_BLUE 1
|
||||
# define COLOR_GREEN 2
|
||||
# define COLOR_RED 4
|
||||
#endif
|
||||
|
||||
#define COLOR_CYAN (COLOR_BLUE | COLOR_GREEN)
|
||||
#define COLOR_MAGENTA (COLOR_RED | COLOR_BLUE)
|
||||
#define COLOR_YELLOW (COLOR_RED | COLOR_GREEN)
|
||||
|
||||
#define COLOR_WHITE 7
|
||||
|
||||
#define LINES 24
|
||||
#define COLS 80
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <memory.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <stdarg.h> /* we need va_list */
|
||||
#include <stddef.h> /* we want wchar_t */
|
||||
#include <stdbool.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include <time.h>
|
||||
#include <sys/types.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <errno.h>
|
||||
|
||||
#define ERR (-1)
|
||||
|
||||
struct cursesd_info
|
||||
{
|
||||
uint8_t screen[LINES][COLS];
|
||||
int32_t x,y;
|
||||
};
|
||||
typedef struct cursesd_info WINDOW;
|
||||
extern WINDOW *stdscr,*curscr;
|
||||
extern int32_t ESCDELAY;
|
||||
typedef char chtype;
|
||||
|
||||
#ifndef __MINGW32__
|
||||
int32_t getch(void); // stub
|
||||
#endif
|
||||
|
||||
int32_t md_readchar(void); // stub
|
||||
|
||||
WINDOW *initscr(void);
|
||||
int32_t endwin(void);
|
||||
int32_t isendwin(void);
|
||||
//SCREEN *newterm(const char *type, FILE *outfd, FILE *infd);
|
||||
//SCREEN *set_term(SCREEN *new);
|
||||
//void delscreen(SCREEN* sp);
|
||||
|
||||
int32_t refresh(void);
|
||||
int32_t wrefresh(WINDOW *win);
|
||||
//int32_t wnoutrefresh(WINDOW *win);
|
||||
//int32_t doupdate(void);
|
||||
int32_t redrawwin(WINDOW *win);
|
||||
int32_t wredrawln(WINDOW *win, int32_t beg_line, int32_t num_lines);
|
||||
|
||||
int32_t erase(void);
|
||||
int32_t werase(WINDOW *win);
|
||||
int32_t clear(void);
|
||||
int32_t wclear(WINDOW *win);
|
||||
int32_t clrtobot(void);
|
||||
int32_t wclrtobot(WINDOW *win);
|
||||
int32_t clrtoeol(void);
|
||||
int32_t wclrtoeol(WINDOW *win);
|
||||
|
||||
int32_t standout(void);
|
||||
int32_t standend(void);
|
||||
int32_t raw(void);
|
||||
int32_t noecho(void);
|
||||
int32_t flushinp(void);
|
||||
int32_t keypad(WINDOW *win, bool bf);
|
||||
|
||||
int32_t clearok(WINDOW *win, bool bf);
|
||||
int32_t idlok(WINDOW *win, bool bf);
|
||||
int32_t leaveok(WINDOW *win, bool bf);
|
||||
|
||||
WINDOW *newwin(int32_t nlines,int32_t ncols,int32_t begin_y,int32_t begin_x); // only LINES,COLS,0,0
|
||||
int32_t delwin(WINDOW *win);
|
||||
int32_t touchwin(WINDOW *win); // stub
|
||||
WINDOW *subwin(WINDOW *orig, int32_t nlines, int32_t ncols, int32_t begin_y, int32_t begin_x); // stub
|
||||
int32_t mvwin(WINDOW *win, int32_t y, int32_t x); // stub
|
||||
int32_t mvcur(int32_t oldrow, int32_t oldcol, int32_t newrow, int32_t newcol);
|
||||
|
||||
char erasechar(void); // stub
|
||||
char killchar(void); // stub
|
||||
|
||||
int32_t move(int32_t y, int32_t x);
|
||||
int32_t wmove(WINDOW *win, int32_t y, int32_t x);
|
||||
|
||||
chtype inch(void);
|
||||
chtype winch(WINDOW *win);
|
||||
chtype mvinch(int32_t y, int32_t x);
|
||||
chtype mvwinch(WINDOW *win, int32_t y, int32_t x);
|
||||
|
||||
int32_t addch(chtype ch);
|
||||
int32_t waddch(WINDOW *win, chtype ch);
|
||||
int32_t mvaddch(int32_t y, int32_t x, chtype ch);
|
||||
int32_t mvwaddch(WINDOW *win, int32_t y, int32_t x, chtype ch);
|
||||
|
||||
int32_t addstr(const char *str);
|
||||
int32_t addnstr(const char *str, int32_t n);
|
||||
int32_t waddstr(WINDOW *win, const char *str);
|
||||
int32_t waddnstr(WINDOW *win, const char *str, int32_t n);
|
||||
int32_t mvaddstr(int32_t y, int32_t x, const char *str);
|
||||
int32_t mvaddnstr(int32_t y, int32_t x, const char *str, int32_t n);
|
||||
int32_t mvwaddstr(WINDOW *win, int32_t y, int32_t x, const char *str);
|
||||
int32_t mvwaddnstr(WINDOW *win, int32_t y, int32_t x, const char *str, int32_t n);
|
||||
|
||||
int32_t wgetnstr(WINDOW *win, char *str, int32_t n); // stub
|
||||
int32_t printw(char *fmt,...);
|
||||
int32_t wprintw(WINDOW *win,char *fmt,...);
|
||||
int32_t mvprintw(int32_t y,int32_t x,char *fmt,...);
|
||||
int32_t mvwprintw(WINDOW *win,int32_t y,int32_t x,char *fmt,...);
|
||||
|
||||
char *unctrl(char c);
|
||||
|
||||
#define A_CHARTEXT 0xff
|
||||
#define baudrate() 9600
|
||||
#define getmaxx(a) COLS
|
||||
#define getmaxy(a) LINES
|
||||
#define getyx(win,_argfory,_argforx) _argfory = win->y, _argforx = win->x
|
||||
|
||||
// functions with only visible effects
|
||||
#define wrefresh(win) 0
|
||||
#define wnoutrefresh(win) 0
|
||||
#define doupdate() 0
|
||||
#define touchwin(win) 0
|
||||
#define standout() 0
|
||||
#define standend() 0
|
||||
#define raw() 0
|
||||
#define keypad(win,bf) 0
|
||||
#define noecho() 0
|
||||
#define flushinp() 0
|
||||
#define clearok(win,bf) 0
|
||||
#define idlok(win,bf) 0
|
||||
#define leaveok(win,bf) 0
|
||||
#define halfdelay(x) 0
|
||||
#define nocbreak() 0
|
||||
#define cbreak() 0
|
||||
#define curs_set(x) 0
|
||||
|
||||
// for tetris
|
||||
#define init_pair(a,b,c) 0
|
||||
#define start_color() 0
|
||||
#define box(a,b,c) 0
|
||||
#define A_REVERSE 0
|
||||
#define COLOR_PAIR(a) 0
|
||||
#define timeout(x) 0
|
||||
// end for tetris
|
||||
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
#endif
|
||||
#ifndef FALSE
|
||||
#define FALSE 0
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,219 +0,0 @@
|
||||
// Copyright (c) 2016-2023 The Hush developers
|
||||
// Distributed under the GPLv3 software license, see the accompanying
|
||||
// file COPYING or https://www.gnu.org/licenses/gpl-3.0.en.html
|
||||
/*
|
||||
* Contains functions for dealing with things that happen in the
|
||||
* future.
|
||||
*
|
||||
* @(#)daemon.c 4.7 (Berkeley) 02/05/99
|
||||
*
|
||||
* Rogue: Exploring the Dungeons of Doom
|
||||
* Copyright (C) 1980-1983, 1985, 1999 Michael Toy, Ken Arnold and Glenn Wichman
|
||||
* All rights reserved.
|
||||
*
|
||||
* See the file LICENSE.TXT for full copyright and licensing information.
|
||||
*/
|
||||
|
||||
//#include <curses.h>
|
||||
#include "rogue.h"
|
||||
|
||||
#define EMPTY 0
|
||||
#define DAEMON -1
|
||||
#define MAXDAEMONS 20
|
||||
|
||||
#define _X_ { EMPTY }
|
||||
|
||||
struct delayed_action d_list[MAXDAEMONS] = {
|
||||
_X_, _X_, _X_, _X_, _X_, _X_, _X_, _X_, _X_, _X_,
|
||||
_X_, _X_, _X_, _X_, _X_, _X_, _X_, _X_, _X_, _X_,
|
||||
};
|
||||
|
||||
/*
|
||||
* d_slot:
|
||||
* Find an empty slot in the daemon/fuse list
|
||||
*/
|
||||
struct delayed_action *
|
||||
d_slot()
|
||||
{
|
||||
register struct delayed_action *dev;
|
||||
|
||||
for (dev = d_list; dev <= &d_list[MAXDAEMONS-1]; dev++)
|
||||
if (dev->d_type == EMPTY)
|
||||
return dev;
|
||||
#ifdef MASTER
|
||||
debug("Ran out of fuse slots");
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* find_slot:
|
||||
* Find a particular slot in the table
|
||||
*/
|
||||
struct delayed_action *
|
||||
find_slot(void (*func)(struct rogue_state *rs,int))
|
||||
{
|
||||
register struct delayed_action *dev;
|
||||
|
||||
for (dev = d_list; dev <= &d_list[MAXDAEMONS-1]; dev++)
|
||||
if (dev->d_type != EMPTY && func == dev->d_func)
|
||||
return dev;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* start_daemon:
|
||||
* Start a daemon, takes a function.
|
||||
*/
|
||||
void
|
||||
start_daemon(void (*func)(struct rogue_state *rs,int), int arg, int type)
|
||||
{
|
||||
register struct delayed_action *dev;
|
||||
|
||||
dev = d_slot();
|
||||
dev->d_type = type;
|
||||
dev->d_func = func;
|
||||
dev->d_arg = arg;
|
||||
dev->d_time = DAEMON;
|
||||
}
|
||||
|
||||
/*
|
||||
* kill_daemon:
|
||||
* Remove a daemon from the list
|
||||
*/
|
||||
void
|
||||
kill_daemon(void (*func)(struct rogue_state *rs,int))
|
||||
{
|
||||
register struct delayed_action *dev;
|
||||
|
||||
if ((dev = find_slot(func)) == NULL)
|
||||
return;
|
||||
/*
|
||||
* Take it out of the list
|
||||
*/
|
||||
dev->d_type = EMPTY;
|
||||
}
|
||||
|
||||
/*
|
||||
* do_daemons:
|
||||
* Run all the daemons that are active with the current flag,
|
||||
* passing the argument to the function.
|
||||
*/
|
||||
void
|
||||
do_daemons(struct rogue_state *rs,int flag)
|
||||
{
|
||||
register struct delayed_action *dev;
|
||||
|
||||
/*
|
||||
* Loop through the devil list
|
||||
*/
|
||||
for (dev = d_list; dev <= &d_list[MAXDAEMONS-1]; dev++)
|
||||
/*
|
||||
* Executing each one, giving it the proper arguments
|
||||
*/
|
||||
if (dev->d_type == flag && dev->d_time == DAEMON)
|
||||
(*dev->d_func)(rs,dev->d_arg);
|
||||
}
|
||||
|
||||
/*
|
||||
* fuse:
|
||||
* Start a fuse to go off in a certain number of turns
|
||||
*/
|
||||
void
|
||||
fuse(void (*func)(struct rogue_state *rs,int), int arg, int time, int type)
|
||||
{
|
||||
register struct delayed_action *wire;
|
||||
|
||||
wire = d_slot();
|
||||
wire->d_type = type;
|
||||
wire->d_func = func;
|
||||
wire->d_arg = arg;
|
||||
wire->d_time = time;
|
||||
}
|
||||
|
||||
/*
|
||||
* lengthen:
|
||||
* Increase the time until a fuse goes off
|
||||
*/
|
||||
void
|
||||
lengthen(void (*func)(struct rogue_state *rs,int), int xtime)
|
||||
{
|
||||
register struct delayed_action *wire;
|
||||
|
||||
if ((wire = find_slot(func)) == NULL)
|
||||
return;
|
||||
wire->d_time += xtime;
|
||||
}
|
||||
|
||||
/*
|
||||
* extinguish:
|
||||
* Put out a fuse
|
||||
*/
|
||||
void
|
||||
extinguish(void (*func)(struct rogue_state *rs,int))
|
||||
{
|
||||
register struct delayed_action *wire;
|
||||
|
||||
if ((wire = find_slot(func)) == NULL)
|
||||
return;
|
||||
wire->d_type = EMPTY;
|
||||
}
|
||||
|
||||
/*
|
||||
* do_fuses:
|
||||
* Decrement counters and start needed fuses
|
||||
*/
|
||||
|
||||
/*char *actionfunc_str(char *str,void *ptr)
|
||||
{
|
||||
if ( ptr == (void *)runners )
|
||||
strcpy(str,"runners");
|
||||
else if ( ptr == (void *)doctor )
|
||||
strcpy(str,"doctor");
|
||||
else if ( ptr == (void *)stomach )
|
||||
strcpy(str,"stomach");
|
||||
else if ( ptr == (void *)nohaste )
|
||||
strcpy(str,"nohaste");
|
||||
else if ( ptr == (void *)unconfuse )
|
||||
strcpy(str,"unconfuse");
|
||||
else if ( ptr == (void *)swander )
|
||||
strcpy(str,"swander");
|
||||
else if ( ptr == (void *)come_down )
|
||||
strcpy(str,"come_down");
|
||||
else if ( ptr == (void *)unsee )
|
||||
strcpy(str,"unsee");
|
||||
else if ( ptr == (void *)sight )
|
||||
strcpy(str,"sight");
|
||||
else if ( ptr == (void *)land )
|
||||
strcpy(str,"land");
|
||||
else if ( ptr == (void *)rollwand )
|
||||
strcpy(str,"rollwand");
|
||||
else if ( ptr == (void *)visuals )
|
||||
strcpy(str,"visuals");
|
||||
else if ( ptr == (void *)turn_see )
|
||||
strcpy(str,"turn_see");
|
||||
else strcpy(str,"no match");
|
||||
return(str);
|
||||
}*/
|
||||
|
||||
void
|
||||
do_fuses(struct rogue_state *rs,int flag)
|
||||
{
|
||||
register struct delayed_action *wire; char str[64];
|
||||
|
||||
/*
|
||||
* Step though the list
|
||||
*/
|
||||
for (wire = d_list; wire <= &d_list[MAXDAEMONS-1]; wire++)
|
||||
/*
|
||||
* Decrementing counters and starting things we want. We also need
|
||||
* to remove the fuse from the list once it has gone off.
|
||||
*/
|
||||
if (flag == wire->d_type && wire->d_time > 0 && --wire->d_time == 0)
|
||||
{
|
||||
//if ( fp != 0 )
|
||||
// fprintf(fp,"t.%d %d %s, ",wire->d_type,wire->d_time,actionfunc_str(str,wire->d_func));
|
||||
wire->d_type = EMPTY;
|
||||
(*wire->d_func)(rs,wire->d_arg);
|
||||
}
|
||||
}
|
||||
@@ -1,364 +0,0 @@
|
||||
// Copyright (c) 2016-2023 The Hush developers
|
||||
// Distributed under the GPLv3 software license, see the accompanying
|
||||
// file COPYING or https://www.gnu.org/licenses/gpl-3.0.en.html
|
||||
/*
|
||||
* All the daemon and fuse functions are in here
|
||||
*
|
||||
* @(#)daemons.c 4.24 (Berkeley) 02/05/99
|
||||
*
|
||||
* Rogue: Exploring the Dungeons of Doom
|
||||
* Copyright (C) 1980-1983, 1985, 1999 Michael Toy, Ken Arnold and Glenn Wichman
|
||||
* All rights reserved.
|
||||
*
|
||||
* See the file LICENSE.TXT for full copyright and licensing information.
|
||||
*/
|
||||
|
||||
//#include <curses.h>
|
||||
#include "rogue.h"
|
||||
|
||||
/*
|
||||
* doctor:
|
||||
* A healing daemon that restors hit points after rest
|
||||
*/
|
||||
void
|
||||
doctor(struct rogue_state *rs,int arg)
|
||||
{
|
||||
register int lv, ohp;
|
||||
if ( rs->logfp != 0 )
|
||||
fprintf(rs->logfp,"doctor\n");
|
||||
|
||||
lv = pstats.s_lvl;
|
||||
ohp = pstats.s_hpt;
|
||||
quiet++;
|
||||
if (lv < 8)
|
||||
{
|
||||
if (quiet + (lv << 1) > 20)
|
||||
pstats.s_hpt++;
|
||||
}
|
||||
else
|
||||
if (quiet >= 3)
|
||||
pstats.s_hpt += rnd(lv - 7) + 1;
|
||||
if (ISRING(LEFT, R_REGEN))
|
||||
pstats.s_hpt++;
|
||||
if (ISRING(RIGHT, R_REGEN))
|
||||
pstats.s_hpt++;
|
||||
if (ohp != pstats.s_hpt)
|
||||
{
|
||||
if (pstats.s_hpt > max_hp)
|
||||
pstats.s_hpt = max_hp;
|
||||
quiet = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Swander:
|
||||
* Called when it is time to start rolling for wandering monsters
|
||||
*/
|
||||
void
|
||||
swander(struct rogue_state *rs,int arg)
|
||||
{
|
||||
if ( rs->logfp != 0 )
|
||||
fprintf(rs->logfp,"swander\n");
|
||||
start_daemon(rollwand, 0, BEFORE);
|
||||
}
|
||||
|
||||
/*
|
||||
* rollwand:
|
||||
* Called to roll to see if a wandering monster starts up
|
||||
*/
|
||||
int between = 0;
|
||||
void
|
||||
rollwand(struct rogue_state *rs,int arg)
|
||||
{
|
||||
if ( rs->logfp != 0 )
|
||||
fprintf(rs->logfp,"rollwand\n");
|
||||
if (++between >= 4)
|
||||
{
|
||||
if (roll(1, 6) == 4)
|
||||
{
|
||||
wanderer(rs);
|
||||
kill_daemon(rollwand);
|
||||
fuse(swander, 0, WANDERTIME, BEFORE);
|
||||
}
|
||||
between = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* unconfuse:
|
||||
* Release the poor player from his confusion
|
||||
*/
|
||||
void
|
||||
unconfuse(struct rogue_state *rs,int arg)
|
||||
{
|
||||
if ( rs->logfp != 0 )
|
||||
fprintf(rs->logfp,"unconfuse\n");
|
||||
player.t_flags &= ~ISHUH;
|
||||
msg(rs,"you feel less %s now", choose_str("trippy", "confused"));
|
||||
}
|
||||
|
||||
/*
|
||||
* unsee:
|
||||
* Turn off the ability to see invisible
|
||||
*/
|
||||
void
|
||||
unsee(struct rogue_state *rs,int arg)
|
||||
{
|
||||
register THING *th;
|
||||
if ( rs->logfp != 0 )
|
||||
fprintf(rs->logfp,"unsee\n");
|
||||
|
||||
for (th = mlist; th != NULL; th = next(th))
|
||||
if (on(*th, ISINVIS) && see_monst(th))
|
||||
mvaddch(th->t_pos.y, th->t_pos.x, th->t_oldch);
|
||||
player.t_flags &= ~CANSEE;
|
||||
}
|
||||
|
||||
/*
|
||||
* sight:
|
||||
* He gets his sight back
|
||||
*/
|
||||
void
|
||||
sight(struct rogue_state *rs,int arg)
|
||||
{
|
||||
if ( rs->logfp != 0 )
|
||||
fprintf(rs->logfp,"sight\n");
|
||||
if (on(player, ISBLIND))
|
||||
{
|
||||
extinguish(sight);
|
||||
player.t_flags &= ~ISBLIND;
|
||||
if (!(proom->r_flags & ISGONE))
|
||||
enter_room(rs,&hero);
|
||||
msg(rs,choose_str("far out! Everything is all cosmic again",
|
||||
"the veil of darkness lifts"));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* nohaste:
|
||||
* End the hasting
|
||||
*/
|
||||
void
|
||||
nohaste(struct rogue_state *rs,int arg)
|
||||
{
|
||||
if ( rs->logfp != 0 )
|
||||
fprintf(rs->logfp,"nohaste\n");
|
||||
player.t_flags &= ~ISHASTE;
|
||||
msg(rs,"you feel yourself slowing down");
|
||||
}
|
||||
|
||||
/*
|
||||
* stomach:
|
||||
* Digest the hero's food
|
||||
*/
|
||||
void
|
||||
stomach(struct rogue_state *rs,int arg)
|
||||
{
|
||||
register int oldfood;
|
||||
int orig_hungry = hungry_state;
|
||||
if ( rs->logfp != 0 )
|
||||
fprintf(rs->logfp,"stomach\n");
|
||||
|
||||
if (food_left <= 0)
|
||||
{
|
||||
if (food_left-- < -STARVETIME)
|
||||
death(rs,'s');
|
||||
/*
|
||||
* the hero is fainting
|
||||
*/
|
||||
if (no_command || rnd(5) != 0)
|
||||
return;
|
||||
no_command += rnd(8) + 4;
|
||||
hungry_state = 3;
|
||||
if (!terse)
|
||||
addmsg(rs,choose_str("the munchies overpower your motor capabilities. ",
|
||||
"you feel too weak from lack of food. "));
|
||||
msg(rs,choose_str("You freak out", "You faint"));
|
||||
}
|
||||
else
|
||||
{
|
||||
oldfood = food_left;
|
||||
food_left -= ring_eat(LEFT) + ring_eat(RIGHT) + 1 - amulet;
|
||||
|
||||
if (food_left < MORETIME && oldfood >= MORETIME)
|
||||
{
|
||||
hungry_state = 2;
|
||||
msg(rs,choose_str("the munchies are interfering with your motor capabilites",
|
||||
"you are starting to feel weak"));
|
||||
}
|
||||
else if (food_left < 2 * MORETIME && oldfood >= 2 * MORETIME)
|
||||
{
|
||||
hungry_state = 1;
|
||||
if (terse)
|
||||
msg(rs,choose_str("getting the munchies", "getting hungry"));
|
||||
else
|
||||
msg(rs,choose_str("you are getting the munchies",
|
||||
"you are starting to get hungry"));
|
||||
}
|
||||
}
|
||||
if (hungry_state != orig_hungry) {
|
||||
player.t_flags &= ~ISRUN;
|
||||
running = FALSE;
|
||||
to_death = FALSE;
|
||||
count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* come_down:
|
||||
* Take the hero down off her acid trip.
|
||||
*/
|
||||
void
|
||||
come_down(struct rogue_state *rs,int arg)
|
||||
{
|
||||
register THING *tp;
|
||||
register bool seemonst;
|
||||
|
||||
if ( rs->logfp != 0 )
|
||||
fprintf(rs->logfp,"come_down\n");
|
||||
if (!on(player, ISHALU))
|
||||
return;
|
||||
|
||||
kill_daemon(visuals);
|
||||
player.t_flags &= ~ISHALU;
|
||||
|
||||
if (on(player, ISBLIND))
|
||||
return;
|
||||
|
||||
/*
|
||||
* undo the things
|
||||
*/
|
||||
for (tp = lvl_obj; tp != NULL; tp = next(tp))
|
||||
if (cansee(rs,tp->o_pos.y, tp->o_pos.x))
|
||||
mvaddch(tp->o_pos.y, tp->o_pos.x, tp->o_type);
|
||||
|
||||
/*
|
||||
* undo the monsters
|
||||
*/
|
||||
seemonst = on(player, SEEMONST);
|
||||
for (tp = mlist; tp != NULL; tp = next(tp))
|
||||
{
|
||||
move(tp->t_pos.y, tp->t_pos.x);
|
||||
if (cansee(rs,tp->t_pos.y, tp->t_pos.x))
|
||||
if (!on(*tp, ISINVIS) || on(player, CANSEE))
|
||||
addch(tp->t_disguise);
|
||||
else
|
||||
addch(chat(tp->t_pos.y, tp->t_pos.x));
|
||||
else if (seemonst)
|
||||
{
|
||||
standout();
|
||||
addch(tp->t_type);
|
||||
standend();
|
||||
}
|
||||
}
|
||||
msg(rs,"Everything looks SO boring now.");
|
||||
}
|
||||
|
||||
/*
|
||||
* visuals:
|
||||
* change the characters for the player
|
||||
*/
|
||||
void
|
||||
visuals(struct rogue_state *rs,int arg)
|
||||
{
|
||||
register THING *tp;
|
||||
register bool seemonst;
|
||||
|
||||
if (!after || (running && jump))
|
||||
return;
|
||||
if ( rs->logfp != 0 )
|
||||
fprintf(rs->logfp,"visuals\n");
|
||||
/*
|
||||
* change the things
|
||||
*/
|
||||
for (tp = lvl_obj; tp != NULL; tp = next(tp))
|
||||
if (cansee(rs,tp->o_pos.y, tp->o_pos.x))
|
||||
mvaddch(tp->o_pos.y, tp->o_pos.x, rnd_thing());
|
||||
|
||||
/*
|
||||
* change the stairs
|
||||
*/
|
||||
if (!seenstairs && cansee(rs,stairs.y, stairs.x))
|
||||
mvaddch(stairs.y, stairs.x, rnd_thing());
|
||||
|
||||
/*
|
||||
* change the monsters
|
||||
*/
|
||||
seemonst = on(player, SEEMONST);
|
||||
for (tp = mlist; tp != NULL; tp = next(tp))
|
||||
{
|
||||
move(tp->t_pos.y, tp->t_pos.x);
|
||||
if (see_monst(tp))
|
||||
{
|
||||
if (tp->t_type == 'X' && tp->t_disguise != 'X')
|
||||
addch(rnd_thing());
|
||||
else
|
||||
addch(rnd(26) + 'A');
|
||||
}
|
||||
else if (seemonst)
|
||||
{
|
||||
standout();
|
||||
addch(rnd(26) + 'A');
|
||||
standend();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* land:
|
||||
* Land from a levitation potion
|
||||
*/
|
||||
void
|
||||
land(struct rogue_state *rs,int arg)
|
||||
{
|
||||
if ( rs->logfp != 0 )
|
||||
fprintf(rs->logfp,"land\n");
|
||||
player.t_flags &= ~ISLEVIT;
|
||||
msg(rs,choose_str("bummer! You've hit the ground",
|
||||
"you float gently to the ground"));
|
||||
}
|
||||
|
||||
/*
|
||||
* turn_see:
|
||||
* Put on or off seeing monsters on this level
|
||||
*/
|
||||
bool
|
||||
turn_see(struct rogue_state *rs,bool turn_off)
|
||||
{
|
||||
THING *mp;
|
||||
bool can_see, add_new;
|
||||
if ( rs->logfp != 0 )
|
||||
fprintf(rs->logfp,"turn_see\n");
|
||||
|
||||
add_new = FALSE;
|
||||
for (mp = mlist; mp != NULL; mp = next(mp))
|
||||
{
|
||||
move(mp->t_pos.y, mp->t_pos.x);
|
||||
can_see = see_monst(mp);
|
||||
if (turn_off)
|
||||
{
|
||||
if (!can_see)
|
||||
addch(mp->t_oldch);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!can_see)
|
||||
standout();
|
||||
if (!on(player, ISHALU))
|
||||
addch(mp->t_type);
|
||||
else
|
||||
addch(rnd(26) + 'A');
|
||||
if (!can_see)
|
||||
{
|
||||
standend();
|
||||
add_new ^= 1;//add_new++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (turn_off)
|
||||
player.t_flags &= ~SEEMONST;
|
||||
else
|
||||
player.t_flags |= SEEMONST;
|
||||
return add_new;
|
||||
}
|
||||
|
||||
@@ -1,519 +0,0 @@
|
||||
// Copyright (c) 2016-2023 The Hush developers
|
||||
// Distributed under the GPLv3 software license, see the accompanying
|
||||
// file COPYING or https://www.gnu.org/licenses/gpl-3.0.en.html
|
||||
/*
|
||||
* global variable initializaton
|
||||
*
|
||||
* @(#)extern.c 4.82 (Berkeley) 02/05/99
|
||||
*
|
||||
* Rogue: Exploring the Dungeons of Doom
|
||||
* Copyright (C) 1980-1983, 1985, 1999 Michael Toy, Ken Arnold and Glenn Wichman
|
||||
* All rights reserved.
|
||||
*
|
||||
* See the file LICENSE.TXT for full copyright and licensing information.
|
||||
*/
|
||||
|
||||
//#include <curses.h>
|
||||
#include "rogue.h"
|
||||
|
||||
|
||||
|
||||
bool after; /* True if we want after daemons */
|
||||
bool again; /* Repeating the last command */
|
||||
int noscore; /* Was a wizard sometime */
|
||||
bool seenstairs; /* Have seen the stairs (for lsd) */
|
||||
bool amulet = FALSE; /* He found the amulet */
|
||||
bool door_stop = FALSE; /* Stop running when we pass a door */
|
||||
bool fight_flush = FALSE; /* True if toilet input */
|
||||
bool firstmove = FALSE; /* First move after setting door_stop */
|
||||
bool got_ltc = FALSE; /* We have gotten the local tty chars */
|
||||
bool has_hit = FALSE; /* Has a "hit" message pending in msg */
|
||||
bool in_shell = FALSE; /* True if executing a shell */
|
||||
bool inv_describe = TRUE; /* Say which way items are being used */
|
||||
bool jump = FALSE; /* Show running as series of jumps */
|
||||
bool kamikaze = FALSE; /* to_death really to DEATH */
|
||||
bool lower_msg = FALSE; /* Messages should start w/lower case */
|
||||
bool move_on = FALSE; /* Next move shouldn't pick up items */
|
||||
bool msg_esc = FALSE; /* Check for ESC from msg's --More-- */
|
||||
bool passgo = FALSE; /* Follow passages */
|
||||
bool playing = TRUE; /* True until he quits */
|
||||
bool q_comm = FALSE; /* Are we executing a 'Q' command? */
|
||||
bool running = FALSE; /* True if player is running */
|
||||
bool save_msg = TRUE; /* Remember last msg */
|
||||
bool see_floor = TRUE; /* Show the lamp illuminated floor */
|
||||
bool stat_msg = FALSE; /* Should status() print as a msg() */
|
||||
bool terse = FALSE; /* True if we should be short */
|
||||
bool to_death = FALSE; /* Fighting is to the death! */
|
||||
bool tombstone = TRUE; /* Print out tombstone at end */
|
||||
#ifdef MASTER
|
||||
int wizard = FALSE; /* True if allows wizard commands */
|
||||
#endif
|
||||
bool pack_used[26] = { /* Is the character used in the pack? */
|
||||
FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE,
|
||||
FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE,
|
||||
FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE
|
||||
};
|
||||
|
||||
char dir_ch; /* Direction from last get_dir() call */
|
||||
char runch; /* Direction player is running */
|
||||
char take; /* Thing she is taking */
|
||||
|
||||
int orig_dsusp; /* Original dsusp char */
|
||||
char file_name[MAXSTR]; /* Save file name */
|
||||
char huh[MAXSTR]; /* The last message printed */
|
||||
char prbuf[2*MAXSTR]; /* buffer for sprintfs */
|
||||
char whoami[MAXSTR]; /* Name of player */
|
||||
char fruit[MAXSTR] = /* Favorite fruit */
|
||||
{ 's', 'l', 'i', 'm', 'e', '-', 'm', 'o', 'l', 'd', '\0' };
|
||||
char home[MAXSTR] = { '\0' }; /* User's home directory */
|
||||
char l_last_comm = '\0'; /* Last last_comm */
|
||||
char l_last_dir = '\0'; /* Last last_dir */
|
||||
char last_comm = '\0'; /* Last command typed */
|
||||
char last_dir = '\0'; /* Last direction given */
|
||||
|
||||
int n_objs; /* # items listed in inventory() call */
|
||||
int ntraps; /* Number of traps on this level */
|
||||
int hungry_state = 0; /* How hungry is he */
|
||||
int inpack = 0; /* Number of things in pack */
|
||||
int inv_type = 0; /* Type of inventory to use */
|
||||
int level = 1; /* What level she is on */
|
||||
int max_hit; /* Max damage done to her in to_death */
|
||||
int max_level; /* Deepest player has gone */
|
||||
int mpos = 0; /* Where cursor is on top line */
|
||||
int no_food = 0; /* Number of levels without food */
|
||||
|
||||
int count = 0; /* Number of times to repeat command */
|
||||
int food_left; /* Amount of food in hero's stomach */
|
||||
int lastscore = -1; /* Score before this turn */
|
||||
int no_command = 0; /* Number of turns asleep */
|
||||
int no_move = 0; /* Number of turns held in place */
|
||||
int purse = 0; /* How much gold he has */
|
||||
int quiet = 0; /* Number of quiet turns */
|
||||
int vf_hit = 0; /* Number of time flytrap has hit */
|
||||
|
||||
|
||||
//int dnum; /* Dungeon number */
|
||||
uint64_t seed; /* Random number seed */
|
||||
|
||||
coord delta; /* Change indicated to get_dir() */
|
||||
coord oldpos; /* Position before last look() call */
|
||||
coord stairs; /* Location of staircase */
|
||||
|
||||
PLACE places[MAXLINES*MAXCOLS]; /* level map */
|
||||
|
||||
const char *p_colors[MAXPOTIONS]; /* Colors of the potions */
|
||||
const char *r_stones[MAXRINGS]; /* Stone settings of the rings */
|
||||
const char *ws_made[MAXSTICKS]; /* What sticks are made of */
|
||||
const char *ws_type[MAXSTICKS]; /* Is it a wand or a staff */
|
||||
|
||||
THING *cur_armor; /* What he is wearing */
|
||||
THING *cur_ring[2]; /* Which rings are being worn */
|
||||
THING *cur_weapon; /* Which weapon he is weilding */
|
||||
THING *l_last_pick = NULL; /* Last last_pick */
|
||||
THING *last_pick = NULL; /* Last object picked in get_item() */
|
||||
THING *lvl_obj = NULL; /* List of objects on this level */
|
||||
THING *mlist = NULL; /* List of monsters on the level */
|
||||
struct room *oldrp; /* Roomin(&oldpos) */
|
||||
THING player; /* His stats */
|
||||
WINDOW *hw = NULL; /* used as a scratch window */
|
||||
char *s_names[MAXSCROLLS]; /* Names of the scrolls */
|
||||
FILE *scoreboard = NULL; /* File descriptor for score file */
|
||||
|
||||
#define INIT_STATS { 16, 0, 1, 10, 12, "1x4", 12 }
|
||||
|
||||
struct stats max_stats = INIT_STATS; /* The maximum for the player */
|
||||
struct stats orig_max_stats = INIT_STATS;
|
||||
|
||||
struct monster monsters[26];
|
||||
struct room passages[MAXPASS],rooms[MAXROOMS]; /* One for each room -- A level */
|
||||
struct obj_info things[NUMTHINGS],ring_info[MAXRINGS],pot_info[MAXPOTIONS],arm_info[MAXARMORS],scr_info[MAXSCROLLS],weap_info[MAXWEAPONS + 1],ws_info[MAXSTICKS];
|
||||
|
||||
////////////// constants
|
||||
#define ___ 1
|
||||
#define XX 10
|
||||
|
||||
const struct obj_info origthings[NUMTHINGS] = {
|
||||
{ 0, 26 }, /* potion */
|
||||
{ 0, 36 }, /* scroll */
|
||||
{ 0, 16 }, /* food */
|
||||
{ 0, 7 }, /* weapon */
|
||||
{ 0, 7 }, /* armor */
|
||||
{ 0, 4 }, /* ring */
|
||||
{ 0, 4 }, /* stick */
|
||||
};
|
||||
|
||||
const struct room origpassages[MAXPASS] = /* One for each passage */
|
||||
{
|
||||
{ {0, 0}, {0, 0}, {0, 0}, 0, ISGONE|ISDARK, 0, {{0,0}} },
|
||||
{ {0, 0}, {0, 0}, {0, 0}, 0, ISGONE|ISDARK, 0, {{0,0}} },
|
||||
{ {0, 0}, {0, 0}, {0, 0}, 0, ISGONE|ISDARK, 0, {{0,0}} },
|
||||
{ {0, 0}, {0, 0}, {0, 0}, 0, ISGONE|ISDARK, 0, {{0,0}} },
|
||||
{ {0, 0}, {0, 0}, {0, 0}, 0, ISGONE|ISDARK, 0, {{0,0}} },
|
||||
{ {0, 0}, {0, 0}, {0, 0}, 0, ISGONE|ISDARK, 0, {{0,0}} },
|
||||
{ {0, 0}, {0, 0}, {0, 0}, 0, ISGONE|ISDARK, 0, {{0,0}} },
|
||||
{ {0, 0}, {0, 0}, {0, 0}, 0, ISGONE|ISDARK, 0, {{0,0}} },
|
||||
{ {0, 0}, {0, 0}, {0, 0}, 0, ISGONE|ISDARK, 0, {{0,0}} },
|
||||
{ {0, 0}, {0, 0}, {0, 0}, 0, ISGONE|ISDARK, 0, {{0,0}} },
|
||||
{ {0, 0}, {0, 0}, {0, 0}, 0, ISGONE|ISDARK, 0, {{0,0}} },
|
||||
{ {0, 0}, {0, 0}, {0, 0}, 0, ISGONE|ISDARK, 0, {{0,0}} }
|
||||
};
|
||||
const struct monster origmonsters[26] =
|
||||
{
|
||||
/* Name CARRY FLAG str, exp, lvl, amr, hpt, dmg */
|
||||
{ "aquator", 0, ISMEAN, { XX, 20, 5, 2, ___, "0x0/0x0" } },
|
||||
{ "bat", 0, ISFLY, { XX, 1, 1, 3, ___, "1x2" } },
|
||||
{ "centaur", 15, 0, { XX, 17, 4, 4, ___, "1x2/1x5/1x5" } },
|
||||
{ "dragon", 100, ISMEAN, { XX,5000, 10, -1, ___, "1x8/1x8/3x10" } },
|
||||
{ "emu", 0, ISMEAN, { XX, 2, 1, 7, ___, "1x2" } },
|
||||
{ "venus flytrap", 0, ISMEAN, { XX, 80, 8, 3, ___, "%%%x0" } },
|
||||
/* NOTE: the damage is %%% so that xstr won't merge this */
|
||||
/* string with others, since it is written on in the program */
|
||||
{ "griffin", 20, ISMEAN|ISFLY|ISREGEN, { XX,2000, 13, 2, ___, "4x3/3x5" } },
|
||||
{ "hobgoblin", 0, ISMEAN, { XX, 3, 1, 5, ___, "1x8" } },
|
||||
{ "ice monster", 0, 0, { XX, 5, 1, 9, ___, "0x0" } },
|
||||
{ "jabberwock", 70, 0, { XX,3000, 15, 6, ___, "2x12/2x4" } },
|
||||
{ "kestrel", 0, ISMEAN|ISFLY, { XX, 1, 1, 7, ___, "1x4" } },
|
||||
{ "leprechaun", 0, 0, { XX, 10, 3, 8, ___, "1x1" } },
|
||||
{ "medusa", 40, ISMEAN, { XX,200, 8, 2, ___, "3x4/3x4/2x5" } },
|
||||
{ "nymph", 100, 0, { XX, 37, 3, 9, ___, "0x0" } },
|
||||
{ "orc", 15, ISGREED,{ XX, 5, 1, 6, ___, "1x8" } },
|
||||
{ "phantom", 0, ISINVIS,{ XX,120, 8, 3, ___, "4x4" } },
|
||||
{ "quagga", 0, ISMEAN, { XX, 15, 3, 3, ___, "1x5/1x5" } },
|
||||
{ "rattlesnake", 0, ISMEAN, { XX, 9, 2, 3, ___, "1x6" } },
|
||||
{ "snake", 0, ISMEAN, { XX, 2, 1, 5, ___, "1x3" } },
|
||||
{ "troll", 50, ISREGEN|ISMEAN,{ XX, 120, 6, 4, ___, "1x8/1x8/2x6" } },
|
||||
{ "black unicorn", 0, ISMEAN, { XX,190, 7, -2, ___, "1x9/1x9/2x9" } },
|
||||
{ "vampire", 20, ISREGEN|ISMEAN,{ XX,350, 8, 1, ___, "1x10" } },
|
||||
{ "wraith", 0, 0, { XX, 55, 5, 4, ___, "1x6" } },
|
||||
{ "xeroc", 30, 0, { XX,100, 7, 7, ___, "4x4" } },
|
||||
{ "yeti", 30, 0, { XX, 50, 4, 6, ___, "1x6/1x6" } },
|
||||
{ "zombie", 0, ISMEAN, { XX, 6, 2, 8, ___, "1x8" } }
|
||||
};
|
||||
#undef ___
|
||||
#undef XX
|
||||
|
||||
const struct obj_info origarm_info[MAXARMORS] = {
|
||||
{ "leather armor", 20, 20, NULL, FALSE },
|
||||
{ "ring mail", 15, 25, NULL, FALSE },
|
||||
{ "studded leather armor", 15, 20, NULL, FALSE },
|
||||
{ "scale mail", 13, 30, NULL, FALSE },
|
||||
{ "chain mail", 12, 75, NULL, FALSE },
|
||||
{ "splint mail", 10, 80, NULL, FALSE },
|
||||
{ "banded mail", 10, 90, NULL, FALSE },
|
||||
{ "plate mail", 5, 150, NULL, FALSE },
|
||||
};
|
||||
const struct obj_info origpot_info[MAXPOTIONS] = {
|
||||
{ "confusion", 7, 5, NULL, FALSE },
|
||||
{ "hallucination", 8, 5, NULL, FALSE },
|
||||
{ "poison", 8, 5, NULL, FALSE },
|
||||
{ "gain strength", 13, 150, NULL, FALSE },
|
||||
{ "see invisible", 3, 100, NULL, FALSE },
|
||||
{ "healing", 13, 130, NULL, FALSE },
|
||||
{ "monster detection", 6, 130, NULL, FALSE },
|
||||
{ "magic detection", 6, 105, NULL, FALSE },
|
||||
{ "raise level", 2, 250, NULL, FALSE },
|
||||
{ "extra healing", 5, 200, NULL, FALSE },
|
||||
{ "haste self", 5, 190, NULL, FALSE },
|
||||
{ "restore strength", 13, 130, NULL, FALSE },
|
||||
{ "blindness", 5, 5, NULL, FALSE },
|
||||
{ "levitation", 6, 75, NULL, FALSE },
|
||||
};
|
||||
const struct obj_info origring_info[MAXRINGS] = {
|
||||
{ "protection", 9, 400, NULL, FALSE },
|
||||
{ "add strength", 9, 400, NULL, FALSE },
|
||||
{ "sustain strength", 5, 280, NULL, FALSE },
|
||||
{ "searching", 10, 420, NULL, FALSE },
|
||||
{ "see invisible", 10, 310, NULL, FALSE },
|
||||
{ "adornment", 1, 10, NULL, FALSE },
|
||||
{ "aggravate monster", 10, 10, NULL, FALSE },
|
||||
{ "dexterity", 8, 440, NULL, FALSE },
|
||||
{ "increase damage", 8, 400, NULL, FALSE },
|
||||
{ "regeneration", 4, 460, NULL, FALSE },
|
||||
{ "slow digestion", 9, 240, NULL, FALSE },
|
||||
{ "teleportation", 5, 30, NULL, FALSE },
|
||||
{ "stealth", 7, 470, NULL, FALSE },
|
||||
{ "maintain armor", 5, 380, NULL, FALSE },
|
||||
};
|
||||
const struct obj_info origscr_info[MAXSCROLLS] = {
|
||||
{ "monster confusion", 7, 140, NULL, FALSE },
|
||||
{ "magic mapping", 4, 150, NULL, FALSE },
|
||||
{ "hold monster", 2, 180, NULL, FALSE },
|
||||
{ "sleep", 3, 5, NULL, FALSE },
|
||||
{ "enchant armor", 7, 160, NULL, FALSE },
|
||||
{ "identify potion", 10, 80, NULL, FALSE },
|
||||
{ "identify scroll", 10, 80, NULL, FALSE },
|
||||
{ "identify weapon", 6, 80, NULL, FALSE },
|
||||
{ "identify armor", 7, 100, NULL, FALSE },
|
||||
{ "identify ring, wand or staff", 10, 115, NULL, FALSE },
|
||||
{ "scare monster", 3, 200, NULL, FALSE },
|
||||
{ "food detection", 2, 60, NULL, FALSE },
|
||||
{ "teleportation", 5, 165, NULL, FALSE },
|
||||
{ "enchant weapon", 8, 150, NULL, FALSE },
|
||||
{ "create monster", 4, 75, NULL, FALSE },
|
||||
{ "remove curse", 7, 105, NULL, FALSE },
|
||||
{ "aggravate monsters", 3, 20, NULL, FALSE },
|
||||
{ "protect armor", 2, 250, NULL, FALSE },
|
||||
};
|
||||
const struct obj_info origweap_info[MAXWEAPONS + 1] = {
|
||||
{ "mace", 11, 8, NULL, FALSE },
|
||||
{ "long sword", 11, 15, NULL, FALSE },
|
||||
{ "short bow", 12, 15, NULL, FALSE },
|
||||
{ "arrow", 12, 1, NULL, FALSE },
|
||||
{ "dagger", 8, 3, NULL, FALSE },
|
||||
{ "two handed sword", 10, 75, NULL, FALSE },
|
||||
{ "dart", 12, 2, NULL, FALSE },
|
||||
{ "shuriken", 12, 5, NULL, FALSE },
|
||||
{ "spear", 12, 5, NULL, FALSE },
|
||||
{ NULL, 0 }, /* DO NOT REMOVE: fake entry for dragon's breath */
|
||||
};
|
||||
const struct obj_info origws_info[MAXSTICKS] = {
|
||||
{ "light", 12, 250, NULL, FALSE },
|
||||
{ "invisibility", 6, 5, NULL, FALSE },
|
||||
{ "lightning", 3, 330, NULL, FALSE },
|
||||
{ "fire", 3, 330, NULL, FALSE },
|
||||
{ "cold", 3, 330, NULL, FALSE },
|
||||
{ "polymorph", 15, 310, NULL, FALSE },
|
||||
{ "magic missile", 10, 170, NULL, FALSE },
|
||||
{ "haste monster", 10, 5, NULL, FALSE },
|
||||
{ "slow monster", 11, 350, NULL, FALSE },
|
||||
{ "drain life", 9, 300, NULL, FALSE },
|
||||
{ "nothing", 1, 5, NULL, FALSE },
|
||||
{ "teleport away", 6, 340, NULL, FALSE },
|
||||
{ "teleport to", 6, 50, NULL, FALSE },
|
||||
{ "cancellation", 5, 280, NULL, FALSE },
|
||||
};
|
||||
|
||||
const struct h_list helpstr[] = {
|
||||
{'?', " prints help", TRUE},
|
||||
{'/', " identify object", TRUE},
|
||||
{'h', " left", TRUE},
|
||||
{'j', " down", TRUE},
|
||||
{'k', " up", TRUE},
|
||||
{'l', " right", TRUE},
|
||||
{'y', " up & left", TRUE},
|
||||
{'u', " up & right", TRUE},
|
||||
{'b', " down & left", TRUE},
|
||||
{'n', " down & right", TRUE},
|
||||
{'H', " run left", FALSE},
|
||||
{'J', " run down", FALSE},
|
||||
{'K', " run up", FALSE},
|
||||
{'L', " run right", FALSE},
|
||||
{'Y', " run up & left", FALSE},
|
||||
{'U', " run up & right", FALSE},
|
||||
{'B', " run down & left", FALSE},
|
||||
{'N', " run down & right", FALSE},
|
||||
{CTRL('H'), " run left until adjacent", FALSE},
|
||||
{CTRL('J'), " run down until adjacent", FALSE},
|
||||
{CTRL('K'), " run up until adjacent", FALSE},
|
||||
{CTRL('L'), " run right until adjacent", FALSE},
|
||||
{CTRL('Y'), " run up & left until adjacent", FALSE},
|
||||
{CTRL('U'), " run up & right until adjacent", FALSE},
|
||||
{CTRL('B'), " run down & left until adjacent", FALSE},
|
||||
{CTRL('N'), " run down & right until adjacent", FALSE},
|
||||
{'\0', " <SHIFT><dir>: run that way", TRUE},
|
||||
{'\0', " <CTRL><dir>: run till adjacent", TRUE},
|
||||
{'f', "<dir> fight till death or near death", TRUE},
|
||||
{'t', "<dir> throw something", TRUE},
|
||||
{'m', "<dir> move onto without picking up", TRUE},
|
||||
{'z', "<dir> zap a wand in a direction", TRUE},
|
||||
{'^', "<dir> identify trap type", TRUE},
|
||||
{'s', " search for trap/secret door", TRUE},
|
||||
{'>', " go down a staircase", TRUE},
|
||||
{'<', " go up a staircase", TRUE},
|
||||
{'.', " rest for a turn", TRUE},
|
||||
{',', " pick something up", TRUE},
|
||||
{'i', " inventory", TRUE},
|
||||
{'I', " inventory single item", TRUE},
|
||||
{'q', " quaff potion", TRUE},
|
||||
{'r', " read scroll", TRUE},
|
||||
{'e', " eat food", TRUE},
|
||||
{'w', " wield a weapon", TRUE},
|
||||
{'W', " wear armor", TRUE},
|
||||
{'T', " take armor off", TRUE},
|
||||
{'P', " put on ring", TRUE},
|
||||
{'R', " remove ring", TRUE},
|
||||
{'d', " drop object", TRUE},
|
||||
{'c', " call object", TRUE},
|
||||
{'a', " repeat last command", TRUE},
|
||||
{')', " print current weapon", TRUE},
|
||||
{']', " print current armor", TRUE},
|
||||
{'=', " print current rings", TRUE},
|
||||
{'@', " print current stats", TRUE},
|
||||
{'D', " recall what's been discovered", TRUE},
|
||||
{'o', " examine/set options", TRUE},
|
||||
{CTRL('R'), " redraw screen", TRUE},
|
||||
{CTRL('P'), " repeat last message", TRUE},
|
||||
{ESCAPE, " cancel command", TRUE},
|
||||
{'S', " save game", TRUE},
|
||||
{'Q', " quit", TRUE},
|
||||
{'!', " shell escape", TRUE},
|
||||
{'F', "<dir> fight till either of you dies", TRUE},
|
||||
{'v', " print version number", TRUE},
|
||||
{0, NULL }
|
||||
};
|
||||
|
||||
const char *inv_t_name[] = {
|
||||
"Overwrite",
|
||||
"Slow",
|
||||
"Clear"
|
||||
};
|
||||
|
||||
const char *tr_name[] = { /* Names of the traps */
|
||||
"a trapdoor",
|
||||
"an arrow trap",
|
||||
"a sleeping gas trap",
|
||||
"a beartrap",
|
||||
"a teleport trap",
|
||||
"a poison dart trap",
|
||||
"a rust trap",
|
||||
"a mysterious trap"
|
||||
};
|
||||
|
||||
const int32_t a_class[MAXARMORS] = { /* Armor class for each armor type */
|
||||
8, /* LEATHER */
|
||||
7, /* RING_MAIL */
|
||||
7, /* STUDDED_LEATHER */
|
||||
6, /* SCALE_MAIL */
|
||||
5, /* CHAIN_MAIL */
|
||||
4, /* SPLINT_MAIL */
|
||||
4, /* BANDED_MAIL */
|
||||
3, /* PLATE_MAIL */
|
||||
};
|
||||
|
||||
const int32_t e_levels[] = {
|
||||
10L,
|
||||
20L,
|
||||
40L,
|
||||
80L,
|
||||
160L,
|
||||
320L,
|
||||
640L,
|
||||
1300L,
|
||||
2600L,
|
||||
5200L,
|
||||
13000L,
|
||||
26000L,
|
||||
50000L,
|
||||
100000L,
|
||||
200000L,
|
||||
400000L,
|
||||
800000L,
|
||||
2000000L,
|
||||
4000000L,
|
||||
8000000L,
|
||||
0L
|
||||
};
|
||||
|
||||
#include <memory.h>
|
||||
extern int between;
|
||||
extern int group;
|
||||
extern coord nh;
|
||||
|
||||
void externs_clear()
|
||||
{
|
||||
int i;
|
||||
after = 0; /* True if we want after daemons */
|
||||
again = 0; /* Repeating the last command */
|
||||
noscore = 0; /* Was a wizard sometime */
|
||||
seenstairs = 0; /* Have seen the stairs (for lsd) */
|
||||
amulet = FALSE; /* He found the amulet */
|
||||
door_stop = FALSE; /* Stop running when we pass a door */
|
||||
fight_flush = FALSE; /* True if toilet input */
|
||||
firstmove = FALSE; /* First move after setting door_stop */
|
||||
got_ltc = FALSE; /* We have gotten the local tty chars */
|
||||
has_hit = FALSE; /* Has a "hit" message pending in msg */
|
||||
in_shell = FALSE; /* True if executing a shell */
|
||||
inv_describe = TRUE; /* Say which way items are being used */
|
||||
jump = FALSE; /* Show running as series of jumps */
|
||||
kamikaze = FALSE; /* to_death really to DEATH */
|
||||
lower_msg = FALSE; /* Messages should start w/lower case */
|
||||
move_on = FALSE; /* Next move shouldn't pick up items */
|
||||
msg_esc = FALSE; /* Check for ESC from msg's --More-- */
|
||||
passgo = FALSE; /* Follow passages */
|
||||
playing = TRUE; /* True until he quits */
|
||||
q_comm = FALSE; /* Are we executing a 'Q' command? */
|
||||
running = FALSE; /* True if player is running */
|
||||
save_msg = TRUE; /* Remember last msg */
|
||||
see_floor = TRUE; /* Show the lamp illuminated floor */
|
||||
stat_msg = FALSE; /* Should status() print as a msg() */
|
||||
terse = FALSE; /* True if we should be short */
|
||||
to_death = FALSE; /* Fighting is to the death! */
|
||||
tombstone = TRUE; /* Print out tombstone at end */
|
||||
#ifdef MASTER
|
||||
int wizard = FALSE; /* True if allows wizard commands */
|
||||
#endif
|
||||
for (i=0; i<26; i++)
|
||||
pack_used[i] = FALSE;
|
||||
for (i=0; i<MAXSCROLLS; i++)
|
||||
if ( s_names[i] != 0 )
|
||||
free(s_names[i]);
|
||||
memset(s_names,0,sizeof(s_names));
|
||||
|
||||
dir_ch = 0; /* Direction from last get_dir() call */
|
||||
memset(file_name,0,sizeof(file_name));
|
||||
memset(huh,0,sizeof(huh));
|
||||
memset(p_colors,0,sizeof(p_colors));
|
||||
memset(prbuf,0,sizeof(prbuf));
|
||||
memset(r_stones,0,sizeof(r_stones));
|
||||
//memset(whoami,0,sizeof(whoami));
|
||||
memset(ws_made,0,sizeof(ws_made));
|
||||
memset(ws_type,0,sizeof(ws_type));
|
||||
runch = 0; /* Direction player is running */
|
||||
take = 0; /* Thing she is taking */
|
||||
orig_dsusp = 0; /* Original dsusp char */
|
||||
memset(home,0,sizeof(home));
|
||||
l_last_comm = '\0'; /* Last last_comm */
|
||||
l_last_dir = '\0'; /* Last last_dir */
|
||||
last_comm = '\0'; /* Last command typed */
|
||||
last_dir = '\0'; /* Last direction given */
|
||||
|
||||
n_objs = 0; /* # items listed in inventory() call */
|
||||
ntraps = 0; /* Number of traps on this level */
|
||||
hungry_state = 0; /* How hungry is he */
|
||||
inpack = 0; /* Number of things in pack */
|
||||
inv_type = 0; /* Type of inventory to use */
|
||||
level = 1; /* What level she is on */
|
||||
max_hit= 0; /* Max damage done to her in to_death */
|
||||
max_level = 0; /* Deepest player has gone */
|
||||
mpos = 0; /* Where cursor is on top line */
|
||||
no_food = 0; /* Number of levels without food */
|
||||
|
||||
count = 0; /* Number of times to repeat command */
|
||||
if ( scoreboard != NULL )
|
||||
{
|
||||
fclose(scoreboard);
|
||||
scoreboard = NULL; /* File descriptor for score file */
|
||||
}
|
||||
food_left = 0; /* Amount of food in hero's stomach */
|
||||
lastscore = -1; /* Score before this turn */
|
||||
no_command = 0; /* Number of turns asleep */
|
||||
no_move = 0; /* Number of turns held in place */
|
||||
purse = 0; /* How much gold he has */
|
||||
quiet = 0; /* Number of quiet turns */
|
||||
vf_hit = 0; /* Number of time flytrap has hit */
|
||||
|
||||
|
||||
memset(&delta,0,sizeof(delta));
|
||||
memset(&oldpos,0,sizeof(oldpos));
|
||||
memset(&stairs,0,sizeof(stairs));
|
||||
|
||||
memset(places,0,sizeof(places));
|
||||
cur_armor = NULL; /* What he is wearing */
|
||||
cur_ring[0] = cur_ring[1] = NULL; /* Which rings are being worn */
|
||||
cur_weapon = NULL; /* Which weapon he is weilding */
|
||||
l_last_pick = NULL; /* Last last_pick */
|
||||
last_pick = NULL; /* Last object picked in get_item() */
|
||||
lvl_obj = NULL; /* List of objects on this level */
|
||||
mlist = NULL; /* List of monsters on the level */
|
||||
memset(&player,0,sizeof(player)); /* His stats */
|
||||
/* restart of game */
|
||||
|
||||
max_stats = orig_max_stats; /* The maximum for the player */
|
||||
|
||||
oldrp = 0; /* Roomin(&oldpos) */
|
||||
memset(rooms,0,sizeof(rooms)); /* One for each room -- A level */
|
||||
|
||||
between = 0;
|
||||
group = 0;
|
||||
memset(&nh,0,sizeof(nh));
|
||||
}
|
||||
@@ -1,203 +0,0 @@
|
||||
// Copyright (c) 2016-2023 The Hush developers
|
||||
// Distributed under the GPLv3 software license, see the accompanying
|
||||
// file COPYING or https://www.gnu.org/licenses/gpl-3.0.en.html
|
||||
/*
|
||||
* Defines for things used in mach_dep.c
|
||||
*
|
||||
* @(#)extern.h 4.35 (Berkeley) 02/05/99
|
||||
*
|
||||
* Rogue: Exploring the Dungeons of Doom
|
||||
* Copyright (C) 1980-1983, 1985, 1999 Michael Toy, Ken Arnold and Glenn Wichman
|
||||
* All rights reserved.
|
||||
*
|
||||
* See the file LICENSE.TXT for full copyright and licensing information.
|
||||
*/
|
||||
|
||||
#ifndef H_EXTERN_ROGUE_H
|
||||
#define H_EXTERN_ROGUE_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#ifdef PDCURSES
|
||||
#undef HAVE_UNISTD_H
|
||||
#undef HAVE_LIMITS_H
|
||||
#undef HAVE_MEMORY_H
|
||||
#undef HAVE_STRING_H
|
||||
#endif
|
||||
#include <stdint.h>
|
||||
#include "config.h"
|
||||
#elif defined(__DJGPP__)
|
||||
#define HAVE_SYS_TYPES_H 1
|
||||
#define HAVE_PROCESS_H 1
|
||||
#define HAVE_PWD_H 1
|
||||
#define HAVE_TERMIOS_H 1
|
||||
#define HAVE_SETGID 1
|
||||
#define HAVE_GETGID 1
|
||||
#define HAVE_SETUID 1
|
||||
#define HAVE_GETUID 1
|
||||
#define HAVE_GETPASS 1
|
||||
#define HAVE_SPAWNL 1
|
||||
#define HAVE_ALARM 1
|
||||
#define HAVE_ERASECHAR 1
|
||||
#define HAVE_KILLCHAR 1
|
||||
#elif defined(_WIN32)
|
||||
#define HAVE_CURSES_H
|
||||
#define HAVE_TERM_H
|
||||
#define HAVE__SPAWNL
|
||||
#define HAVE_SYS_TYPES_H
|
||||
#define HAVE_PROCESS_H
|
||||
#define HAVE_ERASECHAR 1
|
||||
#define HAVE_KILLCHAR 1
|
||||
#elif defined(__CYGWIN__)
|
||||
#define HAVE_SYS_TYPES_H 1
|
||||
#define HAVE_PWD_H 1
|
||||
#define HAVE_PWD_H 1
|
||||
#define HAVE_SYS_UTSNAME_H 1
|
||||
#define HAVE_ARPA_INET_H 1
|
||||
#define HAVE_UNISTD_H 1
|
||||
#define HAVE_TERMIOS_H 1
|
||||
#define HAVE_NCURSES_TERM_H 1
|
||||
#define HAVE_ESCDELAY
|
||||
#define HAVE_SETGID 1
|
||||
#define HAVE_GETGID 1
|
||||
#define HAVE_SETUID 1
|
||||
#define HAVE_GETUID 1
|
||||
#define HAVE_GETPASS 1
|
||||
#define HAVE_GETPWUID 1
|
||||
#define HAVE_WORKING_FORK 1
|
||||
#define HAVE_ALARM 1
|
||||
#define HAVE_SPAWNL 1
|
||||
#define HAVE__SPAWNL 1
|
||||
#define HAVE_ERASECHAR 1
|
||||
#define HAVE_KILLCHAR 1
|
||||
#else /* POSIX */
|
||||
#define HAVE_SYS_TYPES_H 1
|
||||
#define HAVE_PWD_H 1
|
||||
#define HAVE_PWD_H 1
|
||||
#define HAVE_SYS_UTSNAME_H 1
|
||||
#define HAVE_ARPA_INET_H 1
|
||||
#define HAVE_UNISTD_H 1
|
||||
#define HAVE_TERMIOS_H 1
|
||||
#define HAVE_TERM_H 1
|
||||
#define HAVE_SETGID 1
|
||||
#define HAVE_GETGID 1
|
||||
#define HAVE_SETUID 1
|
||||
#define HAVE_GETUID 1
|
||||
#define HAVE_SETREUID 1
|
||||
#define HAVE_SETREGID 1
|
||||
#define HAVE_GETPASS 1
|
||||
#define HAVE_GETPWUID 1
|
||||
#define HAVE_WORKING_FORK 1
|
||||
#define HAVE_ERASECHAR 1
|
||||
#define HAVE_KILLCHAR 1
|
||||
#ifndef _AIX
|
||||
#define HAVE_GETLOADAVG 1
|
||||
#endif
|
||||
#define HAVE_ALARM 1
|
||||
#endif
|
||||
|
||||
#ifdef __DJGPP__
|
||||
#undef HAVE_GETPWUID /* DJGPP's limited version doesn't even work as documented */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Don't change the constants, since they are used for sizes in many
|
||||
* places in the program.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#ifdef _MSC_VER
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#undef SIGTSTP
|
||||
|
||||
#define MAXSTR 1024 /* maximum length of strings */
|
||||
#define MAXLINES 32 /* maximum number of screen lines used */
|
||||
#define MAXCOLS 80 /* maximum number of screen columns used */
|
||||
|
||||
#define RN ((int32_t)((seed = seed*11109+13849) >> 16) & 0xffff)
|
||||
#ifdef CTRL
|
||||
#undef CTRL
|
||||
#endif
|
||||
#define CTRL(c) (c & 037)
|
||||
|
||||
/*
|
||||
* Now all the global variables
|
||||
*/
|
||||
|
||||
extern bool got_ltc, in_shell;
|
||||
extern int wizard;
|
||||
extern char fruit[], prbuf[], whoami[];
|
||||
extern int orig_dsusp;
|
||||
extern FILE *scoreboard;
|
||||
|
||||
/*
|
||||
* Function types
|
||||
*/
|
||||
void externs_clear();
|
||||
|
||||
void auto_save(int);
|
||||
void endit(int sig);
|
||||
void fatal(char *);
|
||||
void getltchars(void);
|
||||
void leave(int);
|
||||
void my_exit(int st);
|
||||
void playltchars(void);
|
||||
void quit(int);
|
||||
int32_t _quit();
|
||||
|
||||
void resetltchars(void);
|
||||
void set_order(int *order, int numthings);
|
||||
void tstp(int ignored);
|
||||
|
||||
char *killname(char monst, bool doart);
|
||||
char *nothing(char type);
|
||||
char *type_name(int type);
|
||||
|
||||
#ifdef CHECKTIME
|
||||
int checkout(void);
|
||||
#endif
|
||||
|
||||
int md_chmod(char *filename, int mode);
|
||||
char *md_crypt(char *key, char *salt);
|
||||
int md_dsuspchar(void);
|
||||
int md_erasechar(void);
|
||||
char *md_gethomedir(void);
|
||||
char *md_getusername(void);
|
||||
int md_getuid(void);
|
||||
char *md_getpass(char *prompt);
|
||||
int md_getpid(void);
|
||||
char *md_getrealname(int uid);
|
||||
void md_init(void);
|
||||
int md_killchar(void);
|
||||
void md_normaluser(void);
|
||||
void md_raw_standout(void);
|
||||
void md_raw_standend(void);
|
||||
int md_readchar(void);
|
||||
int md_setdsuspchar(int c);
|
||||
int md_shellescape(void);
|
||||
void md_sleep(int s);
|
||||
int md_suspchar(void);
|
||||
int md_hasclreol(void);
|
||||
int md_unlink(char *file);
|
||||
int md_unlink_open_file(char *file, FILE *inf);
|
||||
void md_tstpsignal(void);
|
||||
void md_tstphold(void);
|
||||
void md_tstpresume(void);
|
||||
void md_ignoreallsignals(void);
|
||||
void md_onsignal_autosave(void);
|
||||
void md_onsignal_exit(void);
|
||||
void md_onsignal_default(void);
|
||||
int md_issymlink(char *sp);
|
||||
|
||||
int32_t decode_hex(uint8_t *bytes,int32_t n,char *hex);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,684 +0,0 @@
|
||||
// Copyright (c) 2016-2023 The Hush developers
|
||||
// Distributed under the GPLv3 software license, see the accompanying
|
||||
// file COPYING or https://www.gnu.org/licenses/gpl-3.0.en.html
|
||||
/*
|
||||
* All the fighting gets done here
|
||||
*
|
||||
* @(#)fight.c 4.67 (Berkeley) 09/06/83
|
||||
*
|
||||
* Rogue: Exploring the Dungeons of Doom
|
||||
* Copyright (C) 1980-1983, 1985, 1999 Michael Toy, Ken Arnold and Glenn Wichman
|
||||
* All rights reserved.
|
||||
*
|
||||
* See the file LICENSE.TXT for full copyright and licensing information.
|
||||
*/
|
||||
|
||||
//#include <stdlib.h>
|
||||
//#include <curses.h>
|
||||
//#include <string.h>
|
||||
//#include <ctype.h>
|
||||
#include "rogue.h"
|
||||
|
||||
//#define EQSTR(a, b) (strcmp(a, b) == 0)
|
||||
|
||||
const char *h_names[] = { /* strings for hitting */
|
||||
" scored an excellent hit on ",
|
||||
" hit ",
|
||||
" have injured ",
|
||||
" swing and hit ",
|
||||
" scored an excellent hit on ",
|
||||
" hit ",
|
||||
" has injured ",
|
||||
" swings and hits "
|
||||
};
|
||||
|
||||
const char *m_names[] = { /* strings for missing */
|
||||
" miss",
|
||||
" swing and miss",
|
||||
" barely miss",
|
||||
" don't hit",
|
||||
" misses",
|
||||
" swings and misses",
|
||||
" barely misses",
|
||||
" doesn't hit",
|
||||
};
|
||||
|
||||
/*
|
||||
* adjustments to hit probabilities due to strength
|
||||
*/
|
||||
static const int str_plus[] = {
|
||||
-7, -6, -5, -4, -3, -2, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1,
|
||||
1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3,
|
||||
};
|
||||
|
||||
/*
|
||||
* adjustments to damage done due to strength
|
||||
*/
|
||||
static const int add_dam[] = {
|
||||
-7, -6, -5, -4, -3, -2, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 3,
|
||||
3, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6
|
||||
};
|
||||
|
||||
/*
|
||||
* fight:
|
||||
* The player attacks the monster.
|
||||
*/
|
||||
int
|
||||
fight(struct rogue_state *rs,coord *mp, THING *weap, bool thrown)
|
||||
{
|
||||
register THING *tp;
|
||||
register bool did_hit = TRUE;
|
||||
register char *mname, ch;
|
||||
|
||||
/*
|
||||
* Find the monster we want to fight
|
||||
*/
|
||||
#ifdef MASTER
|
||||
if ((tp = moat(mp->y, mp->x)) == NULL)
|
||||
debug("Fight what @ %d,%d", mp->y, mp->x);
|
||||
#else
|
||||
tp = moat(mp->y, mp->x);
|
||||
#endif
|
||||
/*
|
||||
* Since we are fighting, things are not quiet so no healing takes
|
||||
* place.
|
||||
*/
|
||||
count = 0;
|
||||
quiet = 0;
|
||||
runto(rs,mp);
|
||||
/*
|
||||
* Let him know it was really a xeroc (if it was one).
|
||||
*/
|
||||
ch = '\0';
|
||||
if (tp->t_type == 'X' && tp->t_disguise != 'X' && !on(player, ISBLIND))
|
||||
{
|
||||
tp->t_disguise = 'X';
|
||||
if (on(player, ISHALU)) {
|
||||
ch = (char)(rnd(26) + 'A');
|
||||
mvaddch(tp->t_pos.y, tp->t_pos.x, ch);
|
||||
}
|
||||
msg(rs,choose_str("heavy! That's a nasty critter!",
|
||||
"wait! That's a xeroc!"));
|
||||
if (!thrown)
|
||||
return FALSE;
|
||||
}
|
||||
mname = set_mname(tp);
|
||||
did_hit = FALSE;
|
||||
has_hit = (terse && !to_death);
|
||||
if (roll_em(&player, tp, weap, thrown))
|
||||
{
|
||||
did_hit = FALSE;
|
||||
if (thrown)
|
||||
thunk(rs,weap, mname, terse);
|
||||
else
|
||||
hit(rs,(char *) NULL, mname, terse);
|
||||
if (on(player, CANHUH))
|
||||
{
|
||||
did_hit = TRUE;
|
||||
tp->t_flags |= ISHUH;
|
||||
player.t_flags &= ~CANHUH;
|
||||
endmsg(rs);
|
||||
has_hit = FALSE;
|
||||
msg(rs,"your hands stop glowing %s", pick_color("red"));
|
||||
}
|
||||
if (tp->t_stats.s_hpt <= 0)
|
||||
killed(rs,tp, TRUE);
|
||||
else if (did_hit && !on(player, ISBLIND))
|
||||
msg(rs,"%s appears confused", mname);
|
||||
did_hit = TRUE;
|
||||
}
|
||||
else
|
||||
if (thrown)
|
||||
bounce(rs,weap, mname, terse);
|
||||
else
|
||||
miss(rs,(char *) NULL, mname, terse);
|
||||
return did_hit;
|
||||
}
|
||||
|
||||
/*
|
||||
* attack:
|
||||
* The monster attacks the player
|
||||
*/
|
||||
int
|
||||
attack(struct rogue_state *rs,THING *mp)
|
||||
{
|
||||
register char *mname;
|
||||
register int oldhp;
|
||||
|
||||
/*
|
||||
* Since this is an attack, stop running and any healing that was
|
||||
* going on at the time.
|
||||
*/
|
||||
running = FALSE;
|
||||
count = 0;
|
||||
quiet = 0;
|
||||
if (to_death && !on(*mp, ISTARGET))
|
||||
{
|
||||
to_death = FALSE;
|
||||
kamikaze = FALSE;
|
||||
}
|
||||
if (mp->t_type == 'X' && mp->t_disguise != 'X' && !on(player, ISBLIND))
|
||||
{
|
||||
mp->t_disguise = 'X';
|
||||
if (on(player, ISHALU))
|
||||
mvaddch(mp->t_pos.y, mp->t_pos.x, rnd(26) + 'A');
|
||||
}
|
||||
mname = set_mname(mp);
|
||||
oldhp = pstats.s_hpt;
|
||||
if (roll_em(mp, &player, (THING *) NULL, FALSE))
|
||||
{
|
||||
if (mp->t_type != 'I')
|
||||
{
|
||||
if (has_hit)
|
||||
addmsg(rs,". ");
|
||||
hit(rs,mname, (char *) NULL, FALSE);
|
||||
}
|
||||
else
|
||||
if (has_hit)
|
||||
endmsg(rs);
|
||||
has_hit = FALSE;
|
||||
if (pstats.s_hpt <= 0)
|
||||
death(rs,mp->t_type); /* Bye bye life ... */
|
||||
else if (!kamikaze)
|
||||
{
|
||||
oldhp -= pstats.s_hpt;
|
||||
if (oldhp > max_hit)
|
||||
max_hit = oldhp;
|
||||
if (pstats.s_hpt <= max_hit)
|
||||
to_death = FALSE;
|
||||
}
|
||||
if (!on(*mp, ISCANC))
|
||||
switch (mp->t_type)
|
||||
{
|
||||
case 'A':
|
||||
/*
|
||||
* If an aquator hits, you can lose armor class.
|
||||
*/
|
||||
rust_armor(rs,cur_armor);
|
||||
when 'I':
|
||||
/*
|
||||
* The ice monster freezes you
|
||||
*/
|
||||
player.t_flags &= ~ISRUN;
|
||||
if (!no_command)
|
||||
{
|
||||
addmsg(rs,"you are frozen");
|
||||
if (!terse)
|
||||
addmsg(rs," by the %s", mname);
|
||||
endmsg(rs);
|
||||
}
|
||||
no_command += rnd(2) + 2;
|
||||
if (no_command > BORE_LEVEL)
|
||||
death(rs,'h');
|
||||
when 'R':
|
||||
/*
|
||||
* Rattlesnakes have poisonous bites
|
||||
*/
|
||||
if (!save(VS_POISON))
|
||||
{
|
||||
if (!ISWEARING(R_SUSTSTR))
|
||||
{
|
||||
chg_str(-1);
|
||||
if (!terse)
|
||||
msg(rs,"you feel a bite in your leg and now feel weaker");
|
||||
else
|
||||
msg(rs,"a bite has weakened you");
|
||||
}
|
||||
else if (!to_death)
|
||||
{
|
||||
if (!terse)
|
||||
msg(rs,"a bite momentarily weakens you");
|
||||
else
|
||||
msg(rs,"bite has no effect");
|
||||
}
|
||||
}
|
||||
when 'W':
|
||||
case 'V':
|
||||
/*
|
||||
* Wraiths might drain energy levels, and Vampires
|
||||
* can steal max_hp
|
||||
*/
|
||||
if (rnd(100) < (mp->t_type == 'W' ? 15 : 30))
|
||||
{
|
||||
register int fewer;
|
||||
|
||||
if (mp->t_type == 'W')
|
||||
{
|
||||
if (pstats.s_exp == 0)
|
||||
death(rs,'W'); /* All levels gone */
|
||||
if (--pstats.s_lvl == 0)
|
||||
{
|
||||
pstats.s_exp = 0;
|
||||
pstats.s_lvl = 1;
|
||||
}
|
||||
else
|
||||
pstats.s_exp = e_levels[pstats.s_lvl-1]+1;
|
||||
fewer = roll(1, 10);
|
||||
}
|
||||
else
|
||||
fewer = roll(1, 3);
|
||||
pstats.s_hpt -= fewer;
|
||||
max_hp -= fewer;
|
||||
if (pstats.s_hpt <= 0)
|
||||
pstats.s_hpt = 1;
|
||||
if (max_hp <= 0)
|
||||
death(rs,mp->t_type);
|
||||
msg(rs,"you suddenly feel weaker");
|
||||
}
|
||||
when 'F':
|
||||
/*
|
||||
* Venus Flytrap stops the poor guy from moving
|
||||
*/
|
||||
player.t_flags |= ISHELD;
|
||||
sprintf(monsters['F'-'A'].m_stats.s_dmg,"%dx1", ++vf_hit);
|
||||
if (--pstats.s_hpt <= 0)
|
||||
death(rs,'F');
|
||||
when 'L':
|
||||
{
|
||||
/*
|
||||
* Leperachaun steals some gold
|
||||
*/
|
||||
register int lastpurse;
|
||||
|
||||
lastpurse = purse;
|
||||
purse -= GOLDCALC;
|
||||
if (!save(VS_MAGIC))
|
||||
purse -= GOLDCALC + GOLDCALC + GOLDCALC + GOLDCALC;
|
||||
if (purse < 0)
|
||||
purse = 0;
|
||||
remove_mon(rs,&mp->t_pos, mp, FALSE);
|
||||
mp=NULL;
|
||||
if (purse != lastpurse)
|
||||
msg(rs,"your purse feels lighter");
|
||||
}
|
||||
when 'N':
|
||||
{
|
||||
THING *obj, *steal; int nobj;
|
||||
|
||||
/*
|
||||
* Nymph's steal a magic item, look through the pack
|
||||
* and pick out one we like.
|
||||
*/
|
||||
steal = NULL;
|
||||
for (nobj = 0, obj = pack; obj != NULL; obj = next(obj))
|
||||
if (obj != cur_armor && obj != cur_weapon
|
||||
&& obj != cur_ring[LEFT] && obj != cur_ring[RIGHT]
|
||||
&& is_magic(obj) && rnd(++nobj) == 0)
|
||||
steal = obj;
|
||||
if (steal != NULL)
|
||||
{
|
||||
remove_mon(rs,&mp->t_pos, moat(mp->t_pos.y, mp->t_pos.x), FALSE);
|
||||
mp=NULL;
|
||||
leave_pack(rs,steal, FALSE, FALSE);
|
||||
msg(rs,"she stole %s!", inv_name(steal, TRUE));
|
||||
if ( steal->o_count <= 0 )
|
||||
discard(steal);
|
||||
}
|
||||
}
|
||||
otherwise:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (mp->t_type != 'I')
|
||||
{
|
||||
if (has_hit)
|
||||
{
|
||||
addmsg(rs,". ");
|
||||
has_hit = FALSE;
|
||||
}
|
||||
if (mp->t_type == 'F')
|
||||
{
|
||||
pstats.s_hpt -= vf_hit;
|
||||
if (pstats.s_hpt <= 0)
|
||||
death(rs,mp->t_type); /* Bye bye life ... */
|
||||
}
|
||||
miss(rs,mname, (char *) NULL, FALSE);
|
||||
}
|
||||
if (fight_flush && !to_death)
|
||||
flush_type();
|
||||
count = 0;
|
||||
status(rs);
|
||||
if (mp == NULL)
|
||||
return(-1);
|
||||
else
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* set_mname:
|
||||
* return the monster name for the given monster
|
||||
*/
|
||||
char *
|
||||
set_mname(THING *tp)
|
||||
{
|
||||
int ch;
|
||||
char *mname;
|
||||
static char tbuf[MAXSTR] = { 't', 'h', 'e', ' ' };
|
||||
|
||||
if (!see_monst(tp) && !on(player, SEEMONST))
|
||||
return (terse ? (char *)"it" : (char *)"something");
|
||||
else if (on(player, ISHALU))
|
||||
{
|
||||
move(tp->t_pos.y, tp->t_pos.x);
|
||||
ch = toascii(inch());
|
||||
if (!isupper(ch))
|
||||
ch = rnd(26);
|
||||
else
|
||||
ch -= 'A';
|
||||
mname = monsters[ch].m_name;
|
||||
}
|
||||
else
|
||||
mname = monsters[tp->t_type - 'A'].m_name;
|
||||
strcpy(&tbuf[4], mname);
|
||||
return tbuf;
|
||||
}
|
||||
|
||||
/*
|
||||
* swing:
|
||||
* Returns true if the swing hits
|
||||
*/
|
||||
int
|
||||
swing(int at_lvl, int op_arm, int wplus)
|
||||
{
|
||||
int res = rnd(20);
|
||||
int need = (20 - at_lvl) - op_arm;
|
||||
|
||||
return (res + wplus >= need);
|
||||
}
|
||||
|
||||
/*
|
||||
* roll_em:
|
||||
* Roll several attacks
|
||||
*/
|
||||
bool
|
||||
roll_em(THING *thatt, THING *thdef, THING *weap, bool hurl)
|
||||
{
|
||||
register struct stats *att, *def;
|
||||
register char *cp;
|
||||
register int ndice, nsides, def_arm;
|
||||
register bool did_hit = FALSE;
|
||||
register int hplus;
|
||||
register int dplus;
|
||||
register int damage;
|
||||
|
||||
att = &thatt->t_stats;
|
||||
def = &thdef->t_stats;
|
||||
if (weap == NULL)
|
||||
{
|
||||
cp = att->s_dmg;
|
||||
dplus = 0;
|
||||
hplus = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
hplus = (weap == NULL ? 0 : weap->o_hplus);
|
||||
dplus = (weap == NULL ? 0 : weap->o_dplus);
|
||||
if (weap == cur_weapon)
|
||||
{
|
||||
if (ISRING(LEFT, R_ADDDAM))
|
||||
dplus += cur_ring[LEFT]->o_arm;
|
||||
else if (ISRING(LEFT, R_ADDHIT))
|
||||
hplus += cur_ring[LEFT]->o_arm;
|
||||
if (ISRING(RIGHT, R_ADDDAM))
|
||||
dplus += cur_ring[RIGHT]->o_arm;
|
||||
else if (ISRING(RIGHT, R_ADDHIT))
|
||||
hplus += cur_ring[RIGHT]->o_arm;
|
||||
}
|
||||
cp = weap->o_damage;
|
||||
if (hurl)
|
||||
{
|
||||
if ((weap->o_flags&ISMISL) && cur_weapon != NULL &&
|
||||
cur_weapon->o_which == weap->o_launch)
|
||||
{
|
||||
cp = weap->o_hurldmg;
|
||||
hplus += cur_weapon->o_hplus;
|
||||
dplus += cur_weapon->o_dplus;
|
||||
}
|
||||
else if (weap->o_launch < 0)
|
||||
cp = weap->o_hurldmg;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* If the creature being attacked is not running (alseep or held)
|
||||
* then the attacker gets a plus four bonus to hit.
|
||||
*/
|
||||
if (!on(*thdef, ISRUN))
|
||||
hplus += 4;
|
||||
def_arm = def->s_arm;
|
||||
if (def == &pstats)
|
||||
{
|
||||
if (cur_armor != NULL)
|
||||
def_arm = cur_armor->o_arm;
|
||||
if (ISRING(LEFT, R_PROTECT))
|
||||
def_arm -= cur_ring[LEFT]->o_arm;
|
||||
if (ISRING(RIGHT, R_PROTECT))
|
||||
def_arm -= cur_ring[RIGHT]->o_arm;
|
||||
}
|
||||
while(cp != NULL && *cp != '\0')
|
||||
{
|
||||
ndice = atoi(cp);
|
||||
if ((cp = strchr(cp, 'x')) == NULL)
|
||||
break;
|
||||
nsides = atoi(++cp);
|
||||
if (swing(att->s_lvl, def_arm, hplus + str_plus[att->s_str]))
|
||||
{
|
||||
int proll;
|
||||
|
||||
proll = roll(ndice, nsides);
|
||||
#ifdef MASTER
|
||||
if (ndice + nsides > 0 && proll <= 0)
|
||||
debug("Damage for %dx%d came out %d, dplus = %d, add_dam = %d, def_arm = %d", ndice, nsides, proll, dplus, add_dam[att->s_str], def_arm);
|
||||
#endif
|
||||
damage = dplus + proll + add_dam[att->s_str];
|
||||
def->s_hpt -= max(0, damage);
|
||||
did_hit = TRUE;
|
||||
}
|
||||
if ((cp = strchr(cp, '/')) == NULL)
|
||||
break;
|
||||
cp++;
|
||||
}
|
||||
return did_hit;
|
||||
}
|
||||
|
||||
/*
|
||||
* prname:
|
||||
* The print name of a combatant
|
||||
*/
|
||||
char *
|
||||
prname(char *mname, bool upper)
|
||||
{
|
||||
static char tbuf[MAXSTR];
|
||||
|
||||
*tbuf = '\0';
|
||||
if (mname == 0)
|
||||
strcpy(tbuf, "you");
|
||||
else
|
||||
strcpy(tbuf, mname);
|
||||
if (upper)
|
||||
*tbuf = (char) toupper(*tbuf);
|
||||
return tbuf;
|
||||
}
|
||||
|
||||
/*
|
||||
* thunk:
|
||||
* A missile hits a monster
|
||||
*/
|
||||
void
|
||||
thunk(struct rogue_state *rs,THING *weap, char *mname, bool noend)
|
||||
{
|
||||
if (to_death)
|
||||
return;
|
||||
if (weap->o_type == WEAPON)
|
||||
addmsg(rs,"the %s hits ", weap_info[weap->o_which].oi_name);
|
||||
else
|
||||
addmsg(rs,"you hit ");
|
||||
addmsg(rs,"%s", mname);
|
||||
if (!noend)
|
||||
endmsg(rs);
|
||||
}
|
||||
|
||||
/*
|
||||
* hit:
|
||||
* Print a message to indicate a succesful hit
|
||||
*/
|
||||
|
||||
void
|
||||
hit(struct rogue_state *rs,char *er, char *ee, bool noend)
|
||||
{
|
||||
int32_t i; const char *s;
|
||||
|
||||
if (to_death)
|
||||
return;
|
||||
addmsg(rs,prname(er, TRUE));
|
||||
if (terse)
|
||||
s = " hit";
|
||||
else
|
||||
{
|
||||
i = rnd(4);
|
||||
if (er != NULL)
|
||||
i += 4;
|
||||
s = h_names[i];
|
||||
}
|
||||
addmsg(rs,(char *)s);
|
||||
if (!terse)
|
||||
addmsg(rs,prname(ee, FALSE));
|
||||
if (!noend)
|
||||
endmsg(rs);
|
||||
}
|
||||
|
||||
/*
|
||||
* miss:
|
||||
* Print a message to indicate a poor swing
|
||||
*/
|
||||
void
|
||||
miss(struct rogue_state *rs,char *er, char *ee, bool noend)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (to_death)
|
||||
return;
|
||||
addmsg(rs,prname(er, TRUE));
|
||||
if (terse)
|
||||
i = 0;
|
||||
else
|
||||
i = rnd(4);
|
||||
if (er != NULL)
|
||||
i += 4;
|
||||
addmsg(rs,(char *)m_names[i]);
|
||||
if (!terse)
|
||||
addmsg(rs," %s", prname(ee, FALSE));
|
||||
if (!noend)
|
||||
endmsg(rs);
|
||||
}
|
||||
|
||||
/*
|
||||
* bounce:
|
||||
* A missile misses a monster
|
||||
*/
|
||||
void
|
||||
bounce(struct rogue_state *rs,THING *weap, char *mname, bool noend)
|
||||
{
|
||||
if (to_death)
|
||||
return;
|
||||
if (weap->o_type == WEAPON)
|
||||
addmsg(rs,"the %s misses ", weap_info[weap->o_which].oi_name);
|
||||
else
|
||||
addmsg(rs,"you missed ");
|
||||
addmsg(rs,mname);
|
||||
if (!noend)
|
||||
endmsg(rs);
|
||||
}
|
||||
|
||||
/*
|
||||
* remove_mon:
|
||||
* Remove a monster from the screen
|
||||
*/
|
||||
void
|
||||
remove_mon(struct rogue_state *rs,coord *mp, THING *tp, bool waskill)
|
||||
{
|
||||
register THING *obj, *nexti;
|
||||
for (obj = tp->t_pack; obj != NULL; obj = nexti)
|
||||
{
|
||||
nexti = next(obj);
|
||||
obj->o_pos = tp->t_pos;
|
||||
detach(tp->t_pack, obj);
|
||||
if (waskill)
|
||||
fall(rs,obj, FALSE);
|
||||
else discard(obj);
|
||||
}
|
||||
moat(mp->y, mp->x) = NULL;
|
||||
mvaddch(mp->y, mp->x, tp->t_oldch);
|
||||
detach(mlist, tp);
|
||||
if (on(*tp, ISTARGET))
|
||||
{
|
||||
kamikaze = FALSE;
|
||||
to_death = FALSE;
|
||||
if (fight_flush)
|
||||
flush_type();
|
||||
}
|
||||
discard(tp);
|
||||
}
|
||||
|
||||
/*
|
||||
* killed:
|
||||
* Called to put a monster to death
|
||||
*/
|
||||
void
|
||||
killed(struct rogue_state *rs,THING *tp, bool pr)
|
||||
{
|
||||
char *mname;
|
||||
|
||||
pstats.s_exp += tp->t_stats.s_exp;
|
||||
|
||||
/*
|
||||
* If the monster was a venus flytrap, un-hold him
|
||||
*/
|
||||
switch (tp->t_type)
|
||||
{
|
||||
case 'F':
|
||||
player.t_flags &= ~ISHELD;
|
||||
vf_hit = 0;
|
||||
strcpy(monsters['F'-'A'].m_stats.s_dmg, "000x0");
|
||||
when 'L':
|
||||
{
|
||||
THING *gold;
|
||||
|
||||
if (fallpos(&tp->t_pos, &tp->t_room->r_gold) && level >= max_level)
|
||||
{
|
||||
gold = new_item();
|
||||
gold->o_type = GOLD;
|
||||
gold->o_goldval = GOLDCALC;
|
||||
if (save(VS_MAGIC))
|
||||
gold->o_goldval += GOLDCALC + GOLDCALC
|
||||
+ GOLDCALC + GOLDCALC;
|
||||
attach(tp->t_pack, gold);
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Get rid of the monster.
|
||||
*/
|
||||
mname = set_mname(tp);
|
||||
remove_mon(rs,&tp->t_pos, tp, TRUE);
|
||||
if (pr)
|
||||
{
|
||||
if (has_hit)
|
||||
{
|
||||
addmsg(rs,". Defeated ");
|
||||
has_hit = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!terse)
|
||||
addmsg(rs,"you have ");
|
||||
addmsg(rs,"defeated ");
|
||||
}
|
||||
msg(rs,mname);
|
||||
}
|
||||
/*
|
||||
* Do adjustments if he went up a level
|
||||
*/
|
||||
check_level(rs);
|
||||
if (fight_flush)
|
||||
flush_type();
|
||||
}
|
||||
@@ -1,498 +0,0 @@
|
||||
// Copyright (c) 2016-2023 The Hush developers
|
||||
// Distributed under the GPLv3 software license, see the accompanying
|
||||
// file COPYING or https://www.gnu.org/licenses/gpl-3.0.en.html
|
||||
/*
|
||||
* global variable initializaton
|
||||
*
|
||||
* @(#)init.c 4.31 (Berkeley) 02/05/99
|
||||
*
|
||||
* Rogue: Exploring the Dungeons of Doom
|
||||
* Copyright (C) 1980-1983, 1985, 1999 Michael Toy, Ken Arnold and Glenn Wichman
|
||||
* All rights reserved.
|
||||
*
|
||||
* See the file LICENSE.TXT for full copyright and licensing information.
|
||||
*/
|
||||
|
||||
//#include <stdlib.h>
|
||||
//#include <curses.h>
|
||||
//#include <ctype.h>
|
||||
//#include <string.h>
|
||||
#include "rogue.h"
|
||||
|
||||
/*
|
||||
* init_player:
|
||||
* Roll her up
|
||||
*/
|
||||
void rogue_restoreobject(THING *o,struct rogue_packitem *item);
|
||||
|
||||
int32_t rogue_total(THING *o)
|
||||
{
|
||||
if ( (o->o_flags & ISMANY) != 0 )
|
||||
return(1);
|
||||
else return(o->o_count);
|
||||
}
|
||||
|
||||
void restore_player(struct rogue_state *rs)
|
||||
{
|
||||
int32_t i,total = 0; THING *obj;
|
||||
//rs->P.gold = purse;
|
||||
max_hp = rs->P.hitpoints;
|
||||
//pstats.s_hpt = max_hp;
|
||||
pstats.s_str = rs->P.strength & 0xffff;
|
||||
if ( (max_stats.s_str= (rs->P.strength >> 16) & 0xffff) == 0 )
|
||||
max_stats.s_str = 16;
|
||||
if ( pstats.s_str > max_stats.s_str )
|
||||
pstats.s_str = max_stats.s_str;
|
||||
pstats.s_lvl = rs->P.level;
|
||||
pstats.s_exp = rs->P.experience;
|
||||
for (i=0; i<rs->P.packsize&&i<MAXPACK; i++)
|
||||
{
|
||||
obj = new_item();
|
||||
rogue_restoreobject(obj,&rs->P.roguepack[i]);
|
||||
total += rogue_total(obj);
|
||||
if ( total > ROGUE_MAXTOTAL )
|
||||
break;
|
||||
add_pack(rs,obj,TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
void init_player(struct rogue_state *rs)
|
||||
{
|
||||
register THING *obj; int32_t i;
|
||||
pstats = max_stats;
|
||||
food_left = HUNGERTIME;
|
||||
|
||||
if ( rs->restoring != 0 )
|
||||
{
|
||||
// duplicate rng usage of normal case
|
||||
obj = new_item();
|
||||
init_weapon(obj, MACE);
|
||||
free(obj);
|
||||
obj = new_item();
|
||||
init_weapon(obj, BOW);
|
||||
free(obj);
|
||||
obj = new_item();
|
||||
init_weapon(obj, ARROW);
|
||||
obj->o_count = rnd(15) + 25;
|
||||
free(obj);
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* Give him some food
|
||||
*/
|
||||
obj = new_item();
|
||||
obj->o_type = FOOD;
|
||||
obj->o_count = 1;
|
||||
add_pack(rs,obj, TRUE);
|
||||
/*
|
||||
* And his suit of armor
|
||||
*/
|
||||
obj = new_item();
|
||||
obj->o_type = ARMOR;
|
||||
obj->o_which = RING_MAIL;
|
||||
obj->o_arm = a_class[RING_MAIL] - 1;
|
||||
obj->o_flags |= ISKNOW;
|
||||
obj->o_count = 1;
|
||||
cur_armor = obj;
|
||||
add_pack(rs,obj, TRUE);
|
||||
/*
|
||||
* Give him his weaponry. First a mace.
|
||||
*/
|
||||
obj = new_item();
|
||||
init_weapon(obj, MACE);
|
||||
obj->o_hplus = 1;
|
||||
obj->o_dplus = 1;
|
||||
obj->o_flags |= ISKNOW;
|
||||
add_pack(rs,obj, TRUE);
|
||||
cur_weapon = obj;
|
||||
/*
|
||||
* Now a +1 bow
|
||||
*/
|
||||
obj = new_item();
|
||||
init_weapon(obj, BOW);
|
||||
obj->o_hplus = 1;
|
||||
obj->o_flags |= ISKNOW;
|
||||
add_pack(rs,obj, TRUE);
|
||||
/*
|
||||
* Now some arrows
|
||||
*/
|
||||
obj = new_item();
|
||||
init_weapon(obj, ARROW);
|
||||
obj->o_count = rnd(15) + 25;
|
||||
obj->o_flags |= ISKNOW;
|
||||
add_pack(rs,obj, TRUE);
|
||||
//fprintf(stderr,"initial o_count.%d\n",obj->o_count); sleep(3);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Contains defintions and functions for dealing with things like
|
||||
* potions and scrolls
|
||||
*/
|
||||
|
||||
const char *rainbow[] = {
|
||||
"amber",
|
||||
"aquamarine",
|
||||
"black",
|
||||
"blue",
|
||||
"brown",
|
||||
"clear",
|
||||
"crimson",
|
||||
"cyan",
|
||||
"ecru",
|
||||
"gold",
|
||||
"green",
|
||||
"grey",
|
||||
"magenta",
|
||||
"orange",
|
||||
"pink",
|
||||
"plaid",
|
||||
"purple",
|
||||
"red",
|
||||
"silver",
|
||||
"tan",
|
||||
"tangerine",
|
||||
"topaz",
|
||||
"turquoise",
|
||||
"vermilion",
|
||||
"violet",
|
||||
"white",
|
||||
"yellow",
|
||||
};
|
||||
|
||||
#define NCOLORS (sizeof rainbow / sizeof (char *))
|
||||
int cNCOLORS = NCOLORS;
|
||||
|
||||
static const char *sylls[] = {
|
||||
"a", "ab", "ag", "aks", "ala", "an", "app", "arg", "arze", "ash",
|
||||
"bek", "bie", "bit", "bjor", "blu", "bot", "bu", "byt", "comp",
|
||||
"con", "cos", "cre", "dalf", "dan", "den", "do", "e", "eep", "el",
|
||||
"eng", "er", "ere", "erk", "esh", "evs", "fa", "fid", "fri", "fu",
|
||||
"gan", "gar", "glen", "gop", "gre", "ha", "hyd", "i", "ing", "ip",
|
||||
"ish", "it", "ite", "iv", "jo", "kho", "kli", "klis", "la", "lech",
|
||||
"mar", "me", "mi", "mic", "mik", "mon", "mung", "mur", "nej",
|
||||
"nelg", "nep", "ner", "nes", "nes", "nih", "nin", "o", "od", "ood",
|
||||
"org", "orn", "ox", "oxy", "pay", "ple", "plu", "po", "pot",
|
||||
"prok", "re", "rea", "rhov", "ri", "ro", "rog", "rok", "rol", "sa",
|
||||
"san", "sat", "sef", "seh", "shu", "ski", "sna", "sne", "snik",
|
||||
"sno", "so", "sol", "sri", "sta", "sun", "ta", "tab", "tem",
|
||||
"ther", "ti", "tox", "trol", "tue", "turs", "u", "ulk", "um", "un",
|
||||
"uni", "ur", "val", "viv", "vly", "vom", "wah", "wed", "werg",
|
||||
"wex", "whon", "wun", "xo", "y", "yot", "yu", "zant", "zeb", "zim",
|
||||
"zok", "zon", "zum",
|
||||
};
|
||||
|
||||
const STONE stones[] = {
|
||||
{ "agate", 25},
|
||||
{ "alexandrite", 40},
|
||||
{ "amethyst", 50},
|
||||
{ "carnelian", 40},
|
||||
{ "diamond", 300},
|
||||
{ "emerald", 300},
|
||||
{ "germanium", 225},
|
||||
{ "granite", 5},
|
||||
{ "garnet", 50},
|
||||
{ "jade", 150},
|
||||
{ "kryptonite", 300},
|
||||
{ "lapis lazuli", 50},
|
||||
{ "moonstone", 50},
|
||||
{ "obsidian", 15},
|
||||
{ "onyx", 60},
|
||||
{ "opal", 200},
|
||||
{ "pearl", 220},
|
||||
{ "peridot", 63},
|
||||
{ "ruby", 350},
|
||||
{ "sapphire", 285},
|
||||
{ "stibotantalite", 200},
|
||||
{ "tiger eye", 50},
|
||||
{ "topaz", 60},
|
||||
{ "turquoise", 70},
|
||||
{ "taaffeite", 300},
|
||||
{ "zircon", 80},
|
||||
};
|
||||
|
||||
#define NSTONES (sizeof stones / sizeof (STONE))
|
||||
int cNSTONES = NSTONES;
|
||||
|
||||
const char *wood[] = {
|
||||
"avocado wood",
|
||||
"balsa",
|
||||
"bamboo",
|
||||
"banyan",
|
||||
"birch",
|
||||
"cedar",
|
||||
"cherry",
|
||||
"cinnibar",
|
||||
"cypress",
|
||||
"dogwood",
|
||||
"driftwood",
|
||||
"ebony",
|
||||
"elm",
|
||||
"eucalyptus",
|
||||
"fall",
|
||||
"hemlock",
|
||||
"holly",
|
||||
"ironwood",
|
||||
"kukui wood",
|
||||
"mahogany",
|
||||
"manzanita",
|
||||
"maple",
|
||||
"oaken",
|
||||
"persimmon wood",
|
||||
"pecan",
|
||||
"pine",
|
||||
"poplar",
|
||||
"redwood",
|
||||
"rosewood",
|
||||
"spruce",
|
||||
"teak",
|
||||
"walnut",
|
||||
"zebrawood",
|
||||
};
|
||||
|
||||
#define NWOOD (sizeof wood / sizeof (char *))
|
||||
int cNWOOD = NWOOD;
|
||||
|
||||
const char *metal[] = {
|
||||
"aluminum",
|
||||
"beryllium",
|
||||
"bone",
|
||||
"brass",
|
||||
"bronze",
|
||||
"copper",
|
||||
"electrum",
|
||||
"gold",
|
||||
"iron",
|
||||
"lead",
|
||||
"magnesium",
|
||||
"mercury",
|
||||
"nickel",
|
||||
"pewter",
|
||||
"platinum",
|
||||
"steel",
|
||||
"silver",
|
||||
"silicon",
|
||||
"tin",
|
||||
"titanium",
|
||||
"tungsten",
|
||||
"zinc",
|
||||
};
|
||||
|
||||
#define NMETAL (sizeof metal / sizeof (char *))
|
||||
int cNMETAL = NMETAL;
|
||||
#define MAX3(a,b,c) (a > b ? (a > c ? a : c) : (b > c ? b : c))
|
||||
|
||||
static bool used[MAX3(NCOLORS, NSTONES, NWOOD)];
|
||||
|
||||
/*
|
||||
* init_colors:
|
||||
* Initialize the potion color scheme for this time
|
||||
*/
|
||||
void
|
||||
init_colors()
|
||||
{
|
||||
register int i, j;
|
||||
memset(used,0,sizeof(used));
|
||||
for (i = 0; i < NCOLORS; i++)
|
||||
used[i] = FALSE;
|
||||
for (i = 0; i < MAXPOTIONS; i++)
|
||||
{
|
||||
do
|
||||
j = rnd(NCOLORS);
|
||||
until (!used[j]);
|
||||
used[j] = TRUE;
|
||||
p_colors[i] = rainbow[j];
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* init_names:
|
||||
* Generate the names of the various scrolls
|
||||
*/
|
||||
#define MAXNAME 40 /* Max number of characters in a name */
|
||||
|
||||
void
|
||||
init_names()
|
||||
{
|
||||
register int nsyl;
|
||||
register char *cp; const char *sp;
|
||||
register int i, nwords;
|
||||
|
||||
for (i = 0; i < MAXSCROLLS; i++)
|
||||
{
|
||||
cp = prbuf;
|
||||
nwords = rnd(3) + 2;
|
||||
while (nwords--)
|
||||
{
|
||||
nsyl = rnd(3) + 1;
|
||||
while (nsyl--)
|
||||
{
|
||||
sp = sylls[rnd((sizeof sylls) / (sizeof (char *)))];
|
||||
if (&cp[strlen(sp)] > &prbuf[MAXNAME])
|
||||
break;
|
||||
while (*sp)
|
||||
*cp++ = *sp++;
|
||||
}
|
||||
*cp++ = ' ';
|
||||
}
|
||||
*--cp = '\0';
|
||||
s_names[i] = (char *) malloc((unsigned) strlen(prbuf)+1);
|
||||
strcpy(s_names[i], prbuf);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* init_stones:
|
||||
* Initialize the ring stone setting scheme for this time
|
||||
*/
|
||||
void
|
||||
init_stones()
|
||||
{
|
||||
register int i, j;
|
||||
for (i = 0; i < NSTONES; i++)
|
||||
used[i] = FALSE;
|
||||
for (i = 0; i < MAXRINGS; i++)
|
||||
{
|
||||
do
|
||||
j = rnd(NSTONES);
|
||||
until (!used[j]);
|
||||
used[j] = TRUE;
|
||||
r_stones[i] = stones[j].st_name;
|
||||
ring_info[i].oi_worth += stones[j].st_value;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* init_materials:
|
||||
* Initialize the construction materials for wands and staffs
|
||||
*/
|
||||
void
|
||||
init_materials()
|
||||
{
|
||||
register int i, j;
|
||||
register const char *str;
|
||||
static bool metused[NMETAL];
|
||||
memset(metused,0,sizeof(metused));
|
||||
for (i = 0; i < NWOOD; i++)
|
||||
used[i] = FALSE;
|
||||
for (i = 0; i < NMETAL; i++)
|
||||
metused[i] = FALSE;
|
||||
for (i = 0; i < MAXSTICKS; i++)
|
||||
{
|
||||
for (;;)
|
||||
if (rnd(2) == 0)
|
||||
{
|
||||
j = rnd(NMETAL);
|
||||
if (!metused[j])
|
||||
{
|
||||
ws_type[i] = "wand";
|
||||
str = metal[j];
|
||||
metused[j] = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
j = rnd(NWOOD);
|
||||
if (!used[j])
|
||||
{
|
||||
ws_type[i] = "staff";
|
||||
str = wood[j];
|
||||
used[j] = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
ws_made[i] = str;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef MASTER
|
||||
# define NT NUMTHINGS, "things"
|
||||
# define MP MAXPOTIONS, "potions"
|
||||
# define MS MAXSCROLLS, "scrolls"
|
||||
# define MR MAXRINGS, "rings"
|
||||
# define MWS MAXSTICKS, "sticks"
|
||||
# define MW MAXWEAPONS, "weapons"
|
||||
# define MA MAXARMORS, "armor"
|
||||
#else
|
||||
# define NT NUMTHINGS
|
||||
# define MP MAXPOTIONS
|
||||
# define MS MAXSCROLLS
|
||||
# define MR MAXRINGS
|
||||
# define MWS MAXSTICKS
|
||||
# define MW MAXWEAPONS
|
||||
# define MA MAXARMORS
|
||||
#endif
|
||||
|
||||
/*
|
||||
* sumprobs:
|
||||
* Sum up the probabilities for items appearing
|
||||
*/
|
||||
void
|
||||
sumprobs(struct obj_info *info, int bound
|
||||
#ifdef MASTER
|
||||
, char *name
|
||||
#endif
|
||||
)
|
||||
{
|
||||
#ifdef MASTER
|
||||
struct obj_info *start = info;
|
||||
#endif
|
||||
struct obj_info *endp;
|
||||
endp = info + bound;
|
||||
while (++info < endp)
|
||||
info->oi_prob += (info - 1)->oi_prob;
|
||||
#ifdef MASTER
|
||||
badcheck(name, start, bound);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* init_probs:
|
||||
* Initialize the probabilities for the various items
|
||||
*/
|
||||
void
|
||||
init_probs()
|
||||
{
|
||||
sumprobs(things, NT);
|
||||
sumprobs(pot_info, MP);
|
||||
sumprobs(scr_info, MS);
|
||||
sumprobs(ring_info, MR);
|
||||
sumprobs(ws_info, MWS);
|
||||
sumprobs(weap_info, MW);
|
||||
sumprobs(arm_info, MA);
|
||||
}
|
||||
|
||||
#ifdef MASTER
|
||||
/*
|
||||
* badcheck:
|
||||
* Check to see if a series of probabilities sums to 100
|
||||
*/
|
||||
void
|
||||
badcheck(char *name, struct obj_info *info, int bound)
|
||||
{
|
||||
register struct obj_info *end;
|
||||
|
||||
if (info[bound - 1].oi_prob == 100)
|
||||
return;
|
||||
printf("\nBad percentages for %s (bound = %d):\n", name, bound);
|
||||
for (end = &info[bound]; info < end; info++)
|
||||
printf("%3d%% %s\n", info->oi_prob, info->oi_name);
|
||||
printf("[hit RETURN to continue]");
|
||||
fflush(stdout);
|
||||
while (getchar() != '\n')
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* pick_color:
|
||||
* If he is halucinating, pick a random color name and return it,
|
||||
* otherwise return the given color.
|
||||
*/
|
||||
char *
|
||||
pick_color(char *col)
|
||||
{
|
||||
return (on(player, ISHALU) ? (char *)rainbow[rnd(NCOLORS)] : col);
|
||||
}
|
||||
@@ -1,323 +0,0 @@
|
||||
#!/bin/sh
|
||||
# install - install a program, script, or datafile
|
||||
|
||||
scriptversion=2005-05-14.22
|
||||
|
||||
# This originates from X11R5 (mit/util/scripts/install.sh), which was
|
||||
# later released in X11R6 (xc/config/util/install.sh) with the
|
||||
# following copyright and license.
|
||||
#
|
||||
# Copyright (C) 1994 X Consortium
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to
|
||||
# deal in the Software without restriction, including without limitation the
|
||||
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
# sell copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
|
||||
# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
# Except as contained in this notice, the name of the X Consortium shall not
|
||||
# be used in advertising or otherwise to promote the sale, use or other deal-
|
||||
# ings in this Software without prior written authorization from the X Consor-
|
||||
# tium.
|
||||
#
|
||||
#
|
||||
# FSF changes to this file are in the public domain.
|
||||
#
|
||||
# Calling this script install-sh is preferred over install.sh, to prevent
|
||||
# `make' implicit rules from creating a file called install from it
|
||||
# when there is no Makefile.
|
||||
#
|
||||
# This script is compatible with the BSD install script, but was written
|
||||
# from scratch. It can only install one file at a time, a restriction
|
||||
# shared with many OS's install programs.
|
||||
|
||||
# set DOITPROG to echo to test this script
|
||||
|
||||
# Don't use :- since 4.3BSD and earlier shells don't like it.
|
||||
doit="${DOITPROG-}"
|
||||
|
||||
# put in absolute paths if you don't have them in your path; or use env. vars.
|
||||
|
||||
mvprog="${MVPROG-mv}"
|
||||
cpprog="${CPPROG-cp}"
|
||||
chmodprog="${CHMODPROG-chmod}"
|
||||
chownprog="${CHOWNPROG-chown}"
|
||||
chgrpprog="${CHGRPPROG-chgrp}"
|
||||
stripprog="${STRIPPROG-strip}"
|
||||
rmprog="${RMPROG-rm}"
|
||||
mkdirprog="${MKDIRPROG-mkdir}"
|
||||
|
||||
chmodcmd="$chmodprog 0755"
|
||||
chowncmd=
|
||||
chgrpcmd=
|
||||
stripcmd=
|
||||
rmcmd="$rmprog -f"
|
||||
mvcmd="$mvprog"
|
||||
src=
|
||||
dst=
|
||||
dir_arg=
|
||||
dstarg=
|
||||
no_target_directory=
|
||||
|
||||
usage="Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
|
||||
or: $0 [OPTION]... SRCFILES... DIRECTORY
|
||||
or: $0 [OPTION]... -t DIRECTORY SRCFILES...
|
||||
or: $0 [OPTION]... -d DIRECTORIES...
|
||||
|
||||
In the 1st form, copy SRCFILE to DSTFILE.
|
||||
In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
|
||||
In the 4th, create DIRECTORIES.
|
||||
|
||||
Options:
|
||||
-c (ignored)
|
||||
-d create directories instead of installing files.
|
||||
-g GROUP $chgrpprog installed files to GROUP.
|
||||
-m MODE $chmodprog installed files to MODE.
|
||||
-o USER $chownprog installed files to USER.
|
||||
-s $stripprog installed files.
|
||||
-t DIRECTORY install into DIRECTORY.
|
||||
-T report an error if DSTFILE is a directory.
|
||||
--help display this help and exit.
|
||||
--version display version info and exit.
|
||||
|
||||
Environment variables override the default commands:
|
||||
CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG
|
||||
"
|
||||
|
||||
while test -n "$1"; do
|
||||
case $1 in
|
||||
-c) shift
|
||||
continue;;
|
||||
|
||||
-d) dir_arg=true
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-g) chgrpcmd="$chgrpprog $2"
|
||||
shift
|
||||
shift
|
||||
continue;;
|
||||
|
||||
--help) echo "$usage"; exit $?;;
|
||||
|
||||
-m) chmodcmd="$chmodprog $2"
|
||||
shift
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-o) chowncmd="$chownprog $2"
|
||||
shift
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-s) stripcmd=$stripprog
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-t) dstarg=$2
|
||||
shift
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-T) no_target_directory=true
|
||||
shift
|
||||
continue;;
|
||||
|
||||
--version) echo "$0 $scriptversion"; exit $?;;
|
||||
|
||||
*) # When -d is used, all remaining arguments are directories to create.
|
||||
# When -t is used, the destination is already specified.
|
||||
test -n "$dir_arg$dstarg" && break
|
||||
# Otherwise, the last argument is the destination. Remove it from $@.
|
||||
for arg
|
||||
do
|
||||
if test -n "$dstarg"; then
|
||||
# $@ is not empty: it contains at least $arg.
|
||||
set fnord "$@" "$dstarg"
|
||||
shift # fnord
|
||||
fi
|
||||
shift # arg
|
||||
dstarg=$arg
|
||||
done
|
||||
break;;
|
||||
esac
|
||||
done
|
||||
|
||||
if test -z "$1"; then
|
||||
if test -z "$dir_arg"; then
|
||||
echo "$0: no input file specified." >&2
|
||||
exit 1
|
||||
fi
|
||||
# It's OK to call `install-sh -d' without argument.
|
||||
# This can happen when creating conditional directories.
|
||||
exit 0
|
||||
fi
|
||||
|
||||
for src
|
||||
do
|
||||
# Protect names starting with `-'.
|
||||
case $src in
|
||||
-*) src=./$src ;;
|
||||
esac
|
||||
|
||||
if test -n "$dir_arg"; then
|
||||
dst=$src
|
||||
src=
|
||||
|
||||
if test -d "$dst"; then
|
||||
mkdircmd=:
|
||||
chmodcmd=
|
||||
else
|
||||
mkdircmd=$mkdirprog
|
||||
fi
|
||||
else
|
||||
# Waiting for this to be detected by the "$cpprog $src $dsttmp" command
|
||||
# might cause directories to be created, which would be especially bad
|
||||
# if $src (and thus $dsttmp) contains '*'.
|
||||
if test ! -f "$src" && test ! -d "$src"; then
|
||||
echo "$0: $src does not exist." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if test -z "$dstarg"; then
|
||||
echo "$0: no destination specified." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
dst=$dstarg
|
||||
# Protect names starting with `-'.
|
||||
case $dst in
|
||||
-*) dst=./$dst ;;
|
||||
esac
|
||||
|
||||
# If destination is a directory, append the input filename; won't work
|
||||
# if double slashes aren't ignored.
|
||||
if test -d "$dst"; then
|
||||
if test -n "$no_target_directory"; then
|
||||
echo "$0: $dstarg: Is a directory" >&2
|
||||
exit 1
|
||||
fi
|
||||
dst=$dst/`basename "$src"`
|
||||
fi
|
||||
fi
|
||||
|
||||
# This sed command emulates the dirname command.
|
||||
dstdir=`echo "$dst" | sed -e 's,/*$,,;s,[^/]*$,,;s,/*$,,;s,^$,.,'`
|
||||
|
||||
# Make sure that the destination directory exists.
|
||||
|
||||
# Skip lots of stat calls in the usual case.
|
||||
if test ! -d "$dstdir"; then
|
||||
defaultIFS='
|
||||
'
|
||||
IFS="${IFS-$defaultIFS}"
|
||||
|
||||
oIFS=$IFS
|
||||
# Some sh's can't handle IFS=/ for some reason.
|
||||
IFS='%'
|
||||
set x `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'`
|
||||
shift
|
||||
IFS=$oIFS
|
||||
|
||||
pathcomp=
|
||||
|
||||
while test $# -ne 0 ; do
|
||||
pathcomp=$pathcomp$1
|
||||
shift
|
||||
if test ! -d "$pathcomp"; then
|
||||
$mkdirprog "$pathcomp"
|
||||
# mkdir can fail with a `File exist' error in case several
|
||||
# install-sh are creating the directory concurrently. This
|
||||
# is OK.
|
||||
test -d "$pathcomp" || exit
|
||||
fi
|
||||
pathcomp=$pathcomp/
|
||||
done
|
||||
fi
|
||||
|
||||
if test -n "$dir_arg"; then
|
||||
$doit $mkdircmd "$dst" \
|
||||
&& { test -z "$chowncmd" || $doit $chowncmd "$dst"; } \
|
||||
&& { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } \
|
||||
&& { test -z "$stripcmd" || $doit $stripcmd "$dst"; } \
|
||||
&& { test -z "$chmodcmd" || $doit $chmodcmd "$dst"; }
|
||||
|
||||
else
|
||||
dstfile=`basename "$dst"`
|
||||
|
||||
# Make a couple of temp file names in the proper directory.
|
||||
dsttmp=$dstdir/_inst.$$_
|
||||
rmtmp=$dstdir/_rm.$$_
|
||||
|
||||
# Trap to clean up those temp files at exit.
|
||||
trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
|
||||
trap '(exit $?); exit' 1 2 13 15
|
||||
|
||||
# Copy the file name to the temp name.
|
||||
$doit $cpprog "$src" "$dsttmp" &&
|
||||
|
||||
# and set any options; do chmod last to preserve setuid bits.
|
||||
#
|
||||
# If any of these fail, we abort the whole thing. If we want to
|
||||
# ignore errors from any of these, just make sure not to ignore
|
||||
# errors from the above "$doit $cpprog $src $dsttmp" command.
|
||||
#
|
||||
{ test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \
|
||||
&& { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \
|
||||
&& { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \
|
||||
&& { test -z "$chmodcmd" || $doit $chmodcmd "$dsttmp"; } &&
|
||||
|
||||
# Now rename the file to the real destination.
|
||||
{ $doit $mvcmd -f "$dsttmp" "$dstdir/$dstfile" 2>/dev/null \
|
||||
|| {
|
||||
# The rename failed, perhaps because mv can't rename something else
|
||||
# to itself, or perhaps because mv is so ancient that it does not
|
||||
# support -f.
|
||||
|
||||
# Now remove or move aside any old file at destination location.
|
||||
# We try this two ways since rm can't unlink itself on some
|
||||
# systems and the destination file might be busy for other
|
||||
# reasons. In this case, the final cleanup might fail but the new
|
||||
# file should still install successfully.
|
||||
{
|
||||
if test -f "$dstdir/$dstfile"; then
|
||||
$doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null \
|
||||
|| $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null \
|
||||
|| {
|
||||
echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2
|
||||
(exit 1); exit 1
|
||||
}
|
||||
else
|
||||
:
|
||||
fi
|
||||
} &&
|
||||
|
||||
# Now rename the file to the real destination.
|
||||
$doit $mvcmd "$dsttmp" "$dstdir/$dstfile"
|
||||
}
|
||||
}
|
||||
fi || { (exit 1); exit 1; }
|
||||
done
|
||||
|
||||
# The final little trick to "correctly" pass the exit status to the exit trap.
|
||||
{
|
||||
(exit 0); exit 0
|
||||
}
|
||||
|
||||
# Local variables:
|
||||
# eval: (add-hook 'write-file-hooks 'time-stamp)
|
||||
# time-stamp-start: "scriptversion="
|
||||
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||
# time-stamp-end: "$"
|
||||
# End:
|
||||
@@ -1,340 +0,0 @@
|
||||
// Copyright (c) 2016-2023 The Hush developers
|
||||
// Distributed under the GPLv3 software license, see the accompanying
|
||||
// file COPYING or https://www.gnu.org/licenses/gpl-3.0.en.html
|
||||
/*
|
||||
* Various input/output functions
|
||||
*
|
||||
* @(#)io.c 4.32 (Berkeley) 02/05/99
|
||||
*/
|
||||
|
||||
//#include <stdarg.h>
|
||||
//#include <curses.h>
|
||||
//#include <ctype.h>
|
||||
//#include <string.h>
|
||||
|
||||
#include "rogue.h"
|
||||
|
||||
/*
|
||||
* msg:
|
||||
* Display a message at the top of the screen.
|
||||
*/
|
||||
#define MAXMSG (NUMCOLS - sizeof "--More--")
|
||||
|
||||
static char msgbuf[2*MAXMSG+1];
|
||||
static int newpos = 0;
|
||||
|
||||
/* VARARGS1 */
|
||||
int
|
||||
msg(struct rogue_state *rs,char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
/*
|
||||
* if the string is "", just clear the line
|
||||
*/
|
||||
if (*fmt == '\0')
|
||||
{
|
||||
move(0, 0);
|
||||
clrtoeol();
|
||||
mpos = 0;
|
||||
return ~ESCAPE;
|
||||
}
|
||||
/*
|
||||
* otherwise add to the message and flush it out
|
||||
*/
|
||||
va_start(args, fmt);
|
||||
doadd(rs,fmt, args);
|
||||
va_end(args);
|
||||
return endmsg(rs);
|
||||
}
|
||||
|
||||
/*
|
||||
* addmsg:
|
||||
* Add things to the current message
|
||||
*/
|
||||
/* VARARGS1 */
|
||||
void
|
||||
addmsg(struct rogue_state *rs,char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
va_start(args, fmt);
|
||||
doadd(rs,fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
/*
|
||||
* endmsg:
|
||||
* Display a new msg (giving him a chance to see the previous one
|
||||
* if it is up there with the --More--)
|
||||
*/
|
||||
int
|
||||
endmsg(struct rogue_state *rs)
|
||||
{
|
||||
char ch;
|
||||
|
||||
if (save_msg)
|
||||
strcpy(huh, msgbuf);
|
||||
if (mpos)
|
||||
{
|
||||
look(rs,FALSE);
|
||||
mvaddstr(0, mpos, "--More--");
|
||||
if ( rs->sleeptime != 0 )
|
||||
refresh();
|
||||
if (!msg_esc)
|
||||
wait_for(rs,' ');
|
||||
else
|
||||
{
|
||||
while ((ch = readchar(rs)) != ' ')
|
||||
if (ch == ESCAPE)
|
||||
{
|
||||
msgbuf[0] = '\0';
|
||||
mpos = 0;
|
||||
newpos = 0;
|
||||
msgbuf[0] = '\0';
|
||||
return ESCAPE;
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* All messages should start with uppercase, except ones that
|
||||
* start with a pack addressing character
|
||||
*/
|
||||
if (islower(msgbuf[0]) && !lower_msg && msgbuf[1] != ')')
|
||||
msgbuf[0] = (char) toupper(msgbuf[0]);
|
||||
mvaddstr(0, 0, msgbuf);
|
||||
clrtoeol();
|
||||
mpos = newpos;
|
||||
newpos = 0;
|
||||
msgbuf[0] = '\0';
|
||||
if ( rs->sleeptime != 0 )
|
||||
refresh();
|
||||
return ~ESCAPE;
|
||||
}
|
||||
|
||||
/*
|
||||
* doadd:
|
||||
* Perform an add onto the message buffer
|
||||
*/
|
||||
void
|
||||
doadd(struct rogue_state *rs,char *fmt, va_list args)
|
||||
{
|
||||
static char buf[MAXSTR];
|
||||
|
||||
/*
|
||||
* Do the printf into buf
|
||||
*/
|
||||
vsprintf(buf, fmt, args);
|
||||
if (strlen(buf) + newpos >= MAXMSG)
|
||||
endmsg(rs);
|
||||
strcat(msgbuf, buf);
|
||||
newpos = (int) strlen(msgbuf);
|
||||
}
|
||||
|
||||
/*
|
||||
* step_ok:
|
||||
* Returns true if it is ok to step on ch
|
||||
*/
|
||||
int
|
||||
step_ok(int ch)
|
||||
{
|
||||
switch (ch)
|
||||
{
|
||||
case ' ':
|
||||
case '|':
|
||||
case '-':
|
||||
return FALSE;
|
||||
default:
|
||||
return (!isalpha(ch));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* readchar:
|
||||
* Reads and returns a character, checking for gross input errors
|
||||
*/
|
||||
char
|
||||
readchar(struct rogue_state *rs)
|
||||
{
|
||||
char c,ch = -1;
|
||||
if ( rs != 0 && rs->guiflag == 0 )
|
||||
{
|
||||
static uint32_t counter;
|
||||
if ( rs->ind < rs->numkeys )
|
||||
{
|
||||
c = rs->keystrokes[rs->ind++];
|
||||
if ( 0 )
|
||||
{
|
||||
static FILE *fp; static int32_t counter;
|
||||
if ( fp == 0 )
|
||||
fp = fopen("log","wb");
|
||||
if ( fp != 0 )
|
||||
{
|
||||
fprintf(fp,"%d: (%c) hp.%d num.%d gold.%d seed.%llu\n",counter,c,pstats.s_hpt,num_packitems(rs),purse,(long long)seed);
|
||||
fflush(fp);
|
||||
counter++;
|
||||
}
|
||||
}
|
||||
while ( c == 'Q' && rs->ind < rs->numkeys )
|
||||
{
|
||||
//fprintf(stderr,"Got 'Q' next (%c)\n",rs->keystrokes[rs->ind]); sleep(2);
|
||||
if ( rs->keystrokes[rs->ind] == 'y' )
|
||||
return(c);
|
||||
rs->ind++;
|
||||
c = rs->keystrokes[rs->ind++];
|
||||
}
|
||||
return(c);
|
||||
}
|
||||
if ( rs->replaydone != 0 && counter++ < 3 )
|
||||
fprintf(stderr,"replay finished but readchar called\n");
|
||||
rs->replaydone = (uint32_t)time(NULL);
|
||||
if ( counter < 3 || (counter & 1) == 0 )
|
||||
return('y');
|
||||
else return(ESCAPE);
|
||||
}
|
||||
if ( rs == 0 || rs->guiflag != 0 )
|
||||
{
|
||||
ch = (char) md_readchar();
|
||||
|
||||
if (ch == 3)
|
||||
{
|
||||
_quit();
|
||||
return(27);
|
||||
}
|
||||
if ( rs != 0 && rs->guiflag != 0 )
|
||||
{
|
||||
if ( rs->num < sizeof(rs->buffered) )
|
||||
{
|
||||
rs->buffered[rs->num++] = ch;
|
||||
if ( rs->num > (sizeof(rs->buffered)*9)/10 && rs->needflush == 0 )
|
||||
{
|
||||
rs->needflush = (uint32_t)time(NULL);
|
||||
//fprintf(stderr,"needflush.%u %d of %d\n",rs->needflush,rs->num,(int32_t)sizeof(rs->buffered));
|
||||
//sleep(3);
|
||||
}
|
||||
} else fprintf(stderr,"buffer filled without flushed\n");
|
||||
}
|
||||
} else fprintf(stderr,"readchar rs.%p non-gui error?\n",rs);
|
||||
return(ch);
|
||||
}
|
||||
|
||||
/*
|
||||
* status:
|
||||
* Display the important stats line. Keep the cursor where it was.
|
||||
*/
|
||||
void
|
||||
status(struct rogue_state *rs)
|
||||
{
|
||||
register int oy, ox, temp;
|
||||
static int hpwidth = 0;
|
||||
static int s_hungry = 0;
|
||||
static int s_lvl = 0;
|
||||
static int s_pur = -1;
|
||||
static int s_hp = 0;
|
||||
static int s_arm = 0;
|
||||
static str_t s_str = 0;
|
||||
static int s_exp = 0;
|
||||
static char *state_name[] =
|
||||
{
|
||||
"", "Hungry", "Weak", "Faint"
|
||||
};
|
||||
|
||||
/*
|
||||
* If nothing has changed since the last status, don't
|
||||
* bother.
|
||||
*/
|
||||
temp = (cur_armor != NULL ? cur_armor->o_arm : pstats.s_arm);
|
||||
if (s_hp == pstats.s_hpt && s_exp == pstats.s_exp && s_pur == purse
|
||||
&& s_arm == temp && s_str == pstats.s_str && s_lvl == level
|
||||
&& s_hungry == hungry_state
|
||||
&& !stat_msg
|
||||
)
|
||||
return;
|
||||
|
||||
s_arm = temp;
|
||||
|
||||
getyx(stdscr, oy, ox);
|
||||
if (s_hp != max_hp)
|
||||
{
|
||||
temp = max_hp;
|
||||
s_hp = max_hp;
|
||||
for (hpwidth = 0; temp; hpwidth++)
|
||||
temp /= 10;
|
||||
}
|
||||
|
||||
/*
|
||||
* Save current status
|
||||
*/
|
||||
s_lvl = level;
|
||||
s_pur = purse;
|
||||
s_hp = pstats.s_hpt;
|
||||
s_str = pstats.s_str;
|
||||
s_exp = pstats.s_exp;
|
||||
s_hungry = hungry_state;
|
||||
|
||||
if (stat_msg)
|
||||
{
|
||||
move(0, 0);
|
||||
msg(rs,"Level: %d Gold: %-5d Hp: %*d(%*d) Str: %2d(%d) Arm: %-2d Exp: %d/%ld %s",
|
||||
level, purse, hpwidth, pstats.s_hpt, hpwidth, max_hp, pstats.s_str,
|
||||
max_stats.s_str, 10 - s_arm, pstats.s_lvl, pstats.s_exp,
|
||||
state_name[hungry_state]);
|
||||
}
|
||||
else
|
||||
{
|
||||
move(STATLINE, 0);
|
||||
|
||||
printw("Level: %d Gold: %-5d Hp: %*d(%*d) Str: %2d(%d) Arm: %-2d Exp: %d/%d %s",
|
||||
level, purse, hpwidth, pstats.s_hpt, hpwidth, max_hp, pstats.s_str,
|
||||
max_stats.s_str, 10 - s_arm, pstats.s_lvl, pstats.s_exp,
|
||||
state_name[hungry_state]);
|
||||
}
|
||||
|
||||
clrtoeol();
|
||||
move(oy, ox);
|
||||
}
|
||||
|
||||
/*
|
||||
* wait_for
|
||||
* Sit around until the guy types the right key
|
||||
*/
|
||||
void
|
||||
wait_for(struct rogue_state *rs,int ch)
|
||||
{
|
||||
register char c;
|
||||
|
||||
if (ch == '\n')
|
||||
while ((c = readchar(rs)) != '\n' && c != '\r')
|
||||
{
|
||||
if ( rs->replaydone != 0 )
|
||||
return;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
while (readchar(rs) != ch)
|
||||
{
|
||||
if ( rs->replaydone != 0 )
|
||||
return;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* show_win:
|
||||
* Function used to display a window and wait before returning
|
||||
*/
|
||||
void
|
||||
show_win(struct rogue_state *rs,char *message)
|
||||
{
|
||||
WINDOW *win;
|
||||
|
||||
win = hw;
|
||||
wmove(win, 0, 0);
|
||||
waddstr(win, message);
|
||||
touchwin(win);
|
||||
wmove(win, hero.y, hero.x);
|
||||
wrefresh(win);
|
||||
wait_for(rs,' ');
|
||||
clearok(curscr, TRUE);
|
||||
touchwin(stdscr);
|
||||
}
|
||||
@@ -1,182 +0,0 @@
|
||||
// Copyright (c) 2016-2023 The Hush developers
|
||||
// Distributed under the GPLv3 software license, see the accompanying
|
||||
// file COPYING or https://www.gnu.org/licenses/gpl-3.0.en.html
|
||||
/*
|
||||
* Functions for dealing with linked lists of goodies
|
||||
*
|
||||
* @(#)list.c 4.12 (Berkeley) 02/05/99
|
||||
*
|
||||
* Rogue: Exploring the Dungeons of Doom
|
||||
* Copyright (C) 1980-1983, 1985, 1999 Michael Toy, Ken Arnold and Glenn Wichman
|
||||
* All rights reserved.
|
||||
*
|
||||
* See the file LICENSE.TXT for full copyright and licensing information.
|
||||
*/
|
||||
|
||||
//#include <stdlib.h>
|
||||
//#include <curses.h>
|
||||
//#include <memory.h>
|
||||
#include "rogue.h"
|
||||
|
||||
#ifdef MASTER
|
||||
int total = 0; /* total dynamic memory bytes */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* discard:
|
||||
* Free up an item
|
||||
*/
|
||||
|
||||
//#define ENABLE_DEBUG
|
||||
#define MAX_DEBUGPTRS 100000
|
||||
|
||||
int32_t itemcounter;
|
||||
THING *thingptrs[MAX_DEBUGPTRS];
|
||||
int32_t numptrs;
|
||||
|
||||
int32_t thing_find(THING *item)
|
||||
{
|
||||
#ifdef ENABLE_DEBUG
|
||||
int32_t i;
|
||||
for (i=0; i<numptrs; i++)
|
||||
if ( item == thingptrs[i] )
|
||||
return(i);
|
||||
return(-1);
|
||||
#else
|
||||
return(0);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
discard(THING *item)
|
||||
{
|
||||
#ifdef MASTER
|
||||
total--;
|
||||
#endif
|
||||
#ifdef ENABLE_DEBUG
|
||||
{
|
||||
int32_t i;
|
||||
for (i=0; i<numptrs; i++)
|
||||
if ( item == thingptrs[i] )
|
||||
{
|
||||
thingptrs[i] = thingptrs[--numptrs];
|
||||
thingptrs[numptrs] = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
THING *list = pack;
|
||||
for (; list != NULL; list = next(list))
|
||||
{
|
||||
if ( list == item )
|
||||
{
|
||||
fprintf(stderr,"pack item discarded? (%s)\n",inv_name(list,FALSE));
|
||||
sleep(3);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
itemcounter--;
|
||||
free((char *) item);
|
||||
}
|
||||
|
||||
void garbage_collect()
|
||||
{
|
||||
return;
|
||||
int32_t i;
|
||||
fprintf(stderr,"numptrs.%d free them\n",numptrs);
|
||||
for (i=0; i<numptrs; i++)
|
||||
{
|
||||
//fprintf(stderr,"%p _t_type.%d otype.%d (%c)\n",thingptrs[i],thingptrs[i]->_t._t_type,thingptrs[i]->o_type,thingptrs[i]->o_type);
|
||||
free(thingptrs[i]);
|
||||
}
|
||||
memset(thingptrs,0,sizeof(thingptrs));
|
||||
numptrs = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* detach:
|
||||
* takes an item out of whatever linked list it might be in
|
||||
*/
|
||||
|
||||
void
|
||||
_detach(THING **list, THING *item)
|
||||
{
|
||||
if (*list == item)
|
||||
*list = next(item);
|
||||
if (prev(item) != NULL)
|
||||
item->l_prev->l_next = next(item);
|
||||
if (next(item) != NULL)
|
||||
item->l_next->l_prev = prev(item);
|
||||
item->l_next = NULL;
|
||||
item->l_prev = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* _attach:
|
||||
* add an item to the head of a list
|
||||
*/
|
||||
|
||||
void
|
||||
_attach(THING **list, THING *item)
|
||||
{
|
||||
if (*list != NULL)
|
||||
{
|
||||
item->l_next = *list;
|
||||
(*list)->l_prev = item;
|
||||
item->l_prev = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
item->l_next = NULL;
|
||||
item->l_prev = NULL;
|
||||
}
|
||||
*list = item;
|
||||
}
|
||||
|
||||
/*
|
||||
* _free_list:
|
||||
* Throw the whole blamed thing away
|
||||
*/
|
||||
|
||||
void
|
||||
_free_list(THING **ptr)
|
||||
{
|
||||
THING *item;
|
||||
while (*ptr != NULL)
|
||||
{
|
||||
item = *ptr;
|
||||
*ptr = next(item);
|
||||
discard(item);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* new_item
|
||||
* Get a new item with a specified size
|
||||
*/
|
||||
|
||||
THING *
|
||||
new_item(void)
|
||||
{
|
||||
THING *item;
|
||||
|
||||
#ifdef MASTER
|
||||
if ((item = (THING *)calloc(1, sizeof *item)) == NULL)
|
||||
msg(rs,"ran out of memory after %d items", total);
|
||||
else
|
||||
total++;
|
||||
#else
|
||||
item = (THING *)calloc(1, sizeof *item);
|
||||
#endif
|
||||
#ifdef ENABLE_DEBUG
|
||||
if ( numptrs < MAX_DEBUGPTRS )
|
||||
{
|
||||
thingptrs[numptrs++] = item;
|
||||
if ( (++itemcounter % 100) == 0 )
|
||||
fprintf(stderr,"itemcounter.%d\n",itemcounter);
|
||||
}
|
||||
#endif
|
||||
item->l_next = NULL;
|
||||
item->l_prev = NULL;
|
||||
return item;
|
||||
}
|
||||
@@ -1,462 +0,0 @@
|
||||
// Copyright (c) 2016-2023 The Hush developers
|
||||
// Distributed under the GPLv3 software license, see the accompanying
|
||||
// file COPYING or https://www.gnu.org/licenses/gpl-3.0.en.html
|
||||
/*
|
||||
* Various installation dependent routines
|
||||
*
|
||||
* @(#)mach_dep.c 4.37 (Berkeley) 05/23/83
|
||||
*
|
||||
* Rogue: Exploring the Dungeons of Doom
|
||||
* Copyright (C) 1980-1983, 1985, 1999 Michael Toy, Ken Arnold and Glenn Wichman
|
||||
* All rights reserved.
|
||||
*
|
||||
* See the file LICENSE.TXT for full copyright and licensing information.
|
||||
*/
|
||||
|
||||
/*
|
||||
* The various tuneable defines are:
|
||||
*
|
||||
* SCOREFILE Where/if the score file should live.
|
||||
* ALLSCORES Score file is top ten scores, not top ten
|
||||
* players. This is only useful when only a few
|
||||
* people will be playing; otherwise the score file
|
||||
* gets hogged by just a few people.
|
||||
* NUMSCORES Number of scores in the score file (default 10).
|
||||
* NUMNAME String version of NUMSCORES (first character
|
||||
* should be capitalized) (default "Ten").
|
||||
* MAXLOAD What (if any) the maximum load average should be
|
||||
* when people are playing. Since it is divided
|
||||
* by 10, to specify a load limit of 4.0, MAXLOAD
|
||||
* should be "40". If defined, then
|
||||
* LOADAV Should it use it's own routine to get
|
||||
* the load average?
|
||||
* NAMELIST If so, where does the system namelist
|
||||
* hide?
|
||||
* MAXUSERS What (if any) the maximum user count should be
|
||||
* when people are playing. If defined, then
|
||||
* UCOUNT Should it use it's own routine to count
|
||||
* users?
|
||||
* UTMP If so, where does the user list hide?
|
||||
* CHECKTIME How often/if it should check during the game
|
||||
* for high load average.
|
||||
*/
|
||||
|
||||
#include <signal.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <time.h>
|
||||
//#include <curses.h>
|
||||
#include "rogue.h"
|
||||
#include "extern.h"
|
||||
|
||||
#define NOOP(x) (x += 0)
|
||||
|
||||
# ifndef NUMSCORES
|
||||
# define NUMSCORES 10
|
||||
# define NUMNAME "Ten"
|
||||
# endif
|
||||
|
||||
unsigned int numscores = NUMSCORES;
|
||||
char *Numname = NUMNAME;
|
||||
|
||||
# ifdef ALLSCORES
|
||||
bool allscore = TRUE;
|
||||
# else /* ALLSCORES */
|
||||
bool allscore = FALSE;
|
||||
# endif /* ALLSCORES */
|
||||
|
||||
#ifdef CHECKTIME
|
||||
static int num_checks; /* times we've gone over in checkout() */
|
||||
#endif /* CHECKTIME */
|
||||
|
||||
/*
|
||||
* init_check:
|
||||
* Check out too see if it is proper to play the game now
|
||||
*/
|
||||
|
||||
void
|
||||
init_check()
|
||||
{
|
||||
#if defined(MAXLOAD) || defined(MAXUSERS)
|
||||
if (too_much())
|
||||
{
|
||||
printf("Sorry, %s, but the system is too loaded now.\n", whoami);
|
||||
printf("Try again later. Meanwhile, why not enjoy a%s %s?\n",
|
||||
vowelstr(fruit), fruit);
|
||||
if (author())
|
||||
printf("However, since you're a good guy, it's up to you\n");
|
||||
else
|
||||
exit(1);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* open_score:
|
||||
* Open up the score file for future use
|
||||
*/
|
||||
|
||||
void
|
||||
open_score()
|
||||
{
|
||||
#ifdef SCOREFILE
|
||||
char *scorefile = SCOREFILE;
|
||||
/*
|
||||
* We drop setgid privileges after opening the score file, so subsequent
|
||||
* open()'s will fail. Just reuse the earlier filehandle.
|
||||
*/
|
||||
|
||||
if (scoreboard != NULL) {
|
||||
rewind(scoreboard);
|
||||
return;
|
||||
}
|
||||
|
||||
scoreboard = fopen(scorefile, "r+");
|
||||
|
||||
if ((scoreboard == NULL) && (errno == ENOENT))
|
||||
{
|
||||
scoreboard = fopen(scorefile, "w+");
|
||||
md_chmod(scorefile,0664);
|
||||
}
|
||||
|
||||
if (scoreboard == NULL) {
|
||||
fprintf(stderr, "Could not open %s for writing: %s\n", scorefile, strerror(errno));
|
||||
fflush(stderr);
|
||||
}
|
||||
#else
|
||||
scoreboard = NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* setup:
|
||||
* Get starting setup for all games
|
||||
*/
|
||||
|
||||
void
|
||||
setup()
|
||||
{
|
||||
#ifdef CHECKTIME
|
||||
int checkout();
|
||||
#endif
|
||||
|
||||
#ifdef DUMP
|
||||
md_onsignal_autosave();
|
||||
#else
|
||||
md_onsignal_default();
|
||||
#endif
|
||||
|
||||
#ifdef CHECKTIME
|
||||
md_start_checkout_timer(CHECKTIME*60);
|
||||
num_checks = 0;
|
||||
#endif
|
||||
|
||||
raw(); /* Raw mode */
|
||||
noecho(); /* Echo off */
|
||||
keypad(stdscr,1);
|
||||
getltchars(); /* get the local tty chars */
|
||||
}
|
||||
|
||||
/*
|
||||
* getltchars:
|
||||
* Get the local tty chars for later use
|
||||
*/
|
||||
|
||||
void
|
||||
getltchars()
|
||||
{
|
||||
got_ltc = TRUE;
|
||||
orig_dsusp = md_dsuspchar();
|
||||
md_setdsuspchar( md_suspchar() );
|
||||
}
|
||||
|
||||
/*
|
||||
* resetltchars:
|
||||
* Reset the local tty chars to original values.
|
||||
*/
|
||||
void
|
||||
resetltchars(void)
|
||||
{
|
||||
if (got_ltc) {
|
||||
md_setdsuspchar(orig_dsusp);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* playltchars:
|
||||
* Set local tty chars to the values we use when playing.
|
||||
*/
|
||||
void
|
||||
playltchars(void)
|
||||
{
|
||||
if (got_ltc) {
|
||||
md_setdsuspchar( md_suspchar() );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* start_score:
|
||||
* Start the scoring sequence
|
||||
*/
|
||||
|
||||
void
|
||||
start_score()
|
||||
{
|
||||
#ifdef CHECKTIME
|
||||
md_stop_checkout_timer();
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* is_symlink:
|
||||
* See if the file has a symbolic link
|
||||
*/
|
||||
bool
|
||||
is_symlink(char *sp)
|
||||
{
|
||||
#ifdef S_IFLNK
|
||||
struct stat sbuf2;
|
||||
|
||||
if (lstat(sp, &sbuf2) < 0)
|
||||
return FALSE;
|
||||
else
|
||||
return ((sbuf2.st_mode & S_IFMT) != S_IFREG);
|
||||
#else
|
||||
NOOP(sp);
|
||||
return FALSE;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(MAXLOAD) || defined(MAXUSERS)
|
||||
/*
|
||||
* too_much:
|
||||
* See if the system is being used too much for this game
|
||||
*/
|
||||
bool
|
||||
too_much()
|
||||
{
|
||||
#ifdef MAXLOAD
|
||||
double avec[3];
|
||||
#else
|
||||
int cnt;
|
||||
#endif
|
||||
|
||||
#ifdef MAXLOAD
|
||||
md_loadav(avec);
|
||||
if (avec[1] > (MAXLOAD / 10.0))
|
||||
return TRUE;
|
||||
#endif
|
||||
#ifdef MAXUSERS
|
||||
if (ucount() > MAXUSERS)
|
||||
return TRUE;
|
||||
#endif
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* author:
|
||||
* See if a user is an author of the program
|
||||
*/
|
||||
bool
|
||||
author()
|
||||
{
|
||||
#ifdef MASTER
|
||||
if (wizard)
|
||||
return TRUE;
|
||||
#endif
|
||||
switch (md_getuid())
|
||||
{
|
||||
case -1:
|
||||
return TRUE;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CHECKTIME
|
||||
/*
|
||||
* checkout:
|
||||
* Check each CHECKTIME seconds to see if the load is too high
|
||||
*/
|
||||
|
||||
checkout(struct rogue_state *rs,int sig)
|
||||
{
|
||||
static char *msgs[] = {
|
||||
"The load is too high to be playing. Please leave in %0.1f minutes",
|
||||
"Please save your game. You have %0.1f minutes",
|
||||
"Last warning. You have %0.1f minutes to leave",
|
||||
};
|
||||
int checktime;
|
||||
|
||||
if (too_much())
|
||||
{
|
||||
if (author())
|
||||
{
|
||||
num_checks = 1;
|
||||
chmsg(rs,"The load is rather high, O exaulted one");
|
||||
}
|
||||
else if (num_checks++ == 3)
|
||||
fatal("Sorry. You took too long. You are dead\n");
|
||||
checktime = (CHECKTIME * 60) / num_checks;
|
||||
chmsg(rs,msgs[num_checks - 1], ((double) checktime / 60.0));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (num_checks)
|
||||
{
|
||||
num_checks = 0;
|
||||
chmsg(rs,"The load has dropped back down. You have a reprieve");
|
||||
}
|
||||
checktime = (CHECKTIME * 60);
|
||||
}
|
||||
|
||||
md_start_checkout_timer(checktime);
|
||||
}
|
||||
|
||||
/*
|
||||
* chmsg:
|
||||
* checkout()'s version of msg. If we are in the middle of a
|
||||
* shell, do a printf instead of a msg to a the refresh.
|
||||
*/
|
||||
/* VARARGS1 */
|
||||
|
||||
chmsg(struct rogue_state *rs,char *fmt, int arg)
|
||||
{
|
||||
if (!in_shell)
|
||||
msg(rs,fmt, arg);
|
||||
else
|
||||
{
|
||||
printf(fmt, arg);
|
||||
putchar('\n');
|
||||
fflush(stdout);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef UCOUNT
|
||||
/*
|
||||
* ucount:
|
||||
* count number of users on the system
|
||||
*/
|
||||
#include <utmp.h>
|
||||
|
||||
struct utmp buf;
|
||||
|
||||
int
|
||||
ucount()
|
||||
{
|
||||
struct utmp *up;
|
||||
FILE *utmp;
|
||||
int count;
|
||||
|
||||
if ((utmp = fopen(UTMP, "r")) == NULL)
|
||||
return 0;
|
||||
|
||||
up = &buf;
|
||||
count = 0;
|
||||
|
||||
while (fread(up, 1, sizeof (*up), utmp) > 0)
|
||||
if (buf.ut_name[0] != '\0')
|
||||
count++;
|
||||
fclose(utmp);
|
||||
return count;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* lock_sc:
|
||||
* lock the score file. If it takes too long, ask the user if
|
||||
* they care to wait. Return TRUE if the lock is successful.
|
||||
*/
|
||||
static FILE *lfd = NULL;
|
||||
bool
|
||||
lock_sc()
|
||||
{
|
||||
#if defined(SCOREFILE) && defined(LOCKFILE)
|
||||
int cnt;
|
||||
static struct stat sbuf;
|
||||
char *lockfile = LOCKFILE;
|
||||
|
||||
over:
|
||||
if ((lfd=fopen(lockfile, "w+")) != NULL)
|
||||
return TRUE;
|
||||
for (cnt = 0; cnt < 5; cnt++)
|
||||
{
|
||||
md_sleep(1);
|
||||
if ((lfd=fopen(lockfile, "w+")) != NULL)
|
||||
return TRUE;
|
||||
}
|
||||
if (stat(lockfile, &sbuf) < 0)
|
||||
{
|
||||
lfd=fopen(lockfile, "w+");
|
||||
return TRUE;
|
||||
}
|
||||
if (time(NULL) - sbuf.st_mtime > 10)
|
||||
{
|
||||
if (md_unlink(lockfile) < 0)
|
||||
return FALSE;
|
||||
goto over;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("The score file is very busy. Do you want to wait longer\n");
|
||||
printf("for it to become free so your score can get posted?\n");
|
||||
printf("If so, type \"y\"\n");
|
||||
if (fgets(prbuf, MAXSTR, stdin) != 0 )
|
||||
;
|
||||
if (prbuf[0] == 'y')
|
||||
for (;;)
|
||||
{
|
||||
if ((lfd=fopen(lockfile, "w+")) != 0)
|
||||
return TRUE;
|
||||
if (stat(lockfile, &sbuf) < 0)
|
||||
{
|
||||
lfd=fopen(lockfile, "w+");
|
||||
return TRUE;
|
||||
}
|
||||
if (time(NULL) - sbuf.st_mtime > 10)
|
||||
{
|
||||
if (md_unlink(lockfile) < 0)
|
||||
return FALSE;
|
||||
}
|
||||
md_sleep(1);
|
||||
}
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
#else
|
||||
return TRUE;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* unlock_sc:
|
||||
* Unlock the score file
|
||||
*/
|
||||
|
||||
void
|
||||
unlock_sc()
|
||||
{
|
||||
#if defined(SCOREFILE) && defined(LOCKFILE)
|
||||
if (lfd != NULL)
|
||||
fclose(lfd);
|
||||
lfd = NULL;
|
||||
md_unlink(LOCKFILE);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* flush_type:
|
||||
* Flush typeahead for traps, etc.
|
||||
*/
|
||||
|
||||
void
|
||||
flush_type()
|
||||
{
|
||||
flushinp();
|
||||
}
|
||||
1000
src/cc/rogue/main.c
1000
src/cc/rogue/main.c
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,620 +0,0 @@
|
||||
// Copyright (c) 2016-2023 The Hush developers
|
||||
// Distributed under the GPLv3 software license, see the accompanying
|
||||
// file COPYING or https://www.gnu.org/licenses/gpl-3.0.en.html
|
||||
/*
|
||||
* All sorts of miscellaneous routines
|
||||
*
|
||||
* @(#)misc.c 4.66 (Berkeley) 08/06/83
|
||||
*
|
||||
* Rogue: Exploring the Dungeons of Doom
|
||||
* Copyright (C) 1980-1983, 1985, 1999 Michael Toy, Ken Arnold and Glenn Wichman
|
||||
* All rights reserved.
|
||||
*
|
||||
* See the file LICENSE.TXT for full copyright and licensing information.
|
||||
*/
|
||||
|
||||
//#include <stdlib.h>
|
||||
//#include <curses.h>
|
||||
//#include <string.h>
|
||||
//#include <ctype.h>
|
||||
#include "rogue.h"
|
||||
|
||||
/*
|
||||
* look:
|
||||
* A quick glance all around the player
|
||||
*/
|
||||
#undef DEBUG
|
||||
|
||||
|
||||
void
|
||||
look(struct rogue_state *rs,bool wakeup)
|
||||
{
|
||||
int x, y;
|
||||
int ch;
|
||||
THING *tp;
|
||||
PLACE *pp;
|
||||
struct room *rp;
|
||||
int ey, ex;
|
||||
int passcount;
|
||||
char pfl, *fp, pch;
|
||||
int sy, sx, sumhero = 0, diffhero = 0;
|
||||
# ifdef DEBUG
|
||||
static bool done = FALSE;
|
||||
|
||||
if (done)
|
||||
return;
|
||||
done = TRUE;
|
||||
# endif /* DEBUG */
|
||||
passcount = 0;
|
||||
rp = proom;
|
||||
if (!ce(oldpos, hero))
|
||||
{
|
||||
erase_lamp(&oldpos, oldrp);
|
||||
oldpos = hero;
|
||||
oldrp = rp;
|
||||
}
|
||||
ey = hero.y + 1;
|
||||
ex = hero.x + 1;
|
||||
sx = hero.x - 1;
|
||||
sy = hero.y - 1;
|
||||
if (door_stop && !firstmove && running)
|
||||
{
|
||||
sumhero = hero.y + hero.x;
|
||||
diffhero = hero.y - hero.x;
|
||||
}
|
||||
pp = INDEX(hero.y, hero.x);
|
||||
pch = pp->p_ch;
|
||||
pfl = pp->p_flags;
|
||||
|
||||
for (y = sy; y <= ey; y++)
|
||||
if (y > 0 && y < NUMLINES - 1) for (x = sx; x <= ex; x++)
|
||||
{
|
||||
if (x < 0 || x >= NUMCOLS)
|
||||
continue;
|
||||
if (!on(player, ISBLIND))
|
||||
{
|
||||
if (y == hero.y && x == hero.x)
|
||||
continue;
|
||||
}
|
||||
|
||||
pp = INDEX(y, x);
|
||||
ch = pp->p_ch;
|
||||
if (ch == ' ') /* nothing need be done with a ' ' */
|
||||
continue;
|
||||
fp = &pp->p_flags;
|
||||
if (pch != DOOR && ch != DOOR)
|
||||
if ((pfl & F_PASS) != (*fp & F_PASS))
|
||||
continue;
|
||||
if (((*fp & F_PASS) || ch == DOOR) &&
|
||||
((pfl & F_PASS) || pch == DOOR))
|
||||
{
|
||||
if (hero.x != x && hero.y != y &&
|
||||
!step_ok(chat(y, hero.x)) && !step_ok(chat(hero.y, x)))
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((tp = pp->p_monst) == NULL)
|
||||
ch = trip_ch(y, x, ch);
|
||||
else
|
||||
if (on(player, SEEMONST) && on(*tp, ISINVIS))
|
||||
{
|
||||
if (door_stop && !firstmove)
|
||||
running = FALSE;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (wakeup)
|
||||
wake_monster(rs,y, x);
|
||||
if (see_monst(tp))
|
||||
{
|
||||
if (on(player, ISHALU))
|
||||
ch = rnd(26) + 'A';
|
||||
else
|
||||
ch = tp->t_disguise;
|
||||
}
|
||||
}
|
||||
if (on(player, ISBLIND) && (y != hero.y || x != hero.x))
|
||||
continue;
|
||||
|
||||
move(y, x);
|
||||
|
||||
if ((proom->r_flags & ISDARK) && !see_floor && ch == FLOOR)
|
||||
ch = ' ';
|
||||
|
||||
if (tp != NULL || ch != CCHAR( inch() ))
|
||||
addch(ch);
|
||||
|
||||
if (door_stop && !firstmove && running)
|
||||
{
|
||||
switch (runch)
|
||||
{
|
||||
case 'h':
|
||||
if (x == ex)
|
||||
continue;
|
||||
when 'j':
|
||||
if (y == sy)
|
||||
continue;
|
||||
when 'k':
|
||||
if (y == ey)
|
||||
continue;
|
||||
when 'l':
|
||||
if (x == sx)
|
||||
continue;
|
||||
when 'y':
|
||||
if ((y + x) - sumhero >= 1)
|
||||
continue;
|
||||
when 'u':
|
||||
if ((y - x) - diffhero >= 1)
|
||||
continue;
|
||||
when 'n':
|
||||
if ((y + x) - sumhero <= -1)
|
||||
continue;
|
||||
when 'b':
|
||||
if ((y - x) - diffhero <= -1)
|
||||
continue;
|
||||
}
|
||||
switch (ch)
|
||||
{
|
||||
case DOOR:
|
||||
if (x == hero.x || y == hero.y)
|
||||
running = FALSE;
|
||||
break;
|
||||
case PASSAGE:
|
||||
if (x == hero.x || y == hero.y)
|
||||
passcount++;
|
||||
break;
|
||||
case FLOOR:
|
||||
case '|':
|
||||
case '-':
|
||||
case ' ':
|
||||
break;
|
||||
default:
|
||||
running = FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (door_stop && !firstmove && passcount > 1)
|
||||
running = FALSE;
|
||||
if (!running || !jump)
|
||||
mvaddch(hero.y, hero.x, PLAYER);
|
||||
# ifdef DEBUG
|
||||
done = FALSE;
|
||||
# endif /* DEBUG */
|
||||
}
|
||||
|
||||
/*
|
||||
* trip_ch:
|
||||
* Return the character appropriate for this space, taking into
|
||||
* account whether or not the player is tripping.
|
||||
*/
|
||||
int
|
||||
trip_ch(int y, int x, int ch)
|
||||
{
|
||||
if (on(player, ISHALU) && after)
|
||||
switch (ch)
|
||||
{
|
||||
case FLOOR:
|
||||
case ' ':
|
||||
case PASSAGE:
|
||||
case '-':
|
||||
case '|':
|
||||
case DOOR:
|
||||
case TRAP:
|
||||
break;
|
||||
default:
|
||||
if (y != stairs.y || x != stairs.x || !seenstairs)
|
||||
ch = rnd_thing();
|
||||
break;
|
||||
}
|
||||
return ch;
|
||||
}
|
||||
|
||||
/*
|
||||
* erase_lamp:
|
||||
* Erase the area shown by a lamp in a dark room.
|
||||
*/
|
||||
|
||||
void
|
||||
erase_lamp(coord *pos, struct room *rp)
|
||||
{
|
||||
int y, x, ey, sy, ex;
|
||||
|
||||
if (!(see_floor && (rp->r_flags & (ISGONE|ISDARK)) == ISDARK
|
||||
&& !on(player,ISBLIND)))
|
||||
return;
|
||||
|
||||
ey = pos->y + 1;
|
||||
ex = pos->x + 1;
|
||||
sy = pos->y - 1;
|
||||
for (x = pos->x - 1; x <= ex; x++)
|
||||
for (y = sy; y <= ey; y++)
|
||||
{
|
||||
if (y == hero.y && x == hero.x)
|
||||
continue;
|
||||
move(y, x);
|
||||
if (inch() == FLOOR)
|
||||
addch(' ');
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* show_floor:
|
||||
* Should we show the floor in her room at this time?
|
||||
*/
|
||||
bool
|
||||
show_floor()
|
||||
{
|
||||
if ((proom->r_flags & (ISGONE|ISDARK)) == ISDARK && !on(player, ISBLIND))
|
||||
return see_floor;
|
||||
else
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* find_obj:
|
||||
* Find the unclaimed object at y, x
|
||||
*/
|
||||
THING *
|
||||
find_obj(struct rogue_state *rs,int y, int x)
|
||||
{
|
||||
THING *obj;
|
||||
|
||||
for (obj = lvl_obj; obj != NULL; obj = next(obj))
|
||||
{
|
||||
if (obj->o_pos.y == y && obj->o_pos.x == x)
|
||||
return obj;
|
||||
}
|
||||
#ifdef MASTER
|
||||
sprintf(prbuf, "Non-object %d,%d", y, x);
|
||||
msg(rs,prbuf);
|
||||
return NULL;
|
||||
#else
|
||||
/* NOTREACHED */
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* eat:
|
||||
* She wants to eat something, so let her try
|
||||
*/
|
||||
|
||||
void
|
||||
eat(struct rogue_state *rs)
|
||||
{
|
||||
THING *obj;
|
||||
|
||||
if ((obj = get_item(rs,"eat", FOOD)) == NULL)
|
||||
return;
|
||||
if (obj->o_type != FOOD)
|
||||
{
|
||||
if (!terse)
|
||||
msg(rs,"ugh, you would get ill if you ate that");
|
||||
else
|
||||
msg(rs,"that's Inedible!");
|
||||
return;
|
||||
}
|
||||
if (food_left < 0)
|
||||
food_left = 0;
|
||||
if ((food_left += HUNGERTIME - 200 + rnd(400)) > STOMACHSIZE)
|
||||
food_left = STOMACHSIZE;
|
||||
hungry_state = 0;
|
||||
if (obj == cur_weapon)
|
||||
cur_weapon = NULL;
|
||||
if (obj->o_which == 1)
|
||||
msg(rs,"my, that was a yummy %s", fruit);
|
||||
else
|
||||
if (rnd(100) > 70)
|
||||
{
|
||||
pstats.s_exp++;
|
||||
msg(rs,"%s, this food tastes awful", choose_str("bummer", "yuk"));
|
||||
check_level(rs);
|
||||
}
|
||||
else
|
||||
msg(rs,"%s, that tasted good", choose_str("oh, wow", "yum"));
|
||||
leave_pack(rs,obj, FALSE, FALSE);
|
||||
}
|
||||
|
||||
/*
|
||||
* check_level:
|
||||
* Check to see if the guy has gone up a level.
|
||||
*/
|
||||
|
||||
void
|
||||
check_level(struct rogue_state *rs)
|
||||
{
|
||||
int i, add, olevel;
|
||||
|
||||
for (i = 0; e_levels[i] != 0; i++)
|
||||
if (e_levels[i] > pstats.s_exp)
|
||||
break;
|
||||
i++;
|
||||
olevel = pstats.s_lvl;
|
||||
pstats.s_lvl = i;
|
||||
if (i > olevel)
|
||||
{
|
||||
add = roll(i - olevel, 10);
|
||||
max_hp += add;
|
||||
pstats.s_hpt += add;
|
||||
msg(rs,"welcome to level %d", i);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* chg_str:
|
||||
* used to modify the playes strength. It keeps track of the
|
||||
* highest it has been, just in case
|
||||
*/
|
||||
|
||||
void
|
||||
chg_str(int amt)
|
||||
{
|
||||
//auto jl777: strange compiler error
|
||||
uint32_t comp;
|
||||
|
||||
if (amt == 0)
|
||||
return;
|
||||
//add_str(&pstats.s_str, amt);
|
||||
pstats.s_str += amt;
|
||||
if ( pstats.s_str < 3 )
|
||||
pstats.s_str = 3;
|
||||
else if ( pstats.s_str > 31 )
|
||||
pstats.s_str = 31;
|
||||
comp = pstats.s_str;
|
||||
if (ISRING(LEFT, R_ADDSTR))
|
||||
{
|
||||
// add_str(&comp, -cur_ring[LEFT]->o_arm);
|
||||
comp += -cur_ring[LEFT]->o_arm;
|
||||
if ( comp < 3 )
|
||||
comp = 3;
|
||||
else if ( comp > 31 )
|
||||
comp = 31;
|
||||
}
|
||||
if (ISRING(RIGHT, R_ADDSTR))
|
||||
{
|
||||
//add_str(&comp, -cur_ring[RIGHT]->o_arm);
|
||||
comp += -cur_ring[RIGHT]->o_arm;
|
||||
if ( comp < 3 )
|
||||
comp = 3;
|
||||
else if ( comp > 31 )
|
||||
comp = 31;
|
||||
}
|
||||
if ( comp > max_stats.s_str )
|
||||
max_stats.s_str = comp;
|
||||
}
|
||||
|
||||
/*
|
||||
* add_str:
|
||||
* Perform the actual add, checking upper and lower bound limits
|
||||
*/
|
||||
void
|
||||
add_str(str_t *sp, int amt)
|
||||
{
|
||||
if ((*sp += amt) < 3)
|
||||
*sp = 3;
|
||||
else if (*sp > 31)
|
||||
*sp = 31;
|
||||
}
|
||||
|
||||
/*
|
||||
* add_haste:
|
||||
* Add a haste to the player
|
||||
*/
|
||||
bool
|
||||
add_haste(struct rogue_state *rs,bool potion)
|
||||
{
|
||||
if (on(player, ISHASTE))
|
||||
{
|
||||
no_command += rnd(8);
|
||||
player.t_flags &= ~(ISRUN|ISHASTE);
|
||||
extinguish(nohaste);
|
||||
msg(rs,"you faint from exhaustion");
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
player.t_flags |= ISHASTE;
|
||||
if (potion)
|
||||
fuse(nohaste, 0, rnd(4)+4, AFTER);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* aggravate:
|
||||
* Aggravate all the monsters on this level
|
||||
*/
|
||||
|
||||
void
|
||||
aggravate(struct rogue_state *rs)
|
||||
{
|
||||
THING *mp;
|
||||
|
||||
for (mp = mlist; mp != NULL; mp = next(mp))
|
||||
runto(rs,&mp->t_pos);
|
||||
}
|
||||
|
||||
/*
|
||||
* vowelstr:
|
||||
* For printfs: if string starts with a vowel, return "n" for an
|
||||
* "an".
|
||||
*/
|
||||
char *
|
||||
vowelstr(char *str)
|
||||
{
|
||||
switch (*str)
|
||||
{
|
||||
case 'a': case 'A':
|
||||
case 'e': case 'E':
|
||||
case 'i': case 'I':
|
||||
case 'o': case 'O':
|
||||
case 'u': case 'U':
|
||||
return "n";
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* is_current:
|
||||
* See if the object is one of the currently used items
|
||||
*/
|
||||
bool
|
||||
is_current(struct rogue_state *rs,THING *obj)
|
||||
{
|
||||
if (obj == NULL)
|
||||
return FALSE;
|
||||
if (obj == cur_armor || obj == cur_weapon || obj == cur_ring[LEFT]
|
||||
|| obj == cur_ring[RIGHT])
|
||||
{
|
||||
if (!terse)
|
||||
addmsg(rs,"That's already ");
|
||||
msg(rs,"in use");
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* get_dir:
|
||||
* Set up the direction co_ordinate for use in varios "prefix"
|
||||
* commands
|
||||
*/
|
||||
bool
|
||||
get_dir(struct rogue_state *rs)
|
||||
{
|
||||
char *prompt;
|
||||
bool gotit;
|
||||
static coord last_delt= {0,0};
|
||||
|
||||
if (again && last_dir != '\0')
|
||||
{
|
||||
delta.y = last_delt.y;
|
||||
delta.x = last_delt.x;
|
||||
dir_ch = last_dir;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!terse)
|
||||
msg(rs,prompt = "which direction? ");
|
||||
else
|
||||
prompt = "direction: ";
|
||||
do
|
||||
{
|
||||
gotit = TRUE;
|
||||
switch (dir_ch = readchar(rs))
|
||||
{
|
||||
case 'h': case'H': delta.y = 0; delta.x = -1;
|
||||
when 'j': case'J': delta.y = 1; delta.x = 0;
|
||||
when 'k': case'K': delta.y = -1; delta.x = 0;
|
||||
when 'l': case'L': delta.y = 0; delta.x = 1;
|
||||
when 'y': case'Y': delta.y = -1; delta.x = -1;
|
||||
when 'u': case'U': delta.y = -1; delta.x = 1;
|
||||
when 'b': case'B': delta.y = 1; delta.x = -1;
|
||||
when 'n': case'N': delta.y = 1; delta.x = 1;
|
||||
when ESCAPE: last_dir = '\0'; reset_last(); return FALSE;
|
||||
otherwise:
|
||||
mpos = 0;
|
||||
msg(rs,prompt);
|
||||
gotit = FALSE;
|
||||
}
|
||||
} until (gotit);
|
||||
if (isupper(dir_ch))
|
||||
dir_ch = (char) tolower(dir_ch);
|
||||
last_dir = dir_ch;
|
||||
last_delt.y = delta.y;
|
||||
last_delt.x = delta.x;
|
||||
}
|
||||
if (on(player, ISHUH) && rnd(5) == 0)
|
||||
do
|
||||
{
|
||||
delta.y = rnd(3) - 1;
|
||||
delta.x = rnd(3) - 1;
|
||||
} while (delta.y == 0 && delta.x == 0);
|
||||
mpos = 0;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* sign:
|
||||
* Return the sign of the number
|
||||
*/
|
||||
int
|
||||
sign(int nm)
|
||||
{
|
||||
if (nm < 0)
|
||||
return -1;
|
||||
else
|
||||
return (nm > 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* spread:
|
||||
* Give a spread around a given number (+/- 20%)
|
||||
*/
|
||||
int
|
||||
spread(int nm)
|
||||
{
|
||||
return nm - nm / 20 + rnd(nm / 10);
|
||||
}
|
||||
|
||||
/*
|
||||
* call_it:
|
||||
* Call an object something after use.
|
||||
*/
|
||||
|
||||
void
|
||||
call_it(struct rogue_state *rs,struct obj_info *info)
|
||||
{
|
||||
if (info->oi_know)
|
||||
{
|
||||
if (info->oi_guess)
|
||||
{
|
||||
free(info->oi_guess);
|
||||
info->oi_guess = NULL;
|
||||
}
|
||||
}
|
||||
else if (!info->oi_guess)
|
||||
{
|
||||
msg(rs,terse ? (char *)"call it: " : (char *)"what do you want to call it? ");
|
||||
if (get_str(rs,prbuf, stdscr) == NORM)
|
||||
{
|
||||
if (info->oi_guess != NULL)
|
||||
free(info->oi_guess);
|
||||
info->oi_guess = (char *)malloc((unsigned int) strlen(prbuf) + 1);
|
||||
strcpy(info->oi_guess, prbuf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* rnd_thing:
|
||||
* Pick a random thing appropriate for this level
|
||||
*/
|
||||
char
|
||||
rnd_thing()
|
||||
{
|
||||
int i;
|
||||
static char thing_list[] = {
|
||||
POTION, SCROLL, RING, STICK, FOOD, WEAPON, ARMOR, STAIRS, GOLD, AMULET
|
||||
};
|
||||
|
||||
if (level >= AMULETLEVEL)
|
||||
i = rnd(sizeof thing_list / sizeof (char));
|
||||
else
|
||||
i = rnd(sizeof thing_list / sizeof (char) - 1);
|
||||
return thing_list[i];
|
||||
}
|
||||
|
||||
/*
|
||||
str str:
|
||||
* Choose the first or second string depending on whether it the
|
||||
* player is tripping
|
||||
*/
|
||||
char *
|
||||
choose_str(char *ts, char *ns)
|
||||
{
|
||||
return (on(player, ISHALU) ? ts : ns);
|
||||
}
|
||||
@@ -1,258 +0,0 @@
|
||||
// Copyright (c) 2016-2023 The Hush developers
|
||||
// Distributed under the GPLv3 software license, see the accompanying
|
||||
// file COPYING or https://www.gnu.org/licenses/gpl-3.0.en.html
|
||||
/*
|
||||
* File with various monster functions in it, none as evil as KYC
|
||||
*
|
||||
* @(#)monsters.c 4.46 (Berkeley) 02/05/99
|
||||
*
|
||||
* Rogue: Exploring the Dungeons of Doom
|
||||
* Copyright (C) 1980-1983, 1985, 1999 Michael Toy, Ken Arnold and Glenn Wichman
|
||||
* All rights reserved.
|
||||
*
|
||||
* See the file LICENSE.TXT for full copyright and licensing information.
|
||||
*/
|
||||
|
||||
//#include <curses.h>
|
||||
//#include <string.h>
|
||||
#include "rogue.h"
|
||||
//#include <ctype.h>
|
||||
|
||||
/*
|
||||
* List of monsters in rough order of vorpalness
|
||||
*/
|
||||
static char lvl_mons[] = {
|
||||
'K', 'E', 'B', 'S', 'H', 'I', 'R', 'O', 'Z', 'L', 'C', 'Q', 'A',
|
||||
'N', 'Y', 'F', 'T', 'W', 'P', 'X', 'U', 'M', 'V', 'G', 'J', 'D'
|
||||
};
|
||||
|
||||
static char wand_mons[] = {
|
||||
'K', 'E', 'B', 'S', 'H', 0, 'R', 'O', 'Z', 0, 'C', 'Q', 'A',
|
||||
0, 'Y', 0, 'T', 'W', 'P', 0, 'U', 'M', 'V', 'G', 'J', 0
|
||||
};
|
||||
|
||||
/*
|
||||
* randmonster:
|
||||
* Pick a monster to show up. The lower the level,
|
||||
* the meaner the monster.
|
||||
*/
|
||||
char
|
||||
randmonster(bool wander)
|
||||
{
|
||||
int d;
|
||||
char *mons;
|
||||
|
||||
mons = (wander ? wand_mons : lvl_mons);
|
||||
do
|
||||
{
|
||||
d = level + (rnd(10) - 6);
|
||||
if (d < 0)
|
||||
d = rnd(5);
|
||||
if (d > 25)
|
||||
d = rnd(5) + 21;
|
||||
} while (mons[d] == 0);
|
||||
return mons[d];
|
||||
}
|
||||
|
||||
/*
|
||||
* new_monster:
|
||||
* Pick a new monster and add it to the list
|
||||
*/
|
||||
|
||||
void
|
||||
new_monster(struct rogue_state *rs,THING *tp, char type, coord *cp)
|
||||
{
|
||||
struct monster *mp;
|
||||
int lev_add;
|
||||
|
||||
if ((lev_add = level - AMULETLEVEL) < 0)
|
||||
lev_add = 0;
|
||||
attach(mlist, tp);
|
||||
tp->t_type = type;
|
||||
tp->t_disguise = type;
|
||||
tp->t_pos = *cp;
|
||||
move(cp->y, cp->x);
|
||||
tp->t_oldch = CCHAR( inch() );
|
||||
tp->t_room = roomin(rs,cp);
|
||||
moat(cp->y, cp->x) = tp;
|
||||
mp = &monsters[tp->t_type-'A'];
|
||||
tp->t_stats.s_lvl = mp->m_stats.s_lvl + lev_add;
|
||||
tp->t_stats.s_maxhp = tp->t_stats.s_hpt = roll(tp->t_stats.s_lvl, 8);
|
||||
tp->t_stats.s_arm = mp->m_stats.s_arm - lev_add;
|
||||
strcpy(tp->t_stats.s_dmg,mp->m_stats.s_dmg);
|
||||
tp->t_stats.s_str = mp->m_stats.s_str;
|
||||
tp->t_stats.s_exp = mp->m_stats.s_exp + lev_add * 10 + exp_add(tp);
|
||||
tp->t_flags = mp->m_flags;
|
||||
if (level > 29)
|
||||
tp->t_flags |= ISHASTE;
|
||||
tp->t_turn = TRUE;
|
||||
tp->t_pack = NULL;
|
||||
if (ISWEARING(R_AGGR))
|
||||
runto(rs,cp);
|
||||
if (type == 'X')
|
||||
tp->t_disguise = rnd_thing();
|
||||
}
|
||||
|
||||
/*
|
||||
* expadd:
|
||||
* Experience to add for this monster's level/hit points
|
||||
*/
|
||||
int
|
||||
exp_add(THING *tp)
|
||||
{
|
||||
int mod;
|
||||
|
||||
if (tp->t_stats.s_lvl == 1)
|
||||
mod = tp->t_stats.s_maxhp / 8;
|
||||
else
|
||||
mod = tp->t_stats.s_maxhp / 6;
|
||||
if (tp->t_stats.s_lvl > 9)
|
||||
mod *= 20;
|
||||
else if (tp->t_stats.s_lvl > 6)
|
||||
mod *= 4;
|
||||
return mod;
|
||||
}
|
||||
|
||||
/*
|
||||
* wanderer:
|
||||
* Create a new wandering monster and aim it at the player
|
||||
*/
|
||||
|
||||
void
|
||||
wanderer(struct rogue_state *rs)
|
||||
{
|
||||
THING *tp;
|
||||
static coord cp;
|
||||
|
||||
tp = new_item();
|
||||
do
|
||||
{
|
||||
find_floor(rs,(struct room *) NULL, &cp, FALSE, TRUE);
|
||||
} while (roomin(rs,&cp) == proom);
|
||||
new_monster(rs,tp, randmonster(TRUE), &cp);
|
||||
if (on(player, SEEMONST))
|
||||
{
|
||||
standout();
|
||||
if (!on(player, ISHALU))
|
||||
addch(tp->t_type);
|
||||
else
|
||||
addch(rnd(26) + 'A');
|
||||
standend();
|
||||
}
|
||||
runto(rs,&tp->t_pos);
|
||||
#ifdef MASTER
|
||||
if (wizard)
|
||||
msg(rs,"started a wandering %s", monsters[tp->t_type-'A'].m_name);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* wake_monster:
|
||||
* What to do when the hero steps next to a monster
|
||||
*/
|
||||
THING *
|
||||
wake_monster(struct rogue_state *rs,int y, int x)
|
||||
{
|
||||
THING *tp;
|
||||
struct room *rp;
|
||||
char ch, *mname;
|
||||
|
||||
#ifdef MASTER
|
||||
if ((tp = moat(y, x)) == NULL)
|
||||
msg(rs,"can't find monster in wake_monster");
|
||||
#else
|
||||
tp = moat(y, x);
|
||||
if (tp == NULL)
|
||||
endwin(), abort();
|
||||
#endif
|
||||
ch = tp->t_type;
|
||||
/*
|
||||
* Every time he sees mean monster, it might start chasing him
|
||||
*/
|
||||
if (!on(*tp, ISRUN) && rnd(3) != 0 && on(*tp, ISMEAN) && !on(*tp, ISHELD)
|
||||
&& !ISWEARING(R_STEALTH) && !on(player, ISLEVIT))
|
||||
{
|
||||
tp->t_dest = &hero;
|
||||
tp->t_flags |= ISRUN;
|
||||
}
|
||||
if (ch == 'M' && !on(player, ISBLIND) && !on(player, ISHALU)
|
||||
&& !on(*tp, ISFOUND) && !on(*tp, ISCANC) && on(*tp, ISRUN))
|
||||
{
|
||||
rp = proom;
|
||||
if ((rp != NULL && !(rp->r_flags & ISDARK))
|
||||
|| dist(y, x, hero.y, hero.x) < LAMPDIST)
|
||||
{
|
||||
tp->t_flags |= ISFOUND;
|
||||
if (!save(VS_MAGIC))
|
||||
{
|
||||
if (on(player, ISHUH))
|
||||
lengthen(unconfuse, spread(HUHDURATION));
|
||||
else
|
||||
fuse(unconfuse, 0, spread(HUHDURATION), AFTER);
|
||||
player.t_flags |= ISHUH;
|
||||
mname = set_mname(tp);
|
||||
addmsg(rs,"%s", mname);
|
||||
if (strcmp(mname, "it") != 0)
|
||||
addmsg(rs,"'");
|
||||
msg(rs,"s gaze has confused you");
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Let greedy ones guard gold
|
||||
*/
|
||||
if (on(*tp, ISGREED) && !on(*tp, ISRUN))
|
||||
{
|
||||
tp->t_flags |= ISRUN;
|
||||
if (proom->r_goldval)
|
||||
tp->t_dest = &proom->r_gold;
|
||||
else
|
||||
tp->t_dest = &hero;
|
||||
}
|
||||
return tp;
|
||||
}
|
||||
|
||||
/*
|
||||
* give_pack:
|
||||
* Give a pack to a monster if it deserves one
|
||||
*/
|
||||
|
||||
void
|
||||
give_pack(struct rogue_state *rs,THING *tp)
|
||||
{
|
||||
if (level >= max_level && rnd(100) < monsters[tp->t_type-'A'].m_carry)
|
||||
{
|
||||
//fprintf(stderr,"give_pack\n");
|
||||
attach(tp->t_pack, new_thing(rs));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* save_throw:
|
||||
* See if a creature save against something
|
||||
*/
|
||||
int
|
||||
save_throw(int which, THING *tp)
|
||||
{
|
||||
int need;
|
||||
|
||||
need = 14 + which - tp->t_stats.s_lvl / 2;
|
||||
return (roll(1, 20) >= need);
|
||||
}
|
||||
|
||||
/*
|
||||
* save:
|
||||
* See if he saves against various nasty things
|
||||
*/
|
||||
int
|
||||
save(int which)
|
||||
{
|
||||
if (which == VS_MAGIC)
|
||||
{
|
||||
if (ISRING(LEFT, R_PROTECT))
|
||||
which -= cur_ring[LEFT]->o_arm;
|
||||
if (ISRING(RIGHT, R_PROTECT))
|
||||
which -= cur_ring[RIGHT]->o_arm;
|
||||
}
|
||||
return save_throw(which, &player);
|
||||
}
|
||||
@@ -1,429 +0,0 @@
|
||||
// Copyright (c) 2016-2023 The Hush developers
|
||||
// Distributed under the GPLv3 software license, see the accompanying
|
||||
// file COPYING or https://www.gnu.org/licenses/gpl-3.0.en.html
|
||||
/*
|
||||
* hero movement commands
|
||||
*
|
||||
* @(#)move.c 4.49 (Berkeley) 02/05/99
|
||||
*
|
||||
* Rogue: Exploring the Dungeons of Doom
|
||||
* Copyright (C) 1980-1983, 1985, 1999 Michael Toy, Ken Arnold and Glenn Wichman
|
||||
* All rights reserved.
|
||||
*
|
||||
* See the file LICENSE.TXT for full copyright and licensing information.
|
||||
*/
|
||||
|
||||
//#include <curses.h>
|
||||
//#include <ctype.h>
|
||||
#include "rogue.h"
|
||||
|
||||
/*
|
||||
* used to hold the new hero position
|
||||
*/
|
||||
|
||||
coord nh;
|
||||
|
||||
/*
|
||||
* do_run:
|
||||
* Start the hero running
|
||||
*/
|
||||
|
||||
void
|
||||
do_run(char ch)
|
||||
{
|
||||
running = TRUE;
|
||||
after = FALSE;
|
||||
runch = ch;
|
||||
}
|
||||
|
||||
/*
|
||||
* do_move:
|
||||
* Check to see that a move is legal. If it is handle the
|
||||
* consequences (fighting, picking up, etc.)
|
||||
*/
|
||||
|
||||
void
|
||||
do_move(struct rogue_state *rs,int dy, int dx)
|
||||
{
|
||||
char ch, fl;
|
||||
|
||||
firstmove = FALSE;
|
||||
if (no_move)
|
||||
{
|
||||
no_move--;
|
||||
msg(rs,"you are still stuck in the bear trap");
|
||||
return;
|
||||
}
|
||||
/*
|
||||
* Do a confused move (maybe)
|
||||
*/
|
||||
if (on(player, ISHUH) && rnd(5) != 0)
|
||||
{
|
||||
nh = *rndmove(&player);
|
||||
if (ce(nh, hero))
|
||||
{
|
||||
after = FALSE;
|
||||
running = FALSE;
|
||||
to_death = FALSE;
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
over:
|
||||
nh.y = hero.y + dy;
|
||||
nh.x = hero.x + dx;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if he tried to move off the screen or make an illegal
|
||||
* diagonal move, and stop him if he did.
|
||||
*/
|
||||
if (nh.x < 0 || nh.x >= NUMCOLS || nh.y <= 0 || nh.y >= NUMLINES - 1)
|
||||
goto hit_bound;
|
||||
if (!diag_ok(&hero, &nh))
|
||||
{
|
||||
after = FALSE;
|
||||
running = FALSE;
|
||||
return;
|
||||
}
|
||||
if (running && ce(hero, nh))
|
||||
after = running = FALSE;
|
||||
fl = flat(nh.y, nh.x);
|
||||
ch = winat(nh.y, nh.x);
|
||||
if (!(fl & F_REAL) && ch == FLOOR)
|
||||
{
|
||||
if (!on(player, ISLEVIT))
|
||||
{
|
||||
chat(nh.y, nh.x) = ch = TRAP;
|
||||
flat(nh.y, nh.x) |= F_REAL;
|
||||
}
|
||||
}
|
||||
else if (on(player, ISHELD) && ch != 'F')
|
||||
{
|
||||
msg(rs,"you are being held");
|
||||
return;
|
||||
}
|
||||
switch (ch)
|
||||
{
|
||||
case ' ':
|
||||
case '|':
|
||||
case '-':
|
||||
hit_bound:
|
||||
if (passgo && running && (proom->r_flags & ISGONE)
|
||||
&& !on(player, ISBLIND))
|
||||
{
|
||||
bool b1, b2;
|
||||
|
||||
switch (runch)
|
||||
{
|
||||
case 'h':
|
||||
case 'l':
|
||||
b1 = (bool)(hero.y != 1 && turn_ok(hero.y - 1, hero.x));
|
||||
b2 = (bool)(hero.y != NUMLINES - 2 && turn_ok(hero.y + 1, hero.x));
|
||||
if (!(b1 ^ b2))
|
||||
break;
|
||||
if (b1)
|
||||
{
|
||||
runch = 'k';
|
||||
dy = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
runch = 'j';
|
||||
dy = 1;
|
||||
}
|
||||
dx = 0;
|
||||
turnref();
|
||||
goto over;
|
||||
case 'j':
|
||||
case 'k':
|
||||
b1 = (bool)(hero.x != 0 && turn_ok(hero.y, hero.x - 1));
|
||||
b2 = (bool)(hero.x != NUMCOLS - 1 && turn_ok(hero.y, hero.x + 1));
|
||||
if (!(b1 ^ b2))
|
||||
break;
|
||||
if (b1)
|
||||
{
|
||||
runch = 'h';
|
||||
dx = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
runch = 'l';
|
||||
dx = 1;
|
||||
}
|
||||
dy = 0;
|
||||
turnref();
|
||||
goto over;
|
||||
}
|
||||
}
|
||||
running = FALSE;
|
||||
after = FALSE;
|
||||
break;
|
||||
case DOOR:
|
||||
running = FALSE;
|
||||
if (flat(hero.y, hero.x) & F_PASS)
|
||||
enter_room(rs,&nh);
|
||||
goto move_stuff;
|
||||
case TRAP:
|
||||
ch = be_trapped(rs,&nh);
|
||||
if (ch == T_DOOR || ch == T_TELEP)
|
||||
return;
|
||||
goto move_stuff;
|
||||
case PASSAGE:
|
||||
/*
|
||||
* when you're in a corridor, you don't know if you're in
|
||||
* a maze room or not, and there ain't no way to find out
|
||||
* if you're leaving a maze room, so it is necessary to
|
||||
* always recalculate proom.
|
||||
*/
|
||||
proom = roomin(rs,&hero);
|
||||
goto move_stuff;
|
||||
case FLOOR:
|
||||
if (!(fl & F_REAL))
|
||||
be_trapped(rs,&hero);
|
||||
goto move_stuff;
|
||||
case STAIRS:
|
||||
seenstairs = TRUE;
|
||||
/* FALLTHROUGH */
|
||||
default:
|
||||
running = FALSE;
|
||||
if (isupper(ch) || moat(nh.y, nh.x))
|
||||
fight(rs,&nh, cur_weapon, FALSE);
|
||||
else
|
||||
{
|
||||
if (ch != STAIRS)
|
||||
take = ch;
|
||||
move_stuff:
|
||||
mvaddch(hero.y, hero.x, floor_at());
|
||||
if ((fl & F_PASS) && chat(oldpos.y, oldpos.x) == DOOR)
|
||||
leave_room(rs,&nh);
|
||||
hero = nh;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* turn_ok:
|
||||
* Decide whether it is legal to turn onto the given space
|
||||
*/
|
||||
bool
|
||||
turn_ok(int y, int x)
|
||||
{
|
||||
PLACE *pp;
|
||||
|
||||
pp = INDEX(y, x);
|
||||
return (pp->p_ch == DOOR
|
||||
|| (pp->p_flags & (F_REAL|F_PASS)) == (F_REAL|F_PASS));
|
||||
}
|
||||
|
||||
/*
|
||||
* turnref:
|
||||
* Decide whether to refresh at a passage turning or not
|
||||
*/
|
||||
|
||||
void
|
||||
turnref()
|
||||
{
|
||||
PLACE *pp;
|
||||
|
||||
pp = INDEX(hero.y, hero.x);
|
||||
if (!(pp->p_flags & F_SEEN))
|
||||
{
|
||||
if (jump)
|
||||
{
|
||||
leaveok(stdscr, TRUE);
|
||||
if ( globalR.sleeptime != 0 )
|
||||
refresh();
|
||||
leaveok(stdscr, FALSE);
|
||||
}
|
||||
pp->p_flags |= F_SEEN;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* door_open:
|
||||
* Called to illuminate a room. If it is dark, remove anything
|
||||
* that might move.
|
||||
*/
|
||||
|
||||
void
|
||||
door_open(struct rogue_state *rs,struct room *rp)
|
||||
{
|
||||
int y, x;
|
||||
|
||||
if (!(rp->r_flags & ISGONE))
|
||||
for (y = rp->r_pos.y; y < rp->r_pos.y + rp->r_max.y; y++)
|
||||
for (x = rp->r_pos.x; x < rp->r_pos.x + rp->r_max.x; x++)
|
||||
if (isupper(winat(y, x)))
|
||||
wake_monster(rs,y, x);
|
||||
}
|
||||
|
||||
/*
|
||||
* be_trapped:
|
||||
* The guy stepped on a trap.... Make him pay.
|
||||
*/
|
||||
char
|
||||
be_trapped(struct rogue_state *rs,coord *tc)
|
||||
{
|
||||
PLACE *pp;
|
||||
THING *arrow;
|
||||
char tr;
|
||||
|
||||
if (on(player, ISLEVIT))
|
||||
return T_RUST; /* anything that's not a door or teleport */
|
||||
running = FALSE;
|
||||
count = FALSE;
|
||||
pp = INDEX(tc->y, tc->x);
|
||||
pp->p_ch = TRAP;
|
||||
tr = pp->p_flags & F_TMASK;
|
||||
pp->p_flags |= F_SEEN;
|
||||
switch (tr)
|
||||
{
|
||||
case T_DOOR:
|
||||
level++;
|
||||
new_level(rs);
|
||||
msg(rs,"you fell into a trap!");
|
||||
when T_BEAR:
|
||||
no_move += BEARTIME;
|
||||
msg(rs,"you are caught in a bear trap");
|
||||
when T_MYST:
|
||||
switch(rnd(11))
|
||||
{
|
||||
case 0: msg(rs,"you are suddenly in a parallel dimension");
|
||||
when 1: msg(rs,"the light in here suddenly seems %s", rainbow[rnd(cNCOLORS)]);
|
||||
when 2: msg(rs,"you feel a sting in the side of your neck");
|
||||
when 3: msg(rs,"multi-colored lines swirl around you, then fade");
|
||||
when 4: msg(rs,"a %s light flashes in your eyes", rainbow[rnd(cNCOLORS)]);
|
||||
when 5: msg(rs,"a spike shoots past your ear!");
|
||||
when 6: msg(rs,"%s sparks dance across your armor", rainbow[rnd(cNCOLORS)]);
|
||||
when 7: msg(rs,"you suddenly feel very thirsty");
|
||||
when 8: msg(rs,"you feel time speed up suddenly");
|
||||
when 9: msg(rs,"time now seems to be going slower");
|
||||
when 10: msg(rs,"you pack turns %s!", rainbow[rnd(cNCOLORS)]);
|
||||
}
|
||||
when T_SLEEP:
|
||||
no_command += SLEEPTIME;
|
||||
player.t_flags &= ~ISRUN;
|
||||
msg(rs,"a strange white mist envelops you and you fall asleep");
|
||||
when T_ARROW:
|
||||
if (swing(pstats.s_lvl - 1, pstats.s_arm, 1))
|
||||
{
|
||||
pstats.s_hpt -= roll(1, 6);
|
||||
if (pstats.s_hpt <= 0)
|
||||
{
|
||||
msg(rs,"an arrow killed you");
|
||||
death(rs,'a');
|
||||
}
|
||||
else
|
||||
msg(rs,"oh no! An arrow shot you");
|
||||
}
|
||||
else
|
||||
{
|
||||
arrow = new_item();
|
||||
init_weapon(arrow, ARROW);
|
||||
arrow->o_count = 1;
|
||||
arrow->o_pos = hero;
|
||||
fall(rs,arrow, FALSE);
|
||||
msg(rs,"an arrow shoots past you");
|
||||
}
|
||||
when T_TELEP:
|
||||
/*
|
||||
* since the hero's leaving, look() won't put a TRAP
|
||||
* down for us, so we have to do it ourself
|
||||
*/
|
||||
teleport(rs);
|
||||
mvaddch(tc->y, tc->x, TRAP);
|
||||
when T_DART:
|
||||
if (!swing(pstats.s_lvl+1, pstats.s_arm, 1))
|
||||
msg(rs,"a small dart whizzes by your ear and vanishes");
|
||||
else
|
||||
{
|
||||
pstats.s_hpt -= roll(1, 4);
|
||||
if (pstats.s_hpt <= 0)
|
||||
{
|
||||
msg(rs,"a poisoned dart killed you");
|
||||
death(rs,'d');
|
||||
}
|
||||
if (!ISWEARING(R_SUSTSTR) && !save(VS_POISON))
|
||||
chg_str(-1);
|
||||
msg(rs,"a small dart just hit you in the shoulder");
|
||||
}
|
||||
when T_RUST:
|
||||
msg(rs,"a gush of water hits you on the head");
|
||||
rust_armor(rs,cur_armor);
|
||||
}
|
||||
flush_type();
|
||||
return tr;
|
||||
}
|
||||
|
||||
/*
|
||||
* rndmove:
|
||||
* Move in a random direction if the monster/person is confused
|
||||
*/
|
||||
coord *
|
||||
rndmove(THING *who)
|
||||
{
|
||||
THING *obj;
|
||||
int x, y;
|
||||
char ch;
|
||||
static coord ret; /* what we will be returning */
|
||||
|
||||
y = ret.y = who->t_pos.y + rnd(3) - 1;
|
||||
x = ret.x = who->t_pos.x + rnd(3) - 1;
|
||||
/*
|
||||
* Now check to see if that's a legal move. If not, don't move.
|
||||
* (I.e., bump into the wall or whatever)
|
||||
*/
|
||||
if (y == who->t_pos.y && x == who->t_pos.x)
|
||||
return &ret;
|
||||
if (!diag_ok(&who->t_pos, &ret))
|
||||
goto bad;
|
||||
else
|
||||
{
|
||||
ch = winat(y, x);
|
||||
if (!step_ok(ch))
|
||||
goto bad;
|
||||
if (ch == SCROLL)
|
||||
{
|
||||
for (obj = lvl_obj; obj != NULL; obj = next(obj))
|
||||
if (y == obj->o_pos.y && x == obj->o_pos.x)
|
||||
break;
|
||||
if (obj != NULL && obj->o_which == S_SCARE)
|
||||
goto bad;
|
||||
}
|
||||
}
|
||||
return &ret;
|
||||
|
||||
bad:
|
||||
ret = who->t_pos;
|
||||
return &ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* rust_armor:
|
||||
* Rust the given armor, if it is a legal kind to rust, and we
|
||||
* aren't wearing a magic ring.
|
||||
*/
|
||||
|
||||
void
|
||||
rust_armor(struct rogue_state *rs,THING *arm)
|
||||
{
|
||||
if (arm == NULL || arm->o_type != ARMOR || arm->o_which == LEATHER ||
|
||||
arm->o_arm >= 9)
|
||||
return;
|
||||
|
||||
if ((arm->o_flags & ISPROT) || ISWEARING(R_SUSTARM))
|
||||
{
|
||||
if (!to_death)
|
||||
msg(rs,"the rust vanishes instantly");
|
||||
}
|
||||
else
|
||||
{
|
||||
arm->o_arm++;
|
||||
if (!terse)
|
||||
msg(rs,"your armor appears to be weaker now. Oh my!");
|
||||
else
|
||||
msg(rs,"your armor weakens");
|
||||
}
|
||||
}
|
||||
@@ -1,247 +0,0 @@
|
||||
// Copyright (c) 2016-2023 The Hush developers
|
||||
// Distributed under the GPLv3 software license, see the accompanying
|
||||
// file COPYING or https://www.gnu.org/licenses/gpl-3.0.en.html
|
||||
/*
|
||||
* new_level:
|
||||
* Dig and draw a new level
|
||||
*
|
||||
* @(#)new_level.c 4.38 (Berkeley) 02/05/99
|
||||
*
|
||||
* Rogue: Exploring the Dungeons of Doom
|
||||
* Copyright (C) 1980-1983, 1985, 1999 Michael Toy, Ken Arnold and Glenn Wichman
|
||||
* All rights reserved.
|
||||
*
|
||||
* See the file LICENSE.TXT for full copyright and licensing information.
|
||||
*/
|
||||
|
||||
//#include <curses.h>
|
||||
//#include <string.h>
|
||||
#include "rogue.h"
|
||||
|
||||
#define TREAS_ROOM 20 /* one chance in TREAS_ROOM for a treasure room */
|
||||
#define MAXTREAS 10 /* maximum number of treasures in a treasure room */
|
||||
#define MINTREAS 2 /* minimum number of treasures in a treasure room */
|
||||
|
||||
void
|
||||
new_level(struct rogue_state *rs)
|
||||
{
|
||||
THING *tp;
|
||||
PLACE *pp;
|
||||
char *sp;
|
||||
int i;
|
||||
if ( 0 )
|
||||
{
|
||||
static FILE *fp;
|
||||
if ( fp == 0 )
|
||||
fp = fopen("debug","wb");
|
||||
if ( fp != 0 )
|
||||
{
|
||||
fprintf(fp,"newlevel seed.%llu\n",(long long)seed);
|
||||
fflush(fp);
|
||||
}
|
||||
}
|
||||
player.t_flags &= ~ISHELD; /* unhold when you go down just in case */
|
||||
if (level > max_level)
|
||||
max_level = level;
|
||||
/*
|
||||
* Clean things off from last level
|
||||
*/
|
||||
for (pp = places; pp < &places[MAXCOLS*MAXLINES]; pp++)
|
||||
{
|
||||
pp->p_ch = ' ';
|
||||
pp->p_flags = F_REAL;
|
||||
pp->p_monst = NULL;
|
||||
}
|
||||
clear();
|
||||
/*
|
||||
* Free up the monsters on the last level
|
||||
*/
|
||||
for (tp = mlist; tp != NULL; tp = next(tp))
|
||||
free_list(tp->t_pack);
|
||||
free_list(mlist);
|
||||
/*
|
||||
* Throw away stuff left on the previous level (if anything)
|
||||
*/
|
||||
free_list(lvl_obj);
|
||||
do_rooms(rs); /* Draw rooms */
|
||||
do_passages(rs); /* Draw passages */
|
||||
no_food++;
|
||||
//fprintf(stderr,"new_level.%d\n",level);
|
||||
put_things(rs); /* Place objects (if any) */
|
||||
/*
|
||||
* Place the traps
|
||||
*/
|
||||
if (rnd(10) < level)
|
||||
{
|
||||
ntraps = rnd(level / 4) + 1;
|
||||
if (ntraps > MAXTRAPS)
|
||||
ntraps = MAXTRAPS;
|
||||
i = ntraps;
|
||||
while (i--)
|
||||
{
|
||||
/*
|
||||
* not only wouldn't it be NICE to have traps in mazes
|
||||
* (not that we care about being nice), since the trap
|
||||
* number is stored where the passage number is, we
|
||||
* can't actually do it.
|
||||
*/
|
||||
do
|
||||
{
|
||||
find_floor(rs,(struct room *) NULL, &stairs, FALSE, FALSE);
|
||||
} while (chat(stairs.y, stairs.x) != FLOOR);
|
||||
sp = &flat(stairs.y, stairs.x);
|
||||
*sp &= ~F_REAL;
|
||||
*sp |= rnd(NTRAPS);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Place the staircase down.
|
||||
*/
|
||||
find_floor(rs,(struct room *) NULL, &stairs, FALSE, FALSE);
|
||||
chat(stairs.y, stairs.x) = STAIRS;
|
||||
seenstairs = FALSE;
|
||||
|
||||
for (tp = mlist; tp != NULL; tp = next(tp))
|
||||
tp->t_room = roomin(rs,&tp->t_pos);
|
||||
|
||||
find_floor(rs,(struct room *) NULL, &hero, FALSE, TRUE);
|
||||
enter_room(rs,&hero);
|
||||
mvaddch(hero.y, hero.x, PLAYER);
|
||||
if (on(player, SEEMONST))
|
||||
turn_see(rs,FALSE);
|
||||
if (on(player, ISHALU))
|
||||
visuals(rs,0);
|
||||
}
|
||||
|
||||
/*
|
||||
* rnd_room:
|
||||
* Pick a room that is really there
|
||||
*/
|
||||
int
|
||||
rnd_room()
|
||||
{
|
||||
int rm;
|
||||
|
||||
do
|
||||
{
|
||||
rm = rnd(MAXROOMS);
|
||||
} while (rooms[rm].r_flags & ISGONE);
|
||||
return rm;
|
||||
}
|
||||
|
||||
/*
|
||||
* put_things:
|
||||
* Put potions and scrolls on this level
|
||||
*/
|
||||
|
||||
void
|
||||
put_things(struct rogue_state *rs)
|
||||
{
|
||||
int i;
|
||||
THING *obj;
|
||||
|
||||
/*
|
||||
* Once you have found the amulet, the only way to get new stuff is
|
||||
* go down into the dungeon.
|
||||
*/
|
||||
if (amulet && level < max_level)
|
||||
return;
|
||||
/*
|
||||
* check for treasure rooms, and if so, put it in.
|
||||
*/
|
||||
if (rnd(TREAS_ROOM) == 0)
|
||||
treas_room(rs);
|
||||
/*
|
||||
* Do MAXOBJ attempts to put things on a level
|
||||
*/
|
||||
for (i = 0; i < MAXOBJ; i++)
|
||||
if (rnd(100) < 36)
|
||||
{
|
||||
/*
|
||||
* Pick a new object and link it in the list
|
||||
*/
|
||||
obj = new_thing(rs);
|
||||
//fprintf(stderr,"put_things i.%d obj.%p\n",i,obj);
|
||||
attach(lvl_obj, obj);
|
||||
/*
|
||||
* Put it somewhere
|
||||
*/
|
||||
find_floor(rs,(struct room *) NULL, &obj->o_pos, FALSE, FALSE);
|
||||
chat(obj->o_pos.y, obj->o_pos.x) = (char) obj->o_type;
|
||||
}
|
||||
/*
|
||||
* If he is really deep in the dungeon and he hasn't found the
|
||||
* amulet yet, put it somewhere on the ground
|
||||
*/
|
||||
if (level >= AMULETLEVEL && !amulet)
|
||||
{
|
||||
obj = new_item();
|
||||
attach(lvl_obj, obj);
|
||||
obj->o_hplus = 0;
|
||||
obj->o_dplus = 0;
|
||||
strncpy(obj->o_damage,"0x0",sizeof(obj->o_damage));
|
||||
strncpy(obj->o_hurldmg,"0x0",sizeof(obj->o_hurldmg));
|
||||
obj->o_arm = 11;
|
||||
obj->o_type = AMULET;
|
||||
/*
|
||||
* Put it somewhere
|
||||
*/
|
||||
find_floor(rs,(struct room *) NULL, &obj->o_pos, FALSE, FALSE);
|
||||
chat(obj->o_pos.y, obj->o_pos.x) = AMULET;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* treas_room:
|
||||
* Add a treasure room
|
||||
*/
|
||||
#define MAXTRIES 10 /* max number of tries to put down a monster */
|
||||
|
||||
|
||||
void
|
||||
treas_room(struct rogue_state *rs)
|
||||
{
|
||||
int nm;
|
||||
THING *tp;
|
||||
struct room *rp;
|
||||
int spots, num_monst;
|
||||
static coord mp;
|
||||
|
||||
rp = &rooms[rnd_room()];
|
||||
spots = (rp->r_max.y - 2) * (rp->r_max.x - 2) - MINTREAS;
|
||||
if (spots > (MAXTREAS - MINTREAS))
|
||||
spots = (MAXTREAS - MINTREAS);
|
||||
num_monst = nm = rnd(spots) + MINTREAS;
|
||||
while (nm--)
|
||||
{
|
||||
find_floor(rs,rp, &mp, 2 * MAXTRIES, FALSE);
|
||||
//fprintf(stderr,"treas_room\n");
|
||||
tp = new_thing(rs);
|
||||
tp->o_pos = mp;
|
||||
attach(lvl_obj, tp);
|
||||
chat(mp.y, mp.x) = (char) tp->o_type;
|
||||
}
|
||||
|
||||
/*
|
||||
* fill up room with monsters from the next level down
|
||||
*/
|
||||
|
||||
if ((nm = rnd(spots) + MINTREAS) < num_monst + 2)
|
||||
nm = num_monst + 2;
|
||||
spots = (rp->r_max.y - 2) * (rp->r_max.x - 2);
|
||||
if (nm > spots)
|
||||
nm = spots;
|
||||
level++;
|
||||
while (nm--)
|
||||
{
|
||||
spots = 0;
|
||||
if (find_floor(rs,rp, &mp, MAXTRIES, TRUE))
|
||||
{
|
||||
tp = new_item();
|
||||
new_monster(rs,tp, randmonster(FALSE), &mp);
|
||||
tp->t_flags |= ISMEAN; /* no sloughers in THIS room */
|
||||
give_pack(rs,tp);
|
||||
}
|
||||
}
|
||||
level--;
|
||||
}
|
||||
@@ -1,504 +0,0 @@
|
||||
// Copyright (c) 2016-2023 The Hush developers
|
||||
// Distributed under the GPLv3 software license, see the accompanying
|
||||
// file COPYING or https://www.gnu.org/licenses/gpl-3.0.en.html
|
||||
/*
|
||||
* This file has all the code for the option command. I would rather
|
||||
* this command were not necessary, but it is the only way to keep the
|
||||
* wolves off of my back.
|
||||
*
|
||||
* @(#)options.c 4.24 (Berkeley) 05/10/83
|
||||
*
|
||||
* Rogue: Exploring the Dungeons of Doom
|
||||
* Copyright (C) 1980-1983, 1985, 1999 Michael Toy, Ken Arnold and Glenn Wichman
|
||||
* All rights reserved.
|
||||
*
|
||||
* See the file LICENSE.TXT for full copyright and licensing information.
|
||||
*/
|
||||
|
||||
//#include <stdlib.h>
|
||||
//#include <curses.h>
|
||||
//#include <ctype.h>
|
||||
//#include <string.h>
|
||||
#include "rogue.h"
|
||||
|
||||
#define EQSTR(a, b, c) (strncmp(a, b, c) == 0)
|
||||
|
||||
#define NUM_OPTS (sizeof optlist / sizeof (OPTION))
|
||||
|
||||
/*
|
||||
* description of an option and what to do with it
|
||||
*/
|
||||
struct optstruct {
|
||||
char *o_name; /* option name */
|
||||
char *o_prompt; /* prompt for interactive entry */
|
||||
void *o_opt; /* pointer to thing to set */
|
||||
/* function to print value */
|
||||
void (*o_putfunc)(void *opt);
|
||||
/* function to get value interactively */
|
||||
int (*o_getfunc)(struct rogue_state *rs,void *opt, WINDOW *win);
|
||||
};
|
||||
|
||||
typedef struct optstruct OPTION;
|
||||
|
||||
void pr_optname(OPTION *op);
|
||||
|
||||
OPTION optlist[] = {
|
||||
{"terse", "Terse output",
|
||||
&terse, put_bool, get_bool },
|
||||
{"flush", "Flush typeahead during battle",
|
||||
&fight_flush, put_bool, get_bool },
|
||||
{"jump", "Show position only at end of run",
|
||||
&jump, put_bool, get_bool },
|
||||
{"seefloor", "Show the lamp-illuminated floor",
|
||||
&see_floor, put_bool, get_sf },
|
||||
{"passgo", "Follow turnings in passageways",
|
||||
&passgo, put_bool, get_bool },
|
||||
{"tombstone", "Print out tombstone when killed",
|
||||
&tombstone, put_bool, get_bool },
|
||||
{"inven", "Inventory style",
|
||||
&inv_type, put_inv_t, get_inv_t },
|
||||
{"name", "Name",
|
||||
whoami, put_str, get_str },
|
||||
{"fruit", "Fruit",
|
||||
fruit, put_str, get_str },
|
||||
{"file", "Save file",
|
||||
file_name, put_str, get_str }
|
||||
};
|
||||
|
||||
/*
|
||||
* option:
|
||||
* Print and then set options from the terminal
|
||||
*/
|
||||
|
||||
void
|
||||
option(struct rogue_state *rs)
|
||||
{
|
||||
OPTION *op;
|
||||
int retval;
|
||||
|
||||
wclear(hw);
|
||||
/*
|
||||
* Display current values of options
|
||||
*/
|
||||
for (op = optlist; op <= &optlist[NUM_OPTS-1]; op++)
|
||||
{
|
||||
pr_optname(op);
|
||||
(*op->o_putfunc)(op->o_opt);
|
||||
waddch(hw, '\n');
|
||||
}
|
||||
/*
|
||||
* Set values
|
||||
*/
|
||||
wmove(hw, 0, 0);
|
||||
for (op = optlist; op <= &optlist[NUM_OPTS-1]; op++)
|
||||
{
|
||||
pr_optname(op);
|
||||
retval = (*op->o_getfunc)(rs,op->o_opt, hw);
|
||||
if (retval)
|
||||
{
|
||||
if (retval == QUIT)
|
||||
break;
|
||||
else if (op > optlist) { /* MINUS */
|
||||
wmove(hw, (int)(op - optlist) - 1, 0);
|
||||
op -= 2;
|
||||
}
|
||||
else /* trying to back up beyond the top */
|
||||
{
|
||||
putchar('\007');
|
||||
wmove(hw, 0, 0);
|
||||
op--;
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Switch back to original screen
|
||||
*/
|
||||
wmove(hw, LINES - 1, 0);
|
||||
waddstr(hw, "--Press space to continue--");
|
||||
wrefresh(hw);
|
||||
wait_for(rs,' ');
|
||||
clearok(curscr, TRUE);
|
||||
touchwin(stdscr);
|
||||
after = FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* pr_optname:
|
||||
* Print out the option name prompt
|
||||
*/
|
||||
|
||||
void
|
||||
pr_optname(OPTION *op)
|
||||
{
|
||||
wprintw(hw, "%s (\"%s\"): ", op->o_prompt, op->o_name);
|
||||
}
|
||||
|
||||
/*
|
||||
* put_bool
|
||||
* Put out a boolean
|
||||
*/
|
||||
|
||||
void
|
||||
put_bool(void *b)
|
||||
{
|
||||
waddstr(hw, *(bool *) b ? "True" : "False");
|
||||
}
|
||||
|
||||
/*
|
||||
* put_str:
|
||||
* Put out a string
|
||||
*/
|
||||
|
||||
void
|
||||
put_str(void *str)
|
||||
{
|
||||
waddstr(hw, (char *) str);
|
||||
}
|
||||
|
||||
/*
|
||||
* put_inv_t:
|
||||
* Put out an inventory type
|
||||
*/
|
||||
|
||||
void
|
||||
put_inv_t(void *ip)
|
||||
{
|
||||
waddstr(hw, inv_t_name[*(int *) ip]);
|
||||
}
|
||||
|
||||
/*
|
||||
* get_bool:
|
||||
* Allow changing a boolean option and print it out
|
||||
*/
|
||||
int
|
||||
get_bool(struct rogue_state *rs,void *vp, WINDOW *win)
|
||||
{
|
||||
bool *bp = (bool *) vp;
|
||||
int oy, ox;
|
||||
bool op_bad;
|
||||
|
||||
op_bad = TRUE;
|
||||
getyx(win, oy, ox);
|
||||
waddstr(win, *bp ? "True" : "False");
|
||||
while (op_bad)
|
||||
{
|
||||
wmove(win, oy, ox);
|
||||
wrefresh(win);
|
||||
switch (readchar(rs))
|
||||
{
|
||||
case 't':
|
||||
case 'T':
|
||||
*bp = TRUE;
|
||||
op_bad = FALSE;
|
||||
break;
|
||||
case 'f':
|
||||
case 'F':
|
||||
*bp = FALSE;
|
||||
op_bad = FALSE;
|
||||
break;
|
||||
case '\n':
|
||||
case '\r':
|
||||
op_bad = FALSE;
|
||||
break;
|
||||
case ESCAPE:
|
||||
return QUIT;
|
||||
case '-':
|
||||
return MINUS;
|
||||
default:
|
||||
wmove(win, oy, ox + 10);
|
||||
waddstr(win, "(T or F)");
|
||||
}
|
||||
}
|
||||
wmove(win, oy, ox);
|
||||
waddstr(win, *bp ? "True" : "False");
|
||||
waddch(win, '\n');
|
||||
return NORM;
|
||||
}
|
||||
|
||||
/*
|
||||
* get_sf:
|
||||
* Change value and handle transition problems from see_floor to
|
||||
* !see_floor.
|
||||
*/
|
||||
int
|
||||
get_sf(struct rogue_state *rs,void *vp, WINDOW *win)
|
||||
{
|
||||
bool *bp = (bool *) vp;
|
||||
bool was_sf;
|
||||
int retval;
|
||||
|
||||
was_sf = see_floor;
|
||||
retval = get_bool(rs,bp, win);
|
||||
if (retval == QUIT) return(QUIT);
|
||||
if (was_sf != see_floor)
|
||||
{
|
||||
if (!see_floor) {
|
||||
see_floor = TRUE;
|
||||
erase_lamp(&hero, proom);
|
||||
see_floor = FALSE;
|
||||
}
|
||||
else
|
||||
look(rs,FALSE);
|
||||
}
|
||||
return(NORM);
|
||||
}
|
||||
|
||||
/*
|
||||
* get_str:
|
||||
* Set a string option
|
||||
*/
|
||||
#define MAXINP 50 /* max string to read from terminal or environment */
|
||||
|
||||
int
|
||||
get_str(struct rogue_state *rs,void *vopt, WINDOW *win)
|
||||
{
|
||||
char *opt = (char *) vopt;
|
||||
char *sp;
|
||||
int oy, ox;
|
||||
int i;
|
||||
signed char c;
|
||||
static char buf[MAXSTR];
|
||||
|
||||
getyx(win, oy, ox);
|
||||
wrefresh(win);
|
||||
/*
|
||||
* loop reading in the string, and put it in a temporary buffer
|
||||
*/
|
||||
for (sp = buf; (c = readchar(rs)) != '\n' && c != '\r' && c != ESCAPE;
|
||||
wclrtoeol(win), wrefresh(win))
|
||||
{
|
||||
if (c == -1)
|
||||
continue;
|
||||
/*else if (c == erasechar()) // process erase character
|
||||
{
|
||||
if (sp > buf)
|
||||
{
|
||||
sp--;
|
||||
for (i = (int) strlen(unctrl(*sp)); i; i--)
|
||||
waddch(win, '\b');
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else if (c == killchar()) // process kill character
|
||||
{
|
||||
sp = buf;
|
||||
wmove(win, oy, ox);
|
||||
continue;
|
||||
}*/
|
||||
else if (sp == buf)
|
||||
{
|
||||
if (c == '-' && win != stdscr)
|
||||
break;
|
||||
else if (c == '~')
|
||||
{
|
||||
strcpy(buf, home);
|
||||
waddstr(win, home);
|
||||
sp += strlen(home);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (sp >= &buf[MAXINP] || !(isprint(c) || c == ' '))
|
||||
putchar(CTRL('G'));
|
||||
else
|
||||
{
|
||||
*sp++ = c;
|
||||
waddstr(win, unctrl(c));
|
||||
}
|
||||
}
|
||||
*sp = '\0';
|
||||
if (sp > buf) /* only change option if something has been typed */
|
||||
strucpy(opt, buf, (int) strlen(buf));
|
||||
mvwprintw(win, oy, ox, "%s\n", opt);
|
||||
wrefresh(win);
|
||||
if (win == stdscr)
|
||||
mpos += (int)(sp - buf);
|
||||
if (c == '-')
|
||||
return MINUS;
|
||||
else if (c == ESCAPE)
|
||||
return QUIT;
|
||||
else
|
||||
return NORM;
|
||||
}
|
||||
|
||||
/*
|
||||
* get_inv_t
|
||||
* Get an inventory type name
|
||||
*/
|
||||
int
|
||||
get_inv_t(struct rogue_state *rs,void *vp, WINDOW *win)
|
||||
{
|
||||
int *ip = (int *) vp;
|
||||
int oy, ox;
|
||||
bool op_bad;
|
||||
|
||||
op_bad = TRUE;
|
||||
getyx(win, oy, ox);
|
||||
waddstr(win, inv_t_name[*ip]);
|
||||
while (op_bad)
|
||||
{
|
||||
wmove(win, oy, ox);
|
||||
wrefresh(win);
|
||||
switch (readchar(rs))
|
||||
{
|
||||
case 'o':
|
||||
case 'O':
|
||||
*ip = INV_OVER;
|
||||
op_bad = FALSE;
|
||||
break;
|
||||
case 's':
|
||||
case 'S':
|
||||
*ip = INV_SLOW;
|
||||
op_bad = FALSE;
|
||||
break;
|
||||
case 'c':
|
||||
case 'C':
|
||||
*ip = INV_CLEAR;
|
||||
op_bad = FALSE;
|
||||
break;
|
||||
case '\n':
|
||||
case '\r':
|
||||
op_bad = FALSE;
|
||||
break;
|
||||
case ESCAPE:
|
||||
return QUIT;
|
||||
case '-':
|
||||
return MINUS;
|
||||
default:
|
||||
wmove(win, oy, ox + 15);
|
||||
waddstr(win, "(O, S, or C)");
|
||||
}
|
||||
}
|
||||
mvwprintw(win, oy, ox, "%s\n", inv_t_name[*ip]);
|
||||
return NORM;
|
||||
}
|
||||
|
||||
|
||||
#ifdef MASTER
|
||||
/*
|
||||
* get_num:
|
||||
* Get a numeric option
|
||||
*/
|
||||
int
|
||||
get_num(struct rogue_state *rs,void *vp, WINDOW *win)
|
||||
{
|
||||
short *opt = (short *) vp;
|
||||
int i;
|
||||
static char buf[MAXSTR];
|
||||
|
||||
if ((i = get_str(rs,buf, win)) == NORM)
|
||||
*opt = (short) atoi(buf);
|
||||
return i;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* parse_opts:
|
||||
* Parse options from string, usually taken from the environment.
|
||||
* The string is a series of comma seperated values, with booleans
|
||||
* being stated as "name" (true) or "noname" (false), and strings
|
||||
* being "name=....", with the string being defined up to a comma
|
||||
* or the end of the entire option string.
|
||||
*/
|
||||
|
||||
void
|
||||
parse_opts(char *str)
|
||||
{
|
||||
char *sp;
|
||||
OPTION *op;
|
||||
int len;
|
||||
const char **i;
|
||||
char *start;
|
||||
|
||||
while (*str)
|
||||
{
|
||||
/*
|
||||
* Get option name
|
||||
*/
|
||||
for (sp = str; isalpha(*sp); sp++)
|
||||
continue;
|
||||
len = (int)(sp - str);
|
||||
/*
|
||||
* Look it up and deal with it
|
||||
*/
|
||||
for (op = optlist; op <= &optlist[NUM_OPTS-1]; op++)
|
||||
if (EQSTR(str, op->o_name, len))
|
||||
{
|
||||
if (op->o_putfunc == put_bool) /* if option is a boolean */
|
||||
*(bool *)op->o_opt = TRUE; /* NOSTRICT */
|
||||
else /* string option */
|
||||
{
|
||||
/*
|
||||
* Skip to start of string value
|
||||
*/
|
||||
for (str = sp + 1; *str == '='; str++)
|
||||
continue;
|
||||
if (*str == '~')
|
||||
{
|
||||
strcpy((char *) op->o_opt, home); /* NOSTRICT */
|
||||
start = (char *) op->o_opt + strlen(home);/* NOSTRICT */
|
||||
while (*++str == '/')
|
||||
continue;
|
||||
}
|
||||
else
|
||||
start = (char *) op->o_opt; /* NOSTRICT */
|
||||
/*
|
||||
* Skip to end of string value
|
||||
*/
|
||||
for (sp = str + 1; *sp && *sp != ','; sp++)
|
||||
continue;
|
||||
/*
|
||||
* check for type of inventory
|
||||
*/
|
||||
if (op->o_putfunc == put_inv_t)
|
||||
{
|
||||
if (islower(*str))
|
||||
*str = (char) toupper(*str);
|
||||
for (i = inv_t_name; i <= &inv_t_name[INV_CLEAR]; i++)
|
||||
if (strncmp(str, *i, sp - str) == 0)
|
||||
{
|
||||
inv_type = (int)(i - inv_t_name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
strucpy(start, str, (int)(sp - str));
|
||||
}
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* check for "noname" for booleans
|
||||
*/
|
||||
else if (op->o_putfunc == put_bool
|
||||
&& EQSTR(str, "no", 2) && EQSTR(str + 2, op->o_name, len - 2))
|
||||
{
|
||||
*(bool *)op->o_opt = FALSE; /* NOSTRICT */
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* skip to start of next option name
|
||||
*/
|
||||
while (*sp && !isalpha(*sp))
|
||||
sp++;
|
||||
str = sp;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* strucpy:
|
||||
* Copy string using unctrl for things
|
||||
*/
|
||||
|
||||
void
|
||||
strucpy(char *s1, char *s2, int len)
|
||||
{
|
||||
if (len > MAXINP)
|
||||
len = MAXINP;
|
||||
while (len--)
|
||||
{
|
||||
if (isprint(*s2) || *s2 == ' ')
|
||||
*s1++ = *s2;
|
||||
s2++;
|
||||
}
|
||||
*s1 = '\0';
|
||||
}
|
||||
@@ -1,543 +0,0 @@
|
||||
// Copyright (c) 2016-2023 The Hush developers
|
||||
// Distributed under the GPLv3 software license, see the accompanying
|
||||
// file COPYING or https://www.gnu.org/licenses/gpl-3.0.en.html
|
||||
/*
|
||||
* Routines to deal with the pack
|
||||
*
|
||||
* @(#)pack.c 4.40 (Berkeley) 02/05/99
|
||||
*
|
||||
* Rogue: Exploring the Dungeons of Doom
|
||||
* Copyright (C) 1980-1983, 1985, 1999 Michael Toy, Ken Arnold and Glenn Wichman
|
||||
* All rights reserved.
|
||||
*
|
||||
* See the file LICENSE.TXT for full copyright and licensing information.
|
||||
*/
|
||||
|
||||
//#include <string.h>
|
||||
//#include <curses.h>
|
||||
//#include <ctype.h>
|
||||
#include "rogue.h"
|
||||
|
||||
/*
|
||||
* add_pack:
|
||||
* Pick up an object and add it to the pack. If the argument is
|
||||
* non-null use it as the linked_list pointer instead of gettting
|
||||
* it off the ground.
|
||||
*/
|
||||
|
||||
void
|
||||
add_pack(struct rogue_state *rs,THING *obj, bool silent)
|
||||
{
|
||||
THING *op, *lp;
|
||||
bool from_floor;
|
||||
|
||||
from_floor = FALSE;
|
||||
if (obj == NULL)
|
||||
{
|
||||
if ((obj = find_obj(rs,hero.y, hero.x)) == NULL)
|
||||
return;
|
||||
from_floor = TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check for and deal with scare monster scrolls
|
||||
*/
|
||||
if (obj->o_type == SCROLL && obj->o_which == S_SCARE)
|
||||
if (obj->o_flags & ISFOUND)
|
||||
{
|
||||
detach(lvl_obj, obj);
|
||||
mvaddch(hero.y, hero.x, floor_ch());
|
||||
chat(hero.y, hero.x) = (proom->r_flags & ISGONE) ? PASSAGE : FLOOR;
|
||||
discard(obj);
|
||||
msg(rs,"the scroll turns to dust as you pick it up");
|
||||
return;
|
||||
}
|
||||
|
||||
if (pack == NULL)
|
||||
{
|
||||
pack = obj;
|
||||
obj->o_packch = pack_char();
|
||||
inpack++;
|
||||
}
|
||||
else
|
||||
{
|
||||
lp = NULL;
|
||||
for (op = pack; op != NULL; op = next(op))
|
||||
{
|
||||
if (op->o_type != obj->o_type)
|
||||
lp = op;
|
||||
else
|
||||
{
|
||||
while (op->o_type == obj->o_type && op->o_which != obj->o_which)
|
||||
{
|
||||
lp = op;
|
||||
if (next(op) == NULL)
|
||||
break;
|
||||
else
|
||||
op = next(op);
|
||||
}
|
||||
if (op->o_type == obj->o_type && op->o_which == obj->o_which)
|
||||
{
|
||||
if (ISMULT(op->o_type))
|
||||
{
|
||||
if (!pack_room(rs,from_floor, obj))
|
||||
return;
|
||||
op->o_count++;
|
||||
dump_it:
|
||||
discard(obj);
|
||||
obj = op;
|
||||
lp = NULL;
|
||||
goto out;
|
||||
}
|
||||
else if (obj->o_group)
|
||||
{
|
||||
lp = op;
|
||||
while (op->o_type == obj->o_type
|
||||
&& op->o_which == obj->o_which
|
||||
&& op->o_group != obj->o_group)
|
||||
{
|
||||
lp = op;
|
||||
if (next(op) == NULL)
|
||||
break;
|
||||
else
|
||||
op = next(op);
|
||||
}
|
||||
if (op->o_type == obj->o_type
|
||||
&& op->o_which == obj->o_which
|
||||
&& op->o_group == obj->o_group)
|
||||
{
|
||||
op->o_count += obj->o_count;
|
||||
inpack--;
|
||||
if (!pack_room(rs,from_floor, obj))
|
||||
return;
|
||||
goto dump_it;
|
||||
}
|
||||
}
|
||||
else
|
||||
lp = op;
|
||||
}
|
||||
out:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (lp != NULL)
|
||||
{
|
||||
if (!pack_room(rs,from_floor, obj))
|
||||
return;
|
||||
else
|
||||
{
|
||||
obj->o_packch = pack_char();
|
||||
next(obj) = next(lp);
|
||||
prev(obj) = lp;
|
||||
if (next(lp) != NULL)
|
||||
prev(next(lp)) = obj;
|
||||
next(lp) = obj;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
obj->o_flags |= ISFOUND;
|
||||
|
||||
/*
|
||||
* If this was the object of something's desire, that monster will
|
||||
* get mad and run at the hero.
|
||||
*/
|
||||
for (op = mlist; op != NULL; op = next(op))
|
||||
if (op->t_dest == &obj->o_pos)
|
||||
op->t_dest = &hero;
|
||||
|
||||
if (obj->o_type == AMULET)
|
||||
amulet = TRUE;
|
||||
/*
|
||||
* Notify the user
|
||||
*/
|
||||
if (!silent)
|
||||
{
|
||||
if (!terse)
|
||||
addmsg(rs,"you now have ");
|
||||
msg(rs,"%s (%c)", inv_name(obj, !terse), obj->o_packch);
|
||||
}
|
||||
}
|
||||
|
||||
int32_t num_packitems(struct rogue_state *rs)
|
||||
{
|
||||
THING *list = pack;
|
||||
int32_t type = 0,n = 0,total = 0;
|
||||
for (; list != NULL; list = next(list))
|
||||
{
|
||||
if ( thing_find(list) < 0 )
|
||||
{
|
||||
fprintf(stderr,"num_packitems cant find %p\n",list);
|
||||
return(-1);
|
||||
}
|
||||
if ( list->o_packch != 0 )
|
||||
{
|
||||
n++;
|
||||
total += rogue_total(list);
|
||||
}
|
||||
}
|
||||
if ( rs->guiflag != 0 )
|
||||
{
|
||||
char str[MAXSTR];
|
||||
sprintf(str,"strength*2 %d vs total.%d vs %d inventory letters\n",ROGUE_MAXTOTAL,total,n);
|
||||
add_line(rs,"%s",str);
|
||||
}
|
||||
if ( total > ROGUE_MAXTOTAL )
|
||||
return(MAXPACK);
|
||||
return(n);
|
||||
}
|
||||
|
||||
/*
|
||||
* pack_room:
|
||||
* See if there's room in the pack. If not, print out an
|
||||
* appropriate message
|
||||
*/
|
||||
bool pack_room(struct rogue_state *rs,bool from_floor, THING *obj)
|
||||
{
|
||||
inpack = num_packitems(rs);
|
||||
if ( ++inpack > MAXPACK )
|
||||
{
|
||||
if (!terse)
|
||||
addmsg(rs,"there's ");
|
||||
addmsg(rs,"no room");
|
||||
if (!terse)
|
||||
addmsg(rs," in your pack");
|
||||
endmsg(rs);
|
||||
if (from_floor)
|
||||
move_msg(rs,obj);
|
||||
inpack = MAXPACK;
|
||||
return FALSE;
|
||||
}
|
||||
//fprintf(stderr,"inpack.%d vs MAX.%d\n",inpack,MAXPACK), sleep(2);
|
||||
if ( from_floor != 0 )
|
||||
{
|
||||
detach(lvl_obj, obj);
|
||||
mvaddch(hero.y, hero.x, floor_ch());
|
||||
chat(hero.y, hero.x) = (proom->r_flags & ISGONE) ? PASSAGE : FLOOR;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* leave_pack:
|
||||
* take an item out of the pack
|
||||
*/
|
||||
THING *
|
||||
leave_pack(struct rogue_state *rs,THING *obj, bool newobj, bool all)
|
||||
{
|
||||
THING *nobj;
|
||||
|
||||
inpack--;
|
||||
nobj = obj;
|
||||
if (obj->o_count > 1 && !all)
|
||||
{
|
||||
last_pick = obj;
|
||||
obj->o_count--;
|
||||
if (obj->o_group)
|
||||
inpack++;
|
||||
if (newobj)
|
||||
{
|
||||
nobj = new_item();
|
||||
*nobj = *obj;
|
||||
next(nobj) = NULL;
|
||||
prev(nobj) = NULL;
|
||||
nobj->o_count = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
last_pick = NULL;
|
||||
pack_used[obj->o_packch - 'a'] = FALSE;
|
||||
detach(pack, obj);
|
||||
}
|
||||
return nobj;
|
||||
}
|
||||
|
||||
/*
|
||||
* pack_char:
|
||||
* Return the next unused pack character.
|
||||
*/
|
||||
char
|
||||
pack_char()
|
||||
{
|
||||
bool *bp;
|
||||
|
||||
for (bp = pack_used; *bp; bp++)
|
||||
continue;
|
||||
*bp = TRUE;
|
||||
return (char)((int)(bp - pack_used) + 'a');
|
||||
}
|
||||
|
||||
/*
|
||||
* inventory:
|
||||
* List what is in the pack. Return TRUE if there is something of
|
||||
* the given type.
|
||||
*/
|
||||
|
||||
|
||||
bool
|
||||
inventory(struct rogue_state *rs,THING *list, int type)
|
||||
{
|
||||
char inv_temp[MAXSTR];
|
||||
|
||||
n_objs = 0;
|
||||
for (; list != NULL; list = next(list))
|
||||
{
|
||||
if (type && type != list->o_type && !(type == CALLABLE &&
|
||||
list->o_type != FOOD && list->o_type != AMULET) &&
|
||||
!(type == R_OR_S && (list->o_type == RING || list->o_type == STICK)))
|
||||
continue;
|
||||
n_objs++;
|
||||
#ifdef MASTER
|
||||
if (!list->o_packch)
|
||||
strcpy(inv_temp, "%s");
|
||||
else
|
||||
#endif
|
||||
sprintf(inv_temp, "%c) %%s", list->o_packch);
|
||||
msg_esc = TRUE;
|
||||
if (add_line(rs,inv_temp, inv_name(list, FALSE)) == ESCAPE)
|
||||
{
|
||||
msg_esc = FALSE;
|
||||
msg(rs,"");
|
||||
return TRUE;
|
||||
}
|
||||
msg_esc = FALSE;
|
||||
}
|
||||
//if ( n_objs != inpack )
|
||||
// fprintf(stderr,"n_objs.%d vs inpack.%d\n",n_objs,inpack), sleep(2);
|
||||
if (n_objs == 0)
|
||||
{
|
||||
if (terse)
|
||||
msg(rs,type == 0 ? (char *)"empty handed" : (char *)"nothing appropriate");
|
||||
else
|
||||
msg(rs,type == 0 ? (char *)"you are empty handed" : (char *)"you don't have anything appropriate");
|
||||
return FALSE;
|
||||
}
|
||||
end_line(rs);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* pick_up:
|
||||
* Add something to characters pack.
|
||||
*/
|
||||
|
||||
void
|
||||
pick_up(struct rogue_state *rs,char ch)
|
||||
{
|
||||
THING *obj;
|
||||
|
||||
if (on(player, ISLEVIT))
|
||||
return;
|
||||
|
||||
obj = find_obj(rs,hero.y, hero.x);
|
||||
if (move_on)
|
||||
move_msg(rs,obj);
|
||||
else
|
||||
switch (ch)
|
||||
{
|
||||
case GOLD:
|
||||
if (obj == NULL)
|
||||
return;
|
||||
money(rs,obj->o_goldval);
|
||||
detach(lvl_obj, obj);
|
||||
discard(obj);
|
||||
proom->r_goldval = 0;
|
||||
break;
|
||||
default:
|
||||
#ifdef MASTER
|
||||
debug("Where did you pick a '%s' up???", unctrl(ch));
|
||||
#endif
|
||||
case ARMOR:
|
||||
case POTION:
|
||||
case FOOD:
|
||||
case WEAPON:
|
||||
case SCROLL:
|
||||
case AMULET:
|
||||
case RING:
|
||||
case STICK:
|
||||
add_pack(rs,(THING *) NULL, FALSE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* move_msg:
|
||||
* Print out the message if you are just moving onto an object
|
||||
*/
|
||||
|
||||
void
|
||||
move_msg(struct rogue_state *rs,THING *obj)
|
||||
{
|
||||
if (!terse)
|
||||
addmsg(rs,"you ");
|
||||
msg(rs,"moved onto %s", inv_name(obj, TRUE));
|
||||
}
|
||||
|
||||
/*
|
||||
* picky_inven:
|
||||
* Allow player to inventory a single item
|
||||
*/
|
||||
|
||||
void
|
||||
picky_inven(struct rogue_state *rs)
|
||||
{
|
||||
THING *obj;
|
||||
char mch;
|
||||
|
||||
if (pack == NULL)
|
||||
msg(rs,"you aren't carrying anything");
|
||||
else if (next(pack) == NULL)
|
||||
msg(rs,"a) %s", inv_name(pack, FALSE));
|
||||
else
|
||||
{
|
||||
msg(rs,terse ? (char *)"item: " : (char *)"which item do you wish to inventory: ");
|
||||
mpos = 0;
|
||||
if ((mch = readchar(rs)) == ESCAPE)
|
||||
{
|
||||
msg(rs,"");
|
||||
return;
|
||||
}
|
||||
for (obj = pack; obj != NULL; obj = next(obj))
|
||||
if (mch == obj->o_packch)
|
||||
{
|
||||
msg(rs,"%c) %s", mch, inv_name(obj, FALSE));
|
||||
return;
|
||||
}
|
||||
msg(rs,"'%s' not in pack", unctrl(mch));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* get_item:
|
||||
* Pick something out of a pack for a purpose
|
||||
*/
|
||||
THING *
|
||||
get_item(struct rogue_state *rs,char *purpose, int type)
|
||||
{
|
||||
THING *obj;
|
||||
char ch;
|
||||
|
||||
if (pack == NULL)
|
||||
msg(rs,"you aren't carrying anything");
|
||||
else if (again)
|
||||
if (last_pick)
|
||||
return last_pick;
|
||||
else
|
||||
msg(rs,"you ran out");
|
||||
else
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
if ( rs->replaydone != 0 )
|
||||
return(NULL);
|
||||
if (!terse)
|
||||
addmsg(rs,"which object do you want to ");
|
||||
addmsg(rs,purpose);
|
||||
if (terse)
|
||||
addmsg(rs," what");
|
||||
msg(rs,"? (* for list): ");
|
||||
ch = readchar(rs);
|
||||
mpos = 0;
|
||||
/*
|
||||
* Give the poor player a chance to abort the command
|
||||
*/
|
||||
if (ch == ESCAPE)
|
||||
{
|
||||
reset_last();
|
||||
after = FALSE;
|
||||
msg(rs,"");
|
||||
return NULL;
|
||||
}
|
||||
n_objs = 1; /* normal case: person types one char */
|
||||
if (ch == '*')
|
||||
{
|
||||
mpos = 0;
|
||||
if (inventory(rs,pack, type) == 0)
|
||||
{
|
||||
after = FALSE;
|
||||
return NULL;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
for (obj = pack; obj != NULL; obj = next(obj))
|
||||
if (obj->o_packch == ch)
|
||||
break;
|
||||
if (obj == NULL)
|
||||
{
|
||||
//msg(rs,"'%s' is not a valid item",unctrl(ch));
|
||||
//continue;
|
||||
reset_last();
|
||||
after = FALSE;
|
||||
msg(rs,"'%s' is not a valid item",unctrl(ch));
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* money:
|
||||
* Add or subtract gold from the pack
|
||||
*/
|
||||
|
||||
void
|
||||
money(struct rogue_state *rs,int value)
|
||||
{
|
||||
purse += value;
|
||||
mvaddch(hero.y, hero.x, floor_ch());
|
||||
chat(hero.y, hero.x) = (proom->r_flags & ISGONE) ? PASSAGE : FLOOR;
|
||||
if (value > 0)
|
||||
{
|
||||
if (!terse)
|
||||
addmsg(rs,"you found ");
|
||||
msg(rs,"%d gold pieces", value);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* floor_ch:
|
||||
* Return the appropriate floor character for her room
|
||||
*/
|
||||
char
|
||||
floor_ch()
|
||||
{
|
||||
if (proom->r_flags & ISGONE)
|
||||
return PASSAGE;
|
||||
return (show_floor() ? FLOOR : ' ');
|
||||
}
|
||||
|
||||
/*
|
||||
* floor_at:
|
||||
* Return the character at hero's position, taking see_floor
|
||||
* into account
|
||||
*/
|
||||
char
|
||||
floor_at()
|
||||
{
|
||||
char ch;
|
||||
|
||||
ch = chat(hero.y, hero.x);
|
||||
if (ch == FLOOR)
|
||||
ch = floor_ch();
|
||||
return ch;
|
||||
}
|
||||
|
||||
/*
|
||||
* reset_last:
|
||||
* Reset the last command when the current one is aborted
|
||||
*/
|
||||
|
||||
void
|
||||
reset_last()
|
||||
{
|
||||
last_comm = l_last_comm;
|
||||
last_dir = l_last_dir;
|
||||
last_pick = l_last_pick;
|
||||
}
|
||||
@@ -1,427 +0,0 @@
|
||||
// Copyright (c) 2016-2023 The Hush developers
|
||||
// Distributed under the GPLv3 software license, see the accompanying
|
||||
// file COPYING or https://www.gnu.org/licenses/gpl-3.0.en.html
|
||||
/*
|
||||
* Draw the connecting passages
|
||||
*
|
||||
* @(#)passages.c 4.22 (Berkeley) 02/05/99
|
||||
*
|
||||
* Rogue: Exploring the Dungeons of Doom
|
||||
* Copyright (C) 1980-1983, 1985, 1999 Michael Toy, Ken Arnold and Glenn Wichman
|
||||
* All rights reserved.
|
||||
*
|
||||
* See the file LICENSE.TXT for full copyright and licensing information.
|
||||
*/
|
||||
|
||||
//#include <stdlib.h>
|
||||
//#include <curses.h>
|
||||
#include "rogue.h"
|
||||
|
||||
/*
|
||||
* do_passages:
|
||||
* Draw all the passages on a level.
|
||||
*/
|
||||
|
||||
void
|
||||
do_passages(struct rogue_state *rs)
|
||||
{
|
||||
struct rdes *r1, *r2 = NULL;
|
||||
int i, j;
|
||||
int roomcount;
|
||||
static struct rdes
|
||||
{
|
||||
bool conn[MAXROOMS]; /* possible to connect to room i? */
|
||||
bool isconn[MAXROOMS]; /* connection been made to room i? */
|
||||
bool ingraph; /* this room in graph already? */
|
||||
} rdes[MAXROOMS] = {
|
||||
{ { 0, 1, 0, 1, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },
|
||||
{ { 1, 0, 1, 0, 1, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },
|
||||
{ { 0, 1, 0, 0, 0, 1, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },
|
||||
{ { 1, 0, 0, 0, 1, 0, 1, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },
|
||||
{ { 0, 1, 0, 1, 0, 1, 0, 1, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },
|
||||
{ { 0, 0, 1, 0, 1, 0, 0, 0, 1 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },
|
||||
{ { 0, 0, 0, 1, 0, 0, 0, 1, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },
|
||||
{ { 0, 0, 0, 0, 1, 0, 1, 0, 1 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },
|
||||
{ { 0, 0, 0, 0, 0, 1, 0, 1, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },
|
||||
};
|
||||
|
||||
/*
|
||||
* reinitialize room graph description
|
||||
*/
|
||||
for (r1 = rdes; r1 <= &rdes[MAXROOMS-1]; r1++)
|
||||
{
|
||||
for (j = 0; j < MAXROOMS; j++)
|
||||
r1->isconn[j] = FALSE;
|
||||
r1->ingraph = FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* starting with one room, connect it to a random adjacent room and
|
||||
* then pick a new room to start with.
|
||||
*/
|
||||
roomcount = 1;
|
||||
r1 = &rdes[rnd(MAXROOMS)];
|
||||
r1->ingraph = TRUE;
|
||||
do
|
||||
{
|
||||
/*
|
||||
* find a room to connect with
|
||||
*/
|
||||
j = 0;
|
||||
for (i = 0; i < MAXROOMS; i++)
|
||||
if (r1->conn[i] && !rdes[i].ingraph && rnd(++j) == 0)
|
||||
r2 = &rdes[i];
|
||||
/*
|
||||
* if no adjacent rooms are outside the graph, pick a new room
|
||||
* to look from
|
||||
*/
|
||||
if (j == 0)
|
||||
{
|
||||
do
|
||||
r1 = &rdes[rnd(MAXROOMS)];
|
||||
until (r1->ingraph);
|
||||
}
|
||||
/*
|
||||
* otherwise, connect new room to the graph, and draw a tunnel
|
||||
* to it
|
||||
*/
|
||||
else
|
||||
{
|
||||
r2->ingraph = TRUE;
|
||||
i = (int)(r1 - rdes);
|
||||
j = (int)(r2 - rdes);
|
||||
conn(rs,i, j);
|
||||
r1->isconn[j] = TRUE;
|
||||
r2->isconn[i] = TRUE;
|
||||
roomcount++;
|
||||
}
|
||||
} while (roomcount < MAXROOMS);
|
||||
|
||||
/*
|
||||
* attempt to add passages to the graph a random number of times so
|
||||
* that there isn't always just one unique passage through it.
|
||||
*/
|
||||
for (roomcount = rnd(5); roomcount > 0; roomcount--)
|
||||
{
|
||||
r1 = &rdes[rnd(MAXROOMS)]; /* a random room to look from */
|
||||
/*
|
||||
* find an adjacent room not already connected
|
||||
*/
|
||||
j = 0;
|
||||
for (i = 0; i < MAXROOMS; i++)
|
||||
if (r1->conn[i] && !r1->isconn[i] && rnd(++j) == 0)
|
||||
r2 = &rdes[i];
|
||||
/*
|
||||
* if there is one, connect it and look for the next added
|
||||
* passage
|
||||
*/
|
||||
if (j != 0)
|
||||
{
|
||||
i = (int)(r1 - rdes);
|
||||
j = (int)(r2 - rdes);
|
||||
conn(rs,i, j);
|
||||
r1->isconn[j] = TRUE;
|
||||
r2->isconn[i] = TRUE;
|
||||
}
|
||||
}
|
||||
passnum();
|
||||
}
|
||||
|
||||
/*
|
||||
* conn:
|
||||
* Draw a corridor from a room in a certain direction.
|
||||
*/
|
||||
|
||||
void
|
||||
conn(struct rogue_state *rs,int r1, int r2)
|
||||
{
|
||||
struct room *rpf, *rpt = NULL;
|
||||
int rmt;
|
||||
int distance = 0, turn_spot, turn_distance = 0;
|
||||
int rm;
|
||||
char direc;
|
||||
static coord del, curr, turn_delta, spos, epos;
|
||||
|
||||
if (r1 < r2)
|
||||
{
|
||||
rm = r1;
|
||||
if (r1 + 1 == r2)
|
||||
direc = 'r';
|
||||
else
|
||||
direc = 'd';
|
||||
}
|
||||
else
|
||||
{
|
||||
rm = r2;
|
||||
if (r2 + 1 == r1)
|
||||
direc = 'r';
|
||||
else
|
||||
direc = 'd';
|
||||
}
|
||||
rpf = &rooms[rm];
|
||||
/*
|
||||
* Set up the movement variables, in two cases:
|
||||
* first drawing one down.
|
||||
*/
|
||||
if (direc == 'd')
|
||||
{
|
||||
rmt = rm + 3; /* room # of dest */
|
||||
rpt = &rooms[rmt]; /* room pointer of dest */
|
||||
del.x = 0; /* direction of move */
|
||||
del.y = 1;
|
||||
spos.x = rpf->r_pos.x; /* start of move */
|
||||
spos.y = rpf->r_pos.y;
|
||||
epos.x = rpt->r_pos.x; /* end of move */
|
||||
epos.y = rpt->r_pos.y;
|
||||
if (!(rpf->r_flags & ISGONE)) /* if not gone pick door pos */
|
||||
do
|
||||
{
|
||||
spos.x = rpf->r_pos.x + rnd(rpf->r_max.x - 2) + 1;
|
||||
spos.y = rpf->r_pos.y + rpf->r_max.y - 1;
|
||||
} while ((rpf->r_flags&ISMAZE) && !(flat(spos.y, spos.x)&F_PASS));
|
||||
if (!(rpt->r_flags & ISGONE))
|
||||
do
|
||||
{
|
||||
epos.x = rpt->r_pos.x + rnd(rpt->r_max.x - 2) + 1;
|
||||
} while ((rpt->r_flags&ISMAZE) && !(flat(epos.y, epos.x)&F_PASS));
|
||||
distance = abs(spos.y - epos.y) - 1; /* distance to move */
|
||||
turn_delta.y = 0; /* direction to turn */
|
||||
turn_delta.x = (spos.x < epos.x ? 1 : -1);
|
||||
turn_distance = abs(spos.x - epos.x); /* how far to turn */
|
||||
}
|
||||
else if (direc == 'r') /* setup for moving right */
|
||||
{
|
||||
rmt = rm + 1;
|
||||
rpt = &rooms[rmt];
|
||||
del.x = 1;
|
||||
del.y = 0;
|
||||
spos.x = rpf->r_pos.x;
|
||||
spos.y = rpf->r_pos.y;
|
||||
epos.x = rpt->r_pos.x;
|
||||
epos.y = rpt->r_pos.y;
|
||||
if (!(rpf->r_flags & ISGONE))
|
||||
do
|
||||
{
|
||||
spos.x = rpf->r_pos.x + rpf->r_max.x - 1;
|
||||
spos.y = rpf->r_pos.y + rnd(rpf->r_max.y - 2) + 1;
|
||||
} while ((rpf->r_flags&ISMAZE) && !(flat(spos.y, spos.x)&F_PASS));
|
||||
if (!(rpt->r_flags & ISGONE))
|
||||
do
|
||||
{
|
||||
epos.y = rpt->r_pos.y + rnd(rpt->r_max.y - 2) + 1;
|
||||
} while ((rpt->r_flags&ISMAZE) && !(flat(epos.y, epos.x)&F_PASS));
|
||||
distance = abs(spos.x - epos.x) - 1;
|
||||
turn_delta.y = (spos.y < epos.y ? 1 : -1);
|
||||
turn_delta.x = 0;
|
||||
turn_distance = abs(spos.y - epos.y);
|
||||
}
|
||||
#ifdef MASTER
|
||||
else
|
||||
debug("error in connection tables");
|
||||
#endif
|
||||
|
||||
turn_spot = rnd(distance - 1) + 1; /* where turn starts */
|
||||
|
||||
/*
|
||||
* Draw in the doors on either side of the passage or just put #'s
|
||||
* if the rooms are gone.
|
||||
*/
|
||||
if (!(rpf->r_flags & ISGONE))
|
||||
door(rpf, &spos);
|
||||
else
|
||||
putpass(&spos);
|
||||
if (!(rpt->r_flags & ISGONE))
|
||||
door(rpt, &epos);
|
||||
else
|
||||
putpass(&epos);
|
||||
/*
|
||||
* Get ready to move...
|
||||
*/
|
||||
curr.x = spos.x;
|
||||
curr.y = spos.y;
|
||||
while (distance > 0)
|
||||
{
|
||||
/*
|
||||
* Move to new position
|
||||
*/
|
||||
curr.x += del.x;
|
||||
curr.y += del.y;
|
||||
/*
|
||||
* Check if we are at the turn place, if so do the turn
|
||||
*/
|
||||
if (distance == turn_spot)
|
||||
while (turn_distance--)
|
||||
{
|
||||
putpass(&curr);
|
||||
curr.x += turn_delta.x;
|
||||
curr.y += turn_delta.y;
|
||||
}
|
||||
/*
|
||||
* Continue digging along
|
||||
*/
|
||||
putpass(&curr);
|
||||
distance--;
|
||||
}
|
||||
curr.x += del.x;
|
||||
curr.y += del.y;
|
||||
if (!ce(curr, epos))
|
||||
msg(rs,"warning, connectivity problem on this level");
|
||||
}
|
||||
|
||||
/*
|
||||
* putpass:
|
||||
* add a passage character or secret passage here
|
||||
*/
|
||||
|
||||
void
|
||||
putpass(coord *cp)
|
||||
{
|
||||
PLACE *pp;
|
||||
|
||||
pp = INDEX(cp->y, cp->x);
|
||||
pp->p_flags |= F_PASS;
|
||||
if (rnd(10) + 1 < level && rnd(40) == 0)
|
||||
pp->p_flags &= ~F_REAL;
|
||||
else
|
||||
pp->p_ch = PASSAGE;
|
||||
}
|
||||
|
||||
/*
|
||||
* door:
|
||||
* Add a door or possibly a secret door. Also enters the door in
|
||||
* the exits array of the room.
|
||||
*/
|
||||
|
||||
void
|
||||
door(struct room *rm, coord *cp)
|
||||
{
|
||||
PLACE *pp;
|
||||
|
||||
rm->r_exit[rm->r_nexits++] = *cp;
|
||||
|
||||
if (rm->r_flags & ISMAZE)
|
||||
return;
|
||||
|
||||
pp = INDEX(cp->y, cp->x);
|
||||
if (rnd(10) + 1 < level && rnd(5) == 0)
|
||||
{
|
||||
if (cp->y == rm->r_pos.y || cp->y == rm->r_pos.y + rm->r_max.y - 1)
|
||||
pp->p_ch = '-';
|
||||
else
|
||||
pp->p_ch = '|';
|
||||
pp->p_flags &= ~F_REAL;
|
||||
}
|
||||
else
|
||||
pp->p_ch = DOOR;
|
||||
}
|
||||
|
||||
#ifdef MASTER
|
||||
/*
|
||||
* add_pass:
|
||||
* Add the passages to the current window (wizard command)
|
||||
*/
|
||||
|
||||
void
|
||||
add_pass()
|
||||
{
|
||||
PLACE *pp;
|
||||
int y, x;
|
||||
char ch;
|
||||
|
||||
for (y = 1; y < NUMLINES - 1; y++)
|
||||
for (x = 0; x < NUMCOLS; x++)
|
||||
{
|
||||
pp = INDEX(y, x);
|
||||
if ((pp->p_flags & F_PASS) || pp->p_ch == DOOR ||
|
||||
(!(pp->p_flags&F_REAL) && (pp->p_ch == '|' || pp->p_ch == '-')))
|
||||
{
|
||||
ch = pp->p_ch;
|
||||
if (pp->p_flags & F_PASS)
|
||||
ch = PASSAGE;
|
||||
pp->p_flags |= F_SEEN;
|
||||
move(y, x);
|
||||
if (pp->p_monst != NULL)
|
||||
pp->p_monst->t_oldch = pp->p_ch;
|
||||
else if (pp->p_flags & F_REAL)
|
||||
addch(ch);
|
||||
else
|
||||
{
|
||||
standout();
|
||||
addch((pp->p_flags & F_PASS) ? PASSAGE : DOOR);
|
||||
standend();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* passnum:
|
||||
* Assign a number to each passageway
|
||||
*/
|
||||
static int pnum;
|
||||
static bool newpnum;
|
||||
|
||||
|
||||
void
|
||||
passnum()
|
||||
{
|
||||
struct room *rp;
|
||||
int i;
|
||||
|
||||
pnum = 0;
|
||||
newpnum = FALSE;
|
||||
for (rp = passages; rp < &passages[MAXPASS]; rp++)
|
||||
rp->r_nexits = 0;
|
||||
for (rp = rooms; rp < &rooms[MAXROOMS]; rp++)
|
||||
for (i = 0; i < rp->r_nexits; i++)
|
||||
{
|
||||
newpnum ^= 1;//newpnum++;
|
||||
numpass(rp->r_exit[i].y, rp->r_exit[i].x);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* numpass:
|
||||
* Number a passageway square and its brethren
|
||||
*/
|
||||
|
||||
void
|
||||
numpass(int y, int x)
|
||||
{
|
||||
char *fp;
|
||||
struct room *rp;
|
||||
char ch;
|
||||
|
||||
if (x >= NUMCOLS || x < 0 || y >= NUMLINES || y <= 0)
|
||||
return;
|
||||
fp = &flat(y, x);
|
||||
if (*fp & F_PNUM)
|
||||
return;
|
||||
if (newpnum)
|
||||
{
|
||||
pnum++;
|
||||
newpnum = FALSE;
|
||||
}
|
||||
/*
|
||||
* check to see if it is a door or secret door, i.e., a new exit,
|
||||
* or a numerable type of place
|
||||
*/
|
||||
if ((ch = chat(y, x)) == DOOR ||
|
||||
(!(*fp & F_REAL) && (ch == '|' || ch == '-')))
|
||||
{
|
||||
rp = &passages[pnum];
|
||||
rp->r_exit[rp->r_nexits].y = y;
|
||||
rp->r_exit[rp->r_nexits++].x = x;
|
||||
}
|
||||
else if (!(*fp & F_PASS))
|
||||
return;
|
||||
*fp |= pnum;
|
||||
/*
|
||||
* recurse on the surrounding places
|
||||
*/
|
||||
numpass(y + 1, x);
|
||||
numpass(y - 1, x);
|
||||
numpass(y, x + 1);
|
||||
numpass(y, x - 1);
|
||||
}
|
||||
@@ -1,335 +0,0 @@
|
||||
// Copyright (c) 2016-2023 The Hush developers
|
||||
// Distributed under the GPLv3 software license, see the accompanying
|
||||
// file COPYING or https://www.gnu.org/licenses/gpl-3.0.en.html
|
||||
/*
|
||||
* Function(s) for dealing with potions, mmmmmmmmmm, potionzzzzzzz
|
||||
*
|
||||
* @(#)potions.c 4.46 (Berkeley) 06/07/83
|
||||
*
|
||||
* Rogue: Exploring the Dungeons of Doom
|
||||
* Copyright (C) 1980-1983, 1985, 1999 Michael Toy, Ken Arnold and Glenn Wichman
|
||||
* All rights reserved.
|
||||
*
|
||||
* See the file LICENSE.TXT for full copyright and licensing information.
|
||||
*/
|
||||
|
||||
//#include <curses.h>
|
||||
//#include <ctype.h>
|
||||
#include "rogue.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int pa_flags;
|
||||
void (*pa_daemon)(struct rogue_state *rs,int);
|
||||
int pa_time;
|
||||
char *pa_high, *pa_straight;
|
||||
} PACT;
|
||||
|
||||
static PACT p_actions[] =
|
||||
{
|
||||
{ ISHUH, unconfuse, HUHDURATION, /* P_CONFUSE */
|
||||
"what a tripy feeling!",
|
||||
"wait, what's going on here. Huh? What? Who?" },
|
||||
{ ISHALU, come_down, SEEDURATION, /* P_LSD */
|
||||
"Oh, wow! Everything seems so cosmic!",
|
||||
"Oh, wow! Everything seems so cosmic!" },
|
||||
{ 0, NULL, 0 }, /* P_POISON */
|
||||
{ 0, NULL, 0 }, /* P_STRENGTH */
|
||||
{ CANSEE, unsee, SEEDURATION, /* P_SEEINVIS */
|
||||
prbuf,
|
||||
prbuf },
|
||||
{ 0, NULL, 0 }, /* P_HEALING */
|
||||
{ 0, NULL, 0 }, /* P_MFIND */
|
||||
{ 0, NULL, 0 }, /* P_TFIND */
|
||||
{ 0, NULL, 0 }, /* P_RAISE */
|
||||
{ 0, NULL, 0 }, /* P_XHEAL */
|
||||
{ 0, NULL, 0 }, /* P_HASTE */
|
||||
{ 0, NULL, 0 }, /* P_RESTORE */
|
||||
{ ISBLIND, sight, SEEDURATION, /* P_BLIND */
|
||||
"oh, bummer! Everything is dark! Help!",
|
||||
"a cloak of darkness falls around you" },
|
||||
{ ISLEVIT, land, HEALTIME, /* P_LEVIT */
|
||||
"oh, wow! You're floating in the air!",
|
||||
"you start to float in the air" }
|
||||
};
|
||||
|
||||
/*
|
||||
* quaff:
|
||||
* Quaff a potion from the pack
|
||||
*/
|
||||
|
||||
void quaff(struct rogue_state *rs)
|
||||
{
|
||||
THING *obj, *tp, *mp;
|
||||
bool discardit = FALSE;
|
||||
bool show, trip;
|
||||
|
||||
obj = get_item(rs,"quaff", POTION);
|
||||
/*
|
||||
* Make certain that it is somethings that we want to drink
|
||||
*/
|
||||
if (obj == NULL)
|
||||
return;
|
||||
if (obj->o_type != POTION)
|
||||
{
|
||||
if (!terse)
|
||||
msg(rs,"yuk! Why would you want to drink that?");
|
||||
else
|
||||
msg(rs,"that's undrinkable");
|
||||
return;
|
||||
}
|
||||
if (obj == cur_weapon)
|
||||
cur_weapon = NULL;
|
||||
/*
|
||||
* Calculate the effect it has on the poor guy.
|
||||
*/
|
||||
trip = on(player, ISHALU);
|
||||
discardit = (bool)(obj->o_count == 1);
|
||||
leave_pack(rs,obj, FALSE, FALSE);
|
||||
switch (obj->o_which)
|
||||
{
|
||||
case P_CONFUSE:
|
||||
do_pot(rs,P_CONFUSE, !trip);
|
||||
when P_POISON:
|
||||
pot_info[P_POISON].oi_know = TRUE;
|
||||
if (ISWEARING(R_SUSTSTR))
|
||||
msg(rs,"you feel momentarily sick");
|
||||
else
|
||||
{
|
||||
chg_str(-(rnd(3) + 1));
|
||||
msg(rs,"you feel very sick now");
|
||||
come_down(rs,0);
|
||||
}
|
||||
when P_HEALING:
|
||||
pot_info[P_HEALING].oi_know = TRUE;
|
||||
if ((pstats.s_hpt += roll(pstats.s_lvl, 4)) > max_hp)
|
||||
pstats.s_hpt = ++max_hp;
|
||||
sight(rs,0);
|
||||
msg(rs,"you begin to feel better");
|
||||
when P_STRENGTH:
|
||||
pot_info[P_STRENGTH].oi_know = TRUE;
|
||||
chg_str(1);
|
||||
msg(rs,"you feel stronger, now. What bulging muscles!");
|
||||
when P_MFIND:
|
||||
player.t_flags |= SEEMONST;
|
||||
fuse((void(*)(struct rogue_state *rs,int))turn_see, TRUE, HUHDURATION, AFTER);
|
||||
if (!turn_see(rs,FALSE))
|
||||
msg(rs,"you have a %s feeling for a moment, then it passes",
|
||||
choose_str("normal", "strange"));
|
||||
when P_TFIND:
|
||||
/*
|
||||
* Potion of magic detection. Show the potions and scrolls
|
||||
*/
|
||||
show = FALSE;
|
||||
if (lvl_obj != NULL)
|
||||
{
|
||||
wclear(hw);
|
||||
for (tp = lvl_obj; tp != NULL; tp = next(tp))
|
||||
{
|
||||
if (is_magic(tp))
|
||||
{
|
||||
show = TRUE;
|
||||
wmove(hw, tp->o_pos.y, tp->o_pos.x);
|
||||
waddch(hw, MAGIC);
|
||||
pot_info[P_TFIND].oi_know = TRUE;
|
||||
}
|
||||
}
|
||||
for (mp = mlist; mp != NULL; mp = next(mp))
|
||||
{
|
||||
for (tp = mp->t_pack; tp != NULL; tp = next(tp))
|
||||
{
|
||||
if (is_magic(tp))
|
||||
{
|
||||
show = TRUE;
|
||||
wmove(hw, mp->t_pos.y, mp->t_pos.x);
|
||||
waddch(hw, MAGIC);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (show)
|
||||
{
|
||||
pot_info[P_TFIND].oi_know = TRUE;
|
||||
show_win(rs,"You sense the presence of magic on this level.--More--");
|
||||
}
|
||||
else
|
||||
msg(rs,"you have a %s feeling for a moment, then it passes",
|
||||
choose_str("normal", "strange"));
|
||||
when P_LSD:
|
||||
if (!trip)
|
||||
{
|
||||
if (on(player, SEEMONST))
|
||||
turn_see(rs,FALSE);
|
||||
start_daemon(visuals, 0, BEFORE);
|
||||
seenstairs = seen_stairs();
|
||||
}
|
||||
do_pot(rs,P_LSD, TRUE);
|
||||
when P_SEEINVIS:
|
||||
sprintf(prbuf, "this potion tastes like %s juice", fruit);
|
||||
show = on(player, CANSEE);
|
||||
do_pot(rs,P_SEEINVIS, FALSE);
|
||||
if (!show)
|
||||
invis_on();
|
||||
sight(rs,0);
|
||||
when P_RAISE:
|
||||
pot_info[P_RAISE].oi_know = TRUE;
|
||||
msg(rs,"you suddenly feel much more skillful");
|
||||
raise_level(rs);
|
||||
when P_XHEAL:
|
||||
pot_info[P_XHEAL].oi_know = TRUE;
|
||||
if ((pstats.s_hpt += roll(pstats.s_lvl, 8)) > max_hp)
|
||||
{
|
||||
if (pstats.s_hpt > max_hp + pstats.s_lvl + 1)
|
||||
++max_hp;
|
||||
pstats.s_hpt = ++max_hp;
|
||||
}
|
||||
sight(rs,0);
|
||||
come_down(rs,0);
|
||||
msg(rs,"you begin to feel much better");
|
||||
when P_HASTE:
|
||||
pot_info[P_HASTE].oi_know = TRUE;
|
||||
after = FALSE;
|
||||
if (add_haste(rs,TRUE))
|
||||
msg(rs,"you feel yourself moving much faster");
|
||||
when P_RESTORE:
|
||||
if (ISRING(LEFT, R_ADDSTR))
|
||||
add_str(&pstats.s_str, -cur_ring[LEFT]->o_arm);
|
||||
if (ISRING(RIGHT, R_ADDSTR))
|
||||
add_str(&pstats.s_str, -cur_ring[RIGHT]->o_arm);
|
||||
if (pstats.s_str < max_stats.s_str)
|
||||
pstats.s_str = max_stats.s_str;
|
||||
if (ISRING(LEFT, R_ADDSTR))
|
||||
add_str(&pstats.s_str, cur_ring[LEFT]->o_arm);
|
||||
if (ISRING(RIGHT, R_ADDSTR))
|
||||
add_str(&pstats.s_str, cur_ring[RIGHT]->o_arm);
|
||||
msg(rs,"hey, this tastes great. It make you feel warm all over");
|
||||
when P_BLIND:
|
||||
do_pot(rs,P_BLIND, TRUE);
|
||||
when P_LEVIT:
|
||||
do_pot(rs,P_LEVIT, TRUE);
|
||||
#ifdef MASTER
|
||||
otherwise:
|
||||
msg(rs,"what an odd tasting potion!");
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
status(rs);
|
||||
/*
|
||||
* Throw the item away
|
||||
*/
|
||||
|
||||
call_it(rs,&pot_info[obj->o_which]);
|
||||
|
||||
if (discardit)
|
||||
discard(obj);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* is_magic:
|
||||
* Returns true if an object radiates magic
|
||||
*/
|
||||
bool
|
||||
is_magic(THING *obj)
|
||||
{
|
||||
switch (obj->o_type)
|
||||
{
|
||||
case ARMOR:
|
||||
return (bool)((obj->o_flags&ISPROT) || obj->o_arm != a_class[obj->o_which]);
|
||||
case WEAPON:
|
||||
return (bool)(obj->o_hplus != 0 || obj->o_dplus != 0);
|
||||
case POTION:
|
||||
case SCROLL:
|
||||
case STICK:
|
||||
case RING:
|
||||
case AMULET:
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* invis_on:
|
||||
* Turn on the ability to see invisible
|
||||
*/
|
||||
|
||||
void
|
||||
invis_on()
|
||||
{
|
||||
THING *mp;
|
||||
|
||||
player.t_flags |= CANSEE;
|
||||
for (mp = mlist; mp != NULL; mp = next(mp))
|
||||
if (on(*mp, ISINVIS) && see_monst(mp) && !on(player, ISHALU))
|
||||
mvaddch(mp->t_pos.y, mp->t_pos.x, mp->t_disguise);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* seen_stairs:
|
||||
* Return TRUE if the player has seen the stairs
|
||||
*/
|
||||
bool
|
||||
seen_stairs()
|
||||
{
|
||||
THING *tp;
|
||||
|
||||
move(stairs.y, stairs.x);
|
||||
if (inch() == STAIRS) /* it's on the map */
|
||||
return TRUE;
|
||||
if (ce(hero, stairs)) /* It's under him */
|
||||
return TRUE;
|
||||
|
||||
/*
|
||||
* if a monster is on the stairs, this gets hairy
|
||||
*/
|
||||
if ((tp = moat(stairs.y, stairs.x)) != NULL)
|
||||
{
|
||||
if (see_monst(tp) && on(*tp, ISRUN)) /* if it's visible and awake */
|
||||
return TRUE; /* it must have moved there */
|
||||
|
||||
if (on(player, SEEMONST) /* if she can detect monster */
|
||||
&& tp->t_oldch == STAIRS) /* and there once were stairs */
|
||||
return TRUE; /* it must have moved there */
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* raise_level:
|
||||
* The guy just magically went up a level.
|
||||
*/
|
||||
|
||||
void
|
||||
raise_level(struct rogue_state *rs)
|
||||
{
|
||||
pstats.s_exp = e_levels[pstats.s_lvl-1] + 1L;
|
||||
check_level(rs);
|
||||
}
|
||||
|
||||
/*
|
||||
* do_pot:
|
||||
* Do a potion with standard setup. This means it uses a fuse and
|
||||
* turns on a flag
|
||||
*/
|
||||
|
||||
void
|
||||
do_pot(struct rogue_state *rs,int type, bool knowit)
|
||||
{
|
||||
PACT *pp;
|
||||
int t;
|
||||
|
||||
pp = &p_actions[type];
|
||||
if (!pot_info[type].oi_know)
|
||||
pot_info[type].oi_know = knowit;
|
||||
t = spread(pp->pa_time);
|
||||
if (!on(player, pp->pa_flags))
|
||||
{
|
||||
player.t_flags |= pp->pa_flags;
|
||||
fuse(pp->pa_daemon, 0, t, AFTER);
|
||||
look(rs,FALSE);
|
||||
}
|
||||
else
|
||||
lengthen(pp->pa_daemon, t);
|
||||
msg(rs,choose_str(pp->pa_high, pp->pa_straight));
|
||||
}
|
||||
@@ -1,209 +0,0 @@
|
||||
// Copyright (c) 2016-2023 The Hush developers
|
||||
// Distributed under the GPLv3 software license, see the accompanying
|
||||
// file COPYING or https://www.gnu.org/licenses/gpl-3.0.en.html
|
||||
/*
|
||||
* Routines dealing specifically with rings
|
||||
*
|
||||
* @(#)rings.c 4.19 (Berkeley) 05/29/83
|
||||
*
|
||||
* Rogue: Exploring the Dungeons of Doom
|
||||
* Copyright (C) 1980-1983, 1985, 1999 Michael Toy, Ken Arnold and Glenn Wichman
|
||||
* All rights reserved.
|
||||
*
|
||||
* See the file LICENSE.TXT for full copyright and licensing information.
|
||||
*/
|
||||
|
||||
//#include <curses.h>
|
||||
#include "rogue.h"
|
||||
|
||||
/*
|
||||
* ring_on:
|
||||
* Put a ring on a hand
|
||||
*/
|
||||
|
||||
void
|
||||
ring_on(struct rogue_state *rs)
|
||||
{
|
||||
THING *obj;
|
||||
int ring;
|
||||
|
||||
obj = get_item(rs,"put on", RING);
|
||||
/*
|
||||
* Make certain that it is somethings that we want to wear
|
||||
*/
|
||||
if (obj == NULL)
|
||||
return;
|
||||
if (obj->o_type != RING)
|
||||
{
|
||||
if (!terse)
|
||||
msg(rs,"it would be difficult to wrap that around a finger");
|
||||
else
|
||||
msg(rs,"not a ring");
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* find out which hand to put it on
|
||||
*/
|
||||
if (is_current(rs,obj))
|
||||
return;
|
||||
|
||||
if (cur_ring[LEFT] == NULL && cur_ring[RIGHT] == NULL)
|
||||
{
|
||||
if ((ring = gethand(rs)) < 0)
|
||||
return;
|
||||
}
|
||||
else if (cur_ring[LEFT] == NULL)
|
||||
ring = LEFT;
|
||||
else if (cur_ring[RIGHT] == NULL)
|
||||
ring = RIGHT;
|
||||
else
|
||||
{
|
||||
if (!terse)
|
||||
msg(rs,"you already have a ring on each hand");
|
||||
else
|
||||
msg(rs,"wearing two");
|
||||
return;
|
||||
}
|
||||
cur_ring[ring] = obj;
|
||||
|
||||
/*
|
||||
* Calculate the effect it has on the poor guy.
|
||||
*/
|
||||
switch (obj->o_which)
|
||||
{
|
||||
case R_ADDSTR:
|
||||
chg_str(obj->o_arm);
|
||||
break;
|
||||
case R_SEEINVIS:
|
||||
invis_on();
|
||||
break;
|
||||
case R_AGGR:
|
||||
aggravate(rs);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!terse)
|
||||
addmsg(rs,"you are now wearing ");
|
||||
msg(rs,"%s (%c)", inv_name(obj, TRUE), obj->o_packch);
|
||||
}
|
||||
|
||||
/*
|
||||
* ring_off:
|
||||
* take off a ring
|
||||
*/
|
||||
|
||||
void
|
||||
ring_off(struct rogue_state *rs)
|
||||
{
|
||||
int ring;
|
||||
THING *obj;
|
||||
|
||||
if (cur_ring[LEFT] == NULL && cur_ring[RIGHT] == NULL)
|
||||
{
|
||||
if (terse)
|
||||
msg(rs,"no rings");
|
||||
else
|
||||
msg(rs,"you aren't wearing any rings");
|
||||
return;
|
||||
}
|
||||
else if (cur_ring[LEFT] == NULL)
|
||||
ring = RIGHT;
|
||||
else if (cur_ring[RIGHT] == NULL)
|
||||
ring = LEFT;
|
||||
else
|
||||
if ((ring = gethand(rs)) < 0)
|
||||
return;
|
||||
mpos = 0;
|
||||
obj = cur_ring[ring];
|
||||
if (obj == NULL)
|
||||
{
|
||||
msg(rs,"not wearing such a ring");
|
||||
return;
|
||||
}
|
||||
if (dropcheck(rs,obj))
|
||||
msg(rs,"was wearing %s(%c)", inv_name(obj, TRUE), obj->o_packch);
|
||||
}
|
||||
|
||||
/*
|
||||
* gethand:
|
||||
* Which hand is the hero interested in?
|
||||
*/
|
||||
int
|
||||
gethand(struct rogue_state *rs)
|
||||
{
|
||||
int c;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if ( rs->replaydone != 0 )
|
||||
return(-1);
|
||||
if (terse)
|
||||
msg(rs,"left or right ring? ");
|
||||
else
|
||||
msg(rs,"left hand or right hand? ");
|
||||
if ((c = readchar(rs)) == ESCAPE)
|
||||
return -1;
|
||||
mpos = 0;
|
||||
if (c == 'l' || c == 'L')
|
||||
return LEFT;
|
||||
else if (c == 'r' || c == 'R')
|
||||
return RIGHT;
|
||||
if (terse)
|
||||
msg(rs,"L or R");
|
||||
else
|
||||
msg(rs,"please type L or R");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* ring_eat:
|
||||
* How much food does this ring use up?
|
||||
*/
|
||||
int
|
||||
ring_eat(int hand)
|
||||
{
|
||||
THING *ring;
|
||||
int eat;
|
||||
static int uses[] = {
|
||||
1, /* R_PROTECT */ 1, /* R_ADDSTR */
|
||||
1, /* R_SUSTSTR */ -3, /* R_SEARCH */
|
||||
-5, /* R_SEEINVIS */ 0, /* R_NOP */
|
||||
0, /* R_AGGR */ -3, /* R_ADDHIT */
|
||||
-3, /* R_ADDDAM */ 2, /* R_REGEN */
|
||||
-2, /* R_DIGEST */ 0, /* R_TELEPORT */
|
||||
1, /* R_STEALTH */ 1 /* R_SUSTARM */
|
||||
};
|
||||
|
||||
if ((ring = cur_ring[hand]) == NULL)
|
||||
return 0;
|
||||
if ((eat = uses[ring->o_which]) < 0)
|
||||
eat = (rnd(-eat) == 0);
|
||||
if (ring->o_which == R_DIGEST)
|
||||
eat = -eat;
|
||||
return eat;
|
||||
}
|
||||
|
||||
/*
|
||||
* ring_num:
|
||||
* Print ring bonuses
|
||||
*/
|
||||
char *
|
||||
ring_num(THING *obj)
|
||||
{
|
||||
static char buf[10];
|
||||
|
||||
if (!(obj->o_flags & ISKNOW))
|
||||
return "";
|
||||
switch (obj->o_which)
|
||||
{
|
||||
case R_PROTECT:
|
||||
case R_ADDSTR:
|
||||
case R_ADDDAM:
|
||||
case R_ADDHIT:
|
||||
sprintf(buf, " [%s]", num(obj->o_arm, 0, RING));
|
||||
otherwise:
|
||||
return "";
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
@@ -1,464 +0,0 @@
|
||||
// Copyright (c) 2016-2023 The Hush developers
|
||||
// Distributed under the GPLv3 software license, see the accompanying
|
||||
// file COPYING or https://www.gnu.org/licenses/gpl-3.0.en.html
|
||||
/*
|
||||
* File for the fun ends
|
||||
* Death or a total win
|
||||
*
|
||||
* @(#)rip.c 4.57 (Berkeley) 02/05/99
|
||||
*
|
||||
* Rogue: Exploring the Dungeons of Doom
|
||||
* Copyright (C) 1980-1983, 1985, 1999 Michael Toy, Ken Arnold and Glenn Wichman
|
||||
* All rights reserved.
|
||||
*
|
||||
* See the file LICENSE.TXT for full copyright and licensing information.
|
||||
*/
|
||||
|
||||
//#include <stdlib.h>
|
||||
//#include <string.h>
|
||||
//#include <time.h>
|
||||
#include <signal.h>
|
||||
//#include <sys/types.h>
|
||||
//#include <ctype.h>
|
||||
//#include <fcntl.h>
|
||||
//#include <curses.h>
|
||||
#include "rogue.h"
|
||||
#include "score.h"
|
||||
|
||||
static char *rip[] = {
|
||||
" __________\n",
|
||||
" / \\\n",
|
||||
" / REST \\\n",
|
||||
" / IN \\\n",
|
||||
" / PEACE \\\n",
|
||||
" / \\\n",
|
||||
" | |\n",
|
||||
" | |\n",
|
||||
" | killed by a |\n",
|
||||
" | |\n",
|
||||
" | 1980 |\n",
|
||||
" *| * * * | *\n",
|
||||
" ________)/\\\\_//(\\/(/\\)/\\//\\/|_)_______\n",
|
||||
0
|
||||
};
|
||||
|
||||
/*
|
||||
* score:
|
||||
* Figure score and post it.
|
||||
*/
|
||||
/* VARARGS2 */
|
||||
|
||||
void
|
||||
score(struct rogue_state *rs,int amount, int flags, char monst)
|
||||
{
|
||||
SCORE *scp;
|
||||
int i;
|
||||
SCORE *sc2;
|
||||
SCORE *top_ten, *endp;
|
||||
if ( rs->guiflag == 0 )
|
||||
return;
|
||||
# ifdef MASTER
|
||||
int prflags = 0;
|
||||
# endif
|
||||
void (*fp)(int);
|
||||
unsigned int uid;
|
||||
static char *reason[] = {
|
||||
"killed",
|
||||
"quit",
|
||||
"A total winner",
|
||||
"killed with Amulet"
|
||||
};
|
||||
|
||||
start_score();
|
||||
|
||||
if (flags >= 0
|
||||
#ifdef MASTER
|
||||
|| wizard
|
||||
#endif
|
||||
)
|
||||
{
|
||||
mvaddstr(LINES - 1, 0 , "[Press return to continue]");
|
||||
refresh();
|
||||
wgetnstr(stdscr,prbuf,80);
|
||||
endwin();
|
||||
printf("\n");
|
||||
resetltchars();
|
||||
/*
|
||||
* free up space to "guarantee" there is space for the top_ten
|
||||
*/
|
||||
delwin(stdscr);
|
||||
delwin(curscr);
|
||||
if (hw != NULL)
|
||||
delwin(hw);
|
||||
hw = NULL;
|
||||
}
|
||||
|
||||
top_ten = (SCORE *) malloc(numscores * sizeof (SCORE));
|
||||
endp = &top_ten[numscores];
|
||||
for (scp = top_ten; scp < endp; scp++)
|
||||
{
|
||||
scp->sc_score = 0;
|
||||
for (i = 0; i < MAXSTR; i++)
|
||||
scp->sc_name[i] = (unsigned char) rnd(255);
|
||||
scp->sc_flags = RN;
|
||||
scp->sc_level = RN;
|
||||
scp->sc_monster = (unsigned short) RN;
|
||||
scp->sc_uid = RN;
|
||||
}
|
||||
|
||||
signal(SIGINT, SIG_DFL);
|
||||
|
||||
#ifdef MASTER
|
||||
if (wizard)
|
||||
if (strcmp(prbuf, "names") == 0)
|
||||
prflags = 1;
|
||||
else if (strcmp(prbuf, "edit") == 0)
|
||||
prflags = 2;
|
||||
#endif
|
||||
rd_score(top_ten);
|
||||
/*
|
||||
* Insert her in list if need be
|
||||
*/
|
||||
sc2 = NULL;
|
||||
if (!noscore)
|
||||
{
|
||||
uid = md_getuid();
|
||||
for (scp = top_ten; scp < endp; scp++)
|
||||
if (amount > scp->sc_score)
|
||||
break;
|
||||
else if (!allscore && /* only one score per nowin uid */
|
||||
flags != 2 && scp->sc_uid == uid && scp->sc_flags != 2)
|
||||
scp = endp;
|
||||
if (scp < endp)
|
||||
{
|
||||
if (flags != 2 && !allscore)
|
||||
{
|
||||
for (sc2 = scp; sc2 < endp; sc2++)
|
||||
{
|
||||
if (sc2->sc_uid == uid && sc2->sc_flags != 2)
|
||||
break;
|
||||
}
|
||||
if (sc2 >= endp)
|
||||
sc2 = endp - 1;
|
||||
}
|
||||
else
|
||||
sc2 = endp - 1;
|
||||
while (sc2 > scp)
|
||||
{
|
||||
*sc2 = sc2[-1];
|
||||
sc2--;
|
||||
}
|
||||
scp->sc_score = amount;
|
||||
strncpy(scp->sc_name, whoami, MAXSTR);
|
||||
scp->sc_flags = flags;
|
||||
if (flags == 2)
|
||||
scp->sc_level = max_level;
|
||||
else
|
||||
scp->sc_level = level;
|
||||
scp->sc_monster = monst;
|
||||
scp->sc_uid = uid;
|
||||
sc2 = scp;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Print the list
|
||||
*/
|
||||
if (flags != -1)
|
||||
putchar('\n');
|
||||
printf("Top %s %s:\n", Numname, allscore ? "Scores" : "Rogueists");
|
||||
printf(" Score Name\n");
|
||||
for (scp = top_ten; scp < endp; scp++)
|
||||
{
|
||||
if (scp->sc_score) {
|
||||
if (sc2 == scp)
|
||||
md_raw_standout();
|
||||
printf("%2d %5d %s: %s on level %d", (int) (scp - top_ten + 1),
|
||||
scp->sc_score, scp->sc_name, reason[scp->sc_flags],
|
||||
scp->sc_level);
|
||||
if (scp->sc_flags == 0 || scp->sc_flags == 3)
|
||||
printf(" by %s", killname((char) scp->sc_monster, TRUE));
|
||||
#ifdef MASTER
|
||||
if (prflags == 1)
|
||||
{
|
||||
printf(" (%s)", md_getrealname(scp->sc_uid));
|
||||
}
|
||||
else if (prflags == 2)
|
||||
{
|
||||
fflush(stdout);
|
||||
if ( fgets(prbuf,10,stdin) != 0 )
|
||||
fprintf(stderr,"fgets error\n");
|
||||
if (prbuf[0] == 'd')
|
||||
{
|
||||
for (sc2 = scp; sc2 < endp - 1; sc2++)
|
||||
*sc2 = *(sc2 + 1);
|
||||
sc2 = endp - 1;
|
||||
sc2->sc_score = 0;
|
||||
for (i = 0; i < MAXSTR; i++)
|
||||
sc2->sc_name[i] = (char) rnd(255);
|
||||
sc2->sc_flags = RN;
|
||||
sc2->sc_level = RN;
|
||||
sc2->sc_monster = (unsigned short) RN;
|
||||
scp--;
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif /* MASTER */
|
||||
printf(".");
|
||||
if (sc2 == scp)
|
||||
md_raw_standend();
|
||||
putchar('\n');
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* Update the list file
|
||||
*/
|
||||
if (sc2 != NULL)
|
||||
{
|
||||
if (lock_sc())
|
||||
{
|
||||
fp = signal(SIGINT, SIG_IGN);
|
||||
wr_score(top_ten);
|
||||
unlock_sc();
|
||||
signal(SIGINT, fp);
|
||||
}
|
||||
}
|
||||
free(top_ten);
|
||||
}
|
||||
|
||||
/*
|
||||
* death:
|
||||
* Do something really fun when he dies
|
||||
*/
|
||||
|
||||
void
|
||||
death(struct rogue_state *rs,char monst)
|
||||
{
|
||||
char **dp, *killer;
|
||||
struct tm *lt;
|
||||
static time_t date;
|
||||
//struct tm *localtime(const time_t *);
|
||||
if ( rs->guiflag == 0 )
|
||||
{
|
||||
//fprintf(stderr,"death during replay by (%c)\n",monst); //sleep(3);
|
||||
rs->replaydone = (uint32_t)time(NULL);
|
||||
return;
|
||||
}
|
||||
signal(SIGINT, SIG_IGN);
|
||||
purse -= purse / 10;
|
||||
signal(SIGINT, leave);
|
||||
clear();
|
||||
killer = killname(monst, FALSE);
|
||||
if (!tombstone)
|
||||
{
|
||||
mvprintw(LINES - 2, 0, "Killed by ");
|
||||
killer = killname(monst, FALSE);
|
||||
if (monst != 's' && monst != 'h')
|
||||
printw("a%s ", vowelstr(killer));
|
||||
printw("%s with %d gold", killer, purse);
|
||||
}
|
||||
else
|
||||
{
|
||||
time(&date);
|
||||
lt = localtime(&date);
|
||||
move(8, 0);
|
||||
dp = rip;
|
||||
while (*dp)
|
||||
addstr(*dp++);
|
||||
mvaddstr(17, center(killer), killer);
|
||||
if (monst == 's' || monst == 'h')
|
||||
mvaddch(16, 32, ' ');
|
||||
else
|
||||
mvaddstr(16, 33, vowelstr(killer));
|
||||
mvaddstr(14, center(whoami), whoami);
|
||||
sprintf(prbuf, "%d Au", purse);
|
||||
move(15, center(prbuf));
|
||||
addstr(prbuf);
|
||||
sprintf(prbuf, "%4d", 1900+lt->tm_year);
|
||||
mvaddstr(18, 26, prbuf);
|
||||
}
|
||||
move(LINES - 1, 0);
|
||||
refresh();
|
||||
score(rs,purse, amulet ? 3 : 0, monst);
|
||||
rogue_bailout(rs);
|
||||
printf("[Press return to continue]");
|
||||
fflush(stdout);
|
||||
if ( fgets(prbuf,10,stdin) != 0 )
|
||||
;
|
||||
my_exit(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* center:
|
||||
* Return the index to center the given string
|
||||
*/
|
||||
int
|
||||
center(char *str)
|
||||
{
|
||||
return 28 - (((int)strlen(str) + 1) / 2);
|
||||
}
|
||||
|
||||
/*
|
||||
* total_winner:
|
||||
* Code for a winner
|
||||
*/
|
||||
|
||||
void
|
||||
total_winner(struct rogue_state *rs)
|
||||
{
|
||||
THING *obj;
|
||||
struct obj_info *op;
|
||||
int worth = 0;
|
||||
int oldpurse;
|
||||
|
||||
clear();
|
||||
standout();
|
||||
addstr(" \n");
|
||||
addstr(" @ @ @ @ @ @@@ @ @ \n");
|
||||
addstr(" @ @ @@ @@ @ @ @ @ \n");
|
||||
addstr(" @ @ @@@ @ @ @ @ @ @@@ @@@@ @@@ @ @@@ @ \n");
|
||||
addstr(" @@@@ @ @ @ @ @ @ @ @ @ @ @ @ @ @ \n");
|
||||
addstr(" @ @ @ @ @ @ @ @@@@ @ @ @@@@@ @ @ @ \n");
|
||||
addstr(" @ @ @ @ @ @@ @ @ @ @ @ @ @ @ @ @ \n");
|
||||
addstr(" @@@ @@@ @@ @ @ @ @@@@ @@@@ @@@ @@@ @@ @ \n");
|
||||
addstr(" \n");
|
||||
addstr(" Congratulations, you have made it to the light of day! \n");
|
||||
standend();
|
||||
addstr("\nYou have joined the elite ranks of those who have escaped the\n");
|
||||
addstr("Dungeons of Doom alive. You journey home and sell all your loot at\n");
|
||||
addstr("a great profit and are admitted to the Fighters' Guild.\n");
|
||||
mvaddstr(LINES - 1, 0, "--Press space to continue--");
|
||||
refresh();
|
||||
wait_for(rs,' ');
|
||||
clear();
|
||||
mvaddstr(0, 0, " Worth Item\n");
|
||||
oldpurse = purse;
|
||||
for (obj = pack; obj != NULL; obj = next(obj))
|
||||
{
|
||||
switch (obj->o_type)
|
||||
{
|
||||
case FOOD:
|
||||
worth = 2 * obj->o_count;
|
||||
when WEAPON:
|
||||
worth = weap_info[obj->o_which].oi_worth;
|
||||
worth *= 3 * (obj->o_hplus + obj->o_dplus) + obj->o_count;
|
||||
obj->o_flags |= ISKNOW;
|
||||
when ARMOR:
|
||||
worth = arm_info[obj->o_which].oi_worth;
|
||||
worth += (9 - obj->o_arm) * 100;
|
||||
worth += (10 * (a_class[obj->o_which] - obj->o_arm));
|
||||
obj->o_flags |= ISKNOW;
|
||||
when SCROLL:
|
||||
worth = scr_info[obj->o_which].oi_worth;
|
||||
worth *= obj->o_count;
|
||||
op = &scr_info[obj->o_which];
|
||||
if (!op->oi_know)
|
||||
worth /= 2;
|
||||
op->oi_know = TRUE;
|
||||
when POTION:
|
||||
worth = pot_info[obj->o_which].oi_worth;
|
||||
worth *= obj->o_count;
|
||||
op = &pot_info[obj->o_which];
|
||||
if (!op->oi_know)
|
||||
worth /= 2;
|
||||
op->oi_know = TRUE;
|
||||
when RING:
|
||||
op = &ring_info[obj->o_which];
|
||||
worth = op->oi_worth;
|
||||
if (obj->o_which == R_ADDSTR || obj->o_which == R_ADDDAM ||
|
||||
obj->o_which == R_PROTECT || obj->o_which == R_ADDHIT)
|
||||
{
|
||||
if (obj->o_arm > 0)
|
||||
worth += obj->o_arm * 100;
|
||||
else
|
||||
worth = 10;
|
||||
}
|
||||
if (!(obj->o_flags & ISKNOW))
|
||||
worth /= 2;
|
||||
obj->o_flags |= ISKNOW;
|
||||
op->oi_know = TRUE;
|
||||
when STICK:
|
||||
op = &ws_info[obj->o_which];
|
||||
worth = op->oi_worth;
|
||||
worth += 20 * obj->o_charges;
|
||||
if (!(obj->o_flags & ISKNOW))
|
||||
worth /= 2;
|
||||
obj->o_flags |= ISKNOW;
|
||||
op->oi_know = TRUE;
|
||||
when AMULET:
|
||||
worth = 1000;
|
||||
}
|
||||
if (worth < 0)
|
||||
worth = 0;
|
||||
printw("%c) %5d %s\n", obj->o_packch, worth, inv_name(obj, FALSE));
|
||||
purse += worth;
|
||||
}
|
||||
printw(" %5d Gold Pieces ", oldpurse);
|
||||
refresh();
|
||||
score(rs,purse, 2, ' ');
|
||||
my_exit(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* killname:
|
||||
* Convert a code to a monster name
|
||||
*/
|
||||
char *
|
||||
killname(char monst, bool doart)
|
||||
{
|
||||
struct h_list *hp;
|
||||
char *sp;
|
||||
bool article;
|
||||
static struct h_list nlist[] = {
|
||||
{'a', "arrow", TRUE},
|
||||
{'b', "bolt", TRUE},
|
||||
{'d', "dart", TRUE},
|
||||
{'h', "hypothermia", FALSE},
|
||||
{'s', "starvation", FALSE},
|
||||
{'\0'}
|
||||
};
|
||||
|
||||
if (isupper(monst))
|
||||
{
|
||||
sp = monsters[monst-'A'].m_name;
|
||||
article = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
sp = "Wally the Wonder Badger";
|
||||
article = FALSE;
|
||||
for (hp = nlist; hp->h_ch; hp++)
|
||||
if (hp->h_ch == monst)
|
||||
{
|
||||
sp = hp->h_desc;
|
||||
article = hp->h_print;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (doart && article)
|
||||
sprintf(prbuf, "a%s ", vowelstr(sp));
|
||||
else
|
||||
prbuf[0] = '\0';
|
||||
strcat(prbuf, sp);
|
||||
return prbuf;
|
||||
}
|
||||
|
||||
/*
|
||||
* death_monst:
|
||||
* Return a monster appropriate for a random death.
|
||||
*/
|
||||
char
|
||||
death_monst()
|
||||
{
|
||||
static char poss[] =
|
||||
{
|
||||
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L',
|
||||
'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
|
||||
'Y', 'Z', 'a', 'b', 'h', 'd', 's',
|
||||
' ' /* This is provided to generate the "Wally the Wonder Badger"
|
||||
message for killer */
|
||||
};
|
||||
|
||||
return poss[rnd(sizeof poss / sizeof (char))];
|
||||
}
|
||||
@@ -1,96 +0,0 @@
|
||||
.\"
|
||||
.\" @(#)rogue.6 6.2 (Berkeley) 5/6/86
|
||||
.\"
|
||||
.\" Rogue: Exploring the Dungeons of Doom
|
||||
.\" Copyright (C) 1980-1983, 1985, 1986 Michael Toy, Ken Arnold and Glenn Wichman
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" See the file LICENSE.TXT for full copyright and licensing information.
|
||||
.\"
|
||||
.TH ROGUE 6 "May 6, 1986"
|
||||
.UC 4
|
||||
.SH NAME
|
||||
rogue \- Exploring The Dungeons of Doom
|
||||
.SH SYNOPSIS
|
||||
.B rogue
|
||||
[
|
||||
.B \-r
|
||||
]
|
||||
[
|
||||
.I save_file
|
||||
]
|
||||
[
|
||||
.B \-s
|
||||
]
|
||||
[
|
||||
.B \-d
|
||||
]
|
||||
.SH DESCRIPTION
|
||||
.PP
|
||||
.I Rogue
|
||||
is a computer fantasy game with a new twist. It is crt oriented and the
|
||||
object of the game is to survive the attacks of various monsters and get
|
||||
a lot of gold, rather than the puzzle solving orientation of most computer
|
||||
fantasy games.
|
||||
.PP
|
||||
To get started you really only need to know two commands. The command
|
||||
.B ?
|
||||
will give you a list of the available commands and the command
|
||||
.B /
|
||||
will identify the things you see on the screen.
|
||||
.PP
|
||||
To win the game (as opposed to merely playing to beat other people's high
|
||||
scores) you must locate the Amulet of Yendor which is somewhere below
|
||||
the 20th level of the dungeon and get it out. Nobody has achieved this
|
||||
yet and if somebody does, they will probably go down in history as a hero
|
||||
among heroes.
|
||||
.PP
|
||||
When the game ends, either by your death, when you quit, or if you (by
|
||||
some miracle) manage to win,
|
||||
.I rogue
|
||||
will give you a list of the top-ten scorers. The scoring is based entirely
|
||||
upon how much gold you get. There is a 10% penalty for getting yourself
|
||||
killed.
|
||||
.PP
|
||||
If
|
||||
.I save_file
|
||||
is specified,
|
||||
rogue will be restored from the specified saved game file.
|
||||
If the
|
||||
.B \-r
|
||||
option is used, the save game file is presumed to be the default.
|
||||
.PP
|
||||
The
|
||||
.B \-s
|
||||
option will print out the list of scores.
|
||||
.PP
|
||||
The
|
||||
.B \-d
|
||||
option will kill you and try to add you to the score file.
|
||||
.PP
|
||||
For more detailed directions, read the document
|
||||
.I "A Guide to the Dungeons of Doom."
|
||||
.SH AUTHORS
|
||||
Michael C. Toy,
|
||||
Kenneth C. R. C. Arnold,
|
||||
Glenn Wichman
|
||||
.SH FILES
|
||||
.DT
|
||||
.ta \w'rogue.scr\ \ \ 'u
|
||||
rogue.scr Score file
|
||||
.br
|
||||
\fB~\fP/rogue.save Default save file
|
||||
.SH SEE ALSO
|
||||
Michael C. Toy
|
||||
and
|
||||
Kenneth C. R. C. Arnold,
|
||||
.I "A guide to the Dungeons of Doom"
|
||||
.SH BUGS
|
||||
.PP
|
||||
Probably infinite
|
||||
(although countably infinite).
|
||||
However,
|
||||
that Ice Monsters sometimes transfix you permanently is
|
||||
.I not
|
||||
a bug.
|
||||
It's a feature.
|
||||
@@ -1,96 +0,0 @@
|
||||
.\"
|
||||
.\" @(#)rogue.6 6.2 (Berkeley) 5/6/86
|
||||
.\"
|
||||
.\" Rogue: Exploring the Dungeons of Doom
|
||||
.\" Copyright (C) 1980-1983, 1985, 1986 Michael Toy, Ken Arnold and Glenn Wichman
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" See the file LICENSE.TXT for full copyright and licensing information.
|
||||
.\"
|
||||
.TH ROGUE 6 "May 6, 1986"
|
||||
.UC 4
|
||||
.SH NAME
|
||||
rogue \- Exploring The Dungeons of Doom
|
||||
.SH SYNOPSIS
|
||||
.B @PROGRAM@
|
||||
[
|
||||
.B \-r
|
||||
]
|
||||
[
|
||||
.I save_file
|
||||
]
|
||||
[
|
||||
.B \-s
|
||||
]
|
||||
[
|
||||
.B \-d
|
||||
]
|
||||
.SH DESCRIPTION
|
||||
.PP
|
||||
.I Rogue
|
||||
is a computer fantasy game with a new twist. It is crt oriented and the
|
||||
object of the game is to survive the attacks of various monsters and get
|
||||
a lot of gold, rather than the puzzle solving orientation of most computer
|
||||
fantasy games.
|
||||
.PP
|
||||
To get started you really only need to know two commands. The command
|
||||
.B ?
|
||||
will give you a list of the available commands and the command
|
||||
.B /
|
||||
will identify the things you see on the screen.
|
||||
.PP
|
||||
To win the game (as opposed to merely playing to beat other people's high
|
||||
scores) you must locate the Amulet of Yendor which is somewhere below
|
||||
the 20th level of the dungeon and get it out. Nobody has achieved this
|
||||
yet and if somebody does, they will probably go down in history as a hero
|
||||
among heroes.
|
||||
.PP
|
||||
When the game ends, either by your death, when you quit, or if you (by
|
||||
some miracle) manage to win,
|
||||
.I rogue
|
||||
will give you a list of the top-ten scorers. The scoring is based entirely
|
||||
upon how much gold you get. There is a 10% penalty for getting yourself
|
||||
killed.
|
||||
.PP
|
||||
If
|
||||
.I save_file
|
||||
is specified,
|
||||
rogue will be restored from the specified saved game file.
|
||||
If the
|
||||
.B \-r
|
||||
option is used, the save game file is presumed to be the default.
|
||||
.PP
|
||||
The
|
||||
.B \-s
|
||||
option will print out the list of scores.
|
||||
.PP
|
||||
The
|
||||
.B \-d
|
||||
option will kill you and try to add you to the score file.
|
||||
.PP
|
||||
For more detailed directions, read the document
|
||||
.I "A Guide to the Dungeons of Doom."
|
||||
.SH AUTHORS
|
||||
Michael C. Toy,
|
||||
Kenneth C. R. C. Arnold,
|
||||
Glenn Wichman
|
||||
.SH FILES
|
||||
.DT
|
||||
.ta \w'@SCOREFILE@\ \ \ 'u
|
||||
@SCOREFILE@ Score file
|
||||
.br
|
||||
\fB~\fP/rogue.save Default save file
|
||||
.SH SEE ALSO
|
||||
Michael C. Toy
|
||||
and
|
||||
Kenneth C. R. C. Arnold,
|
||||
.I "A guide to the Dungeons of Doom"
|
||||
.SH BUGS
|
||||
.PP
|
||||
Probably infinite
|
||||
(although countably infinite).
|
||||
However,
|
||||
that Ice Monsters sometimes transfix you permanently is
|
||||
.I not
|
||||
a bug.
|
||||
It's a feature.
|
||||
@@ -1,776 +0,0 @@
|
||||
// Copyright (c) 2016-2023 The Hush developers
|
||||
// Distributed under the GPLv3 software license, see the accompanying
|
||||
// file COPYING or https://www.gnu.org/licenses/gpl-3.0.en.html
|
||||
/*
|
||||
* Rogue: Exploring the Dungeons of Doom
|
||||
* Copyright (C) 1980-1983, 1985, 1999 Michael Toy, Ken Arnold and Glenn Wichman
|
||||
* All rights reserved.
|
||||
*
|
||||
* See the file LICENSE.TXT for full copyright and licensing information.
|
||||
*
|
||||
* @(#)main.c 4.22 (Berkeley) 02/05/99
|
||||
*/
|
||||
|
||||
//#include <stdlib.h>
|
||||
//#include <string.h>
|
||||
#include <signal.h>
|
||||
//#include <unistd.h>
|
||||
//#include <curses.h>
|
||||
|
||||
#include "rogue.h"
|
||||
#ifdef STANDALONE
|
||||
#include "../hush3/src/hush_cJSON.h"
|
||||
#else
|
||||
#include "../../hush_cJSON.h"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* main:
|
||||
* The main program, of course
|
||||
*/
|
||||
struct rogue_state globalR;
|
||||
char Gametxidstr[67];
|
||||
void garbage_collect();
|
||||
|
||||
void purge_obj_guess(struct obj_info *array,int32_t n)
|
||||
{
|
||||
int32_t i;
|
||||
for (i=0; i<n; i++)
|
||||
if ( array[i].oi_guess != 0 )
|
||||
free(array[i].oi_guess), array[i].oi_guess = 0;
|
||||
}
|
||||
|
||||
void rogueiterate(struct rogue_state *rs)
|
||||
{
|
||||
THING *tp;
|
||||
seed = rs->seed;
|
||||
//clear();
|
||||
purge_obj_guess(things,NUMTHINGS);
|
||||
purge_obj_guess(ring_info,MAXRINGS);
|
||||
purge_obj_guess(pot_info,MAXPOTIONS);
|
||||
purge_obj_guess(arm_info,MAXARMORS);
|
||||
purge_obj_guess(scr_info,MAXSCROLLS);
|
||||
purge_obj_guess(weap_info,MAXWEAPONS + 1);
|
||||
purge_obj_guess(ws_info,MAXSTICKS);
|
||||
free_list(player._t._t_pack);
|
||||
for (tp = mlist; tp != NULL; tp = next(tp))
|
||||
free_list(tp->t_pack);
|
||||
free_list(mlist);
|
||||
free_list(lvl_obj);
|
||||
garbage_collect();
|
||||
|
||||
externs_clear();
|
||||
memset(d_list,0,sizeof(d_list));
|
||||
|
||||
memcpy(passages,origpassages,sizeof(passages));
|
||||
memcpy(monsters,origmonsters,sizeof(monsters));
|
||||
memcpy(things,origthings,sizeof(things));
|
||||
|
||||
memcpy(ring_info,origring_info,sizeof(ring_info));
|
||||
memcpy(pot_info,origpot_info,sizeof(pot_info));
|
||||
memcpy(arm_info,origarm_info,sizeof(arm_info));
|
||||
memcpy(scr_info,origscr_info,sizeof(scr_info));
|
||||
memcpy(weap_info,origweap_info,sizeof(weap_info));
|
||||
memcpy(ws_info,origws_info,sizeof(ws_info));
|
||||
|
||||
initscr(); /* Start up cursor package */
|
||||
init_probs(); /* Set up prob tables for objects */
|
||||
init_player(rs); /* Set up initial player stats */
|
||||
init_names(); /* Set up names of scrolls */
|
||||
init_colors(); /* Set up colors of potions */
|
||||
init_stones(); /* Set up stone settings of rings */
|
||||
init_materials(); /* Set up materials of wands */
|
||||
setup();
|
||||
|
||||
/*
|
||||
* The screen must be at least NUMLINES x NUMCOLS
|
||||
*/
|
||||
if (LINES < NUMLINES || COLS < NUMCOLS)
|
||||
{
|
||||
printf("\nSorry, the screen must be at least %dx%d\n", NUMLINES, NUMCOLS);
|
||||
endwin();
|
||||
my_exit(1);
|
||||
}
|
||||
//fprintf(stderr,"LINES %d, COLS %d\n",LINES,COLS);
|
||||
|
||||
// Set up windows
|
||||
if ( hw == NULL )
|
||||
{
|
||||
hw = newwin(LINES, COLS, 0, 0);
|
||||
}
|
||||
idlok(stdscr, TRUE);
|
||||
idlok(hw, TRUE);
|
||||
#ifdef MASTER
|
||||
noscore = wizard;
|
||||
#endif
|
||||
new_level(rs); // Draw current level
|
||||
// Start up daemons and fuses
|
||||
start_daemon(runners, 0, AFTER);
|
||||
start_daemon(doctor, 0, AFTER);
|
||||
fuse(swander, 0, WANDERTIME, AFTER);
|
||||
start_daemon(stomach, 0, AFTER);
|
||||
if ( rs->restoring != 0 )
|
||||
{
|
||||
restore_player(rs);
|
||||
}
|
||||
playit(rs);
|
||||
}
|
||||
|
||||
int32_t roguefname(char *fname,uint64_t seed,int32_t counter)
|
||||
{
|
||||
sprintf(fname,"rogue.%llu.%d",(long long)seed,counter);
|
||||
return(0);
|
||||
}
|
||||
|
||||
int32_t flushkeystrokes_local(struct rogue_state *rs,int32_t waitflag)
|
||||
{
|
||||
#ifndef BUILD_ROGUE
|
||||
char fname[1024]; FILE *fp; int32_t i,retflag = -1;
|
||||
rs->counter++;
|
||||
roguefname(fname,rs->seed,rs->counter);
|
||||
if ( (fp= fopen(fname,"wb")) != 0 )
|
||||
{
|
||||
if ( fwrite(rs->buffered,1,rs->num,fp) == rs->num )
|
||||
{
|
||||
rs->num = 0;
|
||||
retflag = 0;
|
||||
fclose(fp);
|
||||
/*if ( (fp= fopen("savefile","wb")) != 0 )
|
||||
{
|
||||
save_file(rs,fp,0);
|
||||
if ( 0 && (fp= fopen("savefile","rb")) != 0 )
|
||||
{
|
||||
for (i=0; i<0x150; i++)
|
||||
fprintf(stderr,"%02x",fgetc(fp));
|
||||
fprintf(stderr," first part rnd.%d\n",rnd(1000));
|
||||
fclose(fp);
|
||||
}*/
|
||||
roguefname(fname,rs->seed,rs->counter+1);
|
||||
if ( (fp= fopen(fname,"wb")) != 0 ) // truncate next file
|
||||
fclose(fp);
|
||||
//fprintf(stderr,"savefile <- %s retflag.%d\n",fname,retflag);
|
||||
//}
|
||||
} else fprintf(stderr,"error writing (%s)\n",fname);
|
||||
} else fprintf(stderr,"error creating (%s)\n",fname);
|
||||
return(retflag);
|
||||
#else
|
||||
return(0);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef BUILD_ROGUE
|
||||
// stubs for inside daemon
|
||||
|
||||
int32_t rogue_progress(struct rogue_state *rs,int32_t waitflag,uint64_t seed,char *keystrokes,int32_t num)
|
||||
{
|
||||
}
|
||||
|
||||
int32_t rogue_setplayerdata(struct rogue_state *rs,char *gametxidstr)
|
||||
{
|
||||
return(-1);
|
||||
}
|
||||
#endif
|
||||
|
||||
int32_t flushkeystrokes(struct rogue_state *rs,int32_t waitflag)
|
||||
{
|
||||
if ( rs->num > 0 )
|
||||
{
|
||||
if ( rogue_progress(rs,waitflag,rs->seed,rs->buffered,rs->num) > 0 )
|
||||
{
|
||||
flushkeystrokes_local(rs,waitflag);
|
||||
memset(rs->buffered,0,sizeof(rs->buffered));
|
||||
}
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
void rogue_bailout(struct rogue_state *rs)
|
||||
{
|
||||
char cmd[512];
|
||||
flushkeystrokes(rs,1);
|
||||
//sleep(5);
|
||||
return;
|
||||
/*fprintf(stderr,"bailing out\n");
|
||||
sprintf(cmd,"./hush-cli -ac_name=ROGUE cclib bailout 17 \\\"[%%22%s%%22]\\\" >> bailout.log",Gametxidstr);
|
||||
if ( system(cmd) != 0 )
|
||||
fprintf(stderr,"error issuing (%s)\n",cmd);*/
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
#ifdef _MSC_VER
|
||||
#define sleep(x) Sleep(1000*(x))
|
||||
#endif
|
||||
#endif
|
||||
|
||||
int32_t rogue_replay2(uint8_t *newdata,uint64_t seed,char *keystrokes,int32_t num,struct rogue_player *player,int32_t sleepmillis)
|
||||
{
|
||||
struct rogue_state *rs; FILE *fp; int32_t i,n;
|
||||
rs = (struct rogue_state *)calloc(1,sizeof(*rs));
|
||||
rs->seed = seed;
|
||||
rs->keystrokes = keystrokes;
|
||||
rs->numkeys = num;
|
||||
rs->sleeptime = sleepmillis * 1000;
|
||||
if ( player != 0 )
|
||||
{
|
||||
rs->P = *player;
|
||||
rs->restoring = 1;
|
||||
//fprintf(stderr,"restore player packsize.%d HP.%d\n",rs->P.packsize,rs->P.hitpoints);
|
||||
if ( rs->P.packsize > MAXPACK )
|
||||
rs->P.packsize = MAXPACK;
|
||||
}
|
||||
globalR = *rs;
|
||||
uint32_t starttime = (uint32_t)time(NULL);
|
||||
rogueiterate(rs);
|
||||
|
||||
/*
|
||||
// keypress after replay
|
||||
printf("[Press return to continue]");
|
||||
fflush(stdout);
|
||||
if (fgets(prbuf, 10, stdin) != 0);
|
||||
*/
|
||||
|
||||
if ( 0 )
|
||||
{
|
||||
fprintf(stderr,"elapsed %d seconds\n",(uint32_t)time(NULL) - starttime);
|
||||
sleep(2);
|
||||
|
||||
starttime = (uint32_t)time(NULL);
|
||||
for (i=0; i<10000; i++)
|
||||
{
|
||||
memset(rs,0,sizeof(*rs));
|
||||
rs->seed = seed;
|
||||
rs->keystrokes = keystrokes;
|
||||
rs->numkeys = num;
|
||||
rs->sleeptime = 0;
|
||||
rogueiterate(rs);
|
||||
}
|
||||
fprintf(stderr,"elapsed %d seconds\n",(uint32_t)time(NULL)-starttime);
|
||||
sleep(3);
|
||||
}
|
||||
if ( (fp= fopen("checkfile","wb")) != 0 )
|
||||
{
|
||||
save_file(rs,fp,0);
|
||||
//fprintf(stderr,"gold.%d hp.%d strength.%d/%d level.%d exp.%d dungeon.%d data[%d]\n",rs->P.gold,rs->P.hitpoints,rs->P.strength&0xffff,rs->P.strength>>16,rs->P.level,rs->P.experience,rs->P.dungeonlevel,rs->playersize);
|
||||
if ( newdata != 0 && rs->playersize > 0 )
|
||||
memcpy(newdata,rs->playerdata,rs->playersize);
|
||||
}
|
||||
n = rs->playersize;
|
||||
free(rs);
|
||||
return(n);
|
||||
}
|
||||
|
||||
long get_filesize(FILE *fp)
|
||||
{
|
||||
long fsize,fpos = ftell(fp);
|
||||
fseek(fp,0,SEEK_END);
|
||||
fsize = ftell(fp);
|
||||
fseek(fp,fpos,SEEK_SET);
|
||||
return(fsize);
|
||||
}
|
||||
|
||||
char *rogue_keystrokesload(int32_t *numkeysp,uint64_t seed,int32_t counter)
|
||||
{
|
||||
char fname[1024],*keystrokes = 0; FILE *fp; long fsize; int32_t num = 0;
|
||||
*numkeysp = 0;
|
||||
while ( 1 )
|
||||
{
|
||||
roguefname(fname,seed,counter);
|
||||
//printf("check (%s)\n",fname);
|
||||
if ( (fp= fopen(fname,"rb")) == 0 )
|
||||
break;
|
||||
if ( (fsize= get_filesize(fp)) <= 0 )
|
||||
{
|
||||
fclose(fp);
|
||||
//printf("fsize.%ld\n",fsize);
|
||||
break;
|
||||
}
|
||||
if ( (keystrokes= (char *)realloc(keystrokes,num+fsize)) == 0 )
|
||||
{
|
||||
fprintf(stderr,"error reallocating keystrokes\n");
|
||||
fclose(fp);
|
||||
return(0);
|
||||
}
|
||||
if ( fread(&keystrokes[num],1,fsize,fp) != fsize )
|
||||
{
|
||||
fprintf(stderr,"error reading keystrokes from (%s)\n",fname);
|
||||
fclose(fp);
|
||||
free(keystrokes);
|
||||
return(0);
|
||||
}
|
||||
fclose(fp);
|
||||
num += fsize;
|
||||
counter++;
|
||||
//fprintf(stderr,"loaded %ld from (%s) total %d\n",fsize,fname,num);
|
||||
}
|
||||
*numkeysp = num;
|
||||
return(keystrokes);
|
||||
}
|
||||
|
||||
int32_t rogue_replay(uint64_t seed,int32_t sleeptime)
|
||||
{
|
||||
FILE *fp; char fname[1024]; char *keystrokes = 0; long fsize; int32_t i,num=0,counter = 0; struct rogue_state *rs; struct rogue_player P,*player = 0;
|
||||
if ( seed == 0 )
|
||||
seed = 777;
|
||||
keystrokes = rogue_keystrokesload(&num,seed,counter);
|
||||
if ( num > 0 )
|
||||
{
|
||||
sprintf(fname,"rogue.%llu.player",(long long)seed);
|
||||
if ( (fp=fopen(fname,"rb")) != 0 )
|
||||
{
|
||||
if ( fread(&P,1,sizeof(P),fp) > 0 )
|
||||
{
|
||||
//printf("max size player\n");
|
||||
player = &P;
|
||||
}
|
||||
fclose(fp);
|
||||
}
|
||||
rogue_replay2(0,seed,keystrokes,num,player,sleeptime);
|
||||
mvaddstr(LINES - 2, 0, (char *)"replay completed");
|
||||
endwin();
|
||||
my_exit(0);
|
||||
}
|
||||
if ( keystrokes != 0 )
|
||||
free(keystrokes);
|
||||
return(num);
|
||||
}
|
||||
|
||||
int rogue(int argc, char **argv, char **envp)
|
||||
{
|
||||
char *env; int lowtime; struct rogue_state *rs = &globalR;
|
||||
memset(rs,0,sizeof(*rs));
|
||||
rs->guiflag = 1;
|
||||
rs->sleeptime = 1; // non-zero to allow refresh()
|
||||
if ( argc == 3 && strlen(argv[2]) == 64 )
|
||||
{
|
||||
#ifdef _WIN32
|
||||
#ifdef _MSC_VER
|
||||
rs->seed = _strtoui64(argv[1], NULL, 10);
|
||||
#else
|
||||
rs->seed = atol(argv[1]); // windows, but not MSVC
|
||||
#endif // _MSC_VER
|
||||
#else
|
||||
rs->seed = atol(argv[1]); // non-windows
|
||||
#endif // _WIN32
|
||||
strcpy(Gametxidstr,argv[2]);
|
||||
fprintf(stderr,"setplayerdata\n");
|
||||
if ( rogue_setplayerdata(rs,Gametxidstr) < 0 )
|
||||
{
|
||||
fprintf(stderr,"invalid gametxid, or already started\n");
|
||||
return(-1);
|
||||
}
|
||||
} else rs->seed = 777;
|
||||
md_init();
|
||||
|
||||
#ifdef MASTER
|
||||
/*
|
||||
* Check to see if he is a wizard
|
||||
*/
|
||||
if (argc >= 2 && argv[1][0] == '\0')
|
||||
if (strcmp(PASSWD, md_crypt(md_getpass("wizard's password: "), "mT")) == 0)
|
||||
{
|
||||
wizard = TRUE;
|
||||
player.t_flags |= SEEMONST;
|
||||
argv++;
|
||||
argc--;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* get home and options from environment
|
||||
*/
|
||||
|
||||
strncpy(home, md_gethomedir(), MAXSTR);
|
||||
|
||||
strcpy(file_name, home);
|
||||
strcat(file_name, "rogue.save");
|
||||
|
||||
if ((env = getenv("ROGUEOPTS")) != NULL)
|
||||
parse_opts(env);
|
||||
//if (env == NULL || whoami[0] == '\0')
|
||||
// strucpy(whoami, md_getusername(), (int) strlen(md_getusername()));
|
||||
lowtime = (int) time(NULL);
|
||||
#ifdef MASTER
|
||||
if (wizard && getenv("SEED") != NULL)
|
||||
rs->seed = atoi(getenv("SEED"));
|
||||
else
|
||||
#endif
|
||||
//dnum = lowtime + md_getpid();
|
||||
if ( rs != 0 )
|
||||
seed = rs->seed;
|
||||
else seed = 777;
|
||||
//dnum = (int)seed;
|
||||
|
||||
open_score();
|
||||
|
||||
/*
|
||||
* Drop setuid/setgid after opening the scoreboard file.
|
||||
*/
|
||||
|
||||
md_normaluser();
|
||||
|
||||
/*
|
||||
* check for print-score option
|
||||
*/
|
||||
|
||||
md_normaluser(); /* we drop any setgid/setuid priveldges here */
|
||||
|
||||
if (argc == 2)
|
||||
{
|
||||
if (strcmp(argv[1], "-s") == 0)
|
||||
{
|
||||
noscore = TRUE;
|
||||
score(rs,0, -1, 0);
|
||||
exit(0);
|
||||
}
|
||||
else if (strcmp(argv[1], "-d") == 0)
|
||||
{
|
||||
rs->seed = rnd(100); /* throw away some rnd()s to break patterns */
|
||||
while (--rs->seed)
|
||||
rnd(100);
|
||||
purse = rnd(100) + 1;
|
||||
level = rnd(100) + 1;
|
||||
initscr();
|
||||
getltchars();
|
||||
death(rs,death_monst());
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
init_check(); /* check for legal startup */
|
||||
if (argc == 2)
|
||||
if (!restore(rs,argv[1], envp)) /* Note: restore will never return */
|
||||
my_exit(1);
|
||||
#ifdef MASTER
|
||||
if (wizard)
|
||||
printf("Hello %s, welcome to dungeon #%d", whoami, dnum);
|
||||
else
|
||||
#endif
|
||||
printf("Hello %s, just a moment while I dig the dungeon... seed.%llu", whoami,(long long)rs->seed);
|
||||
fflush(stdout);
|
||||
fprintf(stderr,"rogueiterate\n");
|
||||
rogueiterate(rs);
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* endit:
|
||||
* Exit the program abnormally.
|
||||
*/
|
||||
|
||||
void
|
||||
endit(int sig)
|
||||
{
|
||||
NOOP(sig);
|
||||
fatal("Okay, bye bye!\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* fatal:
|
||||
* Exit the program, printing a message.
|
||||
*/
|
||||
|
||||
void
|
||||
fatal(char *s)
|
||||
{
|
||||
mvaddstr(LINES - 2, 0, s);
|
||||
refresh();
|
||||
endwin();
|
||||
my_exit(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* rnd:
|
||||
* Pick a very random number.
|
||||
*/
|
||||
int
|
||||
rnd(int range)
|
||||
{
|
||||
return range == 0 ? 0 : abs((int) RN) % range;
|
||||
}
|
||||
|
||||
/*
|
||||
* roll:
|
||||
* Roll a number of dice
|
||||
*/
|
||||
int
|
||||
roll(int number, int sides)
|
||||
{
|
||||
int dtotal = 0;
|
||||
|
||||
while (number--)
|
||||
dtotal += rnd(sides)+1;
|
||||
return dtotal;
|
||||
}
|
||||
|
||||
/*
|
||||
* tstp:
|
||||
* Handle stop and start signals
|
||||
*/
|
||||
|
||||
void
|
||||
tstp(int ignored)
|
||||
{
|
||||
int y, x;
|
||||
int oy, ox;
|
||||
|
||||
NOOP(ignored);
|
||||
|
||||
/*
|
||||
* leave nicely
|
||||
*/
|
||||
getyx(curscr, oy, ox);
|
||||
mvcur(0, COLS - 1, LINES - 1, 0);
|
||||
endwin();
|
||||
resetltchars();
|
||||
fflush(stdout);
|
||||
md_tstpsignal();
|
||||
|
||||
/*
|
||||
* start back up again
|
||||
*/
|
||||
md_tstpresume();
|
||||
raw();
|
||||
noecho();
|
||||
keypad(stdscr,1);
|
||||
playltchars();
|
||||
clearok(curscr, TRUE);
|
||||
wrefresh(curscr);
|
||||
getyx(curscr, y, x);
|
||||
mvcur(y, x, oy, ox);
|
||||
fflush(stdout);
|
||||
wmove(curscr,oy,ox);
|
||||
/*#ifndef __APPLE__
|
||||
#ifndef BUILD_ROGUE
|
||||
curscr->_cury = oy;
|
||||
curscr->_curx = ox;
|
||||
#endif
|
||||
#endif*/
|
||||
}
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
#ifdef _MSC_VER
|
||||
void usleep(int32_t micros)
|
||||
{
|
||||
if (micros < 1000)
|
||||
Sleep(1);
|
||||
else Sleep(micros / 1000);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* playit:
|
||||
* The main loop of the program. Loop until the game is over,
|
||||
* refreshing things and looking at the proper times.
|
||||
*/
|
||||
|
||||
void
|
||||
playit(struct rogue_state *rs)
|
||||
{
|
||||
char *opts;
|
||||
|
||||
/*
|
||||
* set up defaults for slow terminals
|
||||
*/
|
||||
|
||||
if (baudrate() <= 1200)
|
||||
{
|
||||
terse = TRUE;
|
||||
jump = TRUE;
|
||||
see_floor = FALSE;
|
||||
}
|
||||
|
||||
if (md_hasclreol())
|
||||
inv_type = INV_CLEAR;
|
||||
|
||||
/*
|
||||
* parse environment declaration of options
|
||||
*/
|
||||
if ((opts = getenv("ROGUEOPTS")) != NULL)
|
||||
parse_opts(opts);
|
||||
|
||||
|
||||
oldpos = hero;
|
||||
oldrp = roomin(rs,&hero);
|
||||
while (playing)
|
||||
{
|
||||
command(rs); // Command execution
|
||||
if ( rs->guiflag == 0 )
|
||||
{
|
||||
if ( rs->replaydone != 0 )
|
||||
{
|
||||
if ( 0 && rs->sleeptime != 0 )
|
||||
sleep(3);
|
||||
return;
|
||||
}
|
||||
if ( rs->sleeptime != 0 )
|
||||
usleep(rs->sleeptime);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( rs->needflush != 0 )
|
||||
{
|
||||
if ( flushkeystrokes(rs,0) == 0 )
|
||||
rs->needflush = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( rs->guiflag != 0 )
|
||||
flushkeystrokes(rs,1);
|
||||
endit(0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int32_t _quit()
|
||||
{
|
||||
struct rogue_state *rs = &globalR;
|
||||
int oy, ox, c;
|
||||
//fprintf(stderr,"inside quit(%d)\n",sig);
|
||||
getyx(curscr, oy, ox);
|
||||
msg(rs,"really quit?");
|
||||
//sleep(1);
|
||||
if ( (c= readchar(rs)) == 'y')
|
||||
{
|
||||
if ( rs->guiflag != 0 )
|
||||
{
|
||||
signal(SIGINT, leave);
|
||||
clear();
|
||||
mvprintw(LINES - 2, 0, "You quit with %d gold pieces", purse);
|
||||
move(LINES - 1, 0);
|
||||
if ( rs->sleeptime != 0 )
|
||||
refresh();
|
||||
score(rs,purse, 1, 0);
|
||||
flushkeystrokes(rs,1);
|
||||
my_exit(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
//score(rs,purse, 1, 0);
|
||||
//fprintf(stderr,"done! (%c)\n",c);
|
||||
}
|
||||
return(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
//fprintf(stderr,"'Q' answer (%c)\n",c);
|
||||
move(0, 0);
|
||||
clrtoeol();
|
||||
status(rs);
|
||||
move(oy, ox);
|
||||
if ( rs->sleeptime != 0 )
|
||||
refresh();
|
||||
mpos = 0;
|
||||
count = 0;
|
||||
to_death = FALSE;
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* quit:
|
||||
* Have player make certain, then exit.
|
||||
*/
|
||||
|
||||
void quit(int sig)
|
||||
{
|
||||
struct rogue_state *rs = &globalR;
|
||||
int oy, ox, c;
|
||||
//fprintf(stderr,"inside quit(%d)\n",sig);
|
||||
if ( rs->guiflag != 0 )
|
||||
{
|
||||
NOOP(sig);
|
||||
|
||||
/*
|
||||
* Reset the signal in case we got here via an interrupt
|
||||
*/
|
||||
if (!q_comm)
|
||||
mpos = 0;
|
||||
}
|
||||
_quit();
|
||||
}
|
||||
|
||||
/*
|
||||
* leave:
|
||||
* Leave quickly, but curteously
|
||||
*/
|
||||
|
||||
void
|
||||
leave(int sig)
|
||||
{
|
||||
static char buf[BUFSIZ];
|
||||
|
||||
NOOP(sig);
|
||||
|
||||
setbuf(stdout, buf); /* throw away pending output */
|
||||
|
||||
if (!isendwin())
|
||||
{
|
||||
mvcur(0, COLS - 1, LINES - 1, 0);
|
||||
endwin();
|
||||
}
|
||||
|
||||
putchar('\n');
|
||||
my_exit(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* shell:
|
||||
* Let them escape for a while
|
||||
*/
|
||||
|
||||
void
|
||||
shell(struct rogue_state *rs)
|
||||
{
|
||||
if ( rs != 0 && rs->guiflag != 0 )
|
||||
{
|
||||
/*
|
||||
* Set the terminal back to original mode
|
||||
*/
|
||||
move(LINES-1, 0);
|
||||
refresh();
|
||||
endwin();
|
||||
resetltchars();
|
||||
putchar('\n');
|
||||
in_shell = TRUE;
|
||||
after = FALSE;
|
||||
fflush(stdout);
|
||||
/*
|
||||
* Fork and do a shell
|
||||
*/
|
||||
md_shellescape();
|
||||
|
||||
printf("\n[Press return to continue]");
|
||||
fflush(stdout);
|
||||
noecho();
|
||||
raw();
|
||||
keypad(stdscr,1);
|
||||
playltchars();
|
||||
in_shell = FALSE;
|
||||
wait_for(rs,'\n');
|
||||
clearok(stdscr, TRUE);
|
||||
}
|
||||
else fprintf(stderr,"no shell in the blockchain\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* my_exit:
|
||||
* Leave the process properly
|
||||
*/
|
||||
|
||||
void
|
||||
my_exit(int st)
|
||||
{
|
||||
uint32_t counter;
|
||||
resetltchars();
|
||||
if ( globalR.guiflag != 0 || globalR.sleeptime != 0 )
|
||||
exit(st);
|
||||
else if ( counter++ < 10 )
|
||||
{
|
||||
fprintf(stderr,"would have exit.(%d) sleeptime.%d\n",st,globalR.sleeptime);
|
||||
globalR.replaydone = 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,61 +0,0 @@
|
||||
ROGUE(6) ROGUE(6)
|
||||
|
||||
|
||||
|
||||
NAME
|
||||
rogue - Exploring The Dungeons of Doom
|
||||
|
||||
SYNOPSIS
|
||||
rogue [ -r ] [ save_file ] [ -s ] [ -d ]
|
||||
|
||||
DESCRIPTION
|
||||
Rogue is a computer fantasy game with a new twist. It is crt oriented
|
||||
and the object of the game is to survive the attacks of various mon-
|
||||
sters and get a lot of gold, rather than the puzzle solving orientation
|
||||
of most computer fantasy games.
|
||||
|
||||
To get started you really only need to know two commands. The command
|
||||
? will give you a list of the available commands and the command /
|
||||
will identify the things you see on the screen.
|
||||
|
||||
To win the game (as opposed to merely playing to beat other people's
|
||||
high scores) you must locate the Amulet of Yendor which is somewhere
|
||||
below the 20th level of the dungeon and get it out. Nobody has
|
||||
achieved this yet and if somebody does, they will probably go down in
|
||||
history as a hero among heroes.
|
||||
|
||||
When the game ends, either by your death, when you quit, or if you (by
|
||||
some miracle) manage to win, rogue will give you a list of the top-ten
|
||||
scorers. The scoring is based entirely upon how much gold you get.
|
||||
There is a 10% penalty for getting yourself killed.
|
||||
|
||||
If save_file is specified, rogue will be restored from the specified
|
||||
saved game file. If the -r option is used, the save game file is pre-
|
||||
sumed to be the default.
|
||||
|
||||
The -s option will print out the list of scores.
|
||||
|
||||
The -d option will kill you and try to add you to the score file.
|
||||
|
||||
For more detailed directions, read the document A Guide to the Dungeons
|
||||
of Doom.
|
||||
|
||||
AUTHORS
|
||||
Michael C. Toy, Kenneth C. R. C. Arnold, Glenn Wichman
|
||||
|
||||
FILES
|
||||
rogue.scr Score file
|
||||
~/rogue.save Default save file
|
||||
|
||||
SEE ALSO
|
||||
Michael C. Toy and Kenneth C. R. C. Arnold, A guide to the Dungeons of
|
||||
Doom
|
||||
|
||||
BUGS
|
||||
Probably infinite (although countably infinite). However, that Ice
|
||||
Monsters sometimes transfix you permanently is not a bug. It's a fea-
|
||||
ture.
|
||||
|
||||
|
||||
|
||||
4th Berkeley Distribution May 6, 1986 ROGUE(6)
|
||||
@@ -1,61 +0,0 @@
|
||||
ROGUE(6) ROGUE(6)
|
||||
|
||||
|
||||
|
||||
NAME
|
||||
rogue - Exploring The Dungeons of Doom
|
||||
|
||||
SYNOPSIS
|
||||
@PROGRAM@ [ -r ] [ save_file ] [ -s ] [ -d ]
|
||||
|
||||
DESCRIPTION
|
||||
Rogue is a computer fantasy game with a new twist. It is crt oriented
|
||||
and the object of the game is to survive the attacks of various mon-
|
||||
sters and get a lot of gold, rather than the puzzle solving orientation
|
||||
of most computer fantasy games.
|
||||
|
||||
To get started you really only need to know two commands. The command
|
||||
? will give you a list of the available commands and the command /
|
||||
will identify the things you see on the screen.
|
||||
|
||||
To win the game (as opposed to merely playing to beat other people's
|
||||
high scores) you must locate the Amulet of Yendor which is somewhere
|
||||
below the 20th level of the dungeon and get it out. Nobody has
|
||||
achieved this yet and if somebody does, they will probably go down in
|
||||
history as a hero among heroes.
|
||||
|
||||
When the game ends, either by your death, when you quit, or if you (by
|
||||
some miracle) manage to win, rogue will give you a list of the top-ten
|
||||
scorers. The scoring is based entirely upon how much gold you get.
|
||||
There is a 10% penalty for getting yourself killed.
|
||||
|
||||
If save_file is specified, rogue will be restored from the specified
|
||||
saved game file. If the -r option is used, the save game file is pre-
|
||||
sumed to be the default.
|
||||
|
||||
The -s option will print out the list of scores.
|
||||
|
||||
The -d option will kill you and try to add you to the score file.
|
||||
|
||||
For more detailed directions, read the document A Guide to the Dungeons
|
||||
of Doom.
|
||||
|
||||
AUTHORS
|
||||
Michael C. Toy, Kenneth C. R. C. Arnold, Glenn Wichman
|
||||
|
||||
FILES
|
||||
@SCOREFILE@ Score file
|
||||
~/rogue.save Default save file
|
||||
|
||||
SEE ALSO
|
||||
Michael C. Toy and Kenneth C. R. C. Arnold, A guide to the Dungeons of
|
||||
Doom
|
||||
|
||||
BUGS
|
||||
Probably infinite (although countably infinite). However, that Ice
|
||||
Monsters sometimes transfix you permanently is not a bug. It's a fea-
|
||||
ture.
|
||||
|
||||
|
||||
|
||||
4th Berkeley Distribution May 6, 1986 ROGUE(6)
|
||||
@@ -1,11 +0,0 @@
|
||||
[Desktop Entry]
|
||||
Encoding=UTF-8
|
||||
Name=Rogue
|
||||
GenericName=Rogue
|
||||
Comment=The original curses-based adventure game
|
||||
Exec=rogue
|
||||
Icon=rogue.png
|
||||
Terminal=true
|
||||
Type=Application
|
||||
Categories=Game;RolePlaying;
|
||||
Version=1.0
|
||||
@@ -1,858 +0,0 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
A Guide to the Dungeons of Doom
|
||||
|
||||
|
||||
Michael C. Toy
|
||||
Kenneth C. R. C. Arnold
|
||||
|
||||
|
||||
Computer Systems Research Group
|
||||
Department of Electrical Engineering and Computer Science
|
||||
University of California
|
||||
Berkeley, California 94720
|
||||
|
||||
|
||||
|
||||
|
||||
ABSTRACT
|
||||
|
||||
Rogue is a visual CRT based fantasy game which runs
|
||||
under the UNIX timesharing system. This paper de-
|
||||
scribes how to play rogue, and gives a few hints for
|
||||
those who might otherwise get lost in the Dungeons
|
||||
of Doom.
|
||||
|
||||
|
||||
|
||||
|
||||
1. Introduction
|
||||
|
||||
You have just finished your years as a student at the
|
||||
local fighter's guild. After much practice and sweat you
|
||||
have finally completed your training and are ready to embark
|
||||
upon a perilous adventure. As a test of your skills, the
|
||||
local guildmasters have sent you into the Dungeons of Doom.
|
||||
Your task is to return with the Amulet of Yendor. Your
|
||||
reward for the completion of this task will be a full mem-
|
||||
bership in the local guild. In addition, you are allowed to
|
||||
keep all the loot you bring back from the dungeons.
|
||||
|
||||
In preparation for your journey, you are given an
|
||||
enchanted mace, a bow, and a quiver of arrows taken from a
|
||||
dragon's hoard in the far off Dark Mountains. You are also
|
||||
outfitted with elf-crafted armor and given enough food to
|
||||
reach the dungeons. You say goodbye to family and friends
|
||||
for what may be the last time and head up the road.
|
||||
|
||||
You set out on your way to the dungeons and after sev-
|
||||
eral days of uneventful travel, you see the ancient ruins
|
||||
that mark the entrance to the Dungeons of Doom. It is late
|
||||
at night, so you make camp at the entrance and spend the
|
||||
____________________
|
||||
UNIX is a trademark of Bell Laboratories
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
USD:33-2 A Guide to the Dungeons of Doom
|
||||
|
||||
|
||||
night sleeping under the open skies. In the morning you
|
||||
gather your weapons, put on your armor, eat what is almost
|
||||
your last food, and enter the dungeons.
|
||||
|
||||
2. What is going on here?
|
||||
|
||||
You have just begun a game of rogue. Your goal is to
|
||||
grab as much treasure as you can, find the Amulet of Yendor,
|
||||
and get out of the Dungeons of Doom alive. On the screen, a
|
||||
map of where you have been and what you have seen on the
|
||||
current dungeon level is kept. As you explore more of the
|
||||
level, it appears on the screen in front of you.
|
||||
|
||||
Rogue differs from most computer fantasy games in that
|
||||
it is screen oriented. Commands are all one or two
|
||||
keystrokes1 and the results of your commands are displayed
|
||||
graphically on the screen rather than being explained in
|
||||
words.2
|
||||
|
||||
Another major difference between rogue and other com-
|
||||
puter fantasy games is that once you have solved all the
|
||||
puzzles in a standard fantasy game, it has lost most of its
|
||||
excitement and it ceases to be fun. Rogue, on the other
|
||||
hand, generates a new dungeon every time you play it and
|
||||
even the author finds it an entertaining and exciting game.
|
||||
|
||||
3. What do all those things on the screen mean?
|
||||
|
||||
In order to understand what is going on in rogue you
|
||||
have to first get some grasp of what rogue is doing with the
|
||||
screen. The rogue screen is intended to replace the "You
|
||||
can see ..." descriptions of standard fantasy games. Figure
|
||||
1 is a sample of what a rogue screen might look like.
|
||||
|
||||
3.1. The bottom line
|
||||
|
||||
At the bottom line of the screen are a few pieces of
|
||||
cryptic information describing your current status. Here is
|
||||
an explanation of what these things mean:
|
||||
|
||||
Level This number indicates how deep you have gone in the
|
||||
dungeon. It starts at one and goes up as you go
|
||||
deeper into the dungeon.
|
||||
|
||||
Gold The number of gold pieces you have managed to find
|
||||
and keep with you so far.
|
||||
____________________
|
||||
1 As opposed to pseudo English sentences.
|
||||
2 A minimum screen size of 24 lines by 80 columns is re-
|
||||
quired. If the screen is larger, only the 24x80 section
|
||||
will be used for the map.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
A Guide to the Dungeons of Doom USD:33-3
|
||||
|
||||
|
||||
|
||||
____________________________________________________________
|
||||
|
||||
|
||||
------------
|
||||
|..........+
|
||||
|..@....]..|
|
||||
|....B.....|
|
||||
|..........|
|
||||
-----+------
|
||||
|
||||
|
||||
|
||||
Level: 1 Gold: 0 Hp: 12(12) Str: 16(16) Arm: 4 Exp: 1/0
|
||||
|
||||
Figure 1
|
||||
____________________________________________________________
|
||||
|
||||
|
||||
Hp Your current and maximum health points. Health
|
||||
points indicate how much damage you can take before
|
||||
you die. The more you get hit in a fight, the lower
|
||||
they get. You can regain health points by resting.
|
||||
The number in parentheses is the maximum number your
|
||||
health points can reach.
|
||||
|
||||
Str Your current strength and maximum ever strength.
|
||||
This can be any integer less than or equal to 31, or
|
||||
greater than or equal to three. The higher the num-
|
||||
ber, the stronger you are. The number in the paren-
|
||||
theses is the maximum strength you have attained so
|
||||
far this game.
|
||||
|
||||
Arm Your current armor protection. This number indicates
|
||||
how effective your armor is in stopping blows from
|
||||
unfriendly creatures. The higher this number is, the
|
||||
more effective the armor.
|
||||
|
||||
Exp These two numbers give your current experience level
|
||||
and experience points. As you do things, you gain
|
||||
experience points. At certain experience point
|
||||
totals, you gain an experience level. The more expe-
|
||||
rienced you are, the better you are able to fight and
|
||||
to withstand magical attacks.
|
||||
|
||||
3.2. The top line
|
||||
|
||||
The top line of the screen is reserved for printing
|
||||
messages that describe things that are impossible to repre-
|
||||
sent visually. If you see a "--More--" on the top line,
|
||||
this means that rogue wants to print another message on the
|
||||
screen, but it wants to make certain that you have read the
|
||||
one that is there first. To read the next message, just
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
USD:33-4 A Guide to the Dungeons of Doom
|
||||
|
||||
|
||||
type a space.
|
||||
|
||||
3.3. The rest of the screen
|
||||
|
||||
The rest of the screen is the map of the level as you
|
||||
have explored it so far. Each symbol on the screen repre-
|
||||
sents something. Here is a list of what the various symbols
|
||||
mean:
|
||||
|
||||
@ This symbol represents you, the adventurer.
|
||||
|
||||
-| These symbols represent the walls of rooms.
|
||||
|
||||
+ A door to/from a room.
|
||||
|
||||
. The floor of a room.
|
||||
|
||||
# The floor of a passage between rooms.
|
||||
|
||||
* A pile or pot of gold.
|
||||
|
||||
) A weapon of some sort.
|
||||
|
||||
] A piece of armor.
|
||||
|
||||
! A flask containing a magic potion.
|
||||
|
||||
? A piece of paper, usually a magic scroll.
|
||||
|
||||
= A ring with magic properties
|
||||
|
||||
/ A magical staff or wand
|
||||
|
||||
^ A trap, watch out for these.
|
||||
|
||||
% A staircase to other levels
|
||||
|
||||
: A piece of food.
|
||||
|
||||
A-Z The uppercase letters represent the various inhabitants
|
||||
of the Dungeons of Doom. Watch out, they can be nasty
|
||||
and vicious.
|
||||
|
||||
4. Commands
|
||||
|
||||
Commands are given to rogue by typing one or two char-
|
||||
acters. Most commands can be preceded by a count to repeat
|
||||
them (e.g. typing "10s" will do ten searches). Commands for
|
||||
which counts make no sense have the count ignored. To can-
|
||||
cel a count or a prefix, type <ESCAPE>. The list of com-
|
||||
mands is rather long, but it can be read at any time during
|
||||
the game with the "?" command. Here it is for reference,
|
||||
with a short explanation of each command.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
A Guide to the Dungeons of Doom USD:33-5
|
||||
|
||||
|
||||
? The help command. Asks for a character to give help
|
||||
on. If you type a "*", it will list all the commands,
|
||||
otherwise it will explain what the character you typed
|
||||
does.
|
||||
|
||||
/ This is the "What is that on the screen?" command. A
|
||||
"/" followed by any character that you see on the
|
||||
level, will tell you what that character is. For
|
||||
instance, typing "/@" will tell you that the "@" symbol
|
||||
represents you, the player.
|
||||
|
||||
h, H, ^H
|
||||
Move left. You move one space to the left. If you use
|
||||
upper case "h", you will continue to move left until
|
||||
you run into something. This works for all movement
|
||||
commands (e.g. "L" means run in direction "l") If you
|
||||
use the "control" "h", you will continue moving in the
|
||||
specified direction until you pass something interest-
|
||||
ing or run into a wall. You should experiment with
|
||||
this, since it is a very useful command, but very dif-
|
||||
ficult to describe. This also works for all movement
|
||||
commands.
|
||||
|
||||
j Move down.
|
||||
|
||||
k Move up.
|
||||
|
||||
l Move right.
|
||||
|
||||
y Move diagonally up and left.
|
||||
|
||||
u Move diagonally up and right.
|
||||
|
||||
b Move diagonally down and left.
|
||||
|
||||
n Move diagonally down and right.
|
||||
|
||||
t Throw an object. This is a prefix command. When fol-
|
||||
lowed with a direction it throws an object in the spec-
|
||||
ified direction. (e.g. type "th" to throw something to
|
||||
the left.)
|
||||
|
||||
f Fight until someone dies. When followed with a direc-
|
||||
tion this will force you to fight the creature in that
|
||||
direction until either you or it bites the big one.
|
||||
|
||||
m Move onto something without picking it up. This will
|
||||
move you one space in the direction you specify and, if
|
||||
there is an object there you can pick up, it won't do
|
||||
it.
|
||||
|
||||
z Zap prefix. Point a staff or wand in a given direction
|
||||
and fire it. Even non-directional staves must be
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
USD:33-6 A Guide to the Dungeons of Doom
|
||||
|
||||
|
||||
pointed in some direction to be used.
|
||||
|
||||
^ Identify trap command. If a trap is on your map and
|
||||
you can't remember what type it is, you can get rogue
|
||||
to remind you by getting next to it and typing "^" fol-
|
||||
lowed by the direction that would move you on top of
|
||||
it.
|
||||
|
||||
s Search for traps and secret doors. Examine each space
|
||||
immediately adjacent to you for the existence of a trap
|
||||
or secret door. There is a large chance that even if
|
||||
there is something there, you won't find it, so you
|
||||
might have to search a while before you find something.
|
||||
|
||||
> Climb down a staircase to the next level. Not surpris-
|
||||
ingly, this can only be done if you are standing on
|
||||
staircase.
|
||||
|
||||
< Climb up a staircase to the level above. This can't be
|
||||
done without the Amulet of Yendor in your possession.
|
||||
|
||||
. Rest. This is the "do nothing" command. This is good
|
||||
for waiting and healing.
|
||||
|
||||
, Pick up something. This picks up whatever you are cur-
|
||||
rently standing on, if you are standing on anything at
|
||||
all.
|
||||
|
||||
i Inventory. List what you are carrying in your pack.
|
||||
|
||||
I Selective inventory. Tells you what a single item in
|
||||
your pack is.
|
||||
|
||||
q Quaff one of the potions you are carrying.
|
||||
|
||||
r Read one of the scrolls in your pack.
|
||||
|
||||
e Eat food from your pack.
|
||||
|
||||
w Wield a weapon. Take a weapon out of your pack and
|
||||
carry it for use in combat, replacing the one you are
|
||||
currently using (if any).
|
||||
|
||||
W Wear armor. You can only wear one suit of armor at a
|
||||
time. This takes extra time.
|
||||
|
||||
T Take armor off. You can't remove armor that is cursed.
|
||||
This takes extra time.
|
||||
|
||||
P Put on a ring. You can wear only two rings at a time
|
||||
(one on each hand). If you aren't wearing any rings,
|
||||
this command will ask you which hand you want to wear
|
||||
it on, otherwise, it will place it on the unused hand.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
A Guide to the Dungeons of Doom USD:33-7
|
||||
|
||||
|
||||
The program assumes that you wield your sword in your
|
||||
right hand.
|
||||
|
||||
R Remove a ring. If you are only wearing one ring, this
|
||||
command takes it off. If you are wearing two, it will
|
||||
ask you which one you wish to remove,
|
||||
|
||||
d Drop an object. Take something out of your pack and
|
||||
leave it lying on the floor. Only one object can
|
||||
occupy each space. You cannot drop a cursed object at
|
||||
all if you are wielding or wearing it.
|
||||
|
||||
c Call an object something. If you have a type of object
|
||||
in your pack which you wish to remember something
|
||||
about, you can use the call command to give a name to
|
||||
that type of object. This is usually used when you
|
||||
figure out what a potion, scroll, ring, or staff is
|
||||
after you pick it up, or when you want to remember
|
||||
which of those swords in your pack you were wielding.
|
||||
|
||||
D Print out which things you've discovered something
|
||||
about. This command will ask you what type of thing
|
||||
you are interested in. If you type the character for a
|
||||
given type of object (e.g. "!" for potion) it will
|
||||
tell you which kinds of that type of object you've dis-
|
||||
covered (i.e., figured out what they are). This com-
|
||||
mand works for potions, scrolls, rings, and staves and
|
||||
wands.
|
||||
|
||||
o Examine and set options. This command is further
|
||||
explained in the section on options.
|
||||
|
||||
^R Redraws the screen. Useful if spurious messages or
|
||||
transmission errors have messed up the display.
|
||||
|
||||
^P Print last message. Useful when a message disappears
|
||||
before you can read it. This only repeats the last
|
||||
message that was not a mistyped command so that you
|
||||
don't loose anything by accidentally typing the wrong
|
||||
character instead of ^P.
|
||||
|
||||
<ESCAPE>
|
||||
Cancel a command, prefix, or count.
|
||||
|
||||
! Escape to a shell for some commands.
|
||||
|
||||
Q Quit. Leave the game.
|
||||
|
||||
S Save the current game in a file. It will ask you
|
||||
whether you wish to use the default save file. Caveat:
|
||||
Rogue won't let you start up a copy of a saved game,
|
||||
and it removes the save file as soon as you start up a
|
||||
restored game. This is to prevent people from saving a
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
USD:33-8 A Guide to the Dungeons of Doom
|
||||
|
||||
|
||||
game just before a dangerous position and then restart-
|
||||
ing it if they die. To restore a saved game, give the
|
||||
file name as an argument to rogue. As in
|
||||
% rogue save_file
|
||||
|
||||
To restart from the default save file (see below), run
|
||||
% rogue -r
|
||||
|
||||
v Prints the program version number.
|
||||
|
||||
) Print the weapon you are currently wielding
|
||||
|
||||
] Print the armor you are currently wearing
|
||||
|
||||
= Print the rings you are currently wearing
|
||||
|
||||
@ Reprint the status line on the message line
|
||||
|
||||
5. Rooms
|
||||
|
||||
Rooms in the dungeons are either lit or dark. If you
|
||||
walk into a lit room, the entire room will be drawn on the
|
||||
screen as soon as you enter. If you walk into a dark room,
|
||||
it will only be displayed as you explore it. Upon leaving a
|
||||
room, all monsters inside the room are erased from the
|
||||
screen. In the darkness you can only see one space in all
|
||||
directions around you. A corridor is always dark.
|
||||
|
||||
6. Fighting
|
||||
|
||||
If you see a monster and you wish to fight it, just
|
||||
attempt to run into it. Many times a monster you find will
|
||||
mind its own business unless you attack it. It is often the
|
||||
case that discretion is the better part of valor.
|
||||
|
||||
7. Objects you can find
|
||||
|
||||
When you find something in the dungeon, it is common to
|
||||
want to pick the object up. This is accomplished in rogue
|
||||
by walking over the object (unless you use the "m" prefix,
|
||||
see above). If you are carrying too many things, the pro-
|
||||
gram will tell you and it won't pick up the object, other-
|
||||
wise it will add it to your pack and tell you what you just
|
||||
picked up.
|
||||
|
||||
Many of the commands that operate on objects must
|
||||
prompt you to find out which object you want to use. If you
|
||||
change your mind and don't want to do that command after
|
||||
all, just type an <ESCAPE> and the command will be aborted.
|
||||
|
||||
Some objects, like armor and weapons, are easily dif-
|
||||
ferentiated. Others, like scrolls and potions, are given
|
||||
labels which vary according to type. During a game, any two
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
A Guide to the Dungeons of Doom USD:33-9
|
||||
|
||||
|
||||
of the same kind of object with the same label are the same
|
||||
type. However, the labels will vary from game to game.
|
||||
|
||||
When you use one of these labeled objects, if its
|
||||
effect is obvious, rogue will remember what it is for you.
|
||||
If it's effect isn't extremely obvious you will be asked
|
||||
what you want to scribble on it so you will recognize it
|
||||
later, or you can use the "call" command (see above).
|
||||
|
||||
7.1. Weapons
|
||||
|
||||
Some weapons, like arrows, come in bunches, but most
|
||||
come one at a time. In order to use a weapon, you must
|
||||
wield it. To fire an arrow out of a bow, you must first
|
||||
wield the bow, then throw the arrow. You can only wield one
|
||||
weapon at a time, but you can't change weapons if the one
|
||||
you are currently wielding is cursed. The commands to use
|
||||
weapons are "w" (wield) and "t" (throw).
|
||||
|
||||
7.2. Armor
|
||||
|
||||
There are various sorts of armor lying around in the
|
||||
dungeon. Some of it is enchanted, some is cursed, and some
|
||||
is just normal. Different armor types have different armor
|
||||
protection. The higher the armor protection, the more pro-
|
||||
tection the armor affords against the blows of monsters.
|
||||
Here is a list of the various armor types and their normal
|
||||
armor protection:
|
||||
|
||||
|
||||
+-----------------------------------------+
|
||||
| Type Protection |
|
||||
|None 0 |
|
||||
|Leather armor 2 |
|
||||
|Studded leather / Ring mail 3 |
|
||||
|Scale mail 4 |
|
||||
|Chain mail 5 |
|
||||
|Banded mail / Splint mail 6 |
|
||||
|Plate mail 7 |
|
||||
+-----------------------------------------+
|
||||
|
||||
|
||||
If a piece of armor is enchanted, its armor protection will
|
||||
be higher than normal. If a suit of armor is cursed, its
|
||||
armor protection will be lower, and you will not be able to
|
||||
remove it. However, not all armor with a protection that is
|
||||
lower than normal is cursed.
|
||||
|
||||
The commands to use weapons are "W" (wear) and "T"
|
||||
(take off).
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
USD:33-10 A Guide to the Dungeons of Doom
|
||||
|
||||
|
||||
7.3. Scrolls
|
||||
|
||||
Scrolls come with titles in an unknown tongue3. After
|
||||
you read a scroll, it disappears from your pack. The com-
|
||||
mand to use a scroll is "r" (read).
|
||||
|
||||
7.4. Potions
|
||||
|
||||
Potions are labeled by the color of the liquid inside
|
||||
the flask. They disappear after being quaffed. The command
|
||||
to use a scroll is "q" (quaff).
|
||||
|
||||
7.5. Staves and Wands
|
||||
|
||||
Staves and wands do the same kinds of things. Staves
|
||||
are identified by a type of wood; wands by a type of metal
|
||||
or bone. They are generally things you want to do to some-
|
||||
thing over a long distance, so you must point them at what
|
||||
you wish to affect to use them. Some staves are not
|
||||
affected by the direction they are pointed, though. Staves
|
||||
come with multiple magic charges, the number being random,
|
||||
and when they are used up, the staff is just a piece of wood
|
||||
or metal.
|
||||
|
||||
The command to use a wand or staff is "z" (zap)
|
||||
|
||||
7.6. Rings
|
||||
|
||||
Rings are very useful items, since they are relatively
|
||||
permanent magic, unlike the usually fleeting effects of
|
||||
potions, scrolls, and staves. Of course, the bad rings are
|
||||
also more powerful. Most rings also cause you to use up
|
||||
food more rapidly, the rate varying with the type of ring.
|
||||
Rings are differentiated by their stone settings. The com-
|
||||
mands to use rings are "P" (put on) and "R" (remove).
|
||||
|
||||
7.7. Food
|
||||
|
||||
Food is necessary to keep you going. If you go too
|
||||
long without eating you will faint, and eventually die of
|
||||
starvation. The command to use food is "e" (eat).
|
||||
|
||||
8. Options
|
||||
|
||||
Due to variations in personal tastes and conceptions of
|
||||
the way rogue should do things, there are a set of options
|
||||
you can set that cause rogue to behave in various different
|
||||
____________________
|
||||
3 Actually, it's a dialect spoken only by the twenty-sev-
|
||||
en members of a tribe in Outer Mongolia, but you're not sup-
|
||||
posed to know that.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
A Guide to the Dungeons of Doom USD:33-11
|
||||
|
||||
|
||||
ways.
|
||||
|
||||
8.1. Setting the options
|
||||
|
||||
There are two ways to set the options. The first is
|
||||
with the "o" command of rogue; the second is with the
|
||||
"ROGUEOPTS" environment variable4.
|
||||
|
||||
8.1.1. Using the `o' command
|
||||
|
||||
When you type "o" in rogue, it clears the screen and
|
||||
displays the current settings for all the options. It then
|
||||
places the cursor by the value of the first option and waits
|
||||
for you to type. You can type a <RETURN> which means to go
|
||||
to the next option, a "-" which means to go to the previous
|
||||
option, an <ESCAPE> which means to return to the game, or
|
||||
you can give the option a value. For boolean options this
|
||||
merely involves typing "t" for true or "f" for false. For
|
||||
string options, type the new value followed by a <RETURN>.
|
||||
|
||||
8.1.2. Using the ROGUEOPTS variable
|
||||
|
||||
The ROGUEOPTS variable is a string containing a comma
|
||||
separated list of initial values for the various options.
|
||||
Boolean variables can be turned on by listing their name or
|
||||
turned off by putting a "no" in front of the name. Thus to
|
||||
set up an environment variable so that jump is on, terse is
|
||||
off, and the name is set to "Blue Meanie", use the command
|
||||
% setenv ROGUEOPTS "jump,noterse,name=Blue Meanie"5
|
||||
|
||||
8.2. Option list
|
||||
|
||||
Here is a list of the options and an explanation of
|
||||
what each one is for. The default value for each is
|
||||
enclosed in square brackets. For character string options,
|
||||
input over fifty characters will be ignored.
|
||||
|
||||
terse [noterse]
|
||||
Useful for those who are tired of the sometimes lengthy
|
||||
messages of rogue. This is a useful option for playing
|
||||
on slow terminals, so this option defaults to terse if
|
||||
you are on a slow (1200 baud or under) terminal.
|
||||
|
||||
|
||||
____________________
|
||||
4 On Version 6 systems, there is no equivalent of the
|
||||
ROGUEOPTS feature.
|
||||
5 For those of you who use the Bourne shell sh (1), the
|
||||
commands would be
|
||||
$ ROGUEOPTS="jump,noterse,name=Blue Meanie"
|
||||
$ export ROGUEOPTS
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
USD:33-12 A Guide to the Dungeons of Doom
|
||||
|
||||
|
||||
jump [nojump]
|
||||
If this option is set, running moves will not be dis-
|
||||
played until you reach the end of the move. This saves
|
||||
considerable cpu and display time. This option
|
||||
defaults to jump if you are using a slow terminal.
|
||||
|
||||
flush [noflush]
|
||||
All typeahead is thrown away after each round of bat-
|
||||
tle. This is useful for those who type far ahead and
|
||||
then watch in dismay as a Bat kills them.
|
||||
|
||||
seefloor [seefloor]
|
||||
Display the floor around you on the screen as you move
|
||||
through dark rooms. Due to the amount of characters
|
||||
generated, this option defaults to noseefloor if you
|
||||
are using a slow terminal.
|
||||
|
||||
passgo [nopassgo]
|
||||
Follow turnings in passageways. If you run in a pas-
|
||||
sage and you run into stone or a wall, rogue will see
|
||||
if it can turn to the right or left. If it can only
|
||||
turn one way, it will turn that way. If it can turn
|
||||
either or neither, it will stop. This algorithm can
|
||||
sometimes lead to slightly confusing occurrences which
|
||||
is why it defaults to nopassgo.
|
||||
|
||||
tombstone [tombstone]
|
||||
Print out the tombstone at the end if you get killed.
|
||||
This is nice but slow, so you can turn it off if you
|
||||
like.
|
||||
|
||||
inven [overwrite]
|
||||
Inventory type. This can have one of three values:
|
||||
overwrite, slow, or clear. With overwrite the top
|
||||
lines of the map are overwritten with the list when
|
||||
inventory is requested or when "Which item do you wish
|
||||
to . . .? " questions are answered with a "*". How-
|
||||
ever, if the list is longer than a screenful, the
|
||||
screen is cleared. With slow, lists are displayed one
|
||||
item at a time on the top of the screen, and with
|
||||
clear, the screen is cleared, the list is displayed,
|
||||
and then the dungeon level is re-displayed. Due to
|
||||
speed considerations, clear is the default for termi-
|
||||
nals without clear-to-end-of-line capabilities.
|
||||
|
||||
name [account name]
|
||||
This is the name of your character. It is used if you
|
||||
get on the top ten scorer's list.
|
||||
|
||||
fruit [slime-mold]
|
||||
This should hold the name of a fruit that you enjoy
|
||||
eating. It is basically a whimsey that rogue uses in a
|
||||
couple of places.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
A Guide to the Dungeons of Doom USD:33-13
|
||||
|
||||
|
||||
file [~/rogue.save]
|
||||
The default file name for saving the game. If your
|
||||
phone is hung up by accident, rogue will automatically
|
||||
save the game in this file. The file name may start
|
||||
with the special character "~" which expands to be your
|
||||
home directory.
|
||||
|
||||
9. Scoring
|
||||
|
||||
Rogue usually maintains a list of the top scoring peo-
|
||||
ple or scores on your machine. Depending on how it is set
|
||||
up, it can post either the top scores or the top players.
|
||||
In the latter case, each account on the machine can post
|
||||
only one non-winning score on this list. If you score
|
||||
higher than someone else on this list, or better your previ-
|
||||
ous score on the list, you will be inserted in the proper
|
||||
place under your current name. How many scores are kept can
|
||||
also be set up by whoever installs it on your machine.
|
||||
|
||||
If you quit the game, you get out with all of your gold
|
||||
intact. If, however, you get killed in the Dungeons of
|
||||
Doom, your body is forwarded to your next-of-kin, along with
|
||||
90% of your gold; ten percent of your gold is kept by the
|
||||
Dungeons' wizard as a fee6. This should make you consider
|
||||
whether you want to take one last hit at that monster and
|
||||
possibly live, or quit and thus stop with whatever you have.
|
||||
If you quit, you do get all your gold, but if you swing and
|
||||
live, you might find more.
|
||||
|
||||
If you just want to see what the current top play-
|
||||
ers/games list is, you can type
|
||||
% rogue -s
|
||||
|
||||
10. Acknowledgements
|
||||
|
||||
Rogue was originally conceived of by Glenn Wichman and
|
||||
Michael Toy. Ken Arnold and Michael Toy then smoothed out
|
||||
the user interface, and added jillions of new features. We
|
||||
would like to thank Bob Arnold, Michelle Busch, Andy
|
||||
Hatcher, Kipp Hickman, Mark Horton, Daniel Jensen, Bill Joy,
|
||||
Joe Kalash, Steve Maurer, Marty McNary, Jan Miller, and
|
||||
Scott Nelson for their ideas and assistance; and also the
|
||||
teeming multitudes who graciously ignored work, school, and
|
||||
social life to play rogue and send us bugs, complaints, sug-
|
||||
gestions, and just plain flames. And also Mom.
|
||||
|
||||
|
||||
|
||||
____________________
|
||||
6 The Dungeon's wizard is named Wally the Wonder Badger.
|
||||
Invocations should be accompanied by a sizable donation.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,858 +0,0 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
A Guide to the Dungeons of Doom
|
||||
|
||||
|
||||
Michael C. Toy
|
||||
Kenneth C. R. C. Arnold
|
||||
|
||||
|
||||
Computer Systems Research Group
|
||||
Department of Electrical Engineering and Computer Science
|
||||
University of California
|
||||
Berkeley, California 94720
|
||||
|
||||
|
||||
|
||||
|
||||
ABSTRACT
|
||||
|
||||
Rogue is a visual CRT based fantasy game which runs
|
||||
under the UNIX timesharing system. This paper de-
|
||||
scribes how to play rogue, and gives a few hints for
|
||||
those who might otherwise get lost in the Dungeons
|
||||
of Doom.
|
||||
|
||||
|
||||
|
||||
|
||||
1. Introduction
|
||||
|
||||
You have just finished your years as a student at the
|
||||
local fighter's guild. After much practice and sweat you
|
||||
have finally completed your training and are ready to embark
|
||||
upon a perilous adventure. As a test of your skills, the
|
||||
local guildmasters have sent you into the Dungeons of Doom.
|
||||
Your task is to return with the Amulet of Yendor. Your
|
||||
reward for the completion of this task will be a full mem-
|
||||
bership in the local guild. In addition, you are allowed to
|
||||
keep all the loot you bring back from the dungeons.
|
||||
|
||||
In preparation for your journey, you are given an
|
||||
enchanted mace, a bow, and a quiver of arrows taken from a
|
||||
dragon's hoard in the far off Dark Mountains. You are also
|
||||
outfitted with elf-crafted armor and given enough food to
|
||||
reach the dungeons. You say goodbye to family and friends
|
||||
for what may be the last time and head up the road.
|
||||
|
||||
You set out on your way to the dungeons and after sev-
|
||||
eral days of uneventful travel, you see the ancient ruins
|
||||
that mark the entrance to the Dungeons of Doom. It is late
|
||||
at night, so you make camp at the entrance and spend the
|
||||
____________________
|
||||
UNIX is a trademark of Bell Laboratories
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
USD:33-2 A Guide to the Dungeons of Doom
|
||||
|
||||
|
||||
night sleeping under the open skies. In the morning you
|
||||
gather your weapons, put on your armor, eat what is almost
|
||||
your last food, and enter the dungeons.
|
||||
|
||||
2. What is going on here?
|
||||
|
||||
You have just begun a game of rogue. Your goal is to
|
||||
grab as much treasure as you can, find the Amulet of Yendor,
|
||||
and get out of the Dungeons of Doom alive. On the screen, a
|
||||
map of where you have been and what you have seen on the
|
||||
current dungeon level is kept. As you explore more of the
|
||||
level, it appears on the screen in front of you.
|
||||
|
||||
Rogue differs from most computer fantasy games in that
|
||||
it is screen oriented. Commands are all one or two
|
||||
keystrokes1 and the results of your commands are displayed
|
||||
graphically on the screen rather than being explained in
|
||||
words.2
|
||||
|
||||
Another major difference between rogue and other com-
|
||||
puter fantasy games is that once you have solved all the
|
||||
puzzles in a standard fantasy game, it has lost most of its
|
||||
excitement and it ceases to be fun. Rogue, on the other
|
||||
hand, generates a new dungeon every time you play it and
|
||||
even the author finds it an entertaining and exciting game.
|
||||
|
||||
3. What do all those things on the screen mean?
|
||||
|
||||
In order to understand what is going on in rogue you
|
||||
have to first get some grasp of what rogue is doing with the
|
||||
screen. The rogue screen is intended to replace the "You
|
||||
can see ..." descriptions of standard fantasy games. Figure
|
||||
1 is a sample of what a rogue screen might look like.
|
||||
|
||||
3.1. The bottom line
|
||||
|
||||
At the bottom line of the screen are a few pieces of
|
||||
cryptic information describing your current status. Here is
|
||||
an explanation of what these things mean:
|
||||
|
||||
Level This number indicates how deep you have gone in the
|
||||
dungeon. It starts at one and goes up as you go
|
||||
deeper into the dungeon.
|
||||
|
||||
Gold The number of gold pieces you have managed to find
|
||||
and keep with you so far.
|
||||
____________________
|
||||
1 As opposed to pseudo English sentences.
|
||||
2 A minimum screen size of 24 lines by 80 columns is re-
|
||||
quired. If the screen is larger, only the 24x80 section
|
||||
will be used for the map.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
A Guide to the Dungeons of Doom USD:33-3
|
||||
|
||||
|
||||
|
||||
____________________________________________________________
|
||||
|
||||
|
||||
------------
|
||||
|..........+
|
||||
|..@....]..|
|
||||
|....B.....|
|
||||
|..........|
|
||||
-----+------
|
||||
|
||||
|
||||
|
||||
Level: 1 Gold: 0 Hp: 12(12) Str: 16(16) Arm: 4 Exp: 1/0
|
||||
|
||||
Figure 1
|
||||
____________________________________________________________
|
||||
|
||||
|
||||
Hp Your current and maximum health points. Health
|
||||
points indicate how much damage you can take before
|
||||
you die. The more you get hit in a fight, the lower
|
||||
they get. You can regain health points by resting.
|
||||
The number in parentheses is the maximum number your
|
||||
health points can reach.
|
||||
|
||||
Str Your current strength and maximum ever strength.
|
||||
This can be any integer less than or equal to 31, or
|
||||
greater than or equal to three. The higher the num-
|
||||
ber, the stronger you are. The number in the paren-
|
||||
theses is the maximum strength you have attained so
|
||||
far this game.
|
||||
|
||||
Arm Your current armor protection. This number indicates
|
||||
how effective your armor is in stopping blows from
|
||||
unfriendly creatures. The higher this number is, the
|
||||
more effective the armor.
|
||||
|
||||
Exp These two numbers give your current experience level
|
||||
and experience points. As you do things, you gain
|
||||
experience points. At certain experience point
|
||||
totals, you gain an experience level. The more expe-
|
||||
rienced you are, the better you are able to fight and
|
||||
to withstand magical attacks.
|
||||
|
||||
3.2. The top line
|
||||
|
||||
The top line of the screen is reserved for printing
|
||||
messages that describe things that are impossible to repre-
|
||||
sent visually. If you see a "--More--" on the top line,
|
||||
this means that rogue wants to print another message on the
|
||||
screen, but it wants to make certain that you have read the
|
||||
one that is there first. To read the next message, just
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
USD:33-4 A Guide to the Dungeons of Doom
|
||||
|
||||
|
||||
type a space.
|
||||
|
||||
3.3. The rest of the screen
|
||||
|
||||
The rest of the screen is the map of the level as you
|
||||
have explored it so far. Each symbol on the screen repre-
|
||||
sents something. Here is a list of what the various symbols
|
||||
mean:
|
||||
|
||||
@ This symbol represents you, the adventurer.
|
||||
|
||||
-| These symbols represent the walls of rooms.
|
||||
|
||||
+ A door to/from a room.
|
||||
|
||||
. The floor of a room.
|
||||
|
||||
# The floor of a passage between rooms.
|
||||
|
||||
* A pile or pot of gold.
|
||||
|
||||
) A weapon of some sort.
|
||||
|
||||
] A piece of armor.
|
||||
|
||||
! A flask containing a magic potion.
|
||||
|
||||
? A piece of paper, usually a magic scroll.
|
||||
|
||||
= A ring with magic properties
|
||||
|
||||
/ A magical staff or wand
|
||||
|
||||
^ A trap, watch out for these.
|
||||
|
||||
% A staircase to other levels
|
||||
|
||||
: A piece of food.
|
||||
|
||||
A-Z The uppercase letters represent the various inhabitants
|
||||
of the Dungeons of Doom. Watch out, they can be nasty
|
||||
and vicious.
|
||||
|
||||
4. Commands
|
||||
|
||||
Commands are given to rogue by typing one or two char-
|
||||
acters. Most commands can be preceded by a count to repeat
|
||||
them (e.g. typing "10s" will do ten searches). Commands for
|
||||
which counts make no sense have the count ignored. To can-
|
||||
cel a count or a prefix, type <ESCAPE>. The list of com-
|
||||
mands is rather long, but it can be read at any time during
|
||||
the game with the "?" command. Here it is for reference,
|
||||
with a short explanation of each command.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
A Guide to the Dungeons of Doom USD:33-5
|
||||
|
||||
|
||||
? The help command. Asks for a character to give help
|
||||
on. If you type a "*", it will list all the commands,
|
||||
otherwise it will explain what the character you typed
|
||||
does.
|
||||
|
||||
/ This is the "What is that on the screen?" command. A
|
||||
"/" followed by any character that you see on the
|
||||
level, will tell you what that character is. For
|
||||
instance, typing "/@" will tell you that the "@" symbol
|
||||
represents you, the player.
|
||||
|
||||
h, H, ^H
|
||||
Move left. You move one space to the left. If you use
|
||||
upper case "h", you will continue to move left until
|
||||
you run into something. This works for all movement
|
||||
commands (e.g. "L" means run in direction "l") If you
|
||||
use the "control" "h", you will continue moving in the
|
||||
specified direction until you pass something interest-
|
||||
ing or run into a wall. You should experiment with
|
||||
this, since it is a very useful command, but very dif-
|
||||
ficult to describe. This also works for all movement
|
||||
commands.
|
||||
|
||||
j Move down.
|
||||
|
||||
k Move up.
|
||||
|
||||
l Move right.
|
||||
|
||||
y Move diagonally up and left.
|
||||
|
||||
u Move diagonally up and right.
|
||||
|
||||
b Move diagonally down and left.
|
||||
|
||||
n Move diagonally down and right.
|
||||
|
||||
t Throw an object. This is a prefix command. When fol-
|
||||
lowed with a direction it throws an object in the spec-
|
||||
ified direction. (e.g. type "th" to throw something to
|
||||
the left.)
|
||||
|
||||
f Fight until someone dies. When followed with a direc-
|
||||
tion this will force you to fight the creature in that
|
||||
direction until either you or it bites the big one.
|
||||
|
||||
m Move onto something without picking it up. This will
|
||||
move you one space in the direction you specify and, if
|
||||
there is an object there you can pick up, it won't do
|
||||
it.
|
||||
|
||||
z Zap prefix. Point a staff or wand in a given direction
|
||||
and fire it. Even non-directional staves must be
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
USD:33-6 A Guide to the Dungeons of Doom
|
||||
|
||||
|
||||
pointed in some direction to be used.
|
||||
|
||||
^ Identify trap command. If a trap is on your map and
|
||||
you can't remember what type it is, you can get rogue
|
||||
to remind you by getting next to it and typing "^" fol-
|
||||
lowed by the direction that would move you on top of
|
||||
it.
|
||||
|
||||
s Search for traps and secret doors. Examine each space
|
||||
immediately adjacent to you for the existence of a trap
|
||||
or secret door. There is a large chance that even if
|
||||
there is something there, you won't find it, so you
|
||||
might have to search a while before you find something.
|
||||
|
||||
> Climb down a staircase to the next level. Not surpris-
|
||||
ingly, this can only be done if you are standing on
|
||||
staircase.
|
||||
|
||||
< Climb up a staircase to the level above. This can't be
|
||||
done without the Amulet of Yendor in your possession.
|
||||
|
||||
. Rest. This is the "do nothing" command. This is good
|
||||
for waiting and healing.
|
||||
|
||||
, Pick up something. This picks up whatever you are cur-
|
||||
rently standing on, if you are standing on anything at
|
||||
all.
|
||||
|
||||
i Inventory. List what you are carrying in your pack.
|
||||
|
||||
I Selective inventory. Tells you what a single item in
|
||||
your pack is.
|
||||
|
||||
q Quaff one of the potions you are carrying.
|
||||
|
||||
r Read one of the scrolls in your pack.
|
||||
|
||||
e Eat food from your pack.
|
||||
|
||||
w Wield a weapon. Take a weapon out of your pack and
|
||||
carry it for use in combat, replacing the one you are
|
||||
currently using (if any).
|
||||
|
||||
W Wear armor. You can only wear one suit of armor at a
|
||||
time. This takes extra time.
|
||||
|
||||
T Take armor off. You can't remove armor that is cursed.
|
||||
This takes extra time.
|
||||
|
||||
P Put on a ring. You can wear only two rings at a time
|
||||
(one on each hand). If you aren't wearing any rings,
|
||||
this command will ask you which hand you want to wear
|
||||
it on, otherwise, it will place it on the unused hand.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
A Guide to the Dungeons of Doom USD:33-7
|
||||
|
||||
|
||||
The program assumes that you wield your sword in your
|
||||
right hand.
|
||||
|
||||
R Remove a ring. If you are only wearing one ring, this
|
||||
command takes it off. If you are wearing two, it will
|
||||
ask you which one you wish to remove,
|
||||
|
||||
d Drop an object. Take something out of your pack and
|
||||
leave it lying on the floor. Only one object can
|
||||
occupy each space. You cannot drop a cursed object at
|
||||
all if you are wielding or wearing it.
|
||||
|
||||
c Call an object something. If you have a type of object
|
||||
in your pack which you wish to remember something
|
||||
about, you can use the call command to give a name to
|
||||
that type of object. This is usually used when you
|
||||
figure out what a potion, scroll, ring, or staff is
|
||||
after you pick it up, or when you want to remember
|
||||
which of those swords in your pack you were wielding.
|
||||
|
||||
D Print out which things you've discovered something
|
||||
about. This command will ask you what type of thing
|
||||
you are interested in. If you type the character for a
|
||||
given type of object (e.g. "!" for potion) it will
|
||||
tell you which kinds of that type of object you've dis-
|
||||
covered (i.e., figured out what they are). This com-
|
||||
mand works for potions, scrolls, rings, and staves and
|
||||
wands.
|
||||
|
||||
o Examine and set options. This command is further
|
||||
explained in the section on options.
|
||||
|
||||
^R Redraws the screen. Useful if spurious messages or
|
||||
transmission errors have messed up the display.
|
||||
|
||||
^P Print last message. Useful when a message disappears
|
||||
before you can read it. This only repeats the last
|
||||
message that was not a mistyped command so that you
|
||||
don't loose anything by accidentally typing the wrong
|
||||
character instead of ^P.
|
||||
|
||||
<ESCAPE>
|
||||
Cancel a command, prefix, or count.
|
||||
|
||||
! Escape to a shell for some commands.
|
||||
|
||||
Q Quit. Leave the game.
|
||||
|
||||
S Save the current game in a file. It will ask you
|
||||
whether you wish to use the default save file. Caveat:
|
||||
Rogue won't let you start up a copy of a saved game,
|
||||
and it removes the save file as soon as you start up a
|
||||
restored game. This is to prevent people from saving a
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
USD:33-8 A Guide to the Dungeons of Doom
|
||||
|
||||
|
||||
game just before a dangerous position and then restart-
|
||||
ing it if they die. To restore a saved game, give the
|
||||
file name as an argument to rogue. As in
|
||||
% rogue save_file
|
||||
|
||||
To restart from the default save file (see below), run
|
||||
% rogue -r
|
||||
|
||||
v Prints the program version number.
|
||||
|
||||
) Print the weapon you are currently wielding
|
||||
|
||||
] Print the armor you are currently wearing
|
||||
|
||||
= Print the rings you are currently wearing
|
||||
|
||||
@ Reprint the status line on the message line
|
||||
|
||||
5. Rooms
|
||||
|
||||
Rooms in the dungeons are either lit or dark. If you
|
||||
walk into a lit room, the entire room will be drawn on the
|
||||
screen as soon as you enter. If you walk into a dark room,
|
||||
it will only be displayed as you explore it. Upon leaving a
|
||||
room, all monsters inside the room are erased from the
|
||||
screen. In the darkness you can only see one space in all
|
||||
directions around you. A corridor is always dark.
|
||||
|
||||
6. Fighting
|
||||
|
||||
If you see a monster and you wish to fight it, just
|
||||
attempt to run into it. Many times a monster you find will
|
||||
mind its own business unless you attack it. It is often the
|
||||
case that discretion is the better part of valor.
|
||||
|
||||
7. Objects you can find
|
||||
|
||||
When you find something in the dungeon, it is common to
|
||||
want to pick the object up. This is accomplished in rogue
|
||||
by walking over the object (unless you use the "m" prefix,
|
||||
see above). If you are carrying too many things, the pro-
|
||||
gram will tell you and it won't pick up the object, other-
|
||||
wise it will add it to your pack and tell you what you just
|
||||
picked up.
|
||||
|
||||
Many of the commands that operate on objects must
|
||||
prompt you to find out which object you want to use. If you
|
||||
change your mind and don't want to do that command after
|
||||
all, just type an <ESCAPE> and the command will be aborted.
|
||||
|
||||
Some objects, like armor and weapons, are easily dif-
|
||||
ferentiated. Others, like scrolls and potions, are given
|
||||
labels which vary according to type. During a game, any two
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
A Guide to the Dungeons of Doom USD:33-9
|
||||
|
||||
|
||||
of the same kind of object with the same label are the same
|
||||
type. However, the labels will vary from game to game.
|
||||
|
||||
When you use one of these labeled objects, if its
|
||||
effect is obvious, rogue will remember what it is for you.
|
||||
If it's effect isn't extremely obvious you will be asked
|
||||
what you want to scribble on it so you will recognize it
|
||||
later, or you can use the "call" command (see above).
|
||||
|
||||
7.1. Weapons
|
||||
|
||||
Some weapons, like arrows, come in bunches, but most
|
||||
come one at a time. In order to use a weapon, you must
|
||||
wield it. To fire an arrow out of a bow, you must first
|
||||
wield the bow, then throw the arrow. You can only wield one
|
||||
weapon at a time, but you can't change weapons if the one
|
||||
you are currently wielding is cursed. The commands to use
|
||||
weapons are "w" (wield) and "t" (throw).
|
||||
|
||||
7.2. Armor
|
||||
|
||||
There are various sorts of armor lying around in the
|
||||
dungeon. Some of it is enchanted, some is cursed, and some
|
||||
is just normal. Different armor types have different armor
|
||||
protection. The higher the armor protection, the more pro-
|
||||
tection the armor affords against the blows of monsters.
|
||||
Here is a list of the various armor types and their normal
|
||||
armor protection:
|
||||
|
||||
|
||||
+-----------------------------------------+
|
||||
| Type Protection |
|
||||
|None 0 |
|
||||
|Leather armor 2 |
|
||||
|Studded leather / Ring mail 3 |
|
||||
|Scale mail 4 |
|
||||
|Chain mail 5 |
|
||||
|Banded mail / Splint mail 6 |
|
||||
|Plate mail 7 |
|
||||
+-----------------------------------------+
|
||||
|
||||
|
||||
If a piece of armor is enchanted, its armor protection will
|
||||
be higher than normal. If a suit of armor is cursed, its
|
||||
armor protection will be lower, and you will not be able to
|
||||
remove it. However, not all armor with a protection that is
|
||||
lower than normal is cursed.
|
||||
|
||||
The commands to use weapons are "W" (wear) and "T"
|
||||
(take off).
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
USD:33-10 A Guide to the Dungeons of Doom
|
||||
|
||||
|
||||
7.3. Scrolls
|
||||
|
||||
Scrolls come with titles in an unknown tongue3. After
|
||||
you read a scroll, it disappears from your pack. The com-
|
||||
mand to use a scroll is "r" (read).
|
||||
|
||||
7.4. Potions
|
||||
|
||||
Potions are labeled by the color of the liquid inside
|
||||
the flask. They disappear after being quaffed. The command
|
||||
to use a scroll is "q" (quaff).
|
||||
|
||||
7.5. Staves and Wands
|
||||
|
||||
Staves and wands do the same kinds of things. Staves
|
||||
are identified by a type of wood; wands by a type of metal
|
||||
or bone. They are generally things you want to do to some-
|
||||
thing over a long distance, so you must point them at what
|
||||
you wish to affect to use them. Some staves are not
|
||||
affected by the direction they are pointed, though. Staves
|
||||
come with multiple magic charges, the number being random,
|
||||
and when they are used up, the staff is just a piece of wood
|
||||
or metal.
|
||||
|
||||
The command to use a wand or staff is "z" (zap)
|
||||
|
||||
7.6. Rings
|
||||
|
||||
Rings are very useful items, since they are relatively
|
||||
permanent magic, unlike the usually fleeting effects of
|
||||
potions, scrolls, and staves. Of course, the bad rings are
|
||||
also more powerful. Most rings also cause you to use up
|
||||
food more rapidly, the rate varying with the type of ring.
|
||||
Rings are differentiated by their stone settings. The com-
|
||||
mands to use rings are "P" (put on) and "R" (remove).
|
||||
|
||||
7.7. Food
|
||||
|
||||
Food is necessary to keep you going. If you go too
|
||||
long without eating you will faint, and eventually die of
|
||||
starvation. The command to use food is "e" (eat).
|
||||
|
||||
8. Options
|
||||
|
||||
Due to variations in personal tastes and conceptions of
|
||||
the way rogue should do things, there are a set of options
|
||||
you can set that cause rogue to behave in various different
|
||||
____________________
|
||||
3 Actually, it's a dialect spoken only by the twenty-sev-
|
||||
en members of a tribe in Outer Mongolia, but you're not sup-
|
||||
posed to know that.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
A Guide to the Dungeons of Doom USD:33-11
|
||||
|
||||
|
||||
ways.
|
||||
|
||||
8.1. Setting the options
|
||||
|
||||
There are two ways to set the options. The first is
|
||||
with the "o" command of rogue; the second is with the
|
||||
"ROGUEOPTS" environment variable4.
|
||||
|
||||
8.1.1. Using the `o' command
|
||||
|
||||
When you type "o" in rogue, it clears the screen and
|
||||
displays the current settings for all the options. It then
|
||||
places the cursor by the value of the first option and waits
|
||||
for you to type. You can type a <RETURN> which means to go
|
||||
to the next option, a "-" which means to go to the previous
|
||||
option, an <ESCAPE> which means to return to the game, or
|
||||
you can give the option a value. For boolean options this
|
||||
merely involves typing "t" for true or "f" for false. For
|
||||
string options, type the new value followed by a <RETURN>.
|
||||
|
||||
8.1.2. Using the ROGUEOPTS variable
|
||||
|
||||
The ROGUEOPTS variable is a string containing a comma
|
||||
separated list of initial values for the various options.
|
||||
Boolean variables can be turned on by listing their name or
|
||||
turned off by putting a "no" in front of the name. Thus to
|
||||
set up an environment variable so that jump is on, terse is
|
||||
off, and the name is set to "Blue Meanie", use the command
|
||||
% setenv ROGUEOPTS "jump,noterse,name=Blue Meanie"5
|
||||
|
||||
8.2. Option list
|
||||
|
||||
Here is a list of the options and an explanation of
|
||||
what each one is for. The default value for each is
|
||||
enclosed in square brackets. For character string options,
|
||||
input over fifty characters will be ignored.
|
||||
|
||||
terse [noterse]
|
||||
Useful for those who are tired of the sometimes lengthy
|
||||
messages of rogue. This is a useful option for playing
|
||||
on slow terminals, so this option defaults to terse if
|
||||
you are on a slow (1200 baud or under) terminal.
|
||||
|
||||
|
||||
____________________
|
||||
4 On Version 6 systems, there is no equivalent of the
|
||||
ROGUEOPTS feature.
|
||||
5 For those of you who use the Bourne shell sh (1), the
|
||||
commands would be
|
||||
$ ROGUEOPTS="jump,noterse,name=Blue Meanie"
|
||||
$ export ROGUEOPTS
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
USD:33-12 A Guide to the Dungeons of Doom
|
||||
|
||||
|
||||
jump [nojump]
|
||||
If this option is set, running moves will not be dis-
|
||||
played until you reach the end of the move. This saves
|
||||
considerable cpu and display time. This option
|
||||
defaults to jump if you are using a slow terminal.
|
||||
|
||||
flush [noflush]
|
||||
All typeahead is thrown away after each round of bat-
|
||||
tle. This is useful for those who type far ahead and
|
||||
then watch in dismay as a Bat kills them.
|
||||
|
||||
seefloor [seefloor]
|
||||
Display the floor around you on the screen as you move
|
||||
through dark rooms. Due to the amount of characters
|
||||
generated, this option defaults to noseefloor if you
|
||||
are using a slow terminal.
|
||||
|
||||
passgo [nopassgo]
|
||||
Follow turnings in passageways. If you run in a pas-
|
||||
sage and you run into stone or a wall, rogue will see
|
||||
if it can turn to the right or left. If it can only
|
||||
turn one way, it will turn that way. If it can turn
|
||||
either or neither, it will stop. This algorithm can
|
||||
sometimes lead to slightly confusing occurrences which
|
||||
is why it defaults to nopassgo.
|
||||
|
||||
tombstone [tombstone]
|
||||
Print out the tombstone at the end if you get killed.
|
||||
This is nice but slow, so you can turn it off if you
|
||||
like.
|
||||
|
||||
inven [overwrite]
|
||||
Inventory type. This can have one of three values:
|
||||
overwrite, slow, or clear. With overwrite the top
|
||||
lines of the map are overwritten with the list when
|
||||
inventory is requested or when "Which item do you wish
|
||||
to . . .? " questions are answered with a "*". How-
|
||||
ever, if the list is longer than a screenful, the
|
||||
screen is cleared. With slow, lists are displayed one
|
||||
item at a time on the top of the screen, and with
|
||||
clear, the screen is cleared, the list is displayed,
|
||||
and then the dungeon level is re-displayed. Due to
|
||||
speed considerations, clear is the default for termi-
|
||||
nals without clear-to-end-of-line capabilities.
|
||||
|
||||
name [account name]
|
||||
This is the name of your character. It is used if you
|
||||
get on the top ten scorer's list.
|
||||
|
||||
fruit [slime-mold]
|
||||
This should hold the name of a fruit that you enjoy
|
||||
eating. It is basically a whimsey that rogue uses in a
|
||||
couple of places.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
A Guide to the Dungeons of Doom USD:33-13
|
||||
|
||||
|
||||
file [~/rogue.save]
|
||||
The default file name for saving the game. If your
|
||||
phone is hung up by accident, rogue will automatically
|
||||
save the game in this file. The file name may start
|
||||
with the special character "~" which expands to be your
|
||||
home directory.
|
||||
|
||||
9. Scoring
|
||||
|
||||
Rogue usually maintains a list of the top scoring peo-
|
||||
ple or scores on your machine. Depending on how it is set
|
||||
up, it can post either the top scores or the top players.
|
||||
In the latter case, each account on the machine can post
|
||||
only one non-winning score on this list. If you score
|
||||
higher than someone else on this list, or better your previ-
|
||||
ous score on the list, you will be inserted in the proper
|
||||
place under your current name. How many scores are kept can
|
||||
also be set up by whoever installs it on your machine.
|
||||
|
||||
If you quit the game, you get out with all of your gold
|
||||
intact. If, however, you get killed in the Dungeons of
|
||||
Doom, your body is forwarded to your next-of-kin, along with
|
||||
90% of your gold; ten percent of your gold is kept by the
|
||||
Dungeons' wizard as a fee6. This should make you consider
|
||||
whether you want to take one last hit at that monster and
|
||||
possibly live, or quit and thus stop with whatever you have.
|
||||
If you quit, you do get all your gold, but if you swing and
|
||||
live, you might find more.
|
||||
|
||||
If you just want to see what the current top play-
|
||||
ers/games list is, you can type
|
||||
% @PROGRAM@ -s
|
||||
|
||||
10. Acknowledgements
|
||||
|
||||
Rogue was originally conceived of by Glenn Wichman and
|
||||
Michael Toy. Ken Arnold and Michael Toy then smoothed out
|
||||
the user interface, and added jillions of new features. We
|
||||
would like to thank Bob Arnold, Michelle Busch, Andy
|
||||
Hatcher, Kipp Hickman, Mark Horton, Daniel Jensen, Bill Joy,
|
||||
Joe Kalash, Steve Maurer, Marty McNary, Jan Miller, and
|
||||
Scott Nelson for their ideas and assistance; and also the
|
||||
teeming multitudes who graciously ignored work, school, and
|
||||
social life to play rogue and send us bugs, complaints, sug-
|
||||
gestions, and just plain flames. And also Mom.
|
||||
|
||||
|
||||
|
||||
____________________
|
||||
6 The Dungeon's wizard is named Wally the Wonder Badger.
|
||||
Invocations should be accompanied by a sizable donation.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,863 +0,0 @@
|
||||
// Copyright (c) 2016-2023 The Hush developers
|
||||
// Distributed under the GPLv3 software license, see the accompanying
|
||||
// file COPYING or https://www.gnu.org/licenses/gpl-3.0.en.html
|
||||
/*
|
||||
* Rogue definitions and variable declarations
|
||||
*
|
||||
* @(#)rogue.h 5.42 (Berkeley) 08/06/83
|
||||
*
|
||||
* Rogue: Exploring the Dungeons of Doom
|
||||
* Copyright (C) 1980-1983, 1985, 1999 Michael Toy, Ken Arnold and Glenn Wichman
|
||||
* All rights reserved.
|
||||
*
|
||||
* See the file LICENSE.TXT for full copyright and licensing information.
|
||||
*/
|
||||
|
||||
#ifndef H_ROGUE_H
|
||||
#define H_ROGUE_H
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <memory.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <stdarg.h> /* we need va_list */
|
||||
#include <stddef.h> /* we want wchar_t */
|
||||
#include <stdbool.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include <time.h>
|
||||
#include <sys/types.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <errno.h>
|
||||
|
||||
#ifndef BUILD_ROGUE
|
||||
#include <curses.h>
|
||||
#else
|
||||
#include "cursesd.h"
|
||||
#endif
|
||||
|
||||
#ifdef LINES
|
||||
#undef LINES
|
||||
#endif
|
||||
#ifdef COLS
|
||||
#undef COLS
|
||||
#endif
|
||||
|
||||
#define LINES 24
|
||||
#define COLS 80
|
||||
|
||||
#include "extern.h"
|
||||
|
||||
|
||||
#undef lines
|
||||
|
||||
#define NOOP(x) (x += 0)
|
||||
#define CCHAR(x) ( (char) (x & A_CHARTEXT) )
|
||||
/*
|
||||
* Maximum number of different things
|
||||
*/
|
||||
#define MAXROOMS 9
|
||||
#define MAXTHINGS 9
|
||||
#define MAXOBJ 9
|
||||
#define MAXPACK 23
|
||||
#define MAXTRAPS 10
|
||||
#define AMULETLEVEL 26
|
||||
#define NUMTHINGS 7 /* number of types of things */
|
||||
#define MAXPASS 13 /* upper limit on number of passages */
|
||||
#define NUMLINES 24
|
||||
#define NUMCOLS 80
|
||||
#define STATLINE (NUMLINES - 1)
|
||||
#define BORE_LEVEL 50
|
||||
|
||||
/*
|
||||
* return values for get functions
|
||||
*/
|
||||
#define NORM 0 /* normal exit */
|
||||
#define QUIT 1 /* quit option setting */
|
||||
#define MINUS 2 /* back up one option */
|
||||
|
||||
/*
|
||||
* inventory types
|
||||
*/
|
||||
#define INV_OVER 0
|
||||
#define INV_SLOW 1
|
||||
#define INV_CLEAR 2
|
||||
|
||||
/*
|
||||
* All the fun defines
|
||||
*/
|
||||
#define when break;case
|
||||
#define otherwise break;default
|
||||
#define until(expr) while(!(expr))
|
||||
#define next(ptr) (*ptr).l_next
|
||||
#define prev(ptr) (*ptr).l_prev
|
||||
#define winat(y,x) (moat(y,x) != NULL ? moat(y,x)->t_disguise : chat(y,x))
|
||||
#define ce(a,b) ((a).x == (b).x && (a).y == (b).y)
|
||||
#define hero player.t_pos
|
||||
#define pstats player.t_stats
|
||||
#define pack player.t_pack
|
||||
#define proom player.t_room
|
||||
#define max_hp player.t_stats.s_maxhp
|
||||
#define attach(a,b) _attach(&a,b)
|
||||
#define detach(a,b) _detach(&a,b)
|
||||
#define free_list(a) _free_list(&a)
|
||||
#undef max
|
||||
#define max(a,b) ((a) > (b) ? (a) : (b))
|
||||
#define on(thing,flag) ((bool)(((thing).t_flags & (flag)) != 0))
|
||||
#define GOLDCALC (rnd(50 + 10 * level) + 2)
|
||||
#define ISRING(h,r) (cur_ring[h] != NULL && cur_ring[h]->o_which == r)
|
||||
#define ISWEARING(r) (ISRING(LEFT, r) || ISRING(RIGHT, r))
|
||||
#define ISMULT(type) (type == POTION || type == SCROLL || type == FOOD)
|
||||
#define INDEX(y,x) (&places[((x) << 5) + (y)])
|
||||
#define chat(y,x) (places[((x) << 5) + (y)].p_ch)
|
||||
#define flat(y,x) (places[((x) << 5) + (y)].p_flags)
|
||||
#define moat(y,x) (places[((x) << 5) + (y)].p_monst)
|
||||
#define unc(cp) (cp).y, (cp).x
|
||||
#ifdef MASTER
|
||||
#define debug if (wizard) msg
|
||||
#endif
|
||||
|
||||
/*
|
||||
* things that appear on the screens
|
||||
*/
|
||||
#define PASSAGE '#'
|
||||
#define DOOR '+'
|
||||
#define FLOOR '.'
|
||||
#define PLAYER '@'
|
||||
#define TRAP '^'
|
||||
#define STAIRS '%'
|
||||
#define GOLD '*'
|
||||
#define POTION '!'
|
||||
#define SCROLL '?'
|
||||
#define MAGIC '$'
|
||||
#define FOOD ':'
|
||||
#define WEAPON ')'
|
||||
#define ARMOR ']'
|
||||
#define AMULET ','
|
||||
#define RING '='
|
||||
#define STICK '/'
|
||||
#define CALLABLE -1
|
||||
#define R_OR_S -2
|
||||
|
||||
/*
|
||||
* Various constants
|
||||
*/
|
||||
#define BEARTIME spread(3)
|
||||
#define SLEEPTIME spread(5)
|
||||
#define HOLDTIME spread(2)
|
||||
#define WANDERTIME spread(70)
|
||||
#define BEFORE spread(1)
|
||||
#define AFTER spread(2)
|
||||
#define HEALTIME 30
|
||||
#define HUHDURATION 20
|
||||
#define SEEDURATION 850
|
||||
#define HUNGERTIME 1300
|
||||
#define MORETIME 150
|
||||
#define STOMACHSIZE 2000
|
||||
#define STARVETIME 850
|
||||
#define ESCAPE 27
|
||||
#define LEFT 0
|
||||
#define RIGHT 1
|
||||
#define BOLT_LENGTH 6
|
||||
#define LAMPDIST 3
|
||||
#ifdef MASTER
|
||||
#ifndef PASSWD
|
||||
#define PASSWD "mTBellIQOsLNA"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Save against things
|
||||
*/
|
||||
#define VS_POISON 00
|
||||
#define VS_PARALYZATION 00
|
||||
#define VS_DEATH 00
|
||||
#define VS_BREATH 02
|
||||
#define VS_MAGIC 03
|
||||
|
||||
/*
|
||||
* Various flag bits
|
||||
*/
|
||||
/* flags for rooms */
|
||||
#define ISDARK 0000001 /* room is dark */
|
||||
#define ISGONE 0000002 /* room is gone (a corridor) */
|
||||
#define ISMAZE 0000004 /* room is gone (a corridor) */
|
||||
|
||||
/* flags for objects */
|
||||
#define ISCURSED 000001 /* object is cursed */
|
||||
#define ISKNOW 0000002 /* player knows details about the object */
|
||||
#define ISMISL 0000004 /* object is a missile type */
|
||||
#define ISMANY 0000010 /* object comes in groups */
|
||||
/* ISFOUND 0000020 ...is used for both objects and creatures */
|
||||
#define ISPROT 0000040 /* armor is permanently protected */
|
||||
|
||||
/* flags for creatures */
|
||||
#define CANHUH 0000001 /* creature can confuse */
|
||||
#define CANSEE 0000002 /* creature can see invisible creatures */
|
||||
#define ISBLIND 0000004 /* creature is blind */
|
||||
#define ISCANC 0000010 /* creature has special qualities cancelled */
|
||||
#define ISLEVIT 0000010 /* hero is levitating */
|
||||
#define ISFOUND 0000020 /* creature has been seen (used for objects) */
|
||||
#define ISGREED 0000040 /* creature runs to protect gold */
|
||||
#define ISHASTE 0000100 /* creature has been hastened */
|
||||
#define ISTARGET 000200 /* creature is the target of an 'f' command */
|
||||
#define ISHELD 0000400 /* creature has been held */
|
||||
#define ISHUH 0001000 /* creature is confused */
|
||||
#define ISINVIS 0002000 /* creature is invisible */
|
||||
#define ISMEAN 0004000 /* creature can wake when player enters room */
|
||||
#define ISHALU 0004000 /* hero is on acid trip */
|
||||
#define ISREGEN 0010000 /* creature can regenerate */
|
||||
#define ISRUN 0020000 /* creature is running at the player */
|
||||
#define SEEMONST 040000 /* hero can detect unseen monsters */
|
||||
#define ISFLY 0040000 /* creature can fly */
|
||||
#define ISSLOW 0100000 /* creature has been slowed */
|
||||
|
||||
/*
|
||||
* Flags for level map
|
||||
*/
|
||||
#define F_PASS 0x80 /* is a passageway */
|
||||
#define F_SEEN 0x40 /* have seen this spot before */
|
||||
#define F_DROPPED 0x20 /* object was dropped here */
|
||||
#define F_LOCKED 0x20 /* door is locked */
|
||||
#define F_REAL 0x10 /* what you see is what you get */
|
||||
#define F_PNUM 0x0f /* passage number mask */
|
||||
#define F_TMASK 0x07 /* trap number mask */
|
||||
|
||||
/*
|
||||
* Trap types
|
||||
*/
|
||||
#define T_DOOR 00
|
||||
#define T_ARROW 01
|
||||
#define T_SLEEP 02
|
||||
#define T_BEAR 03
|
||||
#define T_TELEP 04
|
||||
#define T_DART 05
|
||||
#define T_RUST 06
|
||||
#define T_MYST 07
|
||||
#define NTRAPS 8
|
||||
|
||||
/*
|
||||
* Potion types
|
||||
*/
|
||||
#define P_CONFUSE 0
|
||||
#define P_LSD 1
|
||||
#define P_POISON 2
|
||||
#define P_STRENGTH 3
|
||||
#define P_SEEINVIS 4
|
||||
#define P_HEALING 5
|
||||
#define P_MFIND 6
|
||||
#define P_TFIND 7
|
||||
#define P_RAISE 8
|
||||
#define P_XHEAL 9
|
||||
#define P_HASTE 10
|
||||
#define P_RESTORE 11
|
||||
#define P_BLIND 12
|
||||
#define P_LEVIT 13
|
||||
#define MAXPOTIONS 14
|
||||
|
||||
/*
|
||||
* Scroll types
|
||||
*/
|
||||
#define S_CONFUSE 0
|
||||
#define S_MAP 1
|
||||
#define S_HOLD 2
|
||||
#define S_SLEEP 3
|
||||
#define S_ARMOR 4
|
||||
#define S_ID_POTION 5
|
||||
#define S_ID_SCROLL 6
|
||||
#define S_ID_WEAPON 7
|
||||
#define S_ID_ARMOR 8
|
||||
#define S_ID_R_OR_S 9
|
||||
#define S_SCARE 10
|
||||
#define S_FDET 11
|
||||
#define S_TELEP 12
|
||||
#define S_ENCH 13
|
||||
#define S_CREATE 14
|
||||
#define S_REMOVE 15
|
||||
#define S_AGGR 16
|
||||
#define S_PROTECT 17
|
||||
#define MAXSCROLLS 18
|
||||
|
||||
/*
|
||||
* Weapon types
|
||||
*/
|
||||
#define MACE 0
|
||||
#define SWORD 1
|
||||
#define BOW 2
|
||||
#define ARROW 3
|
||||
#define DAGGER 4
|
||||
#define TWOSWORD 5
|
||||
#define DART 6
|
||||
#define SHIRAKEN 7
|
||||
#define SPEAR 8
|
||||
#define FLAME 9 /* fake entry for dragon breath (ick) */
|
||||
#define MAXWEAPONS 9 /* this should equal FLAME */
|
||||
|
||||
/*
|
||||
* Armor types
|
||||
*/
|
||||
#define LEATHER 0
|
||||
#define RING_MAIL 1
|
||||
#define STUDDED_LEATHER 2
|
||||
#define SCALE_MAIL 3
|
||||
#define CHAIN_MAIL 4
|
||||
#define SPLINT_MAIL 5
|
||||
#define BANDED_MAIL 6
|
||||
#define PLATE_MAIL 7
|
||||
#define MAXARMORS 8
|
||||
|
||||
/*
|
||||
* Ring types
|
||||
*/
|
||||
#define R_PROTECT 0
|
||||
#define R_ADDSTR 1
|
||||
#define R_SUSTSTR 2
|
||||
#define R_SEARCH 3
|
||||
#define R_SEEINVIS 4
|
||||
#define R_NOP 5
|
||||
#define R_AGGR 6
|
||||
#define R_ADDHIT 7
|
||||
#define R_ADDDAM 8
|
||||
#define R_REGEN 9
|
||||
#define R_DIGEST 10
|
||||
#define R_TELEPORT 11
|
||||
#define R_STEALTH 12
|
||||
#define R_SUSTARM 13
|
||||
#define MAXRINGS 14
|
||||
|
||||
/*
|
||||
* Rod/Wand/Staff types
|
||||
*/
|
||||
#define WS_LIGHT 0
|
||||
#define WS_INVIS 1
|
||||
#define WS_ELECT 2
|
||||
#define WS_FIRE 3
|
||||
#define WS_COLD 4
|
||||
#define WS_POLYMORPH 5
|
||||
#define WS_MISSILE 6
|
||||
#define WS_HASTE_M 7
|
||||
#define WS_SLOW_M 8
|
||||
#define WS_DRAIN 9
|
||||
#define WS_NOP 10
|
||||
#define WS_TELAWAY 11
|
||||
#define WS_TELTO 12
|
||||
#define WS_CANCEL 13
|
||||
#define MAXSTICKS 14
|
||||
|
||||
/*
|
||||
* Now we define the structures and types
|
||||
*/
|
||||
|
||||
#define SMALLVAL 0.000000000000001
|
||||
#define SATOSHIDEN ((uint64_t)100000000L)
|
||||
#define dstr(x) ((double)(x) / SATOSHIDEN)
|
||||
|
||||
#ifndef _BITS256
|
||||
#define _BITS256
|
||||
union _bits256 { uint8_t bytes[32]; uint16_t ushorts[16]; uint32_t uints[8]; uint64_t ulongs[4]; uint64_t txid; };
|
||||
typedef union _bits256 bits256;
|
||||
#endif
|
||||
|
||||
#include "rogue_player.h" // interface to rpc
|
||||
|
||||
struct rogue_state
|
||||
{
|
||||
uint64_t seed;
|
||||
char *keystrokes,*keystrokeshex;
|
||||
uint32_t needflush,replaydone;
|
||||
int32_t numkeys,ind,num,guiflag,counter,sleeptime,playersize,restoring,lastnum;
|
||||
FILE *logfp;
|
||||
struct rogue_player P;
|
||||
char buffered[10000];
|
||||
uint8_t playerdata[10000];
|
||||
};
|
||||
extern struct rogue_state globalR;
|
||||
|
||||
int rogue(int argc, char **argv, char **envp);
|
||||
void rogueiterate(struct rogue_state *rs);
|
||||
int32_t roguefname(char *fname,uint64_t seed,int32_t counter);
|
||||
int32_t flushkeystrokes(struct rogue_state *rs,int32_t waitflag);
|
||||
int32_t rogue_restorepack(struct rogue_state *rs);
|
||||
void restore_player(struct rogue_state *rs);
|
||||
int32_t rogue_replay2(uint8_t *newdata,uint64_t seed,char *keystrokes,int32_t num,struct rogue_player *player,int32_t sleepmillis);
|
||||
void rogue_bailout(struct rogue_state *rs);
|
||||
int32_t rogue_progress(struct rogue_state *rs,int32_t waitflag,uint64_t seed,char *keystrokes,int32_t num);
|
||||
int32_t rogue_setplayerdata(struct rogue_state *rs,char *gametxidstr);
|
||||
|
||||
#define ROGUE_MAXTOTAL (pstats.s_str*2)
|
||||
|
||||
/*
|
||||
* Help list
|
||||
*/
|
||||
struct h_list {
|
||||
char h_ch;
|
||||
char *h_desc;
|
||||
bool h_print;
|
||||
};
|
||||
|
||||
/*
|
||||
* Coordinate data type
|
||||
*/
|
||||
typedef struct {
|
||||
int x;
|
||||
int y;
|
||||
} coord;
|
||||
|
||||
typedef unsigned int str_t;
|
||||
|
||||
/*
|
||||
* Stuff about objects
|
||||
*/
|
||||
struct obj_info {
|
||||
char *oi_name;
|
||||
int oi_prob;
|
||||
int oi_worth;
|
||||
char *oi_guess;
|
||||
bool oi_know;
|
||||
};
|
||||
|
||||
/*
|
||||
* Room structure
|
||||
*/
|
||||
struct room {
|
||||
coord r_pos; /* Upper left corner */
|
||||
coord r_max; /* Size of room */
|
||||
coord r_gold; /* Where the gold is */
|
||||
int r_goldval; /* How much the gold is worth */
|
||||
short r_flags; /* info about the room */
|
||||
int r_nexits; /* Number of exits */
|
||||
coord r_exit[12]; /* Where the exits are */
|
||||
};
|
||||
|
||||
/*
|
||||
* Structure describing a fighting being
|
||||
*/
|
||||
struct stats {
|
||||
str_t s_str; /* Strength */
|
||||
int s_exp; /* Experience */
|
||||
int s_lvl; /* level of mastery */
|
||||
int s_arm; /* Armor class */
|
||||
int s_hpt; /* Hit points */
|
||||
char s_dmg[13]; /* String describing damage done */
|
||||
int s_maxhp; /* Max hit points */
|
||||
};
|
||||
|
||||
/*
|
||||
* Structure for monsters and player
|
||||
*/
|
||||
union thing {
|
||||
struct {
|
||||
union thing *_l_next, *_l_prev; /* Next pointer in link */
|
||||
coord _t_pos; /* Position */
|
||||
bool _t_turn; /* If slowed, is it a turn to move */
|
||||
char _t_type; /* What it is */
|
||||
char _t_disguise; /* What mimic looks like */
|
||||
char _t_oldch; /* Character that was where it was */
|
||||
coord *_t_dest; /* Where it is running to */
|
||||
short _t_flags; /* State word */
|
||||
struct stats _t_stats; /* Physical description */
|
||||
struct room *_t_room; /* Current room for thing */
|
||||
union thing *_t_pack; /* What the thing is carrying */
|
||||
int _t_reserved;
|
||||
} _t;
|
||||
struct {
|
||||
union thing *_l_next, *_l_prev; /* Next pointer in link */
|
||||
int _o_type; /* What kind of object it is */
|
||||
coord _o_pos; /* Where it lives on the screen */
|
||||
char *_o_text; /* What it says if you read it */
|
||||
int _o_launch; /* What you need to launch it */
|
||||
char _o_packch; /* What character it is in the pack */
|
||||
char _o_damage[8]; /* Damage if used like sword */
|
||||
char _o_hurldmg[8]; /* Damage if thrown */
|
||||
int _o_count; /* count for plural objects */
|
||||
int _o_which; /* Which object of a type it is */
|
||||
int _o_hplus; /* Plusses to hit */
|
||||
int _o_dplus; /* Plusses to damage */
|
||||
int _o_arm; /* Armor protection */
|
||||
int _o_flags; /* information about objects */
|
||||
int _o_group; /* group number for this object */
|
||||
char *_o_label; /* Label for object */
|
||||
} _o;
|
||||
};
|
||||
|
||||
typedef union thing THING;
|
||||
|
||||
#define l_next _t._l_next
|
||||
#define l_prev _t._l_prev
|
||||
#define t_pos _t._t_pos
|
||||
#define t_turn _t._t_turn
|
||||
#define t_type _t._t_type
|
||||
#define t_disguise _t._t_disguise
|
||||
#define t_oldch _t._t_oldch
|
||||
#define t_dest _t._t_dest
|
||||
#define t_flags _t._t_flags
|
||||
#define t_stats _t._t_stats
|
||||
#define t_pack _t._t_pack
|
||||
#define t_room _t._t_room
|
||||
#define t_reserved _t._t_reserved
|
||||
#define o_type _o._o_type
|
||||
#define o_pos _o._o_pos
|
||||
#define o_text _o._o_text
|
||||
#define o_launch _o._o_launch
|
||||
#define o_packch _o._o_packch
|
||||
#define o_damage _o._o_damage
|
||||
#define o_hurldmg _o._o_hurldmg
|
||||
#define o_count _o._o_count
|
||||
#define o_which _o._o_which
|
||||
#define o_hplus _o._o_hplus
|
||||
#define o_dplus _o._o_dplus
|
||||
#define o_arm _o._o_arm
|
||||
#define o_charges o_arm
|
||||
#define o_goldval o_arm
|
||||
#define o_flags _o._o_flags
|
||||
#define o_group _o._o_group
|
||||
#define o_label _o._o_label
|
||||
|
||||
/*
|
||||
* describe a place on the level map
|
||||
*/
|
||||
typedef struct {
|
||||
char p_ch;
|
||||
char p_flags;
|
||||
THING *p_monst;
|
||||
} PLACE;
|
||||
|
||||
/*
|
||||
* Array containing information on all the various types of monsters
|
||||
*/
|
||||
struct monster {
|
||||
char *m_name; /* What to call the monster */
|
||||
int m_carry; /* Probability of carrying something */
|
||||
short m_flags; /* things about the monster */
|
||||
struct stats m_stats; /* Initial stats */
|
||||
};
|
||||
|
||||
/*
|
||||
* External variables
|
||||
*/
|
||||
extern const char *tr_name[],*inv_t_name[];
|
||||
extern const int32_t a_class[], e_levels[];
|
||||
extern const struct h_list helpstr[];
|
||||
extern const char *h_names[],*m_names[];
|
||||
|
||||
|
||||
extern const struct monster origmonsters[26];
|
||||
extern const struct room origpassages[MAXPASS];
|
||||
extern const struct obj_info origthings[NUMTHINGS],origring_info[MAXRINGS],origpot_info[MAXPOTIONS],origarm_info[MAXARMORS],origscr_info[MAXSCROLLS],origws_info[MAXSTICKS],origweap_info[MAXWEAPONS + 1];
|
||||
extern struct monster monsters[26];
|
||||
extern struct room passages[MAXPASS];
|
||||
extern struct obj_info things[NUMTHINGS],ring_info[MAXRINGS],pot_info[MAXPOTIONS],arm_info[MAXARMORS],scr_info[MAXSCROLLS],weap_info[MAXWEAPONS + 1],ws_info[MAXSTICKS];
|
||||
|
||||
extern bool after, again, allscore, amulet, door_stop, fight_flush,
|
||||
firstmove, has_hit, inv_describe, jump, kamikaze,
|
||||
lower_msg, move_on, msg_esc, pack_used[],
|
||||
passgo, playing, q_comm, running, save_msg, see_floor,
|
||||
seenstairs, stat_msg, terse, to_death, tombstone;
|
||||
|
||||
extern char dir_ch, file_name[], home[], huh[],
|
||||
l_last_comm, l_last_dir, last_comm, last_dir, *Numname,
|
||||
outbuf[], *release, *s_names[], runch, take;
|
||||
extern const char *ws_made[], *r_stones[], *p_colors[], *ws_type[];
|
||||
|
||||
extern int count, food_left, hungry_state, inpack,
|
||||
inv_type, lastscore, level, max_hit, max_level, mpos,
|
||||
n_objs, no_command, no_food, no_move, noscore, ntraps, purse,
|
||||
quiet, vf_hit;
|
||||
|
||||
extern unsigned int numscores;
|
||||
|
||||
extern uint64_t seed;
|
||||
|
||||
extern WINDOW *hw;
|
||||
|
||||
extern coord delta, oldpos, stairs;
|
||||
|
||||
extern PLACE places[];
|
||||
|
||||
extern THING *cur_armor, *cur_ring[], *cur_weapon, *l_last_pick,
|
||||
*last_pick, *lvl_obj, *mlist, player;
|
||||
|
||||
|
||||
extern struct room *oldrp, rooms[];
|
||||
|
||||
extern struct stats max_stats;
|
||||
|
||||
|
||||
/*
|
||||
* Function types
|
||||
*/
|
||||
void _attach(THING **list, THING *item);
|
||||
void _detach(THING **list, THING *item);
|
||||
void _free_list(THING **ptr);
|
||||
void addmsg(struct rogue_state *rs,char *fmt, ...);
|
||||
bool add_haste(struct rogue_state *rs,bool potion);
|
||||
char add_line(struct rogue_state *rs,char *fmt, char *arg);
|
||||
void add_pack(struct rogue_state *rs,THING *obj, bool silent);
|
||||
void add_pass(void);
|
||||
void add_str(str_t *sp, int amt);
|
||||
void accnt_maze(int y, int x, int ny, int nx);
|
||||
void aggravate(struct rogue_state *rs);
|
||||
int attack(struct rogue_state *rs,THING *mp);
|
||||
void badcheck(char *name, struct obj_info *info, int bound);
|
||||
void bounce(struct rogue_state *rs,THING *weap, char *mname, bool noend);
|
||||
void call(struct rogue_state *rs);
|
||||
void call_it(struct rogue_state *rs,struct obj_info *info);
|
||||
bool cansee(struct rogue_state *rs,int y, int x);
|
||||
int center(char *str);
|
||||
void chg_str(int amt);
|
||||
void check_level(struct rogue_state *rs);
|
||||
void conn(struct rogue_state *rs,int r1, int r2);
|
||||
void command(struct rogue_state *rs);
|
||||
void create_obj(struct rogue_state *rs);
|
||||
|
||||
void current(struct rogue_state *rs,THING *cur, char *how, char *where);
|
||||
void d_level(struct rogue_state *rs);
|
||||
void death(struct rogue_state *rs,char monst);
|
||||
char death_monst(void);
|
||||
void dig(struct rogue_state *rs,int y, int x);
|
||||
void discard(THING *item);
|
||||
void discovered(struct rogue_state *rs);
|
||||
int dist(int y1, int x1, int y2, int x2);
|
||||
int dist_cp(coord *c1, coord *c2);
|
||||
int do_chase(struct rogue_state *rs,THING *th);
|
||||
void do_daemons(struct rogue_state *rs,int flag);
|
||||
void do_fuses(struct rogue_state *rs,int flag);
|
||||
void do_maze(struct rogue_state *rs,struct room *rp);
|
||||
void do_motion(struct rogue_state *rs,THING *obj, int ydelta, int xdelta);
|
||||
void do_move(struct rogue_state *rs,int dy, int dx);
|
||||
void do_passages(struct rogue_state *rs);
|
||||
void do_pot(struct rogue_state *rs,int type, bool knowit);
|
||||
void do_rooms(struct rogue_state *rs);
|
||||
void do_run(char ch);
|
||||
void do_zap(struct rogue_state *rs);
|
||||
void doadd(struct rogue_state *rs,char *fmt, va_list args);
|
||||
void door(struct room *rm, coord *cp);
|
||||
void door_open(struct rogue_state *rs,struct room *rp);
|
||||
void drain(struct rogue_state *rs);
|
||||
void draw_room(struct rogue_state *rs,struct room *rp);
|
||||
void drop(struct rogue_state *rs);
|
||||
void eat(struct rogue_state *rs);
|
||||
size_t encread(char *start, size_t size, FILE *inf);
|
||||
size_t encwrite(char *start, size_t size, FILE *outf);
|
||||
int endmsg(struct rogue_state *rs);
|
||||
void enter_room(struct rogue_state *rs,coord *cp);
|
||||
void erase_lamp(coord *pos, struct room *rp);
|
||||
int exp_add(THING *tp);
|
||||
void extinguish(void (*func)(struct rogue_state *rs,int));
|
||||
void fall(struct rogue_state *rs,THING *obj, bool pr);
|
||||
void fire_bolt(struct rogue_state *rs,coord *start, coord *dir, char *name);
|
||||
char floor_at(void);
|
||||
void flush_type(void);
|
||||
int fight(struct rogue_state *rs,coord *mp, THING *weap, bool thrown);
|
||||
void fix_stick(THING *cur);
|
||||
void fuse(void (*func)(struct rogue_state *rs,int), int arg, int time, int type);
|
||||
bool get_dir(struct rogue_state *rs);
|
||||
int gethand(struct rogue_state *rs);
|
||||
void give_pack(struct rogue_state *rs,THING *tp);
|
||||
void help(struct rogue_state *rs);
|
||||
void hit(struct rogue_state *rs,char *er, char *ee, bool noend);
|
||||
void horiz(struct room *rp, int starty);
|
||||
void leave_room(struct rogue_state *rs,coord *cp);
|
||||
void lengthen(void (*func)(struct rogue_state *rs,int), int xtime);
|
||||
void look(struct rogue_state *rs,bool wakeup);
|
||||
int hit_monster(struct rogue_state *rs,int y, int x, THING *obj);
|
||||
void identify(struct rogue_state *rs);
|
||||
void illcom(struct rogue_state *rs,int ch);
|
||||
void init_check(void);
|
||||
void init_colors(void);
|
||||
void init_materials(void);
|
||||
void init_names(void);
|
||||
void init_player(struct rogue_state *rs);
|
||||
void init_probs(void);
|
||||
void init_stones(void);
|
||||
void init_weapon(THING *weap, int which);
|
||||
bool inventory(struct rogue_state *rs,THING *list, int type);
|
||||
void invis_on(void);
|
||||
void killed(struct rogue_state *rs,THING *tp, bool pr);
|
||||
void kill_daemon(void (*func)(struct rogue_state *rs,int));
|
||||
bool lock_sc(void);
|
||||
void miss(struct rogue_state *rs,char *er, char *ee, bool noend);
|
||||
void missile(struct rogue_state *rs,int ydelta, int xdelta);
|
||||
void money(struct rogue_state *rs,int value);
|
||||
int move_monst(struct rogue_state *rs,THING *tp);
|
||||
void move_msg(struct rogue_state *rs,THING *obj);
|
||||
int msg(struct rogue_state *rs,char *fmt, ...);
|
||||
void nameit(THING *obj, const char *type, const char *which, struct obj_info *op, char *(*prfunc)(THING *));
|
||||
void new_level(struct rogue_state *rs);
|
||||
void new_monster(struct rogue_state *rs,THING *tp, char type, coord *cp);
|
||||
void numpass(int y, int x);
|
||||
void option(struct rogue_state *rs);
|
||||
void open_score(void);
|
||||
void parse_opts(char *str);
|
||||
void passnum(void);
|
||||
char *pick_color(char *col);
|
||||
int pick_one(struct rogue_state *rs,struct obj_info *info, int nitems);
|
||||
void pick_up(struct rogue_state *rs,char ch);
|
||||
void picky_inven(struct rogue_state *rs);
|
||||
void pr_spec(struct obj_info *info, int nitems);
|
||||
void pr_list(void);
|
||||
void put_bool(void *b);
|
||||
void put_inv_t(void *ip);
|
||||
void put_str(void *str);
|
||||
void put_things(struct rogue_state *rs);
|
||||
void putpass(coord *cp);
|
||||
void print_disc(struct rogue_state *rs,char);
|
||||
void quaff(struct rogue_state *rs);
|
||||
void raise_level(struct rogue_state *rs);
|
||||
char randmonster(bool wander);
|
||||
void read_scroll(struct rogue_state *rs);
|
||||
void relocate(struct rogue_state *rs,THING *th, coord *new_loc);
|
||||
void remove_mon(struct rogue_state *rs,coord *mp, THING *tp, bool waskill);
|
||||
void reset_last(void);
|
||||
bool restore(struct rogue_state *rs,char *file, char **envp);
|
||||
int ring_eat(int hand);
|
||||
void ring_on(struct rogue_state *rs);
|
||||
void ring_off(struct rogue_state *rs);
|
||||
int rnd(int range);
|
||||
int rnd_room(void);
|
||||
int roll(int number, int sides);
|
||||
int rs_save_file(struct rogue_state *rs,FILE *savef);
|
||||
int rs_restore_file(FILE *inf);
|
||||
void runto(struct rogue_state *rs,coord *runner);
|
||||
void rust_armor(struct rogue_state *rs,THING *arm);
|
||||
int save(int which);
|
||||
void save_file(struct rogue_state *rs,FILE *savef,int32_t guiflag);
|
||||
void save_game(struct rogue_state *rs);
|
||||
int save_throw(int which, THING *tp);
|
||||
void score(struct rogue_state *rs,int amount, int flags, char monst);
|
||||
void search(struct rogue_state *rs);
|
||||
void set_know(THING *obj, struct obj_info *info);
|
||||
void set_oldch(THING *tp, coord *cp);
|
||||
void setup(void);
|
||||
void shell(struct rogue_state *rs);
|
||||
bool show_floor(void);
|
||||
void show_map(void);
|
||||
void show_win(struct rogue_state *rs,char *message);
|
||||
int sign(int nm);
|
||||
int spread(int nm);
|
||||
void start_daemon(void (*func)(struct rogue_state *rs,int), int arg, int type);
|
||||
void start_score(void);
|
||||
void status(struct rogue_state *rs);
|
||||
int step_ok(int ch);
|
||||
void strucpy(char *s1, char *s2, int len);
|
||||
int swing(int at_lvl, int op_arm, int wplus);
|
||||
void take_off(struct rogue_state *rs);
|
||||
void teleport(struct rogue_state *rs);
|
||||
void total_winner(struct rogue_state *rs);
|
||||
void thunk(struct rogue_state *rs,THING *weap, char *mname, bool noend);
|
||||
void treas_room(struct rogue_state *rs);
|
||||
void turnref(void);
|
||||
void u_level(struct rogue_state *rs);
|
||||
void uncurse(THING *obj);
|
||||
void unlock_sc(void);
|
||||
void vert(struct room *rp, int startx);
|
||||
void wait_for(struct rogue_state *rs,int ch);
|
||||
THING *wake_monster(struct rogue_state *rs,int y, int x);
|
||||
void wanderer(struct rogue_state *rs);
|
||||
void waste_time(struct rogue_state *rs);
|
||||
void wear(struct rogue_state *rs);
|
||||
void whatis(struct rogue_state *rs,bool insist, int type);
|
||||
void wield(struct rogue_state *rs);
|
||||
|
||||
bool chase(THING *tp, coord *ee);
|
||||
bool diag_ok(coord *sp, coord *ep);
|
||||
bool dropcheck(struct rogue_state *rs,THING *obj);
|
||||
bool fallpos(coord *pos, coord *newpos);
|
||||
bool find_floor(struct rogue_state *rs,struct room *rp, coord *cp, int limit, bool monst);
|
||||
bool is_magic(THING *obj);
|
||||
bool is_symlink(char *sp);
|
||||
bool levit_check(struct rogue_state *rs);
|
||||
bool pack_room(struct rogue_state *rs,bool from_floor, THING *obj);
|
||||
bool roll_em(THING *thatt, THING *thdef, THING *weap, bool hurl);
|
||||
bool see_monst(THING *mp);
|
||||
bool seen_stairs(void);
|
||||
bool turn_ok(int y, int x);
|
||||
bool turn_see(struct rogue_state *rs,bool turn_off);
|
||||
bool is_current(struct rogue_state *rs,THING *obj);
|
||||
int passwd(void);
|
||||
|
||||
char be_trapped(struct rogue_state *rs,coord *tc);
|
||||
char floor_ch(void);
|
||||
char pack_char(void);
|
||||
char readchar(struct rogue_state *rs);
|
||||
char rnd_thing(void);
|
||||
|
||||
char *charge_str(THING *obj);
|
||||
char *choose_str(char *ts, char *ns);
|
||||
char *inv_name(THING *obj, bool drop);
|
||||
char *nullstr(THING *ignored);
|
||||
char *num(int n1, int n2, char type);
|
||||
char *ring_num(THING *obj);
|
||||
char *set_mname(THING *tp);
|
||||
char *vowelstr(char *str);
|
||||
|
||||
int get_bool(struct rogue_state *rs,void *vp, WINDOW *win);
|
||||
int get_inv_t(struct rogue_state *rs,void *vp, WINDOW *win);
|
||||
int get_num(struct rogue_state *rs,void *vp, WINDOW *win);
|
||||
int get_sf(struct rogue_state *rs,void *vp, WINDOW *win);
|
||||
int get_str(struct rogue_state *rs,void *vopt, WINDOW *win);
|
||||
int trip_ch(int y, int x, int ch);
|
||||
|
||||
coord *find_dest(struct rogue_state *rs,THING *tp);
|
||||
coord *rndmove(THING *who);
|
||||
|
||||
THING *find_obj(struct rogue_state *rs,int y, int x);
|
||||
THING *get_item(struct rogue_state *rs,char *purpose, int type);
|
||||
THING *leave_pack(struct rogue_state *rs,THING *obj, bool newobj, bool all);
|
||||
THING *new_item(void);
|
||||
THING *new_thing(struct rogue_state *rs);
|
||||
void end_line(struct rogue_state *rs);
|
||||
int32_t num_packitems(struct rogue_state *rs);
|
||||
int32_t rogue_total(THING *o);
|
||||
|
||||
void runners(struct rogue_state *rs,int);
|
||||
void land(struct rogue_state *rs,int);
|
||||
void visuals(struct rogue_state *rs,int);
|
||||
void come_down(struct rogue_state *rs,int);
|
||||
void stomach(struct rogue_state *rs,int);
|
||||
void nohaste(struct rogue_state *rs,int);
|
||||
void sight(struct rogue_state *rs,int);
|
||||
void unconfuse(struct rogue_state *rs,int);
|
||||
void rollwand(struct rogue_state *rs,int);
|
||||
void unsee(struct rogue_state *rs,int);
|
||||
void swander(struct rogue_state *rs,int);
|
||||
void doctor(struct rogue_state *rs,int);
|
||||
|
||||
void playit(struct rogue_state *rs);
|
||||
|
||||
struct room *roomin(struct rogue_state *rs,coord *cp);
|
||||
int32_t thing_find(THING *ptr);
|
||||
|
||||
#define MAXDAEMONS 20
|
||||
|
||||
extern struct delayed_action {
|
||||
int d_type;
|
||||
void (*d_func)(struct rogue_state *rs,int);
|
||||
int d_arg;
|
||||
int d_time;
|
||||
} d_list[MAXDAEMONS];
|
||||
|
||||
typedef struct {
|
||||
char *st_name;
|
||||
int st_value;
|
||||
} STONE;
|
||||
|
||||
extern int total;
|
||||
extern int between;
|
||||
extern int group;
|
||||
extern coord nh;
|
||||
extern const char *rainbow[];
|
||||
extern int cNCOLORS;
|
||||
extern const STONE stones[];
|
||||
extern int cNSTONES;
|
||||
extern const char *wood[];
|
||||
extern int cNWOOD;
|
||||
extern const char *metal[];
|
||||
extern int cNMETAL;
|
||||
|
||||
//extern WINDOW *stdscr,*curscr;
|
||||
|
||||
#endif
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,892 +0,0 @@
|
||||
.\"
|
||||
.\" @(#)rogue.me 6.2 (Berkeley) 4/28/86
|
||||
.\"
|
||||
.\" Rogue: Exploring the Dungeons of Doom
|
||||
.\" Copyright (C) 1980-1983, 1985, 1986 Michael Toy, Ken Arnold and Glenn Wichman
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" See the file LICENSE.TXT for full copyright and licensing information.
|
||||
.\"
|
||||
.ds E \s-2<ESCAPE>\s0
|
||||
.ds R \s-2<RETURN>\s0
|
||||
.ds U \s-2UNIX\s0
|
||||
.ie t .ds _ \d\(mi\u
|
||||
.el .ds _ _
|
||||
.de Cs
|
||||
\&\\$3\*(lq\\$1\*(rq\\$2
|
||||
..
|
||||
.sp 5
|
||||
.ce 1000
|
||||
.ps +4
|
||||
.vs +4p
|
||||
.b
|
||||
A Guide to the Dungeons of Doom
|
||||
.r
|
||||
.vs
|
||||
.ps
|
||||
.sp 2
|
||||
.i
|
||||
Michael C. Toy
|
||||
Kenneth C. R. C. Arnold
|
||||
.r
|
||||
.sp 2
|
||||
Computer Systems Research Group
|
||||
Department of Electrical Engineering and Computer Science
|
||||
University of California
|
||||
Berkeley, California 94720
|
||||
.sp 4
|
||||
.i ABSTRACT
|
||||
.ce 0
|
||||
.(b I F
|
||||
.bi Rogue
|
||||
is a visual CRT based fantasy game
|
||||
which runs under the \*U\(dg timesharing system.
|
||||
.(f
|
||||
\fR\(dg\*U is a trademark of Bell Laboratories\fP
|
||||
.)f
|
||||
This paper describes how to play rogue,
|
||||
and gives a few hints
|
||||
for those who might otherwise get lost in the Dungeons of Doom.
|
||||
.)b
|
||||
\".he '''\fBA Guide to the Dungeons of Doom\fP'
|
||||
\" .fo ''- % -''
|
||||
.eh 'USD:33-%''A Guide to the Dungeons of Doom'
|
||||
.oh 'A Guide to the Dungeons of Doom''USD:33-%'
|
||||
.sh 1 Introduction
|
||||
.pp
|
||||
You have just finished your years as a student at the local fighter's guild.
|
||||
After much practice and sweat you have finally completed your training
|
||||
and are ready to embark upon a perilous adventure.
|
||||
As a test of your skills,
|
||||
the local guildmasters have sent you into the Dungeons of Doom.
|
||||
Your task is to return with the Amulet of Yendor.
|
||||
Your reward for the completion of this task
|
||||
will be a full membership in the local guild.
|
||||
In addition,
|
||||
you are allowed to keep all the loot you bring back from the dungeons.
|
||||
.pp
|
||||
In preparation for your journey,
|
||||
you are given an enchanted mace,
|
||||
a bow, and a quiver of arrows
|
||||
taken from a dragon's hoard in the far off Dark Mountains.
|
||||
You are also outfitted with elf-crafted armor
|
||||
and given enough food to reach the dungeons.
|
||||
You say goodbye to family and friends for what may be the last time
|
||||
and head up the road.
|
||||
.pp
|
||||
You set out on your way to the dungeons
|
||||
and after several days of uneventful travel,
|
||||
you see the ancient ruins
|
||||
that mark the entrance to the Dungeons of Doom.
|
||||
It is late at night,
|
||||
so you make camp at the entrance
|
||||
and spend the night sleeping under the open skies.
|
||||
In the morning you gather your weapons,
|
||||
put on your armor,
|
||||
eat what is almost your last food,
|
||||
and enter the dungeons.
|
||||
.sh 1 "What is going on here?"
|
||||
.pp
|
||||
You have just begun a game of rogue.
|
||||
Your goal is to grab as much treasure as you can,
|
||||
find the Amulet of Yendor,
|
||||
and get out of the Dungeons of Doom alive.
|
||||
On the screen,
|
||||
a map of where you have been
|
||||
and what you have seen on the current dungeon level is kept.
|
||||
As you explore more of the level,
|
||||
it appears on the screen in front of you.
|
||||
.pp
|
||||
Rogue differs from most computer fantasy games in that it is screen oriented.
|
||||
Commands are all one or two keystrokes\**
|
||||
.(f
|
||||
\** As opposed to pseudo English sentences.
|
||||
.)f
|
||||
and the results of your commands
|
||||
are displayed graphically on the screen rather
|
||||
than being explained in words.\**
|
||||
.(f
|
||||
\** A minimum screen size of 24 lines by 80 columns is required.
|
||||
If the screen is larger, only the 24x80 section will be used
|
||||
for the map.
|
||||
.)f
|
||||
.pp
|
||||
Another major difference between rogue and other computer fantasy games
|
||||
is that once you have solved all the puzzles in a standard fantasy game,
|
||||
it has lost most of its excitement and it ceases to be fun.
|
||||
Rogue,
|
||||
on the other hand,
|
||||
generates a new dungeon every time you play it
|
||||
and even the author finds it an entertaining and exciting game.
|
||||
.sh 1 "What do all those things on the screen mean?"
|
||||
.pp
|
||||
In order to understand what is going on in rogue
|
||||
you have to first get some grasp of what rogue is doing with the screen.
|
||||
The rogue screen is intended
|
||||
to replace the \*(lqYou can see ...\*(rq descriptions
|
||||
of standard fantasy games.
|
||||
Figure 1 is a sample of what a rogue screen might look like.
|
||||
.(z
|
||||
.hl
|
||||
.nf
|
||||
.TS
|
||||
center;
|
||||
ce0 ce0 ce0 ce0 ce0 ce0 ce0 ce0 ce0 ce0 ce0 ce.
|
||||
- - - - - - - - - - - -
|
||||
| . . . . . . . . . . +
|
||||
| . . @ . . . . ] . . |
|
||||
| . . . . B . . . . . |
|
||||
| . . . . . . . . . . |
|
||||
- - - - - + - - - - - -
|
||||
.TE
|
||||
|
||||
|
||||
.ce 1000
|
||||
Level: 1 Gold: 0 Hp: 12(12) Str: 16(16) Arm: 4 Exp: 1/0
|
||||
|
||||
Figure 1
|
||||
.ce
|
||||
.hl
|
||||
.)z
|
||||
.sh 2 "The bottom line"
|
||||
.pp
|
||||
At the bottom line of the screen
|
||||
are a few pieces of cryptic information
|
||||
describing your current status.
|
||||
Here is an explanation of what these things mean:
|
||||
.ip Level \w'Level\ \ 'u
|
||||
This number indicates how deep you have gone in the dungeon.
|
||||
It starts at one and goes up as you go deeper into the dungeon.
|
||||
.ip Gold \w'Level\ \ 'u
|
||||
The number of gold pieces you have managed to find
|
||||
and keep with you so far.
|
||||
.ip Hp \w'Level\ \ 'u
|
||||
Your current and maximum health points.
|
||||
Health points indicate how much damage you can take before you die.
|
||||
The more you get hit in a fight,
|
||||
the lower they get.
|
||||
You can regain health points by resting.
|
||||
The number in parentheses
|
||||
is the maximum number your health points can reach.
|
||||
.ip Str \w'Level\ \ 'u
|
||||
Your current strength and maximum ever strength.
|
||||
This can be any integer less than or equal to 31,
|
||||
or greater than or equal to three.
|
||||
The higher the number,
|
||||
the stronger you are.
|
||||
The number in the parentheses
|
||||
is the maximum strength you have attained so far this game.
|
||||
.ip Arm \w'Level\ \ 'u
|
||||
Your current armor protection.
|
||||
This number indicates how effective your armor is
|
||||
in stopping blows from unfriendly creatures.
|
||||
The higher this number is,
|
||||
the more effective the armor.
|
||||
.ip Exp \w'Level\ \ 'u
|
||||
These two numbers give your current experience level
|
||||
and experience points.
|
||||
As you do things,
|
||||
you gain experience points.
|
||||
At certain experience point totals,
|
||||
you gain an experience level.
|
||||
The more experienced you are,
|
||||
the better you are able to fight and to withstand magical attacks.
|
||||
.sh 2 "The top line"
|
||||
.pp
|
||||
The top line of the screen is reserved
|
||||
for printing messages that describe things
|
||||
that are impossible to represent visually.
|
||||
If you see a \*(lq--More--\*(rq on the top line,
|
||||
this means that rogue wants to print another message on the screen,
|
||||
but it wants to make certain
|
||||
that you have read the one that is there first.
|
||||
To read the next message,
|
||||
just type a space.
|
||||
.sh 2 "The rest of the screen"
|
||||
.pp
|
||||
The rest of the screen is the map of the level
|
||||
as you have explored it so far.
|
||||
Each symbol on the screen represents something.
|
||||
Here is a list of what the various symbols mean:
|
||||
.ip @
|
||||
This symbol represents you, the adventurer.
|
||||
.ip "-\^|"
|
||||
These symbols represent the walls of rooms.
|
||||
.ip +
|
||||
A door to/from a room.
|
||||
.ip .
|
||||
The floor of a room.
|
||||
.ip #
|
||||
The floor of a passage between rooms.
|
||||
.ip *
|
||||
A pile or pot of gold.
|
||||
.ip )
|
||||
A weapon of some sort.
|
||||
.ip ]
|
||||
A piece of armor.
|
||||
.ip !
|
||||
A flask containing a magic potion.
|
||||
.ip ?
|
||||
A piece of paper, usually a magic scroll.
|
||||
.ip =
|
||||
A ring with magic properties
|
||||
.ip /
|
||||
A magical staff or wand
|
||||
.ip ^
|
||||
A trap, watch out for these.
|
||||
.ip %
|
||||
A staircase to other levels
|
||||
.ip :
|
||||
A piece of food.
|
||||
.ip A-Z
|
||||
The uppercase letters
|
||||
represent the various inhabitants of the Dungeons of Doom.
|
||||
Watch out, they can be nasty and vicious.
|
||||
.sh 1 Commands
|
||||
.pp
|
||||
Commands are given to rogue by typing one or two characters.
|
||||
Most commands can be preceded by a count to repeat them
|
||||
(e.g. typing
|
||||
.Cs 10s
|
||||
will do ten searches).
|
||||
Commands for which counts make no sense
|
||||
have the count ignored.
|
||||
To cancel a count or a prefix,
|
||||
type \*E.
|
||||
The list of commands is rather long,
|
||||
but it can be read at any time during the game with the
|
||||
.Cs ?
|
||||
command.
|
||||
Here it is for reference,
|
||||
with a short explanation of each command.
|
||||
.ip ?
|
||||
The help command.
|
||||
Asks for a character to give help on.
|
||||
If you type a
|
||||
.Cs * ,
|
||||
it will list all the commands,
|
||||
otherwise it will explain what the character you typed does.
|
||||
.ip /
|
||||
This is the \*(lqWhat is that on the screen?\*(rq command.
|
||||
A
|
||||
.Cs /
|
||||
followed by any character that you see on the level,
|
||||
will tell you what that character is.
|
||||
For instance,
|
||||
typing
|
||||
.Cs /@
|
||||
will tell you that the
|
||||
.Cs @
|
||||
symbol represents you, the player.
|
||||
.ip "h, H, ^H"
|
||||
Move left.
|
||||
You move one space to the left.
|
||||
If you use upper case
|
||||
.Cs h ,
|
||||
you will continue to move left until you run into something.
|
||||
This works for all movement commands
|
||||
(e.g.
|
||||
.Cs L
|
||||
means run in direction
|
||||
.Cs l )
|
||||
If you use the \*(lqcontrol\*(rq
|
||||
.Cs h ,
|
||||
you will continue moving in the specified direction
|
||||
until you pass something interesting or run into a wall.
|
||||
You should experiment with this,
|
||||
since it is a very useful command,
|
||||
but very difficult to describe.
|
||||
This also works for all movement commands.
|
||||
.ip j
|
||||
Move down.
|
||||
.ip k
|
||||
Move up.
|
||||
.ip l
|
||||
Move right.
|
||||
.ip y
|
||||
Move diagonally up and left.
|
||||
.ip u
|
||||
Move diagonally up and right.
|
||||
.ip b
|
||||
Move diagonally down and left.
|
||||
.ip n
|
||||
Move diagonally down and right.
|
||||
.ip t
|
||||
Throw an object.
|
||||
This is a prefix command.
|
||||
When followed with a direction
|
||||
it throws an object in the specified direction.
|
||||
(e.g. type
|
||||
.Cs th
|
||||
to throw
|
||||
something to the left.)
|
||||
.ip f
|
||||
Fight until someone dies.
|
||||
When followed with a direction
|
||||
this will force you to fight the creature in that direction
|
||||
until either you or it bites the big one.
|
||||
.ip m
|
||||
Move onto something without picking it up.
|
||||
This will move you one space in the direction you specify and,
|
||||
if there is an object there you can pick up,
|
||||
it won't do it.
|
||||
.ip z
|
||||
Zap prefix.
|
||||
Point a staff or wand in a given direction
|
||||
and fire it.
|
||||
Even non-directional staves must be pointed in some direction
|
||||
to be used.
|
||||
.ip ^
|
||||
Identify trap command.
|
||||
If a trap is on your map
|
||||
and you can't remember what type it is,
|
||||
you can get rogue to remind you
|
||||
by getting next to it and typing
|
||||
.Cs ^
|
||||
followed by the direction that would move you on top of it.
|
||||
.ip s
|
||||
Search for traps and secret doors.
|
||||
Examine each space immediately adjacent to you
|
||||
for the existence of a trap or secret door.
|
||||
There is a large chance that even if there is something there,
|
||||
you won't find it,
|
||||
so you might have to search a while before you find something.
|
||||
.ip >
|
||||
Climb down a staircase to the next level.
|
||||
Not surprisingly, this can only be done if you are standing on staircase.
|
||||
.ip <
|
||||
Climb up a staircase to the level above.
|
||||
This can't be done without the Amulet of Yendor in your possession.
|
||||
.ip "."
|
||||
Rest.
|
||||
This is the \*(lqdo nothing\*(rq command.
|
||||
This is good for waiting and healing.
|
||||
.ip ,
|
||||
Pick up something.
|
||||
This picks up whatever you are currently standing on,
|
||||
if you are standing on anything at all.
|
||||
.ip i
|
||||
Inventory.
|
||||
List what you are carrying in your pack.
|
||||
.ip I
|
||||
Selective inventory.
|
||||
Tells you what a single item in your pack is.
|
||||
.ip q
|
||||
Quaff one of the potions you are carrying.
|
||||
.ip r
|
||||
Read one of the scrolls in your pack.
|
||||
.ip e
|
||||
Eat food from your pack.
|
||||
.ip w
|
||||
Wield a weapon.
|
||||
Take a weapon out of your pack and carry it for use in combat,
|
||||
replacing the one you are currently using (if any).
|
||||
.ip W
|
||||
Wear armor.
|
||||
You can only wear one suit of armor at a time.
|
||||
This takes extra time.
|
||||
.ip T
|
||||
Take armor off.
|
||||
You can't remove armor that is cursed.
|
||||
This takes extra time.
|
||||
.ip P
|
||||
Put on a ring.
|
||||
You can wear only two rings at a time
|
||||
(one on each hand).
|
||||
If you aren't wearing any rings,
|
||||
this command will ask you which hand you want to wear it on,
|
||||
otherwise, it will place it on the unused hand.
|
||||
The program assumes that you wield your sword in your right hand.
|
||||
.ip R
|
||||
Remove a ring.
|
||||
If you are only wearing one ring,
|
||||
this command takes it off.
|
||||
If you are wearing two,
|
||||
it will ask you which one you wish to remove,
|
||||
.ip d
|
||||
Drop an object.
|
||||
Take something out of your pack and leave it lying on the floor.
|
||||
Only one object can occupy each space.
|
||||
You cannot drop a cursed object at all
|
||||
if you are wielding or wearing it.
|
||||
.ip c
|
||||
Call an object something.
|
||||
If you have a type of object in your pack
|
||||
which you wish to remember something about,
|
||||
you can use the call command to give a name to that type of object.
|
||||
This is usually used when you figure out what a
|
||||
potion, scroll, ring, or staff is
|
||||
after you pick it up,
|
||||
or when you want to remember
|
||||
which of those swords in your pack you were wielding.
|
||||
.ip D
|
||||
Print out which things you've discovered something about.
|
||||
This command will ask you what type of thing you are interested in.
|
||||
If you type the character for a given type of object
|
||||
(\fIe.g.\fP
|
||||
.Cs !
|
||||
for potion)
|
||||
it will tell you which kinds of that type of object you've discovered
|
||||
(\fIi.e.\fP, figured out what they are).
|
||||
This command works for potions, scrolls, rings, and staves and wands.
|
||||
.ip o
|
||||
Examine and set options.
|
||||
This command is further explained in the section on options.
|
||||
.ip ^R
|
||||
Redraws the screen.
|
||||
Useful if spurious messages or transmission errors
|
||||
have messed up the display.
|
||||
.ip ^P
|
||||
Print last message.
|
||||
Useful when a message disappears before you can read it.
|
||||
This only repeats the last message
|
||||
that was not a mistyped command
|
||||
so that you don't loose anything by accidentally typing
|
||||
the wrong character instead of ^P.
|
||||
.ip \*E
|
||||
Cancel a command, prefix, or count.
|
||||
.ip !
|
||||
Escape to a shell for some commands.
|
||||
.ip Q
|
||||
Quit.
|
||||
Leave the game.
|
||||
.ip S
|
||||
Save the current game in a file.
|
||||
It will ask you whether you wish to use the default save file.
|
||||
.i Caveat :
|
||||
Rogue won't let you start up a copy of a saved game,
|
||||
and it removes the save file as soon as you start up a restored game.
|
||||
This is to prevent people from saving a game just before a dangerous position
|
||||
and then restarting it if they die.
|
||||
To restore a saved game,
|
||||
give the file name as an argument to rogue.
|
||||
As in
|
||||
.ti +1i
|
||||
.nf
|
||||
% rogue \fIsave\*_file\fP
|
||||
.ip
|
||||
To restart from the default save file (see below),
|
||||
run
|
||||
.ti +1i
|
||||
.nf
|
||||
% rogue \-r
|
||||
.ip v
|
||||
Prints the program version number.
|
||||
.ip )
|
||||
Print the weapon you are currently wielding
|
||||
.ip ]
|
||||
Print the armor you are currently wearing
|
||||
.ip =
|
||||
Print the rings you are currently wearing
|
||||
.ip @
|
||||
Reprint the status line on the message line
|
||||
.sh 1 Rooms
|
||||
.pp
|
||||
Rooms in the dungeons are either lit or dark.
|
||||
If you walk into a lit room,
|
||||
the entire room will be drawn on the screen as soon as you enter.
|
||||
If you walk into a dark room,
|
||||
it will only be displayed as you explore it.
|
||||
Upon leaving a room,
|
||||
all monsters inside the room
|
||||
are erased from the screen.
|
||||
In the darkness you can only see one space
|
||||
in all directions around you.
|
||||
A corridor is always dark.
|
||||
.sh 1 Fighting
|
||||
.pp
|
||||
If you see a monster and you wish to fight it,
|
||||
just attempt to run into it.
|
||||
Many times a monster you find will mind its own business
|
||||
unless you attack it.
|
||||
It is often the case that discretion is the better part of valor.
|
||||
.sh 1 "Objects you can find"
|
||||
.pp
|
||||
When you find something in the dungeon,
|
||||
it is common to want to pick the object up.
|
||||
This is accomplished in rogue by walking over the object
|
||||
(unless you use the
|
||||
.Cs m
|
||||
prefix, see above).
|
||||
If you are carrying too many things,
|
||||
the program will tell you and it won't pick up the object,
|
||||
otherwise it will add it to your pack
|
||||
and tell you what you just picked up.
|
||||
.pp
|
||||
Many of the commands that operate on objects must prompt you
|
||||
to find out which object you want to use.
|
||||
If you change your mind and don't want to do that command after all,
|
||||
just type an \*E and the command will be aborted.
|
||||
.pp
|
||||
Some objects, like armor and weapons,
|
||||
are easily differentiated.
|
||||
Others, like scrolls and potions,
|
||||
are given labels which vary according to type.
|
||||
During a game,
|
||||
any two of the same kind of object
|
||||
with the same label
|
||||
are the same type.
|
||||
However,
|
||||
the labels will vary from game to game.
|
||||
.pp
|
||||
When you use one of these labeled objects,
|
||||
if its effect is obvious,
|
||||
rogue will remember what it is for you.
|
||||
If it's effect isn't extremely obvious
|
||||
you will be asked what you want to scribble on it
|
||||
so you will recognize it later,
|
||||
or you can use the
|
||||
.Cs call
|
||||
command
|
||||
(see above).
|
||||
.sh 2 Weapons
|
||||
.pp
|
||||
Some weapons,
|
||||
like arrows,
|
||||
come in bunches,
|
||||
but most come one at a time.
|
||||
In order to use a weapon,
|
||||
you must wield it.
|
||||
To fire an arrow out of a bow,
|
||||
you must first wield the bow,
|
||||
then throw the arrow.
|
||||
You can only wield one weapon at a time,
|
||||
but you can't change weapons if the one
|
||||
you are currently wielding is cursed.
|
||||
The commands to use weapons are
|
||||
.Cs w
|
||||
(wield)
|
||||
and
|
||||
.Cs t
|
||||
(throw).
|
||||
.sh 2 Armor
|
||||
.pp
|
||||
There are various sorts of armor lying around in the dungeon.
|
||||
Some of it is enchanted,
|
||||
some is cursed,
|
||||
and some is just normal.
|
||||
Different armor types have different armor protection.
|
||||
The higher the armor protection,
|
||||
the more protection the armor affords against the blows of monsters.
|
||||
Here is a list of the various armor types and their normal armor protection:
|
||||
.(b
|
||||
.TS
|
||||
box center;
|
||||
l r.
|
||||
\ \ \fIType Protection\fP
|
||||
None 0
|
||||
Leather armor 2
|
||||
Studded leather / Ring mail 3
|
||||
Scale mail 4
|
||||
Chain mail 5
|
||||
Banded mail / Splint mail 6
|
||||
Plate mail 7
|
||||
.TE
|
||||
.)b
|
||||
.lp
|
||||
If a piece of armor is enchanted,
|
||||
its armor protection will be higher than normal.
|
||||
If a suit of armor is cursed,
|
||||
its armor protection will be lower,
|
||||
and you will not be able to remove it.
|
||||
However, not all armor with a protection that is lower than normal is cursed.
|
||||
.pp
|
||||
The commands to use weapons are
|
||||
.Cs W
|
||||
(wear)
|
||||
and
|
||||
.Cs T
|
||||
(take off).
|
||||
.sh 2 Scrolls
|
||||
.pp
|
||||
Scrolls come with titles in an unknown tongue\**.
|
||||
.(f
|
||||
\** Actually, it's a dialect spoken only by the twenty-seven members
|
||||
of a tribe in Outer Mongolia,
|
||||
but you're not supposed to
|
||||
.i know
|
||||
that.
|
||||
.)f
|
||||
After you read a scroll,
|
||||
it disappears from your pack.
|
||||
The command to use a scroll is
|
||||
.Cs r
|
||||
(read).
|
||||
.sh 2 Potions
|
||||
.pp
|
||||
Potions are labeled by the color of the liquid inside the flask.
|
||||
They disappear after being quaffed.
|
||||
The command to use a scroll is
|
||||
.Cs q
|
||||
(quaff).
|
||||
.sh 2 "Staves and Wands"
|
||||
.pp
|
||||
Staves and wands do the same kinds of things.
|
||||
Staves are identified by a type of wood;
|
||||
wands by a type of metal or bone.
|
||||
They are generally things you want to do to something
|
||||
over a long distance,
|
||||
so you must point them at what you wish to affect
|
||||
to use them.
|
||||
Some staves are not affected by the direction they are pointed, though.
|
||||
Staves come with multiple magic charges,
|
||||
the number being random,
|
||||
and when they are used up,
|
||||
the staff is just a piece of wood or metal.
|
||||
.pp
|
||||
The command to use a wand or staff is
|
||||
.Cs z
|
||||
(zap)
|
||||
.sh 2 Rings
|
||||
.pp
|
||||
Rings are very useful items,
|
||||
since they are relatively permanent magic,
|
||||
unlike the usually fleeting effects of potions, scrolls, and staves.
|
||||
Of course,
|
||||
the bad rings are also more powerful.
|
||||
Most rings also cause you to use up food more rapidly,
|
||||
the rate varying with the type of ring.
|
||||
Rings are differentiated by their stone settings.
|
||||
The commands to use rings are
|
||||
.Cs P
|
||||
(put on)
|
||||
and
|
||||
.Cs R
|
||||
(remove).
|
||||
.sh 2 Food
|
||||
.pp
|
||||
Food is necessary to keep you going.
|
||||
If you go too long without eating you will faint,
|
||||
and eventually die of starvation.
|
||||
The command to use food is
|
||||
.Cs e
|
||||
(eat).
|
||||
.sh 1 Options
|
||||
.pp
|
||||
Due to variations in personal tastes
|
||||
and conceptions of the way rogue should do things,
|
||||
there are a set of options you can set
|
||||
that cause rogue to behave in various different ways.
|
||||
.sh 2 "Setting the options"
|
||||
.pp
|
||||
There are two ways to set the options.
|
||||
The first is with the
|
||||
.Cs o
|
||||
command of rogue;
|
||||
the second is with the
|
||||
.Cs ROGUEOPTS
|
||||
environment variable\**.
|
||||
.(f
|
||||
\** On Version 6 systems,
|
||||
there is no equivalent of the ROGUEOPTS feature.
|
||||
.br
|
||||
.)f
|
||||
.br
|
||||
.sh 3 "Using the `o' command"
|
||||
.pp
|
||||
When you type
|
||||
.Cs o
|
||||
in rogue,
|
||||
it clears the screen
|
||||
and displays the current settings for all the options.
|
||||
It then places the cursor by the value of the first option
|
||||
and waits for you to type.
|
||||
You can type a \*R
|
||||
which means to go to the next option,
|
||||
a
|
||||
.Cs \-
|
||||
which means to go to the previous option,
|
||||
an \*E
|
||||
which means to return to the game,
|
||||
or you can give the option a value.
|
||||
For boolean options this merely involves typing
|
||||
.Cs t
|
||||
for true or
|
||||
.Cs f
|
||||
for false.
|
||||
For string options,
|
||||
type the new value followed by a \*R.
|
||||
.sh 3 "Using the ROGUEOPTS variable"
|
||||
.pp
|
||||
The ROGUEOPTS variable is a string
|
||||
containing a comma separated list of initial values
|
||||
for the various options.
|
||||
Boolean variables can be turned on by listing their name
|
||||
or turned off by putting a
|
||||
.Cs no
|
||||
in front of the name.
|
||||
Thus to set up an environment variable so that
|
||||
.b jump
|
||||
is on,
|
||||
.b terse
|
||||
is off,
|
||||
and the
|
||||
.b name
|
||||
is set to \*(lqBlue Meanie\*(rq,
|
||||
use the command
|
||||
.nf
|
||||
.ti +3n
|
||||
% setenv ROGUEOPTS "jump,noterse,name=Blue Meanie"\**
|
||||
.fi
|
||||
.(f
|
||||
\**
|
||||
For those of you who use the Bourne shell sh (1), the commands would be
|
||||
.in +3
|
||||
.nf
|
||||
$ ROGUEOPTS="jump,noterse,name=Blue Meanie"
|
||||
$ export ROGUEOPTS
|
||||
.fi
|
||||
.in +0
|
||||
.)f
|
||||
.sh 2 "Option list"
|
||||
.pp
|
||||
Here is a list of the options
|
||||
and an explanation of what each one is for.
|
||||
The default value for each is enclosed in square brackets.
|
||||
For character string options,
|
||||
input over fifty characters will be ignored.
|
||||
.ip "\fBterse\fP [\fI\^noterse\^\fP]"
|
||||
Useful for those who are tired of the sometimes lengthy messages of rogue.
|
||||
This is a useful option for playing on slow terminals,
|
||||
so this option defaults to
|
||||
.i terse
|
||||
if you
|
||||
are on a slow (1200 baud or under) terminal.
|
||||
.ip "\fBjump\fP [\fI\^nojump\^\fP]"
|
||||
If this option is set,
|
||||
running moves will not be displayed
|
||||
until you reach the end of the move.
|
||||
This saves considerable cpu and display time.
|
||||
This option defaults to
|
||||
.i jump
|
||||
if you are using a slow terminal.
|
||||
.ip "\fBflush\fP [\fI\^noflush\^\fP]"
|
||||
All typeahead is thrown away after each round of battle.
|
||||
This is useful for those who type far ahead
|
||||
and then watch in dismay as a Bat kills them.
|
||||
.ip "\fBseefloor\fP [\fI\^seefloor\^\fP]"
|
||||
Display the floor around you on the screen
|
||||
as you move through dark rooms.
|
||||
Due to the amount of characters generated,
|
||||
this option defaults to
|
||||
.i noseefloor
|
||||
if you are using a slow terminal.
|
||||
.ip "\fBpassgo\fP [\fI\^nopassgo\^\fP]"
|
||||
Follow turnings in passageways.
|
||||
If you run in a passage
|
||||
and you run into stone or a wall,
|
||||
rogue will see if it can turn to the right or left.
|
||||
If it can only turn one way,
|
||||
it will turn that way.
|
||||
If it can turn either or neither,
|
||||
it will stop.
|
||||
This algorithm can sometimes lead to slightly confusing occurrences
|
||||
which is why it defaults to \fInopassgo\fP.
|
||||
.ip "\fBtombstone\fP [\fI\^tombstone\^\fP]"
|
||||
Print out the tombstone at the end if you get killed.
|
||||
This is nice but slow, so you can turn it off if you like.
|
||||
.ip "\fBinven\fP [\fI\^overwrite\^\fP]"
|
||||
Inventory type.
|
||||
This can have one of three values:
|
||||
.i overwrite ,
|
||||
.i slow ,
|
||||
or
|
||||
.i clear .
|
||||
With
|
||||
.i overwrite
|
||||
the top lines of the map are overwritten
|
||||
with the list
|
||||
when inventory is requested
|
||||
or when
|
||||
\*(lqWhich item do you wish to \fB. . .\fP? \*(rq questions
|
||||
are answered with a
|
||||
.Cs * .
|
||||
However, if the list is longer than a screenful,
|
||||
the screen is cleared.
|
||||
With
|
||||
.i slow ,
|
||||
lists are displayed one item at a time on the top of the screen,
|
||||
and with
|
||||
.i clear ,
|
||||
the screen is cleared,
|
||||
the list is displayed,
|
||||
and then the dungeon level is re-displayed.
|
||||
Due to speed considerations,
|
||||
.i clear
|
||||
is the default for terminals without
|
||||
clear-to-end-of-line capabilities.
|
||||
.ip "\fBname\fP [account name]"
|
||||
This is the name of your character.
|
||||
It is used if you get on the top ten scorer's list.
|
||||
.ip "\fBfruit\fP [\fI\^slime-mold\^\fP]"
|
||||
This should hold the name of a fruit that you enjoy eating.
|
||||
It is basically a whimsey that rogue uses in a couple of places.
|
||||
.ip "\fBfile\fP [\fI\^~/rogue.save\^\fP]"
|
||||
The default file name for saving the game.
|
||||
If your phone is hung up by accident,
|
||||
rogue will automatically save the game in this file.
|
||||
The file name may start with the special character
|
||||
.Cs ~
|
||||
which expands to be your home directory.
|
||||
.sh 1 Scoring
|
||||
.pp
|
||||
Rogue usually maintains a list
|
||||
of the top scoring people or scores on your machine.
|
||||
Depending on how it is set up,
|
||||
it can post either the top scores
|
||||
or the top players.
|
||||
In the latter case,
|
||||
each account on the machine
|
||||
can post only one non-winning score on this list.
|
||||
If you score higher than someone else on this list,
|
||||
or better your previous score on the list,
|
||||
you will be inserted in the proper place
|
||||
under your current name.
|
||||
How many scores are kept
|
||||
can also be set up by whoever installs it on your machine.
|
||||
.pp
|
||||
If you quit the game, you get out with all of your gold intact.
|
||||
If, however, you get killed in the Dungeons of Doom,
|
||||
your body is forwarded to your next-of-kin,
|
||||
along with 90% of your gold;
|
||||
ten percent of your gold is kept by the Dungeons' wizard as a fee\**.
|
||||
.(f
|
||||
\** The Dungeon's wizard is named Wally the Wonder Badger.
|
||||
Invocations should be accompanied by a sizable donation.
|
||||
.)f
|
||||
This should make you consider whether you want to take one last hit
|
||||
at that monster and possibly live,
|
||||
or quit and thus stop with whatever you have.
|
||||
If you quit, you do get all your gold,
|
||||
but if you swing and live, you might find more.
|
||||
.pp
|
||||
If you just want to see what the current top players/games list is,
|
||||
you can type
|
||||
.ti +1i
|
||||
.nf
|
||||
% rogue \-s
|
||||
.br
|
||||
.sh 1 Acknowledgements
|
||||
.pp
|
||||
Rogue was originally conceived of by Glenn Wichman and Michael Toy.
|
||||
Ken Arnold and Michael Toy then smoothed out the user interface,
|
||||
and added jillions of new features.
|
||||
We would like to thank
|
||||
Bob Arnold,
|
||||
Michelle Busch,
|
||||
Andy Hatcher,
|
||||
Kipp Hickman,
|
||||
Mark Horton,
|
||||
Daniel Jensen,
|
||||
Bill Joy,
|
||||
Joe Kalash,
|
||||
Steve Maurer,
|
||||
Marty McNary,
|
||||
Jan Miller,
|
||||
and
|
||||
Scott Nelson
|
||||
for their ideas and assistance;
|
||||
and also the teeming multitudes
|
||||
who graciously ignored work, school, and social life to play rogue
|
||||
and send us bugs, complaints, suggestions, and just plain flames.
|
||||
And also Mom.
|
||||
@@ -1,892 +0,0 @@
|
||||
.\"
|
||||
.\" @(#)rogue.me 6.2 (Berkeley) 4/28/86
|
||||
.\"
|
||||
.\" Rogue: Exploring the Dungeons of Doom
|
||||
.\" Copyright (C) 1980-1983, 1985, 1986 Michael Toy, Ken Arnold and Glenn Wichman
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" See the file LICENSE.TXT for full copyright and licensing information.
|
||||
.\"
|
||||
.ds E \s-2<ESCAPE>\s0
|
||||
.ds R \s-2<RETURN>\s0
|
||||
.ds U \s-2UNIX\s0
|
||||
.ie t .ds _ \d\(mi\u
|
||||
.el .ds _ _
|
||||
.de Cs
|
||||
\&\\$3\*(lq\\$1\*(rq\\$2
|
||||
..
|
||||
.sp 5
|
||||
.ce 1000
|
||||
.ps +4
|
||||
.vs +4p
|
||||
.b
|
||||
A Guide to the Dungeons of Doom
|
||||
.r
|
||||
.vs
|
||||
.ps
|
||||
.sp 2
|
||||
.i
|
||||
Michael C. Toy
|
||||
Kenneth C. R. C. Arnold
|
||||
.r
|
||||
.sp 2
|
||||
Computer Systems Research Group
|
||||
Department of Electrical Engineering and Computer Science
|
||||
University of California
|
||||
Berkeley, California 94720
|
||||
.sp 4
|
||||
.i ABSTRACT
|
||||
.ce 0
|
||||
.(b I F
|
||||
.bi Rogue
|
||||
is a visual CRT based fantasy game
|
||||
which runs under the \*U\(dg timesharing system.
|
||||
.(f
|
||||
\fR\(dg\*U is a trademark of Bell Laboratories\fP
|
||||
.)f
|
||||
This paper describes how to play rogue,
|
||||
and gives a few hints
|
||||
for those who might otherwise get lost in the Dungeons of Doom.
|
||||
.)b
|
||||
\".he '''\fBA Guide to the Dungeons of Doom\fP'
|
||||
\" .fo ''- % -''
|
||||
.eh 'USD:33-%''A Guide to the Dungeons of Doom'
|
||||
.oh 'A Guide to the Dungeons of Doom''USD:33-%'
|
||||
.sh 1 Introduction
|
||||
.pp
|
||||
You have just finished your years as a student at the local fighter's guild.
|
||||
After much practice and sweat you have finally completed your training
|
||||
and are ready to embark upon a perilous adventure.
|
||||
As a test of your skills,
|
||||
the local guildmasters have sent you into the Dungeons of Doom.
|
||||
Your task is to return with the Amulet of Yendor.
|
||||
Your reward for the completion of this task
|
||||
will be a full membership in the local guild.
|
||||
In addition,
|
||||
you are allowed to keep all the loot you bring back from the dungeons.
|
||||
.pp
|
||||
In preparation for your journey,
|
||||
you are given an enchanted mace,
|
||||
a bow, and a quiver of arrows
|
||||
taken from a dragon's hoard in the far off Dark Mountains.
|
||||
You are also outfitted with elf-crafted armor
|
||||
and given enough food to reach the dungeons.
|
||||
You say goodbye to family and friends for what may be the last time
|
||||
and head up the road.
|
||||
.pp
|
||||
You set out on your way to the dungeons
|
||||
and after several days of uneventful travel,
|
||||
you see the ancient ruins
|
||||
that mark the entrance to the Dungeons of Doom.
|
||||
It is late at night,
|
||||
so you make camp at the entrance
|
||||
and spend the night sleeping under the open skies.
|
||||
In the morning you gather your weapons,
|
||||
put on your armor,
|
||||
eat what is almost your last food,
|
||||
and enter the dungeons.
|
||||
.sh 1 "What is going on here?"
|
||||
.pp
|
||||
You have just begun a game of rogue.
|
||||
Your goal is to grab as much treasure as you can,
|
||||
find the Amulet of Yendor,
|
||||
and get out of the Dungeons of Doom alive.
|
||||
On the screen,
|
||||
a map of where you have been
|
||||
and what you have seen on the current dungeon level is kept.
|
||||
As you explore more of the level,
|
||||
it appears on the screen in front of you.
|
||||
.pp
|
||||
Rogue differs from most computer fantasy games in that it is screen oriented.
|
||||
Commands are all one or two keystrokes\**
|
||||
.(f
|
||||
\** As opposed to pseudo English sentences.
|
||||
.)f
|
||||
and the results of your commands
|
||||
are displayed graphically on the screen rather
|
||||
than being explained in words.\**
|
||||
.(f
|
||||
\** A minimum screen size of 24 lines by 80 columns is required.
|
||||
If the screen is larger, only the 24x80 section will be used
|
||||
for the map.
|
||||
.)f
|
||||
.pp
|
||||
Another major difference between rogue and other computer fantasy games
|
||||
is that once you have solved all the puzzles in a standard fantasy game,
|
||||
it has lost most of its excitement and it ceases to be fun.
|
||||
Rogue,
|
||||
on the other hand,
|
||||
generates a new dungeon every time you play it
|
||||
and even the author finds it an entertaining and exciting game.
|
||||
.sh 1 "What do all those things on the screen mean?"
|
||||
.pp
|
||||
In order to understand what is going on in rogue
|
||||
you have to first get some grasp of what rogue is doing with the screen.
|
||||
The rogue screen is intended
|
||||
to replace the \*(lqYou can see ...\*(rq descriptions
|
||||
of standard fantasy games.
|
||||
Figure 1 is a sample of what a rogue screen might look like.
|
||||
.(z
|
||||
.hl
|
||||
.nf
|
||||
.TS
|
||||
center;
|
||||
ce0 ce0 ce0 ce0 ce0 ce0 ce0 ce0 ce0 ce0 ce0 ce.
|
||||
- - - - - - - - - - - -
|
||||
| . . . . . . . . . . +
|
||||
| . . @ . . . . ] . . |
|
||||
| . . . . B . . . . . |
|
||||
| . . . . . . . . . . |
|
||||
- - - - - + - - - - - -
|
||||
.TE
|
||||
|
||||
|
||||
.ce 1000
|
||||
Level: 1 Gold: 0 Hp: 12(12) Str: 16(16) Arm: 4 Exp: 1/0
|
||||
|
||||
Figure 1
|
||||
.ce
|
||||
.hl
|
||||
.)z
|
||||
.sh 2 "The bottom line"
|
||||
.pp
|
||||
At the bottom line of the screen
|
||||
are a few pieces of cryptic information
|
||||
describing your current status.
|
||||
Here is an explanation of what these things mean:
|
||||
.ip Level \w'Level\ \ 'u
|
||||
This number indicates how deep you have gone in the dungeon.
|
||||
It starts at one and goes up as you go deeper into the dungeon.
|
||||
.ip Gold \w'Level\ \ 'u
|
||||
The number of gold pieces you have managed to find
|
||||
and keep with you so far.
|
||||
.ip Hp \w'Level\ \ 'u
|
||||
Your current and maximum health points.
|
||||
Health points indicate how much damage you can take before you die.
|
||||
The more you get hit in a fight,
|
||||
the lower they get.
|
||||
You can regain health points by resting.
|
||||
The number in parentheses
|
||||
is the maximum number your health points can reach.
|
||||
.ip Str \w'Level\ \ 'u
|
||||
Your current strength and maximum ever strength.
|
||||
This can be any integer less than or equal to 31,
|
||||
or greater than or equal to three.
|
||||
The higher the number,
|
||||
the stronger you are.
|
||||
The number in the parentheses
|
||||
is the maximum strength you have attained so far this game.
|
||||
.ip Arm \w'Level\ \ 'u
|
||||
Your current armor protection.
|
||||
This number indicates how effective your armor is
|
||||
in stopping blows from unfriendly creatures.
|
||||
The higher this number is,
|
||||
the more effective the armor.
|
||||
.ip Exp \w'Level\ \ 'u
|
||||
These two numbers give your current experience level
|
||||
and experience points.
|
||||
As you do things,
|
||||
you gain experience points.
|
||||
At certain experience point totals,
|
||||
you gain an experience level.
|
||||
The more experienced you are,
|
||||
the better you are able to fight and to withstand magical attacks.
|
||||
.sh 2 "The top line"
|
||||
.pp
|
||||
The top line of the screen is reserved
|
||||
for printing messages that describe things
|
||||
that are impossible to represent visually.
|
||||
If you see a \*(lq--More--\*(rq on the top line,
|
||||
this means that rogue wants to print another message on the screen,
|
||||
but it wants to make certain
|
||||
that you have read the one that is there first.
|
||||
To read the next message,
|
||||
just type a space.
|
||||
.sh 2 "The rest of the screen"
|
||||
.pp
|
||||
The rest of the screen is the map of the level
|
||||
as you have explored it so far.
|
||||
Each symbol on the screen represents something.
|
||||
Here is a list of what the various symbols mean:
|
||||
.ip @
|
||||
This symbol represents you, the adventurer.
|
||||
.ip "-\^|"
|
||||
These symbols represent the walls of rooms.
|
||||
.ip +
|
||||
A door to/from a room.
|
||||
.ip .
|
||||
The floor of a room.
|
||||
.ip #
|
||||
The floor of a passage between rooms.
|
||||
.ip *
|
||||
A pile or pot of gold.
|
||||
.ip )
|
||||
A weapon of some sort.
|
||||
.ip ]
|
||||
A piece of armor.
|
||||
.ip !
|
||||
A flask containing a magic potion.
|
||||
.ip ?
|
||||
A piece of paper, usually a magic scroll.
|
||||
.ip =
|
||||
A ring with magic properties
|
||||
.ip /
|
||||
A magical staff or wand
|
||||
.ip ^
|
||||
A trap, watch out for these.
|
||||
.ip %
|
||||
A staircase to other levels
|
||||
.ip :
|
||||
A piece of food.
|
||||
.ip A-Z
|
||||
The uppercase letters
|
||||
represent the various inhabitants of the Dungeons of Doom.
|
||||
Watch out, they can be nasty and vicious.
|
||||
.sh 1 Commands
|
||||
.pp
|
||||
Commands are given to rogue by typing one or two characters.
|
||||
Most commands can be preceded by a count to repeat them
|
||||
(e.g. typing
|
||||
.Cs 10s
|
||||
will do ten searches).
|
||||
Commands for which counts make no sense
|
||||
have the count ignored.
|
||||
To cancel a count or a prefix,
|
||||
type \*E.
|
||||
The list of commands is rather long,
|
||||
but it can be read at any time during the game with the
|
||||
.Cs ?
|
||||
command.
|
||||
Here it is for reference,
|
||||
with a short explanation of each command.
|
||||
.ip ?
|
||||
The help command.
|
||||
Asks for a character to give help on.
|
||||
If you type a
|
||||
.Cs * ,
|
||||
it will list all the commands,
|
||||
otherwise it will explain what the character you typed does.
|
||||
.ip /
|
||||
This is the \*(lqWhat is that on the screen?\*(rq command.
|
||||
A
|
||||
.Cs /
|
||||
followed by any character that you see on the level,
|
||||
will tell you what that character is.
|
||||
For instance,
|
||||
typing
|
||||
.Cs /@
|
||||
will tell you that the
|
||||
.Cs @
|
||||
symbol represents you, the player.
|
||||
.ip "h, H, ^H"
|
||||
Move left.
|
||||
You move one space to the left.
|
||||
If you use upper case
|
||||
.Cs h ,
|
||||
you will continue to move left until you run into something.
|
||||
This works for all movement commands
|
||||
(e.g.
|
||||
.Cs L
|
||||
means run in direction
|
||||
.Cs l )
|
||||
If you use the \*(lqcontrol\*(rq
|
||||
.Cs h ,
|
||||
you will continue moving in the specified direction
|
||||
until you pass something interesting or run into a wall.
|
||||
You should experiment with this,
|
||||
since it is a very useful command,
|
||||
but very difficult to describe.
|
||||
This also works for all movement commands.
|
||||
.ip j
|
||||
Move down.
|
||||
.ip k
|
||||
Move up.
|
||||
.ip l
|
||||
Move right.
|
||||
.ip y
|
||||
Move diagonally up and left.
|
||||
.ip u
|
||||
Move diagonally up and right.
|
||||
.ip b
|
||||
Move diagonally down and left.
|
||||
.ip n
|
||||
Move diagonally down and right.
|
||||
.ip t
|
||||
Throw an object.
|
||||
This is a prefix command.
|
||||
When followed with a direction
|
||||
it throws an object in the specified direction.
|
||||
(e.g. type
|
||||
.Cs th
|
||||
to throw
|
||||
something to the left.)
|
||||
.ip f
|
||||
Fight until someone dies.
|
||||
When followed with a direction
|
||||
this will force you to fight the creature in that direction
|
||||
until either you or it bites the big one.
|
||||
.ip m
|
||||
Move onto something without picking it up.
|
||||
This will move you one space in the direction you specify and,
|
||||
if there is an object there you can pick up,
|
||||
it won't do it.
|
||||
.ip z
|
||||
Zap prefix.
|
||||
Point a staff or wand in a given direction
|
||||
and fire it.
|
||||
Even non-directional staves must be pointed in some direction
|
||||
to be used.
|
||||
.ip ^
|
||||
Identify trap command.
|
||||
If a trap is on your map
|
||||
and you can't remember what type it is,
|
||||
you can get rogue to remind you
|
||||
by getting next to it and typing
|
||||
.Cs ^
|
||||
followed by the direction that would move you on top of it.
|
||||
.ip s
|
||||
Search for traps and secret doors.
|
||||
Examine each space immediately adjacent to you
|
||||
for the existence of a trap or secret door.
|
||||
There is a large chance that even if there is something there,
|
||||
you won't find it,
|
||||
so you might have to search a while before you find something.
|
||||
.ip >
|
||||
Climb down a staircase to the next level.
|
||||
Not surprisingly, this can only be done if you are standing on staircase.
|
||||
.ip <
|
||||
Climb up a staircase to the level above.
|
||||
This can't be done without the Amulet of Yendor in your possession.
|
||||
.ip "."
|
||||
Rest.
|
||||
This is the \*(lqdo nothing\*(rq command.
|
||||
This is good for waiting and healing.
|
||||
.ip ,
|
||||
Pick up something.
|
||||
This picks up whatever you are currently standing on,
|
||||
if you are standing on anything at all.
|
||||
.ip i
|
||||
Inventory.
|
||||
List what you are carrying in your pack.
|
||||
.ip I
|
||||
Selective inventory.
|
||||
Tells you what a single item in your pack is.
|
||||
.ip q
|
||||
Quaff one of the potions you are carrying.
|
||||
.ip r
|
||||
Read one of the scrolls in your pack.
|
||||
.ip e
|
||||
Eat food from your pack.
|
||||
.ip w
|
||||
Wield a weapon.
|
||||
Take a weapon out of your pack and carry it for use in combat,
|
||||
replacing the one you are currently using (if any).
|
||||
.ip W
|
||||
Wear armor.
|
||||
You can only wear one suit of armor at a time.
|
||||
This takes extra time.
|
||||
.ip T
|
||||
Take armor off.
|
||||
You can't remove armor that is cursed.
|
||||
This takes extra time.
|
||||
.ip P
|
||||
Put on a ring.
|
||||
You can wear only two rings at a time
|
||||
(one on each hand).
|
||||
If you aren't wearing any rings,
|
||||
this command will ask you which hand you want to wear it on,
|
||||
otherwise, it will place it on the unused hand.
|
||||
The program assumes that you wield your sword in your right hand.
|
||||
.ip R
|
||||
Remove a ring.
|
||||
If you are only wearing one ring,
|
||||
this command takes it off.
|
||||
If you are wearing two,
|
||||
it will ask you which one you wish to remove,
|
||||
.ip d
|
||||
Drop an object.
|
||||
Take something out of your pack and leave it lying on the floor.
|
||||
Only one object can occupy each space.
|
||||
You cannot drop a cursed object at all
|
||||
if you are wielding or wearing it.
|
||||
.ip c
|
||||
Call an object something.
|
||||
If you have a type of object in your pack
|
||||
which you wish to remember something about,
|
||||
you can use the call command to give a name to that type of object.
|
||||
This is usually used when you figure out what a
|
||||
potion, scroll, ring, or staff is
|
||||
after you pick it up,
|
||||
or when you want to remember
|
||||
which of those swords in your pack you were wielding.
|
||||
.ip D
|
||||
Print out which things you've discovered something about.
|
||||
This command will ask you what type of thing you are interested in.
|
||||
If you type the character for a given type of object
|
||||
(\fIe.g.\fP
|
||||
.Cs !
|
||||
for potion)
|
||||
it will tell you which kinds of that type of object you've discovered
|
||||
(\fIi.e.\fP, figured out what they are).
|
||||
This command works for potions, scrolls, rings, and staves and wands.
|
||||
.ip o
|
||||
Examine and set options.
|
||||
This command is further explained in the section on options.
|
||||
.ip ^R
|
||||
Redraws the screen.
|
||||
Useful if spurious messages or transmission errors
|
||||
have messed up the display.
|
||||
.ip ^P
|
||||
Print last message.
|
||||
Useful when a message disappears before you can read it.
|
||||
This only repeats the last message
|
||||
that was not a mistyped command
|
||||
so that you don't loose anything by accidentally typing
|
||||
the wrong character instead of ^P.
|
||||
.ip \*E
|
||||
Cancel a command, prefix, or count.
|
||||
.ip !
|
||||
Escape to a shell for some commands.
|
||||
.ip Q
|
||||
Quit.
|
||||
Leave the game.
|
||||
.ip S
|
||||
Save the current game in a file.
|
||||
It will ask you whether you wish to use the default save file.
|
||||
.i Caveat :
|
||||
Rogue won't let you start up a copy of a saved game,
|
||||
and it removes the save file as soon as you start up a restored game.
|
||||
This is to prevent people from saving a game just before a dangerous position
|
||||
and then restarting it if they die.
|
||||
To restore a saved game,
|
||||
give the file name as an argument to rogue.
|
||||
As in
|
||||
.ti +1i
|
||||
.nf
|
||||
% rogue \fIsave\*_file\fP
|
||||
.ip
|
||||
To restart from the default save file (see below),
|
||||
run
|
||||
.ti +1i
|
||||
.nf
|
||||
% rogue \-r
|
||||
.ip v
|
||||
Prints the program version number.
|
||||
.ip )
|
||||
Print the weapon you are currently wielding
|
||||
.ip ]
|
||||
Print the armor you are currently wearing
|
||||
.ip =
|
||||
Print the rings you are currently wearing
|
||||
.ip @
|
||||
Reprint the status line on the message line
|
||||
.sh 1 Rooms
|
||||
.pp
|
||||
Rooms in the dungeons are either lit or dark.
|
||||
If you walk into a lit room,
|
||||
the entire room will be drawn on the screen as soon as you enter.
|
||||
If you walk into a dark room,
|
||||
it will only be displayed as you explore it.
|
||||
Upon leaving a room,
|
||||
all monsters inside the room
|
||||
are erased from the screen.
|
||||
In the darkness you can only see one space
|
||||
in all directions around you.
|
||||
A corridor is always dark.
|
||||
.sh 1 Fighting
|
||||
.pp
|
||||
If you see a monster and you wish to fight it,
|
||||
just attempt to run into it.
|
||||
Many times a monster you find will mind its own business
|
||||
unless you attack it.
|
||||
It is often the case that discretion is the better part of valor.
|
||||
.sh 1 "Objects you can find"
|
||||
.pp
|
||||
When you find something in the dungeon,
|
||||
it is common to want to pick the object up.
|
||||
This is accomplished in rogue by walking over the object
|
||||
(unless you use the
|
||||
.Cs m
|
||||
prefix, see above).
|
||||
If you are carrying too many things,
|
||||
the program will tell you and it won't pick up the object,
|
||||
otherwise it will add it to your pack
|
||||
and tell you what you just picked up.
|
||||
.pp
|
||||
Many of the commands that operate on objects must prompt you
|
||||
to find out which object you want to use.
|
||||
If you change your mind and don't want to do that command after all,
|
||||
just type an \*E and the command will be aborted.
|
||||
.pp
|
||||
Some objects, like armor and weapons,
|
||||
are easily differentiated.
|
||||
Others, like scrolls and potions,
|
||||
are given labels which vary according to type.
|
||||
During a game,
|
||||
any two of the same kind of object
|
||||
with the same label
|
||||
are the same type.
|
||||
However,
|
||||
the labels will vary from game to game.
|
||||
.pp
|
||||
When you use one of these labeled objects,
|
||||
if its effect is obvious,
|
||||
rogue will remember what it is for you.
|
||||
If it's effect isn't extremely obvious
|
||||
you will be asked what you want to scribble on it
|
||||
so you will recognize it later,
|
||||
or you can use the
|
||||
.Cs call
|
||||
command
|
||||
(see above).
|
||||
.sh 2 Weapons
|
||||
.pp
|
||||
Some weapons,
|
||||
like arrows,
|
||||
come in bunches,
|
||||
but most come one at a time.
|
||||
In order to use a weapon,
|
||||
you must wield it.
|
||||
To fire an arrow out of a bow,
|
||||
you must first wield the bow,
|
||||
then throw the arrow.
|
||||
You can only wield one weapon at a time,
|
||||
but you can't change weapons if the one
|
||||
you are currently wielding is cursed.
|
||||
The commands to use weapons are
|
||||
.Cs w
|
||||
(wield)
|
||||
and
|
||||
.Cs t
|
||||
(throw).
|
||||
.sh 2 Armor
|
||||
.pp
|
||||
There are various sorts of armor lying around in the dungeon.
|
||||
Some of it is enchanted,
|
||||
some is cursed,
|
||||
and some is just normal.
|
||||
Different armor types have different armor protection.
|
||||
The higher the armor protection,
|
||||
the more protection the armor affords against the blows of monsters.
|
||||
Here is a list of the various armor types and their normal armor protection:
|
||||
.(b
|
||||
.TS
|
||||
box center;
|
||||
l r.
|
||||
\ \ \fIType Protection\fP
|
||||
None 0
|
||||
Leather armor 2
|
||||
Studded leather / Ring mail 3
|
||||
Scale mail 4
|
||||
Chain mail 5
|
||||
Banded mail / Splint mail 6
|
||||
Plate mail 7
|
||||
.TE
|
||||
.)b
|
||||
.lp
|
||||
If a piece of armor is enchanted,
|
||||
its armor protection will be higher than normal.
|
||||
If a suit of armor is cursed,
|
||||
its armor protection will be lower,
|
||||
and you will not be able to remove it.
|
||||
However, not all armor with a protection that is lower than normal is cursed.
|
||||
.pp
|
||||
The commands to use weapons are
|
||||
.Cs W
|
||||
(wear)
|
||||
and
|
||||
.Cs T
|
||||
(take off).
|
||||
.sh 2 Scrolls
|
||||
.pp
|
||||
Scrolls come with titles in an unknown tongue\**.
|
||||
.(f
|
||||
\** Actually, it's a dialect spoken only by the twenty-seven members
|
||||
of a tribe in Outer Mongolia,
|
||||
but you're not supposed to
|
||||
.i know
|
||||
that.
|
||||
.)f
|
||||
After you read a scroll,
|
||||
it disappears from your pack.
|
||||
The command to use a scroll is
|
||||
.Cs r
|
||||
(read).
|
||||
.sh 2 Potions
|
||||
.pp
|
||||
Potions are labeled by the color of the liquid inside the flask.
|
||||
They disappear after being quaffed.
|
||||
The command to use a scroll is
|
||||
.Cs q
|
||||
(quaff).
|
||||
.sh 2 "Staves and Wands"
|
||||
.pp
|
||||
Staves and wands do the same kinds of things.
|
||||
Staves are identified by a type of wood;
|
||||
wands by a type of metal or bone.
|
||||
They are generally things you want to do to something
|
||||
over a long distance,
|
||||
so you must point them at what you wish to affect
|
||||
to use them.
|
||||
Some staves are not affected by the direction they are pointed, though.
|
||||
Staves come with multiple magic charges,
|
||||
the number being random,
|
||||
and when they are used up,
|
||||
the staff is just a piece of wood or metal.
|
||||
.pp
|
||||
The command to use a wand or staff is
|
||||
.Cs z
|
||||
(zap)
|
||||
.sh 2 Rings
|
||||
.pp
|
||||
Rings are very useful items,
|
||||
since they are relatively permanent magic,
|
||||
unlike the usually fleeting effects of potions, scrolls, and staves.
|
||||
Of course,
|
||||
the bad rings are also more powerful.
|
||||
Most rings also cause you to use up food more rapidly,
|
||||
the rate varying with the type of ring.
|
||||
Rings are differentiated by their stone settings.
|
||||
The commands to use rings are
|
||||
.Cs P
|
||||
(put on)
|
||||
and
|
||||
.Cs R
|
||||
(remove).
|
||||
.sh 2 Food
|
||||
.pp
|
||||
Food is necessary to keep you going.
|
||||
If you go too long without eating you will faint,
|
||||
and eventually die of starvation.
|
||||
The command to use food is
|
||||
.Cs e
|
||||
(eat).
|
||||
.sh 1 Options
|
||||
.pp
|
||||
Due to variations in personal tastes
|
||||
and conceptions of the way rogue should do things,
|
||||
there are a set of options you can set
|
||||
that cause rogue to behave in various different ways.
|
||||
.sh 2 "Setting the options"
|
||||
.pp
|
||||
There are two ways to set the options.
|
||||
The first is with the
|
||||
.Cs o
|
||||
command of rogue;
|
||||
the second is with the
|
||||
.Cs ROGUEOPTS
|
||||
environment variable\**.
|
||||
.(f
|
||||
\** On Version 6 systems,
|
||||
there is no equivalent of the ROGUEOPTS feature.
|
||||
.br
|
||||
.)f
|
||||
.br
|
||||
.sh 3 "Using the `o' command"
|
||||
.pp
|
||||
When you type
|
||||
.Cs o
|
||||
in rogue,
|
||||
it clears the screen
|
||||
and displays the current settings for all the options.
|
||||
It then places the cursor by the value of the first option
|
||||
and waits for you to type.
|
||||
You can type a \*R
|
||||
which means to go to the next option,
|
||||
a
|
||||
.Cs \-
|
||||
which means to go to the previous option,
|
||||
an \*E
|
||||
which means to return to the game,
|
||||
or you can give the option a value.
|
||||
For boolean options this merely involves typing
|
||||
.Cs t
|
||||
for true or
|
||||
.Cs f
|
||||
for false.
|
||||
For string options,
|
||||
type the new value followed by a \*R.
|
||||
.sh 3 "Using the ROGUEOPTS variable"
|
||||
.pp
|
||||
The ROGUEOPTS variable is a string
|
||||
containing a comma separated list of initial values
|
||||
for the various options.
|
||||
Boolean variables can be turned on by listing their name
|
||||
or turned off by putting a
|
||||
.Cs no
|
||||
in front of the name.
|
||||
Thus to set up an environment variable so that
|
||||
.b jump
|
||||
is on,
|
||||
.b terse
|
||||
is off,
|
||||
and the
|
||||
.b name
|
||||
is set to \*(lqBlue Meanie\*(rq,
|
||||
use the command
|
||||
.nf
|
||||
.ti +3n
|
||||
% setenv ROGUEOPTS "jump,noterse,name=Blue Meanie"\**
|
||||
.fi
|
||||
.(f
|
||||
\**
|
||||
For those of you who use the Bourne shell sh (1), the commands would be
|
||||
.in +3
|
||||
.nf
|
||||
$ ROGUEOPTS="jump,noterse,name=Blue Meanie"
|
||||
$ export ROGUEOPTS
|
||||
.fi
|
||||
.in +0
|
||||
.)f
|
||||
.sh 2 "Option list"
|
||||
.pp
|
||||
Here is a list of the options
|
||||
and an explanation of what each one is for.
|
||||
The default value for each is enclosed in square brackets.
|
||||
For character string options,
|
||||
input over fifty characters will be ignored.
|
||||
.ip "\fBterse\fP [\fI\^noterse\^\fP]"
|
||||
Useful for those who are tired of the sometimes lengthy messages of rogue.
|
||||
This is a useful option for playing on slow terminals,
|
||||
so this option defaults to
|
||||
.i terse
|
||||
if you
|
||||
are on a slow (1200 baud or under) terminal.
|
||||
.ip "\fBjump\fP [\fI\^nojump\^\fP]"
|
||||
If this option is set,
|
||||
running moves will not be displayed
|
||||
until you reach the end of the move.
|
||||
This saves considerable cpu and display time.
|
||||
This option defaults to
|
||||
.i jump
|
||||
if you are using a slow terminal.
|
||||
.ip "\fBflush\fP [\fI\^noflush\^\fP]"
|
||||
All typeahead is thrown away after each round of battle.
|
||||
This is useful for those who type far ahead
|
||||
and then watch in dismay as a Bat kills them.
|
||||
.ip "\fBseefloor\fP [\fI\^seefloor\^\fP]"
|
||||
Display the floor around you on the screen
|
||||
as you move through dark rooms.
|
||||
Due to the amount of characters generated,
|
||||
this option defaults to
|
||||
.i noseefloor
|
||||
if you are using a slow terminal.
|
||||
.ip "\fBpassgo\fP [\fI\^nopassgo\^\fP]"
|
||||
Follow turnings in passageways.
|
||||
If you run in a passage
|
||||
and you run into stone or a wall,
|
||||
rogue will see if it can turn to the right or left.
|
||||
If it can only turn one way,
|
||||
it will turn that way.
|
||||
If it can turn either or neither,
|
||||
it will stop.
|
||||
This algorithm can sometimes lead to slightly confusing occurrences
|
||||
which is why it defaults to \fInopassgo\fP.
|
||||
.ip "\fBtombstone\fP [\fI\^tombstone\^\fP]"
|
||||
Print out the tombstone at the end if you get killed.
|
||||
This is nice but slow, so you can turn it off if you like.
|
||||
.ip "\fBinven\fP [\fI\^overwrite\^\fP]"
|
||||
Inventory type.
|
||||
This can have one of three values:
|
||||
.i overwrite ,
|
||||
.i slow ,
|
||||
or
|
||||
.i clear .
|
||||
With
|
||||
.i overwrite
|
||||
the top lines of the map are overwritten
|
||||
with the list
|
||||
when inventory is requested
|
||||
or when
|
||||
\*(lqWhich item do you wish to \fB. . .\fP? \*(rq questions
|
||||
are answered with a
|
||||
.Cs * .
|
||||
However, if the list is longer than a screenful,
|
||||
the screen is cleared.
|
||||
With
|
||||
.i slow ,
|
||||
lists are displayed one item at a time on the top of the screen,
|
||||
and with
|
||||
.i clear ,
|
||||
the screen is cleared,
|
||||
the list is displayed,
|
||||
and then the dungeon level is re-displayed.
|
||||
Due to speed considerations,
|
||||
.i clear
|
||||
is the default for terminals without
|
||||
clear-to-end-of-line capabilities.
|
||||
.ip "\fBname\fP [account name]"
|
||||
This is the name of your character.
|
||||
It is used if you get on the top ten scorer's list.
|
||||
.ip "\fBfruit\fP [\fI\^slime-mold\^\fP]"
|
||||
This should hold the name of a fruit that you enjoy eating.
|
||||
It is basically a whimsey that rogue uses in a couple of places.
|
||||
.ip "\fBfile\fP [\fI\^~/rogue.save\^\fP]"
|
||||
The default file name for saving the game.
|
||||
If your phone is hung up by accident,
|
||||
rogue will automatically save the game in this file.
|
||||
The file name may start with the special character
|
||||
.Cs ~
|
||||
which expands to be your home directory.
|
||||
.sh 1 Scoring
|
||||
.pp
|
||||
Rogue usually maintains a list
|
||||
of the top scoring people or scores on your machine.
|
||||
Depending on how it is set up,
|
||||
it can post either the top scores
|
||||
or the top players.
|
||||
In the latter case,
|
||||
each account on the machine
|
||||
can post only one non-winning score on this list.
|
||||
If you score higher than someone else on this list,
|
||||
or better your previous score on the list,
|
||||
you will be inserted in the proper place
|
||||
under your current name.
|
||||
How many scores are kept
|
||||
can also be set up by whoever installs it on your machine.
|
||||
.pp
|
||||
If you quit the game, you get out with all of your gold intact.
|
||||
If, however, you get killed in the Dungeons of Doom,
|
||||
your body is forwarded to your next-of-kin,
|
||||
along with 90% of your gold;
|
||||
ten percent of your gold is kept by the Dungeons' wizard as a fee\**.
|
||||
.(f
|
||||
\** The Dungeon's wizard is named Wally the Wonder Badger.
|
||||
Invocations should be accompanied by a sizable donation.
|
||||
.)f
|
||||
This should make you consider whether you want to take one last hit
|
||||
at that monster and possibly live,
|
||||
or quit and thus stop with whatever you have.
|
||||
If you quit, you do get all your gold,
|
||||
but if you swing and live, you might find more.
|
||||
.pp
|
||||
If you just want to see what the current top players/games list is,
|
||||
you can type
|
||||
.ti +1i
|
||||
.nf
|
||||
% @PROGRAM@ \-s
|
||||
.br
|
||||
.sh 1 Acknowledgements
|
||||
.pp
|
||||
Rogue was originally conceived of by Glenn Wichman and Michael Toy.
|
||||
Ken Arnold and Michael Toy then smoothed out the user interface,
|
||||
and added jillions of new features.
|
||||
We would like to thank
|
||||
Bob Arnold,
|
||||
Michelle Busch,
|
||||
Andy Hatcher,
|
||||
Kipp Hickman,
|
||||
Mark Horton,
|
||||
Daniel Jensen,
|
||||
Bill Joy,
|
||||
Joe Kalash,
|
||||
Steve Maurer,
|
||||
Marty McNary,
|
||||
Jan Miller,
|
||||
and
|
||||
Scott Nelson
|
||||
for their ideas and assistance;
|
||||
and also the teeming multitudes
|
||||
who graciously ignored work, school, and social life to play rogue
|
||||
and send us bugs, complaints, suggestions, and just plain flames.
|
||||
And also Mom.
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 1005 B |
@@ -1,107 +0,0 @@
|
||||
Name: rogue
|
||||
Version: 5.4.4
|
||||
Release: 1%{?dist}
|
||||
Summary: The original graphical adventure game
|
||||
|
||||
Group: Amusements/Games
|
||||
License: BSD
|
||||
URL: http://rogue.rogueforge.net/
|
||||
Source0: http://rogue.rogueforge.net/files/rogue5.4/rogue5.4.4-src.tar.gz
|
||||
Source1: rogue.desktop
|
||||
Source2: rogue.png
|
||||
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
|
||||
|
||||
BuildRequires: desktop-file-utils
|
||||
BuildRequires: ncurses-devel
|
||||
|
||||
%description
|
||||
The one, the only, the original graphical adventure game that spawned
|
||||
an entire genre.
|
||||
|
||||
%prep
|
||||
%setup -q -n %{name}%{version}
|
||||
|
||||
|
||||
%build
|
||||
%configure --enable-setgid=games --enable-scorefile=%{_var}/games/roguelike/rogue54.scr --enable-lockfile=%{_var}/games/roguelike/rogue54.lck
|
||||
make %{_smp_mflags}
|
||||
|
||||
|
||||
%install
|
||||
rm -rf $RPM_BUILD_ROOT
|
||||
|
||||
make install DESTDIR=$RPM_BUILD_ROOT
|
||||
|
||||
desktop-file-install --vendor fedora \
|
||||
--dir ${RPM_BUILD_ROOT}%{_datadir}/applications \
|
||||
%{SOURCE1}
|
||||
mkdir -p $RPM_BUILD_ROOT/%{_datadir}/icons/hicolor/32x32/apps/
|
||||
install -p -m 644 %{SOURCE2} $RPM_BUILD_ROOT/%{_datadir}/icons/hicolor/32x32/apps/
|
||||
|
||||
|
||||
%clean
|
||||
rm -rf $RPM_BUILD_ROOT
|
||||
|
||||
%post
|
||||
touch --no-create %{_datadir}/icons/hicolor || :
|
||||
if [ -x %{_bindir}/gtk-update-icon-cache ]; then
|
||||
%{_bindir}/gtk-update-icon-cache --quiet %{_datadir}/icons/hicolor || :
|
||||
fi
|
||||
|
||||
%postun
|
||||
touch --no-create %{_datadir}/icons/hicolor || :
|
||||
if [ -x %{_bindir}/gtk-update-icon-cache ]; then
|
||||
%{_bindir}/gtk-update-icon-cache --quiet %{_datadir}/icons/hicolor || :
|
||||
fi
|
||||
|
||||
|
||||
%files
|
||||
%defattr(-,root,root,-)
|
||||
%attr(2755,games,games) %{_bindir}/rogue
|
||||
%{_mandir}/man6/rogue.6.gz
|
||||
%{_datadir}/applications/fedora-%{name}.desktop
|
||||
%{_datadir}/icons/hicolor/32x32/apps/rogue.png
|
||||
%dir %attr(0775,games,games) %{_var}/games/roguelike
|
||||
%config(noreplace) %attr(0664,games,games) %{_var}/games/roguelike/rogue54.scr
|
||||
%doc %{_docdir}/%{name}-%{version}
|
||||
|
||||
|
||||
%changelog
|
||||
* Sun Sep 2 2007 Wart <wart at kobold.org> 5.4.4-1
|
||||
- Update to 5.4.4
|
||||
|
||||
* Mon Aug 20 2007 Wart <wart at kobold.org> 5.4.3-1
|
||||
- Update to 5.4.3
|
||||
|
||||
* Sun Jul 15 2007 Wart <wart at kobold.org> 5.4.2-9
|
||||
- New upstream home page and download URL
|
||||
- Add patch when reading long values from the save file on 64-bit arch
|
||||
(BZ #248283)
|
||||
- Add patch removing many compiler warnings
|
||||
- Use proper version in the .desktop file
|
||||
|
||||
* Sat Mar 3 2007 Wart <wart at kobold.org> 5.4.2-8
|
||||
- Use better sourceforge download url
|
||||
- Use more precise desktop file categories
|
||||
|
||||
* Mon Aug 28 2006 Wart <wart at kobold.org> 5.4.2-7
|
||||
- Rebuild for Fedora Extras
|
||||
|
||||
* Tue May 16 2006 Wart <wart at kobold.org> 5.4.2-6
|
||||
- Added empty initial scoreboard file.
|
||||
|
||||
* Mon May 15 2006 Wart <wart at kobold.org> 5.4.2-5
|
||||
- Better setuid/setgid handling (again) (BZ #187392)
|
||||
|
||||
* Thu Mar 30 2006 Wart <wart at kobold.org> 5.4.2-4
|
||||
- Better setuid/setgid handling (BZ #187392)
|
||||
- Resize desktop icon to match directory name
|
||||
|
||||
* Mon Mar 13 2006 Wart <wart at kobold.org> 5.4.2-3
|
||||
- Added icon for .desktop file.
|
||||
|
||||
* Sun Mar 12 2006 Wart <wart at kobold.org> 5.4.2-2
|
||||
- Added missing BR: ncurses-devel, desktop-file-utils
|
||||
|
||||
* Sat Feb 25 2006 Wart <wart at kobold.org> 5.4.2-1
|
||||
- Initial spec file.
|
||||
@@ -1,27 +0,0 @@
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 14
|
||||
VisualStudioVersion = 14.0.25420.1
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "rogue54", "rogue54.vcxproj", "{9EA0D326-8097-4ADA-82EA-4DB1F5CAA8F6}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Win32 = Debug|Win32
|
||||
Debug|x64 = Debug|x64
|
||||
Release|Win32 = Release|Win32
|
||||
Release|x64 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{9EA0D326-8097-4ADA-82EA-4DB1F5CAA8F6}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{9EA0D326-8097-4ADA-82EA-4DB1F5CAA8F6}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{9EA0D326-8097-4ADA-82EA-4DB1F5CAA8F6}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{9EA0D326-8097-4ADA-82EA-4DB1F5CAA8F6}.Debug|x64.Build.0 = Debug|x64
|
||||
{9EA0D326-8097-4ADA-82EA-4DB1F5CAA8F6}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{9EA0D326-8097-4ADA-82EA-4DB1F5CAA8F6}.Release|Win32.Build.0 = Release|Win32
|
||||
{9EA0D326-8097-4ADA-82EA-4DB1F5CAA8F6}.Release|x64.ActiveCfg = Release|x64
|
||||
{9EA0D326-8097-4ADA-82EA-4DB1F5CAA8F6}.Release|x64.Build.0 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
@@ -1,396 +0,0 @@
|
||||
<?xml version="1.0" encoding="Windows-1252"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="8.00"
|
||||
Name="rogue54"
|
||||
ProjectGUID="{9EA0D326-8097-4ADA-82EA-4DB1F5CAA8F6}"
|
||||
Keyword="Win32Proj"
|
||||
>
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"
|
||||
/>
|
||||
</Platforms>
|
||||
<ToolFiles>
|
||||
</ToolFiles>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
OutputDirectory="Debug"
|
||||
IntermediateDirectory="Debug"
|
||||
ConfigurationType="1"
|
||||
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC70.vsprops"
|
||||
CharacterSet="2"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
InlineFunctionExpansion="0"
|
||||
AdditionalIncludeDirectories="../pdcurses"
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_CRT_SECURE_NO_DEPRECATE;ALLSCORES;MASTER;SCOREFILE=\"rogue54.scr\";LOCKFILE=\"rogue54.lck\""
|
||||
StringPooling="true"
|
||||
MinimalRebuild="false"
|
||||
ExceptionHandling="0"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="0"
|
||||
BufferSecurityCheck="true"
|
||||
EnableFunctionLevelLinking="true"
|
||||
DisableLanguageExtensions="false"
|
||||
ForceConformanceInForLoopScope="true"
|
||||
UsePrecompiledHeader="0"
|
||||
BrowseInformation="0"
|
||||
WarningLevel="4"
|
||||
Detect64BitPortabilityProblems="true"
|
||||
DebugInformationFormat="4"
|
||||
CompileAs="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies="Ws2_32.lib pdcurses.lib advapi32.lib shfolder.lib user32.lib"
|
||||
OutputFile="$(OutDir)/rogue54.exe"
|
||||
LinkIncremental="2"
|
||||
AdditionalLibraryDirectories="..\pdcurses"
|
||||
IgnoreAllDefaultLibraries="false"
|
||||
IgnoreDefaultLibraryNames=""
|
||||
GenerateDebugInformation="true"
|
||||
ProgramDatabaseFile="$(OutDir)/rogue54.pdb"
|
||||
SubSystem="1"
|
||||
TargetMachine="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|Win32"
|
||||
OutputDirectory="Release"
|
||||
IntermediateDirectory="Release"
|
||||
ConfigurationType="1"
|
||||
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC70.vsprops"
|
||||
CharacterSet="2"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="2"
|
||||
InlineFunctionExpansion="1"
|
||||
OmitFramePointers="true"
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS"
|
||||
StringPooling="true"
|
||||
RuntimeLibrary="0"
|
||||
EnableFunctionLevelLinking="true"
|
||||
UsePrecompiledHeader="2"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="true"
|
||||
DebugInformationFormat="3"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
OutputFile="$(OutDir)/rogue54.exe"
|
||||
LinkIncremental="1"
|
||||
GenerateDebugInformation="true"
|
||||
SubSystem="2"
|
||||
OptimizeReferences="2"
|
||||
EnableCOMDATFolding="2"
|
||||
TargetMachine="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<References>
|
||||
</References>
|
||||
<Files>
|
||||
<Filter
|
||||
Name="Source Files"
|
||||
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm"
|
||||
>
|
||||
<File
|
||||
RelativePath="armor.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="chase.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="command.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="daemon.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="daemons.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="extern.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="fight.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="findpw.c"
|
||||
>
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32"
|
||||
ExcludedFromBuild="true"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="init.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="io.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="list.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="mach_dep.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="main.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="mdport.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="misc.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="monsters.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="move.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="new_level.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="options.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="pack.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="passages.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="potions.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="rings.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="rip.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="rooms.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="save.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="scedit.c"
|
||||
>
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32"
|
||||
ExcludedFromBuild="true"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="scmisc.c"
|
||||
>
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32"
|
||||
ExcludedFromBuild="true"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="scrolls.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="state.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="sticks.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="things.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="vers.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="weapons.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="wizard.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="xcrypt.c"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Header Files"
|
||||
Filter="h;hpp;hxx;hm;inl;inc"
|
||||
>
|
||||
<File
|
||||
RelativePath="extern.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="rogue.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="score.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Resource Files"
|
||||
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
|
||||
>
|
||||
</Filter>
|
||||
<File
|
||||
RelativePath="LICENSE.TXT"
|
||||
>
|
||||
</File>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
||||
@@ -1,257 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{9EA0D326-8097-4ADA-82EA-4DB1F5CAA8F6}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<UseOfMfc>false</UseOfMfc>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
<Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC70.props" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
<Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC70.props" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
<Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC70.props" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
<Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC70.props" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup>
|
||||
<_ProjectFileVersion>14.0.25431.1</_ProjectFileVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<OutDir>Debug\</OutDir>
|
||||
<IntDir>Debug\</IntDir>
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<OutDir>Release\</OutDir>
|
||||
<IntDir>Release\</IntDir>
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<InlineFunctionExpansion>Default</InlineFunctionExpansion>
|
||||
<AdditionalIncludeDirectories>../pdcurses;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_CRT_SECURE_NO_DEPRECATE;ALLSCORES;MASTER;SCOREFILE="rogue54.scr";LOCKFILE="rogue54.lck";%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<StringPooling>true</StringPooling>
|
||||
<MinimalRebuild>false</MinimalRebuild>
|
||||
<ExceptionHandling />
|
||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<BufferSecurityCheck>true</BufferSecurityCheck>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<DisableLanguageExtensions>false</DisableLanguageExtensions>
|
||||
<ForceConformanceInForLoopScope>true</ForceConformanceInForLoopScope>
|
||||
<PrecompiledHeader />
|
||||
<BrowseInformation />
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
|
||||
<CompileAs>CompileAsC</CompileAs>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>Ws2_32.lib;pdcurses.lib;advapi32.lib;shfolder.lib;user32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<OutputFile>$(OutDir)rogue54.exe</OutputFile>
|
||||
<AdditionalLibraryDirectories>..\pdcurses;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<ProgramDatabaseFile>$(OutDir)rogue54.pdb</ProgramDatabaseFile>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<TargetMachine>MachineX86</TargetMachine>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<InlineFunctionExpansion>Default</InlineFunctionExpansion>
|
||||
<AdditionalIncludeDirectories>$(ProjectDir)x86_64-w64-msvc\deps\install\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;PDC_DLL_BUILD;PDC_WIDE;PDCDEBUG;_CRT_SECURE_NO_DEPRECATE;ALLSCORES;SCOREFILE="rogue54.scr";LOCKFILE="rogue54.lck";%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<StringPooling>true</StringPooling>
|
||||
<MinimalRebuild>false</MinimalRebuild>
|
||||
<ExceptionHandling>
|
||||
</ExceptionHandling>
|
||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<BufferSecurityCheck>true</BufferSecurityCheck>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<DisableLanguageExtensions>false</DisableLanguageExtensions>
|
||||
<ForceConformanceInForLoopScope>true</ForceConformanceInForLoopScope>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<BrowseInformation>
|
||||
</BrowseInformation>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<CompileAs>CompileAsC</CompileAs>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>Ws2_32.lib;wincon\pdcurses.lib;libcurl_imp.lib;advapi32.lib;shfolder.lib;user32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<OutputFile>$(OutDir)rogue54.exe</OutputFile>
|
||||
<AdditionalLibraryDirectories>$(ProjectDir)x86_64-w64-msvc\deps\install\lib;$(ProjectDir)x86_64-w64-msvc\deps\install\Release\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<ProgramDatabaseFile>$(OutDir)rogue54.pdb</ProgramDatabaseFile>
|
||||
<SubSystem>Console</SubSystem>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
|
||||
<OmitFramePointers>true</OmitFramePointers>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<StringPooling>true</StringPooling>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<AdditionalIncludeDirectories>$(ProjectDir)\x86_64-w64-msvc\include\ncursesw;$(ProjectDir)\x86_64-w64-msvc\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<OutputFile>$(OutDir)rogue54.exe</OutputFile>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<TargetMachine>MachineX86</TargetMachine>
|
||||
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
|
||||
<OmitFramePointers>true</OmitFramePointers>
|
||||
<PreprocessorDefinitions>WIN32;_WINDOWS;NDEBUG;PDC_DLL_BUILD;PDC_WIDE;PDCDEBUG;_CRT_SECURE_NO_DEPRECATE;ALLSCORES;SCOREFILE="rogue54.scr";LOCKFILE="rogue54.lck";%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<StringPooling>true</StringPooling>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<AdditionalIncludeDirectories>$(ProjectDir)x86_64-w64-msvc\deps\install\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PrecompiledHeaderFile>stdafx.h</PrecompiledHeaderFile>
|
||||
<CompileAs>CompileAsC</CompileAs>
|
||||
<ExceptionHandling />
|
||||
<BrowseInformation />
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<OutputFile>$(OutDir)rogue54.exe</OutputFile>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<AdditionalLibraryDirectories>$(ProjectDir)x86_64-w64-msvc\deps\install\lib;$(ProjectDir)x86_64-w64-msvc\deps\install\Release\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalDependencies>Ws2_32.lib;wincon\pdcurses.lib;libcurl_imp.lib;advapi32.lib;shfolder.lib;user32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<IgnoreSpecificDefaultLibraries>%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
|
||||
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
|
||||
<ForceSymbolReferences>%(ForceSymbolReferences)</ForceSymbolReferences>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="armor.c" />
|
||||
<ClCompile Include="chase.c" />
|
||||
<ClCompile Include="command.c" />
|
||||
<ClCompile Include="daemon.c" />
|
||||
<ClCompile Include="daemons.c" />
|
||||
<ClCompile Include="extern.c" />
|
||||
<ClCompile Include="fight.c" />
|
||||
<ClCompile Include="init.c" />
|
||||
<ClCompile Include="io.c" />
|
||||
<ClCompile Include="list.c" />
|
||||
<ClCompile Include="mach_dep.c" />
|
||||
<ClCompile Include="main.c" />
|
||||
<ClCompile Include="mdport.c" />
|
||||
<ClCompile Include="misc.c" />
|
||||
<ClCompile Include="monsters.c" />
|
||||
<ClCompile Include="move.c" />
|
||||
<ClCompile Include="new_level.c" />
|
||||
<ClCompile Include="options.c" />
|
||||
<ClCompile Include="pack.c" />
|
||||
<ClCompile Include="passages.c" />
|
||||
<ClCompile Include="potions.c" />
|
||||
<ClCompile Include="rings.c" />
|
||||
<ClCompile Include="rip.c" />
|
||||
<ClCompile Include="rogue.c" />
|
||||
<ClCompile Include="rooms.c" />
|
||||
<ClCompile Include="save.c" />
|
||||
<ClCompile Include="scrolls.c" />
|
||||
<ClCompile Include="state.c" />
|
||||
<ClCompile Include="sticks.c" />
|
||||
<ClCompile Include="things.c" />
|
||||
<ClCompile Include="vers.c" />
|
||||
<ClCompile Include="weapons.c" />
|
||||
<ClCompile Include="wizard.c" />
|
||||
<ClCompile Include="xcrypt.c" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="extern.h" />
|
||||
<ClInclude Include="rogue.h" />
|
||||
<ClInclude Include="score.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Text Include="LICENSE.TXT" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
@@ -1,64 +0,0 @@
|
||||
@echo off
|
||||
echo Rogue Build Script by Decker (c) 2019
|
||||
|
||||
@REM Check for Visual Studio
|
||||
call set "VSPATH="
|
||||
if defined VS140COMNTOOLS ( if not defined VSPATH (
|
||||
call set "VSPATH=%%VS140COMNTOOLS%%"
|
||||
) )
|
||||
|
||||
@REM check if we already have the tools in the environment
|
||||
if exist "%VCINSTALLDIR%" (
|
||||
goto compile
|
||||
)
|
||||
|
||||
if not defined VSPATH (
|
||||
echo You need Microsoft Visual Studio 15 installed
|
||||
pause
|
||||
exit
|
||||
)
|
||||
|
||||
@REM set up the environment
|
||||
if exist "%VSPATH%..\..\vc\vcvarsall.bat" (
|
||||
call "%%VSPATH%%..\..\vc\vcvarsall.bat" amd64
|
||||
goto compile
|
||||
)
|
||||
|
||||
echo Unable to set up the environment
|
||||
pause
|
||||
exit
|
||||
|
||||
:compile
|
||||
|
||||
mkdir x86_64-w64-msvc\deps
|
||||
mkdir x86_64-w64-msvc\deps\install
|
||||
|
||||
pushd x86_64-w64-msvc\deps
|
||||
|
||||
:compile_pdcurses
|
||||
rem git clone https://github.com/wmcbrine/PDCurses PDCurses.org
|
||||
git clone https://github.com/Bill-Gray/PDCurses
|
||||
|
||||
set PREFIX_DIR=%CD%\install
|
||||
|
||||
pushd PDCurses
|
||||
mkdir build64 & pushd build64
|
||||
rem cmake -G"Visual Studio 14 2015 Win64" -DPDC_WIDE=ON -DCMAKE_INSTALL_PREFIX=%PREFIX_DIR% -DCMAKE_BUILD_TYPE=Debug -DPDCDEBUG=ON ..
|
||||
cmake -G"Visual Studio 14 2015 Win64" -DPDC_WIDE=ON -DCMAKE_INSTALL_PREFIX=%PREFIX_DIR% -DCMAKE_BUILD_TYPE=Release ..
|
||||
popd
|
||||
rem cmake --build build64 --config Debug --target install
|
||||
cmake --build build64 --config Release --target install
|
||||
popd
|
||||
|
||||
:compile_curl
|
||||
|
||||
git clone https://github.com/curl/curl
|
||||
pushd curl
|
||||
|
||||
mkdir build64 & pushd build64
|
||||
cmake -G "Visual Studio 14 2015 Win64" -DCMAKE_INSTALL_PREFIX=%PREFIX_DIR% -DCMAKE_USE_WINSSL:BOOL=ON ..
|
||||
cmake --build . --config Release --target libcurl
|
||||
cmake --build . --config Release --target install
|
||||
popd
|
||||
popd
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user